Porting applications with pthreads

This list of differences encountered with pthreads and mutexes on z/OS UNIX System Services was originally created by customers who subscribe to the mvs-oe mailing list: Dwayne Blumenberg, Chuck Gehr, Thomas Vogler, and Stephen Wild.

Most of these differences exist because z/OS UNIX UNIX implemented the POSIX.4a draft 6 standard rather than the final version, POSIX.1c draft 10. The book Pthreads Programming by Nichols, Buttlar, and Farrell (ISBN 1-56592-115-1) has a chapter on these differences.

  • alarm() and malarm() functions

    The functions alarm() and malarm() will send the SIGALRM signal only to the thread that called alarm() and malarm(). On some other platforms, SIGALRM can be sent to any thread in the process.

  • Thread-safe variants of POSIX routines

    The pthreads standard defines thread-safe variants of existing POSIX functions (for example, strtok_r instead of strtok); however, these are not available under z/OS UNIX. IBM's response is that under z/OS UNIX the normal versions are thread-safe so you can use them directly. Because the two variants have differing prototypes, this represents a problem if you are porting code which contains the thread-safe variants. You have to either change the code or provide your own versions of the _r routines which map onto the "normal" ones. Here is an example of how to use a macro to create your own version:

    #define strtok_r(s,sep,lasts) strtok(s,sep)
    
  • pthread_delete_key()

    The pthread_delete_key() function is not provided.

  • pthread_attr_setdetachstate

    z/OS UNIX doesn't define pthread_create_detached(), and the call to pthread_attr_setdetachstate() is slightly different, so look at the interface. You can set a variable to __DETATCHED and use this on the call instead.

  • Defaults for DETACHSTATE

    For pthread_attr_setdetachstate(), OS/390 UNIX and other platforms vary in their defaults for DETACHSTATE.

  • Process-shared attribute for mutexes

    z/OS UNIX supports mutexes shared across processes. 

  • Process-shared for pthread Shared Condition Variables

    z/OS UNIX  supports Pthread Shared Condition Variables across processes.

  • pthread_getspecific

    pthread_getspecific() has a slightly different prototype under z/OS UNIX than that specified in the standard.

    z/OS UNIX provides two forms of pthread_getspecific:

    • pthread_getspecific()
    • pthread_getspecific_d8_np()
  • Value returned on error

    When z/OS UNIX pthread functions encounter an error they return -1 and set errno. Other platforms return the error number as the function value. For example, pthread_mutex_trylock() returns -1 and errno contains EBUSY when the lock is occupied, instead of the POSIX-specified behaviour to return a value of EBUSY.

  • Using a C++ function pointer

    If you are using C++, you must use specific declarations for functions that will be passed as function pointers to calls such as pthread_create() and pthread_cleanup_push(), so that they have C linkage. This is also a problem for qsort(), atexit(), bsd_signal(), and for defining signal catchers, signal() and sigaction(). This is not specifically a pthread issue -- this limitation appplies to all OS/390 C functions. Compilers on some other platforms do not discourage mixing C++ and C functions, which allows undesirable programming practices such as trying to use a C++ function when invoking pthread_create().

    Here are some solutions for a situation where C++ code needs the compiler to use C linkage:

    • Declare the functions extern "C". Using an extern "C" wrapper around the function declarations is more portable. If you are writing code for multiple platforms, use this approach.

      Make the function pointer a typedef with extern "C" wrapped around it. Then use the typedef in the structure.

    • Force C linkage to these procedures by using the __cdecl modifier in the function declarations and function definition. This approach is more convenient because it requires fewer code changes, but it is less portable.
    • If the funtion is a member of a class, declare the function as static __cdecl. The static declaration should be required on most platforms to keep the class instance's "this" from being passed as an argument to the function. __ cdecl is required on OS/390 to tell the compiler to generate a function that uses standard C argument and stack manipulation conventions.
  • sigwait

    z/OS UNIX implements sigwait as:

    int sigwait(sigset_t *set);
    

    In the standard it is:

    int sigwait(sigset_t *set, int *sig);
    

    z/OS UNIX returns the signal that interrupts the sigwait function as a ReturnValue; the standard has it being returned in *sig.

    So sigwait has a different prototype under OS/390 UNIX than in the standard. The confusion over which prototype to use extends to other platforms.

Contact IBM

Browse z/OS