Thread functions:
Thread package functions:
All synchronization mechanisms follow a simple scheme. The user has to aquire a handle for the mechanism calling some new_... function which allocates the mechanism and initializes it appropriate. After using the mechanism it is freed by a call to the corresponding delete_... function. These functions asure efficient allocation and correct alignment that cannot be garanteed for static or dynamic memory from the compiler.
Synchronization with condition variables:
Before starting the package, the user can change the package's configuration. This configuration usually uses machine dependent default values, so no extra configuration is necessary. Nevertheless, configuration is possible and can help to improve the performance of the target program, either because the machine configuration has changed and/or the application needs special treatment by the package. This tuning can be done by encoding application specific values into the source code by use of mthr_config(3) or on runtime by commandline options that can be evaluated by mthr_configv(3).
Calling mthr_startup(3) initializes the thread package, allocates the necessary data and starts the kernelthreads that are used as virtual processors. Whenever one of these virtual processors becomes idle it searches for the next runnable thread and starts it. So from this moment on, userlevel threads can be created by mthr_create(3) and will be scheduled on one of the idle processors.
As with usual C programs, the process terminates when it reaches the end of main() returns from main() or exits due to exit(3). This is also true for programs using the mthreads package. To terminate the execution of one specific thread, you can use mthr_exit(3). As the thread that executes main() is handled like each other userlevel thread, using mthr_exit() terminates this thread but not the whole application. On the other hand, if you intend to terminate the whole application as it has reached its end or due to some fatal error you can still use the usual exit() call. In addition to this call there exists the mthr_halt() function. In contrast to exit() this function calls a shutdown handler,i.e. some function that might do some cleanup, like flushing outputbuffers, closing files etc. before terminating the application. The default shutdown handler does nothing but terminate the application, but the user can install its own shutdown handler by a call to mthr_set_shutdownhandler().
The third implicit possibility to terminate the process is that the last userlevel thread does its mthr_exit(). This calls the shutdown handler too, so you don't have to think about which thread will be the last one and should call exit() or mthr_halt().
#include <stdio.h> #include <stdlib.h> #include "mthread.h" mutex_p mp; int no_threads = 0; void *hello(void *arg) { mutex_lock(mp); printf("This is thread %d\n",(int)arg); no_threads++; mutex_unlock(mp); mthr_exit(0); } void own_shutdown_handler(int exitvalue) { printf("%d threads have been executed\n",no_threads); exit(exitvalue); } void main(int argc, char *argv[]) { int i; /* configuring the package */ mthr_config_v(&argc, argv); /* starting the package */ mthr_startup(); /* set our own shutdown handler */ mthr_set_shutdownhandler(own_shutdown_handler); /* create a mutex lock and some threads */ mp = new_mutex(); for(i=0;i<100;i++) mthr_create(0, DETACHED, hello, (void *)i); /* terminate the main thread */ mthr_exit(0); }
The mthreads library is not compatible to the cps library, as it allocates kernelthreads itself. Therefore applications may not be linked with the cps library. Using the standard CONVEX compiler, this library is automatically linked, so it's better to link the application manually using ld(1).
A typical call to ld(1) might look like:
/usr/convex/bin/ld /usr/convex/all/crt0.o application.o +tmspp1 +over -lmthread -lqt -lail -lc
This example assumes that all libraries are in default directories. Other directories can be specified by the environment variable LD_LIBRARY_PATH or by the linker option -L.
The debugger cxdb seems to have problems with mthreads too. It's still not clear whether this problem is caused by mthreads, the debugger or the cps library again.