9. Converse -POSIX threads

We have implemented the POSIX threads API on top of Converse threads. To use the Converse -pthreads, you must include the header file: #include <cpthreads.h>

Refer to the POSIX threads documentation for the documentation on the pthreads functions and types. Although Converse -pthreads threads are POSIX-compliant in most ways, there are some specific things one needs to know to use our implementation.

9.1 Pthreads and Converse

Our pthreads implementation is designed to exist within a Converse environment. For example, to send messages inside a POSIX program, you would still use the usual Converse messaging primitives.

9.2 Suppressing Name Conflicts

Some people may wish to use Converse pthreads on machines that already have a pthreads implementation in the standard library. This may cause some name-conflicts as we define the pthreads functions, and the system include files do too. To avoid such conflicts, we provide an alternative set of names beginning with the word Cpthread. These names are interchangeable with their pthread equivalents. In addition, you may prevent Converse from defining the pthread names at all with the preprocessor symbol SUPPRESS_PTHREADS:

#include <cpthreads.h>

9.3 Interoperating with Other Thread Packages

Converse programs are typically multilingual programs. There may be modules written using POSIX threads, but other modules may use other thread APIs. The POSIX threads implementation has the following restriction: you may only call the pthreads functions from inside threads created with pthread_create. Threads created by other thread packages (for example, the CthThread package) may not use the pthreads functions.

9.4 Preemptive Context Switching

Most implementations of POSIX threads perform time-slicing: when a thread has run for a while, it automatically gives up the CPU to another thread. Our implementation is currently nonpreemptive (no time-slicing). Threads give up control at two points:

Usually, the first rule is sufficient to make most programs work. However, a few programs (particularly, those that busy-wait) may need explicit insertion of yields.

9.5 Limits on Blocking Operations in main

Converse has a rule about blocking operations -- there are certain pieces of code that may not block. This was an efficiency decision. In particular, the main function, Converse handlers, and the Converse startup function (see ConverseInit) may not block. You must be aware of this when using the POSIX threads functions with Converse .

There is a contradiction here -- the POSIX standard requires that the pthreads functions work from inside main. However, many of them block, and Converse forbids blocking inside main. This contradiction can be resolved by renaming your posix-compliant main to something else: for example, mymain. Then, through the normal Converse startup procedure, create a POSIX thread to run mymain. We provide a convenience function to do this, called Cpthreads_start_main. The startup code will be much like this:

void mystartup(int argc, char **argv)
  Cpthreads_start_main(mymain, argc, argv);

int main(int argc, char **argv)
  ConverseInit(mystartup, argc, argv, 0, 0);

This creates the first POSIX thread on each processor, which runs the function mymain. The mymain function is executing in a POSIX thread, and it may use any pthread function it wishes.

9.6 CpthreadModuleInit

On each processor, the function CpthreadModuleInit must be called before any other pthread function is called. This is shown in the example in the previous section.