blob: 2f57b36e19a3eb610a1d1f606ff2cf9ef12e9bc6 [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
72#else /* Default case */
73# define PY_PTHREAD_STD
74
Guido van Rossum1a623111996-08-08 18:53:41 +000075#endif
76
Guido van Rossumd6353e21997-05-13 17:51:13 +000077
78/* set default attribute object for different versions */
79
80#if defined(PY_PTHREAD_D4) || defined(PY_PTHREAD_D7)
81# define pthread_attr_default pthread_attr_default
82# define pthread_mutexattr_default pthread_mutexattr_default
83# define pthread_condattr_default pthread_condattr_default
Guido van Rossum64f91051997-05-22 20:41:59 +000084#elif defined(PY_PTHREAD_STD) || defined(PY_PTHREAD_D6)
Guido van Rossumd6353e21997-05-13 17:51:13 +000085# define pthread_attr_default ((pthread_attr_t *)NULL)
86# define pthread_mutexattr_default ((pthread_mutexattr_t *)NULL)
87# define pthread_condattr_default ((pthread_condattr_t *)NULL)
Guido van Rossum1a623111996-08-08 18:53:41 +000088#endif
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000089
Guido van Rossumd6353e21997-05-13 17:51:13 +000090
Guido van Rossumb98b1b31994-05-11 08:42:04 +000091/* A pthread mutex isn't sufficient to model the Python lock type
92 * because, according to Draft 5 of the docs (P1003.4a/D5), both of the
93 * following are undefined:
94 * -> a thread tries to lock a mutex it already has locked
95 * -> a thread tries to unlock a mutex locked by a different thread
96 * pthread mutexes are designed for serializing threads over short pieces
97 * of code anyway, so wouldn't be an appropriate implementation of
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000098 * Python's locks regardless.
Guido van Rossumb98b1b31994-05-11 08:42:04 +000099 *
100 * The pthread_lock struct implements a Python lock as a "locked?" bit
101 * and a <condition, mutex> pair. In general, if the bit can be acquired
102 * instantly, it is, else the pair is used to block the thread until the
103 * bit is cleared. 9 May 1994 tim@ksr.com
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000104 */
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000105
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000106typedef struct {
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000107 char locked; /* 0=unlocked, 1=locked */
108 /* a <cond, mutex> pair to handle an acquire of a locked lock */
109 pthread_cond_t lock_released;
110 pthread_mutex_t mut;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000111} pthread_lock;
112
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000113#define CHECK_STATUS(name) if (status < 0) { perror(name); error=1; }
114
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000115/*
116 * Initialization.
117 */
118static void _init_thread _P0()
119{
120}
121
122/*
123 * Thread support.
124 */
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000125
126
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000127int start_new_thread _P2(func, void (*func) _P((void *)), arg, void *arg)
128{
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000129 pthread_t th;
Guido van Rossume944da81994-05-23 12:43:41 +0000130 int success;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000131 dprintf(("start_new_thread called\n"));
132 if (!initialized)
133 init_thread();
Guido van Rossumd6353e21997-05-13 17:51:13 +0000134
135 success = pthread_create(&th,
136#if defined(PY_PTHREAD_D4)
137 pthread_attr_default,
138 (pthread_startroutine_t)func,
139 (pthread_addr_t)arg
Guido van Rossum64f91051997-05-22 20:41:59 +0000140#elif defined(PY_PTHREAD_D6)
141 pthread_attr_default,
142 (void* (*)_P((void *)))func,
143 arg
Guido van Rossumd6353e21997-05-13 17:51:13 +0000144#elif defined(PY_PTHREAD_D7)
145 pthread_attr_default,
146 func,
147 arg
148#elif defined(PY_PTHREAD_STD)
149 (pthread_attr_t*)NULL,
150 (void* (*)_P((void *)))func,
151 (void *)arg
152#endif
153 );
154
155 if (success >= 0) {
Guido van Rossum64f91051997-05-22 20:41:59 +0000156#if defined(PY_THREAD_D4) || defined(PY_PTHREAD_D6) || defined(PY_PTHREAD_D7)
Guido van Rossumd6353e21997-05-13 17:51:13 +0000157 pthread_detach(&th);
158#elif defined(PY_PTHREAD_STD)
Guido van Rossumf4806c21997-04-30 19:59:22 +0000159 pthread_detach(th);
Guido van Rossumd6353e21997-05-13 17:51:13 +0000160#endif
161 }
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000162 return success < 0 ? 0 : 1;
163}
164
Guido van Rossume944da81994-05-23 12:43:41 +0000165long get_thread_ident _P0()
166{
Guido van Rossum2565bff1995-01-09 17:50:47 +0000167 pthread_t threadid;
Guido van Rossume944da81994-05-23 12:43:41 +0000168 if (!initialized)
169 init_thread();
Guido van Rossum2565bff1995-01-09 17:50:47 +0000170 /* Jump through some hoops for Alpha OSF/1 */
171 threadid = pthread_self();
172 return (long) *(long *) &threadid;
Guido van Rossume944da81994-05-23 12:43:41 +0000173}
174
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000175static void do_exit_thread _P1(no_cleanup, int no_cleanup)
176{
177 dprintf(("exit_thread called\n"));
Guido van Rossum730806d1998-04-10 22:27:42 +0000178 if (!initialized) {
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000179 if (no_cleanup)
180 _exit(0);
181 else
182 exit(0);
Guido van Rossum730806d1998-04-10 22:27:42 +0000183 }
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000184}
185
186void exit_thread _P0()
187{
188 do_exit_thread(0);
189}
190
191void _exit_thread _P0()
192{
193 do_exit_thread(1);
194}
195
196#ifndef NO_EXIT_PROG
197static void do_exit_prog _P2(status, int status, no_cleanup, int no_cleanup)
198{
199 dprintf(("exit_prog(%d) called\n", status));
200 if (!initialized)
201 if (no_cleanup)
202 _exit(status);
203 else
204 exit(status);
205}
206
207void exit_prog _P1(status, int status)
208{
209 do_exit_prog(status, 0);
210}
211
212void _exit_prog _P1(status, int status)
213{
214 do_exit_prog(status, 1);
215}
216#endif /* NO_EXIT_PROG */
217
218/*
219 * Lock support.
220 */
221type_lock allocate_lock _P0()
222{
223 pthread_lock *lock;
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000224 int status, error = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000225
226 dprintf(("allocate_lock called\n"));
227 if (!initialized)
228 init_thread();
229
230 lock = (pthread_lock *) malloc(sizeof(pthread_lock));
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000231 if (lock) {
232 lock->locked = 0;
233
234 status = pthread_mutex_init(&lock->mut,
235 pthread_mutexattr_default);
236 CHECK_STATUS("pthread_mutex_init");
237
238 status = pthread_cond_init(&lock->lock_released,
239 pthread_condattr_default);
240 CHECK_STATUS("pthread_cond_init");
241
242 if (error) {
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000243 free((void *)lock);
244 lock = 0;
245 }
246 }
247
248 dprintf(("allocate_lock() -> %lx\n", (long)lock));
249 return (type_lock) lock;
250}
251
252void free_lock _P1(lock, type_lock lock)
253{
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000254 pthread_lock *thelock = (pthread_lock *)lock;
255 int status, error = 0;
256
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000257 dprintf(("free_lock(%lx) called\n", (long)lock));
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000258
259 status = pthread_mutex_destroy( &thelock->mut );
260 CHECK_STATUS("pthread_mutex_destroy");
261
262 status = pthread_cond_destroy( &thelock->lock_released );
263 CHECK_STATUS("pthread_cond_destroy");
264
265 free((void *)thelock);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000266}
267
268int acquire_lock _P2(lock, type_lock lock, waitflag, int waitflag)
269{
270 int success;
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000271 pthread_lock *thelock = (pthread_lock *)lock;
272 int status, error = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000273
274 dprintf(("acquire_lock(%lx, %d) called\n", (long)lock, waitflag));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000275
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000276 status = pthread_mutex_lock( &thelock->mut );
277 CHECK_STATUS("pthread_mutex_lock[1]");
278 success = thelock->locked == 0;
279 if (success) thelock->locked = 1;
280 status = pthread_mutex_unlock( &thelock->mut );
281 CHECK_STATUS("pthread_mutex_unlock[1]");
282
283 if ( !success && waitflag ) {
284 /* continue trying until we get the lock */
285
286 /* mut must be locked by me -- part of the condition
287 * protocol */
288 status = pthread_mutex_lock( &thelock->mut );
289 CHECK_STATUS("pthread_mutex_lock[2]");
290 while ( thelock->locked ) {
291 status = pthread_cond_wait(&thelock->lock_released,
292 &thelock->mut);
293 CHECK_STATUS("pthread_cond_wait");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000294 }
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000295 thelock->locked = 1;
296 status = pthread_mutex_unlock( &thelock->mut );
297 CHECK_STATUS("pthread_mutex_unlock[2]");
298 success = 1;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000299 }
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000300 if (error) success = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000301 dprintf(("acquire_lock(%lx, %d) -> %d\n", (long)lock, waitflag, success));
302 return success;
303}
304
305void release_lock _P1(lock, type_lock lock)
306{
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000307 pthread_lock *thelock = (pthread_lock *)lock;
308 int status, error = 0;
309
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000310 dprintf(("release_lock(%lx) called\n", (long)lock));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000311
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000312 status = pthread_mutex_lock( &thelock->mut );
313 CHECK_STATUS("pthread_mutex_lock[3]");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000314
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000315 thelock->locked = 0;
316
317 status = pthread_mutex_unlock( &thelock->mut );
318 CHECK_STATUS("pthread_mutex_unlock[3]");
319
320 /* wake up someone (anyone, if any) waiting on the lock */
321 status = pthread_cond_signal( &thelock->lock_released );
322 CHECK_STATUS("pthread_cond_signal");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000323}
324
325/*
326 * Semaphore support.
327 */
Guido van Rossum7af81301997-01-17 21:06:41 +0000328
329struct semaphore {
330 pthread_mutex_t mutex;
331 pthread_cond_t cond;
332 int value;
333};
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000334
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000335type_sema allocate_sema _P1(value, int value)
336{
Guido van Rossum7af81301997-01-17 21:06:41 +0000337 struct semaphore *sema;
338 int status, error = 0;
339
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000340 dprintf(("allocate_sema called\n"));
341 if (!initialized)
342 init_thread();
343
Guido van Rossum7af81301997-01-17 21:06:41 +0000344 sema = (struct semaphore *) malloc(sizeof(struct semaphore));
345 if (sema != NULL) {
346 sema->value = value;
347 status = pthread_mutex_init(&sema->mutex,
348 pthread_mutexattr_default);
349 CHECK_STATUS("pthread_mutex_init");
350 status = pthread_cond_init(&sema->cond,
351 pthread_condattr_default);
352 CHECK_STATUS("pthread_cond_init");
353 if (error) {
354 free((void *) sema);
355 sema = NULL;
356 }
357 }
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000358 dprintf(("allocate_sema() -> %lx\n", (long) sema));
359 return (type_sema) sema;
360}
361
362void free_sema _P1(sema, type_sema sema)
363{
Guido van Rossum7af81301997-01-17 21:06:41 +0000364 int status, error = 0;
365 struct semaphore *thesema = (struct semaphore *) sema;
366
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000367 dprintf(("free_sema(%lx) called\n", (long) sema));
Guido van Rossum7af81301997-01-17 21:06:41 +0000368 status = pthread_cond_destroy(&thesema->cond);
369 CHECK_STATUS("pthread_cond_destroy");
370 status = pthread_mutex_destroy(&thesema->mutex);
371 CHECK_STATUS("pthread_mutex_destroy");
372 free((void *) thesema);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000373}
374
Guido van Rossumcf1474b1996-10-08 14:17:53 +0000375int down_sema _P2(sema, type_sema sema, waitflag, int waitflag)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000376{
Guido van Rossum7af81301997-01-17 21:06:41 +0000377 int status, error = 0, success;
378 struct semaphore *thesema = (struct semaphore *) sema;
379
Guido van Rossumcf1474b1996-10-08 14:17:53 +0000380 dprintf(("down_sema(%lx, %d) called\n", (long) sema, waitflag));
Guido van Rossum7af81301997-01-17 21:06:41 +0000381 status = pthread_mutex_lock(&thesema->mutex);
382 CHECK_STATUS("pthread_mutex_lock");
383 if (waitflag) {
384 while (!error && thesema->value <= 0) {
385 status = pthread_cond_wait(&thesema->cond,
386 &thesema->mutex);
387 CHECK_STATUS("pthread_cond_wait");
388 }
389 }
390 if (error)
391 success = 0;
392 else if (thesema->value > 0) {
393 thesema->value--;
394 success = 1;
395 }
396 else
397 success = 0;
398 status = pthread_mutex_unlock(&thesema->mutex);
399 CHECK_STATUS("pthread_mutex_unlock");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000400 dprintf(("down_sema(%lx) return\n", (long) sema));
Guido van Rossum7af81301997-01-17 21:06:41 +0000401 return success;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000402}
403
404void up_sema _P1(sema, type_sema sema)
405{
Guido van Rossum7af81301997-01-17 21:06:41 +0000406 int status, error = 0;
407 struct semaphore *thesema = (struct semaphore *) sema;
408
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000409 dprintf(("up_sema(%lx)\n", (long) sema));
Guido van Rossum7af81301997-01-17 21:06:41 +0000410 status = pthread_mutex_lock(&thesema->mutex);
411 CHECK_STATUS("pthread_mutex_lock");
412 thesema->value++;
413 status = pthread_cond_signal(&thesema->cond);
414 CHECK_STATUS("pthread_cond_signal");
415 status = pthread_mutex_unlock(&thesema->mutex);
416 CHECK_STATUS("pthread_mutex_unlock");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000417}