blob: 8e6ca86ed926681fb894d43c3082465ef7355809 [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
69#elif defined(__unix) && defined(__sparc)
70# define PY_PTHREAD_STD
Guido van Rossumc8fba8e1997-05-15 12:24:53 +000071#elif defined(__linux)
72# define PY_PTHREAD_STD
Guido van Rossum64f91051997-05-22 20:41:59 +000073#elif defined(__DGUX)
74# define PY_PTHREAD_D6
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"));
178 if (!initialized)
179 if (no_cleanup)
180 _exit(0);
181 else
182 exit(0);
183}
184
185void exit_thread _P0()
186{
187 do_exit_thread(0);
188}
189
190void _exit_thread _P0()
191{
192 do_exit_thread(1);
193}
194
195#ifndef NO_EXIT_PROG
196static void do_exit_prog _P2(status, int status, no_cleanup, int no_cleanup)
197{
198 dprintf(("exit_prog(%d) called\n", status));
199 if (!initialized)
200 if (no_cleanup)
201 _exit(status);
202 else
203 exit(status);
204}
205
206void exit_prog _P1(status, int status)
207{
208 do_exit_prog(status, 0);
209}
210
211void _exit_prog _P1(status, int status)
212{
213 do_exit_prog(status, 1);
214}
215#endif /* NO_EXIT_PROG */
216
217/*
218 * Lock support.
219 */
220type_lock allocate_lock _P0()
221{
222 pthread_lock *lock;
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000223 int status, error = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000224
225 dprintf(("allocate_lock called\n"));
226 if (!initialized)
227 init_thread();
228
229 lock = (pthread_lock *) malloc(sizeof(pthread_lock));
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000230 if (lock) {
231 lock->locked = 0;
232
233 status = pthread_mutex_init(&lock->mut,
234 pthread_mutexattr_default);
235 CHECK_STATUS("pthread_mutex_init");
236
237 status = pthread_cond_init(&lock->lock_released,
238 pthread_condattr_default);
239 CHECK_STATUS("pthread_cond_init");
240
241 if (error) {
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000242 free((void *)lock);
243 lock = 0;
244 }
245 }
246
247 dprintf(("allocate_lock() -> %lx\n", (long)lock));
248 return (type_lock) lock;
249}
250
251void free_lock _P1(lock, type_lock lock)
252{
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000253 pthread_lock *thelock = (pthread_lock *)lock;
254 int status, error = 0;
255
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000256 dprintf(("free_lock(%lx) called\n", (long)lock));
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000257
258 status = pthread_mutex_destroy( &thelock->mut );
259 CHECK_STATUS("pthread_mutex_destroy");
260
261 status = pthread_cond_destroy( &thelock->lock_released );
262 CHECK_STATUS("pthread_cond_destroy");
263
264 free((void *)thelock);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000265}
266
267int acquire_lock _P2(lock, type_lock lock, waitflag, int waitflag)
268{
269 int success;
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000270 pthread_lock *thelock = (pthread_lock *)lock;
271 int status, error = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000272
273 dprintf(("acquire_lock(%lx, %d) called\n", (long)lock, waitflag));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000274
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000275 status = pthread_mutex_lock( &thelock->mut );
276 CHECK_STATUS("pthread_mutex_lock[1]");
277 success = thelock->locked == 0;
278 if (success) thelock->locked = 1;
279 status = pthread_mutex_unlock( &thelock->mut );
280 CHECK_STATUS("pthread_mutex_unlock[1]");
281
282 if ( !success && waitflag ) {
283 /* continue trying until we get the lock */
284
285 /* mut must be locked by me -- part of the condition
286 * protocol */
287 status = pthread_mutex_lock( &thelock->mut );
288 CHECK_STATUS("pthread_mutex_lock[2]");
289 while ( thelock->locked ) {
290 status = pthread_cond_wait(&thelock->lock_released,
291 &thelock->mut);
292 CHECK_STATUS("pthread_cond_wait");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000293 }
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000294 thelock->locked = 1;
295 status = pthread_mutex_unlock( &thelock->mut );
296 CHECK_STATUS("pthread_mutex_unlock[2]");
297 success = 1;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000298 }
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000299 if (error) success = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000300 dprintf(("acquire_lock(%lx, %d) -> %d\n", (long)lock, waitflag, success));
301 return success;
302}
303
304void release_lock _P1(lock, type_lock lock)
305{
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000306 pthread_lock *thelock = (pthread_lock *)lock;
307 int status, error = 0;
308
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000309 dprintf(("release_lock(%lx) called\n", (long)lock));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000310
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000311 status = pthread_mutex_lock( &thelock->mut );
312 CHECK_STATUS("pthread_mutex_lock[3]");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000313
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000314 thelock->locked = 0;
315
316 status = pthread_mutex_unlock( &thelock->mut );
317 CHECK_STATUS("pthread_mutex_unlock[3]");
318
319 /* wake up someone (anyone, if any) waiting on the lock */
320 status = pthread_cond_signal( &thelock->lock_released );
321 CHECK_STATUS("pthread_cond_signal");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000322}
323
324/*
325 * Semaphore support.
326 */
Guido van Rossum7af81301997-01-17 21:06:41 +0000327
328struct semaphore {
329 pthread_mutex_t mutex;
330 pthread_cond_t cond;
331 int value;
332};
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000333
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000334type_sema allocate_sema _P1(value, int value)
335{
Guido van Rossum7af81301997-01-17 21:06:41 +0000336 struct semaphore *sema;
337 int status, error = 0;
338
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000339 dprintf(("allocate_sema called\n"));
340 if (!initialized)
341 init_thread();
342
Guido van Rossum7af81301997-01-17 21:06:41 +0000343 sema = (struct semaphore *) malloc(sizeof(struct semaphore));
344 if (sema != NULL) {
345 sema->value = value;
346 status = pthread_mutex_init(&sema->mutex,
347 pthread_mutexattr_default);
348 CHECK_STATUS("pthread_mutex_init");
349 status = pthread_cond_init(&sema->cond,
350 pthread_condattr_default);
351 CHECK_STATUS("pthread_cond_init");
352 if (error) {
353 free((void *) sema);
354 sema = NULL;
355 }
356 }
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000357 dprintf(("allocate_sema() -> %lx\n", (long) sema));
358 return (type_sema) sema;
359}
360
361void free_sema _P1(sema, type_sema sema)
362{
Guido van Rossum7af81301997-01-17 21:06:41 +0000363 int status, error = 0;
364 struct semaphore *thesema = (struct semaphore *) sema;
365
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000366 dprintf(("free_sema(%lx) called\n", (long) sema));
Guido van Rossum7af81301997-01-17 21:06:41 +0000367 status = pthread_cond_destroy(&thesema->cond);
368 CHECK_STATUS("pthread_cond_destroy");
369 status = pthread_mutex_destroy(&thesema->mutex);
370 CHECK_STATUS("pthread_mutex_destroy");
371 free((void *) thesema);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000372}
373
Guido van Rossumcf1474b1996-10-08 14:17:53 +0000374int down_sema _P2(sema, type_sema sema, waitflag, int waitflag)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000375{
Guido van Rossum7af81301997-01-17 21:06:41 +0000376 int status, error = 0, success;
377 struct semaphore *thesema = (struct semaphore *) sema;
378
Guido van Rossumcf1474b1996-10-08 14:17:53 +0000379 dprintf(("down_sema(%lx, %d) called\n", (long) sema, waitflag));
Guido van Rossum7af81301997-01-17 21:06:41 +0000380 status = pthread_mutex_lock(&thesema->mutex);
381 CHECK_STATUS("pthread_mutex_lock");
382 if (waitflag) {
383 while (!error && thesema->value <= 0) {
384 status = pthread_cond_wait(&thesema->cond,
385 &thesema->mutex);
386 CHECK_STATUS("pthread_cond_wait");
387 }
388 }
389 if (error)
390 success = 0;
391 else if (thesema->value > 0) {
392 thesema->value--;
393 success = 1;
394 }
395 else
396 success = 0;
397 status = pthread_mutex_unlock(&thesema->mutex);
398 CHECK_STATUS("pthread_mutex_unlock");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000399 dprintf(("down_sema(%lx) return\n", (long) sema));
Guido van Rossum7af81301997-01-17 21:06:41 +0000400 return success;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000401}
402
403void up_sema _P1(sema, type_sema sema)
404{
Guido van Rossum7af81301997-01-17 21:06:41 +0000405 int status, error = 0;
406 struct semaphore *thesema = (struct semaphore *) sema;
407
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000408 dprintf(("up_sema(%lx)\n", (long) sema));
Guido van Rossum7af81301997-01-17 21:06:41 +0000409 status = pthread_mutex_lock(&thesema->mutex);
410 CHECK_STATUS("pthread_mutex_lock");
411 thesema->value++;
412 status = pthread_cond_signal(&thesema->cond);
413 CHECK_STATUS("pthread_cond_signal");
414 status = pthread_mutex_unlock(&thesema->mutex);
415 CHECK_STATUS("pthread_mutex_unlock");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000416}