INFORMIX
DataBlade Developers Kit User's Guide
Chapter 4: C Programming Guidelines
Home Contents Index Master Index New Book

DataBlade Module C Programming Guidelines

This section contains guidelines for writing C code that runs in Informix Dynamic Server virtual processors. Follow the guidelines in the following sections to ensure that your DataBlade module executes safely and efficiently, without disturbing other Informix database server processes:

If your routine must use blocking system calls or is not thread-safe, you must run it in a user-defined virtual processor.

Avoid Unsafe System and Library Calls

Informix Dynamic Server processes many threads concurrently by using migrating threads among virtual processors. System and library calls are considered unsafe because they impair concurrency. An unsafe system call is one that blocks, causing the virtual processor to stall the CPU until the call returns, or one that allocates resources local to the virtual processor instead of in shared memory.

The DataBlade API provides safe alternatives to many system calls; use these routines in your DataBlade module code.

Restrictions by Virtual Processor Class

DataBlade modules that run in the CPU VP have the best performance because they minimize context switch time. To run in a CPU VP, however, a DataBlade module must avoid unsafe system calls.

If your user-defined routines run in a user-defined virtual processor, you can use I/O blocking system calls, but not other unsafe system calls. See "When to Use a User-Defined Virtual Processor" for more information.

Safe POSIX Calls

Many POSIX calls are unsafe because they indirectly use blocking system calls. The following table lists POSIX calls that are safe for use in a DataBlade module that runs in the CPU VP.

Category Safe Calls Notes

character

isalnum, isalpha, isascii, isastream, isatty, iscntrl, isdigit, isgraph, islower, isprint, ispunct, isspace, isupper, isxdigit

string manipulation

toascii, tolower, toupper

string parsing

getopt, getsubopt

Must consider effect of possible thread switches on static memory.

multibyte string

mbtowc, wctomb, mblen, mbstowcs, wcstombs

string

sprintf, sscanf, strcasecmp, strcat, strchr, strcmp, strcoll, strcpy, strcspn, strdup, strerror, strlen, strncasecmp, strncat, strncmp, strncpy, strpbrk, strrchr, strsignal, strspn, strstr, strtod, strtok, strtok_r, strtol, strtoll, strtoul, strtoull, strxfrm

numeric

a64l, abs, atof, atoi, atol, atoll, div, drand48, econvert, ecvt, erand48, fconvert, fcvt, gconvert, gcvt, l64a, labs, ldiv, llabs, lldiv, lltostr, lrand48, mrand48, nrand48, qeconvert, qfconvert, qgconvert, rand, random, seconvert, sfconvert, sgconvert, srand, srand48, srandom, strtoll

The random number generator seed is stored in static memory, so you must reseed it whenever a thread switch might have occurred.

time

ascftime, asctime, asctime_r, cftime, clock, ctime, ctime_r, difftime, gettimeofday, gmtime, gmtime_r, localtime, localtime_r, mktime, strftime

No time zone changes are permitted.

date

getdate

sort/search

bsearch, qsort, lfind, lsearch

encryption

crypt, setkey, encrypt

memory management

memccpy, memchr, memcmp, memcpy, memmove, memset

environment

getenv

bit manipulation

ffs

byte manipulation

swab

structure member manipulation

offsetof

trigonometric functions

acos, acosh, asin, asinh, atan, atan2, atanh, cos, cosh, sin, sinh, tan, tanh

bessel functions

j0, j1, jn, y0, y1, yn

root extraction

cbrt, sqrt

rounding

ceil, floor, rint

IEEE functions

copysign, isnan, fabs, fmod, nextafter, remainder

error functions

erf, erfc

exponentials and logarithms

exp, expm1, log, log10, log1p, pow

gamma functions

lgamma, lgamma_r

signgam is in static memory, so contents are unreliable after a thread switch.

euclidean distance

hypot

Calls to any other standard library interface or operating system routine are not considered safe to use in a CPU VP. Use only the routines listed in this table.

Do Not Use Signals

Informix Dynamic Server reserves all operating system signals for its own use. Your DataBlade module routines must not raise, handle, or mask signals.

Write Thread-Safe Code

For Informix Dynamic Server to process many threads in an efficient, concurrent manner, your code must be thread-safe. See "Thread Management" for a description of how the Informix database server handles threads.

Use DataBlade API Memory Management Functions

To allocate and release memory, use only the DataBlade API memory allocation functions: mi_alloc(), mi_free(), and related routines. These functions allocate space in memory shared by all Informix database server virtual processors. If you use the C library malloc() and free() routines, the memory you allocate cannot be accessed if the thread migrates from one virtual processor to another, and it might overwrite memory addresses that will be needed by the database server.

Do Not Use Global or Static Variables

Global and static variables are not safe because:

Therefore, your user-defined routines must use only stack variables and memory allocated with the DataBlade API memory allocation routines. Both of these types of memory remain accessible when a thread migrates to another virtual processor.

You can use global and static variables only if your user-defined routines are confined to a nonyielding, user-defined virtual processor class containing a single virtual processor. See "When to Use a User-Defined Virtual Processor" for more information.

Use the MI_FPARAM Structure to Track Private States

Most user-defined routines execute once and do not need data saved from previous executions. However, the database server calls iterator routines repeatedly to process a set of data.

For iterative functions that must save information over repeated calls, use the MI_FPARAM structure to save a pointer to memory allocated using mi_dalloc() with the PER_COMMAND duration. The database server passes the same MI_FPARAM structure on each function call for the duration of the query.

See the DataBlade API Programmer's Manual for more information about MI_FPARAM.

Write User-Defined Routines That Yield

Informix Dynamic Server is a nonpreemptive, multithreaded execution engine. If a routine does not yield regularly, it can diminish overall database server throughput by preventing other threads from executing.

User-defined routines that run in the CPU VP must yield the processor regularly so that other threads can execute. Routines that do not yield regularly must run in a user-defined virtual processor. See "User-Defined Virtual Processors" for more information.

To yield the processor, call the mi_yield() DataBlade API function regularly. Add mi_yield() calls to the beginning or end of lengthy loops and before or after an especially expensive computation. See the DataBlade API Programmer's Manual for information on using mi_yield().

Many DataBlade API routines, including all file and large object I/O routines, call mi_yield() after scheduling an I/O or other expensive operation. For this reason, use DataBlade API routines whenever possible in your DataBlade module code.

See "Thread Management" for more information on threads and yielding.




DataBlade Developers Kit User's Guide, version 3.6
Copyright © 1998, Informix Software, Inc. All rights reserved.