blob: 0d59ced0b86d7d12d401f010d86c21ec408e400c [file] [log] [blame]
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +00001/***********************************************************
Guido van Rossum6d023c91995-01-04 19:12:13 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +00004
5 All Rights Reserved
6
Guido van Rossumd266eb41996-10-25 14:44:06 +00007Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +00009provided that the above copyright notice appear in all copies and that
Guido van Rossumd266eb41996-10-25 14:44:06 +000010both that copyright notice and this permission notice appear in
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000011supporting documentation, and that the names of Stichting Mathematisch
Guido van Rossumd266eb41996-10-25 14:44:06 +000012Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000016
Guido van Rossumd266eb41996-10-25 14:44:06 +000017While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000029
30******************************************************************/
31
Guido van Rossum66020991996-06-11 18:32:18 +000032/* Posix threads interface */
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000033
Guido van Rossum66020991996-06-11 18:32:18 +000034#include <stdlib.h>
35#include <pthread.h>
36
Guido van Rossum1a623111996-08-08 18:53:41 +000037
Guido van Rossumd6353e21997-05-13 17:51:13 +000038/* try to determine what version of the Pthread Standard is installed.
39 * this is important, since all sorts of parameter types changed from
40 * draft to draft and there are several (incompatible) drafts in
41 * common use. these macros are a start, at least.
42 * 12 May 1997 -- david arnold <davida@pobox.com>
43 */
44
45#if defined(__ultrix) && defined(__mips) && defined(_DECTHREADS_)
46/* _DECTHREADS_ is defined in cma.h which is included by pthread.h */
47# define PY_PTHREAD_D4
48
49#elif defined(__osf__) && defined (__alpha)
50/* _DECTHREADS_ is defined in cma.h which is included by pthread.h */
51# if !defined(_PTHREAD_ENV_ALPHA) || defined(_PTHREAD_USE_D4) || defined(PTHREAD_USE_D4)
52# define PY_PTHREAD_D4
53# else
54# define PY_PTHREAD_STD
55# endif
56
57#elif defined(_AIX)
Guido van Rossum1a623111996-08-08 18:53:41 +000058/* SCHED_BG_NP is defined if using AIX DCE pthreads
59 * but it is unsupported by AIX 4 pthreads. Default
60 * attributes for AIX 4 pthreads equal to NULL. For
61 * AIX DCE pthreads they should be left unchanged.
62 */
Guido van Rossumd6353e21997-05-13 17:51:13 +000063# if !defined(SCHED_BG_NP)
64# define PY_PTHREAD_STD
65# else
66# define PY_PTHREAD_D7
67# endif
68
Guido van Rossum64f91051997-05-22 20:41:59 +000069#elif defined(__DGUX)
70# define PY_PTHREAD_D6
Guido van Rossum46ff1901997-06-02 22:25:45 +000071
Guido van Rossum89df70b1998-05-07 13:28:23 +000072#elif defined(__hpux)
73/* From what I can see, HP-UX 10.20 pthreads looks
74 * like D4 flavour.
75 */
76# define PY_PTHREAD_D4
77
Guido van Rossum46ff1901997-06-02 22:25:45 +000078#else /* Default case */
79# define PY_PTHREAD_STD
80
Guido van Rossum1a623111996-08-08 18:53:41 +000081#endif
82
Guido van Rossumd6353e21997-05-13 17:51:13 +000083
84/* set default attribute object for different versions */
85
86#if defined(PY_PTHREAD_D4) || defined(PY_PTHREAD_D7)
87# define pthread_attr_default pthread_attr_default
88# define pthread_mutexattr_default pthread_mutexattr_default
89# define pthread_condattr_default pthread_condattr_default
Guido van Rossum64f91051997-05-22 20:41:59 +000090#elif defined(PY_PTHREAD_STD) || defined(PY_PTHREAD_D6)
Guido van Rossumd6353e21997-05-13 17:51:13 +000091# define pthread_attr_default ((pthread_attr_t *)NULL)
92# define pthread_mutexattr_default ((pthread_mutexattr_t *)NULL)
93# define pthread_condattr_default ((pthread_condattr_t *)NULL)
Guido van Rossum1a623111996-08-08 18:53:41 +000094#endif
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000095
Guido van Rossumd6353e21997-05-13 17:51:13 +000096
Guido van Rossumb98b1b31994-05-11 08:42:04 +000097/* A pthread mutex isn't sufficient to model the Python lock type
98 * because, according to Draft 5 of the docs (P1003.4a/D5), both of the
99 * following are undefined:
100 * -> a thread tries to lock a mutex it already has locked
101 * -> a thread tries to unlock a mutex locked by a different thread
102 * pthread mutexes are designed for serializing threads over short pieces
103 * of code anyway, so wouldn't be an appropriate implementation of
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000104 * Python's locks regardless.
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000105 *
106 * The pthread_lock struct implements a Python lock as a "locked?" bit
107 * and a <condition, mutex> pair. In general, if the bit can be acquired
108 * instantly, it is, else the pair is used to block the thread until the
109 * bit is cleared. 9 May 1994 tim@ksr.com
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000110 */
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000111
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000112typedef struct {
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000113 char locked; /* 0=unlocked, 1=locked */
114 /* a <cond, mutex> pair to handle an acquire of a locked lock */
115 pthread_cond_t lock_released;
116 pthread_mutex_t mut;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000117} pthread_lock;
118
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000119#define CHECK_STATUS(name) if (status < 0) { perror(name); error=1; }
120
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000121/*
122 * Initialization.
123 */
124static void _init_thread _P0()
125{
126}
127
128/*
129 * Thread support.
130 */
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000131
132
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000133int start_new_thread _P2(func, void (*func) _P((void *)), arg, void *arg)
134{
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000135 pthread_t th;
Guido van Rossume944da81994-05-23 12:43:41 +0000136 int success;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000137 dprintf(("start_new_thread called\n"));
138 if (!initialized)
139 init_thread();
Guido van Rossumd6353e21997-05-13 17:51:13 +0000140
141 success = pthread_create(&th,
142#if defined(PY_PTHREAD_D4)
143 pthread_attr_default,
144 (pthread_startroutine_t)func,
145 (pthread_addr_t)arg
Guido van Rossum64f91051997-05-22 20:41:59 +0000146#elif defined(PY_PTHREAD_D6)
147 pthread_attr_default,
148 (void* (*)_P((void *)))func,
149 arg
Guido van Rossumd6353e21997-05-13 17:51:13 +0000150#elif defined(PY_PTHREAD_D7)
151 pthread_attr_default,
152 func,
153 arg
154#elif defined(PY_PTHREAD_STD)
155 (pthread_attr_t*)NULL,
156 (void* (*)_P((void *)))func,
157 (void *)arg
158#endif
159 );
160
161 if (success >= 0) {
Guido van Rossum64f91051997-05-22 20:41:59 +0000162#if defined(PY_THREAD_D4) || defined(PY_PTHREAD_D6) || defined(PY_PTHREAD_D7)
Guido van Rossumd6353e21997-05-13 17:51:13 +0000163 pthread_detach(&th);
164#elif defined(PY_PTHREAD_STD)
Guido van Rossumf4806c21997-04-30 19:59:22 +0000165 pthread_detach(th);
Guido van Rossumd6353e21997-05-13 17:51:13 +0000166#endif
167 }
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000168 return success < 0 ? 0 : 1;
169}
170
Guido van Rossume944da81994-05-23 12:43:41 +0000171long get_thread_ident _P0()
172{
Guido van Rossum2565bff1995-01-09 17:50:47 +0000173 pthread_t threadid;
Guido van Rossume944da81994-05-23 12:43:41 +0000174 if (!initialized)
175 init_thread();
Guido van Rossum2565bff1995-01-09 17:50:47 +0000176 /* Jump through some hoops for Alpha OSF/1 */
177 threadid = pthread_self();
178 return (long) *(long *) &threadid;
Guido van Rossume944da81994-05-23 12:43:41 +0000179}
180
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000181static void do_exit_thread _P1(no_cleanup, int no_cleanup)
182{
183 dprintf(("exit_thread called\n"));
Guido van Rossum730806d1998-04-10 22:27:42 +0000184 if (!initialized) {
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000185 if (no_cleanup)
186 _exit(0);
187 else
188 exit(0);
Guido van Rossum730806d1998-04-10 22:27:42 +0000189 }
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000190}
191
192void exit_thread _P0()
193{
194 do_exit_thread(0);
195}
196
197void _exit_thread _P0()
198{
199 do_exit_thread(1);
200}
201
202#ifndef NO_EXIT_PROG
203static void do_exit_prog _P2(status, int status, no_cleanup, int no_cleanup)
204{
205 dprintf(("exit_prog(%d) called\n", status));
206 if (!initialized)
207 if (no_cleanup)
208 _exit(status);
209 else
210 exit(status);
211}
212
213void exit_prog _P1(status, int status)
214{
215 do_exit_prog(status, 0);
216}
217
218void _exit_prog _P1(status, int status)
219{
220 do_exit_prog(status, 1);
221}
222#endif /* NO_EXIT_PROG */
223
224/*
225 * Lock support.
226 */
227type_lock allocate_lock _P0()
228{
229 pthread_lock *lock;
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000230 int status, error = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000231
232 dprintf(("allocate_lock called\n"));
233 if (!initialized)
234 init_thread();
235
236 lock = (pthread_lock *) malloc(sizeof(pthread_lock));
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000237 if (lock) {
238 lock->locked = 0;
239
240 status = pthread_mutex_init(&lock->mut,
241 pthread_mutexattr_default);
242 CHECK_STATUS("pthread_mutex_init");
243
244 status = pthread_cond_init(&lock->lock_released,
245 pthread_condattr_default);
246 CHECK_STATUS("pthread_cond_init");
247
248 if (error) {
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000249 free((void *)lock);
250 lock = 0;
251 }
252 }
253
254 dprintf(("allocate_lock() -> %lx\n", (long)lock));
255 return (type_lock) lock;
256}
257
258void free_lock _P1(lock, type_lock lock)
259{
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000260 pthread_lock *thelock = (pthread_lock *)lock;
261 int status, error = 0;
262
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000263 dprintf(("free_lock(%lx) called\n", (long)lock));
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000264
265 status = pthread_mutex_destroy( &thelock->mut );
266 CHECK_STATUS("pthread_mutex_destroy");
267
268 status = pthread_cond_destroy( &thelock->lock_released );
269 CHECK_STATUS("pthread_cond_destroy");
270
271 free((void *)thelock);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000272}
273
274int acquire_lock _P2(lock, type_lock lock, waitflag, int waitflag)
275{
276 int success;
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000277 pthread_lock *thelock = (pthread_lock *)lock;
278 int status, error = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000279
280 dprintf(("acquire_lock(%lx, %d) called\n", (long)lock, waitflag));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000281
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000282 status = pthread_mutex_lock( &thelock->mut );
283 CHECK_STATUS("pthread_mutex_lock[1]");
284 success = thelock->locked == 0;
285 if (success) thelock->locked = 1;
286 status = pthread_mutex_unlock( &thelock->mut );
287 CHECK_STATUS("pthread_mutex_unlock[1]");
288
289 if ( !success && waitflag ) {
290 /* continue trying until we get the lock */
291
292 /* mut must be locked by me -- part of the condition
293 * protocol */
294 status = pthread_mutex_lock( &thelock->mut );
295 CHECK_STATUS("pthread_mutex_lock[2]");
296 while ( thelock->locked ) {
297 status = pthread_cond_wait(&thelock->lock_released,
298 &thelock->mut);
299 CHECK_STATUS("pthread_cond_wait");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000300 }
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000301 thelock->locked = 1;
302 status = pthread_mutex_unlock( &thelock->mut );
303 CHECK_STATUS("pthread_mutex_unlock[2]");
304 success = 1;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000305 }
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000306 if (error) success = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000307 dprintf(("acquire_lock(%lx, %d) -> %d\n", (long)lock, waitflag, success));
308 return success;
309}
310
311void release_lock _P1(lock, type_lock lock)
312{
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000313 pthread_lock *thelock = (pthread_lock *)lock;
314 int status, error = 0;
315
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000316 dprintf(("release_lock(%lx) called\n", (long)lock));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000317
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000318 status = pthread_mutex_lock( &thelock->mut );
319 CHECK_STATUS("pthread_mutex_lock[3]");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000320
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000321 thelock->locked = 0;
322
323 status = pthread_mutex_unlock( &thelock->mut );
324 CHECK_STATUS("pthread_mutex_unlock[3]");
325
326 /* wake up someone (anyone, if any) waiting on the lock */
327 status = pthread_cond_signal( &thelock->lock_released );
328 CHECK_STATUS("pthread_cond_signal");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000329}
330
331/*
332 * Semaphore support.
333 */
Guido van Rossum7af81301997-01-17 21:06:41 +0000334
335struct semaphore {
336 pthread_mutex_t mutex;
337 pthread_cond_t cond;
338 int value;
339};
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000340
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000341type_sema allocate_sema _P1(value, int value)
342{
Guido van Rossum7af81301997-01-17 21:06:41 +0000343 struct semaphore *sema;
344 int status, error = 0;
345
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000346 dprintf(("allocate_sema called\n"));
347 if (!initialized)
348 init_thread();
349
Guido van Rossum7af81301997-01-17 21:06:41 +0000350 sema = (struct semaphore *) malloc(sizeof(struct semaphore));
351 if (sema != NULL) {
352 sema->value = value;
353 status = pthread_mutex_init(&sema->mutex,
354 pthread_mutexattr_default);
355 CHECK_STATUS("pthread_mutex_init");
356 status = pthread_cond_init(&sema->cond,
357 pthread_condattr_default);
358 CHECK_STATUS("pthread_cond_init");
359 if (error) {
360 free((void *) sema);
361 sema = NULL;
362 }
363 }
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000364 dprintf(("allocate_sema() -> %lx\n", (long) sema));
365 return (type_sema) sema;
366}
367
368void free_sema _P1(sema, type_sema sema)
369{
Guido van Rossum7af81301997-01-17 21:06:41 +0000370 int status, error = 0;
371 struct semaphore *thesema = (struct semaphore *) sema;
372
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000373 dprintf(("free_sema(%lx) called\n", (long) sema));
Guido van Rossum7af81301997-01-17 21:06:41 +0000374 status = pthread_cond_destroy(&thesema->cond);
375 CHECK_STATUS("pthread_cond_destroy");
376 status = pthread_mutex_destroy(&thesema->mutex);
377 CHECK_STATUS("pthread_mutex_destroy");
378 free((void *) thesema);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000379}
380
Guido van Rossumcf1474b1996-10-08 14:17:53 +0000381int down_sema _P2(sema, type_sema sema, waitflag, int waitflag)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000382{
Guido van Rossum7af81301997-01-17 21:06:41 +0000383 int status, error = 0, success;
384 struct semaphore *thesema = (struct semaphore *) sema;
385
Guido van Rossumcf1474b1996-10-08 14:17:53 +0000386 dprintf(("down_sema(%lx, %d) called\n", (long) sema, waitflag));
Guido van Rossum7af81301997-01-17 21:06:41 +0000387 status = pthread_mutex_lock(&thesema->mutex);
388 CHECK_STATUS("pthread_mutex_lock");
389 if (waitflag) {
390 while (!error && thesema->value <= 0) {
391 status = pthread_cond_wait(&thesema->cond,
392 &thesema->mutex);
393 CHECK_STATUS("pthread_cond_wait");
394 }
395 }
396 if (error)
397 success = 0;
398 else if (thesema->value > 0) {
399 thesema->value--;
400 success = 1;
401 }
402 else
403 success = 0;
404 status = pthread_mutex_unlock(&thesema->mutex);
405 CHECK_STATUS("pthread_mutex_unlock");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000406 dprintf(("down_sema(%lx) return\n", (long) sema));
Guido van Rossum7af81301997-01-17 21:06:41 +0000407 return success;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000408}
409
410void up_sema _P1(sema, type_sema sema)
411{
Guido van Rossum7af81301997-01-17 21:06:41 +0000412 int status, error = 0;
413 struct semaphore *thesema = (struct semaphore *) sema;
414
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000415 dprintf(("up_sema(%lx)\n", (long) sema));
Guido van Rossum7af81301997-01-17 21:06:41 +0000416 status = pthread_mutex_lock(&thesema->mutex);
417 CHECK_STATUS("pthread_mutex_lock");
418 thesema->value++;
419 status = pthread_cond_signal(&thesema->cond);
420 CHECK_STATUS("pthread_cond_signal");
421 status = pthread_mutex_unlock(&thesema->mutex);
422 CHECK_STATUS("pthread_mutex_unlock");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000423}