Below is Sasha Mikheev's documentation on the pthreads support (POSIX threads) which is valid on June 7th, 1996 (date of message.) I have changed the path names only since the tree has changed. Otherwise, the docs are correct. -- Wolfpack --- Begin message Hi, I have finished documenting pthreads implementation. Pls look at the results and tell me what can be improved. Implementation: Empire now uses its own thread layer. It makes using another threading library much easier. The interfase is modeled after the LWP library which is what empire server uses by default. The interface is specified in the include/empthread.h file. Implementations should go into src/lib/empthread/xxx.c. Empire assumes that thread can not be preempted while it is running. The _only_ places where context switch between threads can occur are: empth_sleep(), empth_yield(), empth_select(), empth_sem_wait(). That is in sleep, in waiting for I/O on filedescriptor, semaphore or voluntary yielding control or exiting. In empire empth_select is called only on sockets so the context switch can occur only on the network I/O. Also each empire thread can have it is own context which is restored automatically after the context switch. Currently it is used for each thread to have player specic data. (struct player) LWP implementation: Almost nothing has changed there. src/lib/empthread/lwp.c is a very simple wrapper around the LWP library. The only change is that thread inherits its flags if they are not explicitly set. For more details on LWP internals read Dave Pare's description in doc/threads. POSIX threaads: (pthreads) Unlike LWP pthreads are preemtive. The steps must be taken to insure that thread is preempted only as described above. It is done by creating a global mutex mtx_ctxsw. At the any given moment only one thread can be running and have a lock on mtx_ctxsw. Every other thread is waiting for the mtx_ctxsw to become avaiable. It is done by calling pthread_mtx_lock(). When thread enters into empth_sleep(), empth_yield(), empth_exit(), empth_sem_wait() empth_select() it releases the mutex by calling pthread_mtx_unlock() and thus allowing other thread to get a lock. Thread context is implemented by using pthread_getspecific and pthread_setspecific functions. Killing other thread is done by setting victim thread state into EMPTH_KILLED and sending alarm signal to the victim thread. The later has to be done to wake up a thread waiting on I/O in empth_select. Then the victim will examine its state and if it is set to KILLED it will terminate its execution. Unfortunately pthread_kill seems not to be working/exists in some pthread implementations. But fortunately empire always does some I/O before doing empth_terminate(). Semaphores are not available in pthreads thus mutexes and conditional variables are used to implement them. See the code and or OS design book for details. Problems: On linux with libc 2.1.18 mit pthread library does not wake up a thread upon the delivery of a signal. Which means that server can not be stopped short by kill -9 and empth_wakeup() is not working. Fortunately in current server data are always written to player before the call to empth_wakeup so players threads will never wait in select forever. Probably it will be solved when linux libc gets upgraded to latest pthread library. In addition installing pthreads on Linux is difficult. By default linux libc has pthread stubs in but pthread code is disabled. So you have either recompile libc or grab mit pthreads and install them manually. Meanwhile I do not recommend to use pthreads on linux unless you know what you are doing. On solaris 2.5 select does not set errno to EINTR when select is broken by soignal sent by pthread_kill. It doesnt affect anything. On OSF/1 the older version of pthread is used. It has slightly changed function semantics. Also it lacks pthread_kill funcion which means that empth_wakeup() is not working. Calling pthread_exit() from the main thread crashes the program. According to the manual program should not exit until all threads exited. The workaround is to send main into while(1) { sleep(60); } loop; -- Sasha Mikheev There is a saying in Cairhienin, though i have heard it as far away NetVision Israel, Ltd as Tarabon and Saldaea: sasha@netvision.net.il Tel +972-4-8550330 Take what you want and pay for it. http://aldan.netvision.net.il/~sasha