blob: c83cd2d8a1208a3596059b61adc03680682399f2 [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#ifdef _AIX
38
39#ifndef SCHED_BG_NP
40/* SCHED_BG_NP is defined if using AIX DCE pthreads
41 * but it is unsupported by AIX 4 pthreads. Default
42 * attributes for AIX 4 pthreads equal to NULL. For
43 * AIX DCE pthreads they should be left unchanged.
44 */
45#define pthread_attr_default NULL
46#define pthread_mutexattr_default NULL
47#define pthread_condattr_default NULL
48#endif
49
50#else
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000051#define pthread_attr_default ((pthread_attr_t *)0)
52#define pthread_mutexattr_default ((pthread_mutexattr_t *)0)
53#define pthread_condattr_default ((pthread_condattr_t *)0)
Guido van Rossum1a623111996-08-08 18:53:41 +000054#endif
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000055
Guido van Rossumb98b1b31994-05-11 08:42:04 +000056/* A pthread mutex isn't sufficient to model the Python lock type
57 * because, according to Draft 5 of the docs (P1003.4a/D5), both of the
58 * following are undefined:
59 * -> a thread tries to lock a mutex it already has locked
60 * -> a thread tries to unlock a mutex locked by a different thread
61 * pthread mutexes are designed for serializing threads over short pieces
62 * of code anyway, so wouldn't be an appropriate implementation of
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000063 * Python's locks regardless.
Guido van Rossumb98b1b31994-05-11 08:42:04 +000064 *
65 * The pthread_lock struct implements a Python lock as a "locked?" bit
66 * and a <condition, mutex> pair. In general, if the bit can be acquired
67 * instantly, it is, else the pair is used to block the thread until the
68 * bit is cleared. 9 May 1994 tim@ksr.com
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000069 */
Guido van Rossumb98b1b31994-05-11 08:42:04 +000070
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000071typedef struct {
Guido van Rossumb98b1b31994-05-11 08:42:04 +000072 char locked; /* 0=unlocked, 1=locked */
73 /* a <cond, mutex> pair to handle an acquire of a locked lock */
74 pthread_cond_t lock_released;
75 pthread_mutex_t mut;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000076} pthread_lock;
77
Guido van Rossumb98b1b31994-05-11 08:42:04 +000078#define CHECK_STATUS(name) if (status < 0) { perror(name); error=1; }
79
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000080/*
81 * Initialization.
82 */
83static void _init_thread _P0()
84{
85}
86
87/*
88 * Thread support.
89 */
Guido van Rossumb98b1b31994-05-11 08:42:04 +000090
91
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000092int start_new_thread _P2(func, void (*func) _P((void *)), arg, void *arg)
93{
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000094 pthread_t th;
Guido van Rossume944da81994-05-23 12:43:41 +000095 int success;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +000096 dprintf(("start_new_thread called\n"));
97 if (!initialized)
98 init_thread();
Guido van Rossum66020991996-06-11 18:32:18 +000099 success = pthread_create(&th, pthread_attr_default,
100 (void* (*) _P((void *)))func, arg);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000101 return success < 0 ? 0 : 1;
102}
103
Guido van Rossume944da81994-05-23 12:43:41 +0000104long get_thread_ident _P0()
105{
Guido van Rossum2565bff1995-01-09 17:50:47 +0000106 pthread_t threadid;
Guido van Rossume944da81994-05-23 12:43:41 +0000107 if (!initialized)
108 init_thread();
Guido van Rossum2565bff1995-01-09 17:50:47 +0000109 /* Jump through some hoops for Alpha OSF/1 */
110 threadid = pthread_self();
111 return (long) *(long *) &threadid;
Guido van Rossume944da81994-05-23 12:43:41 +0000112}
113
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000114static void do_exit_thread _P1(no_cleanup, int no_cleanup)
115{
116 dprintf(("exit_thread called\n"));
117 if (!initialized)
118 if (no_cleanup)
119 _exit(0);
120 else
121 exit(0);
122}
123
124void exit_thread _P0()
125{
126 do_exit_thread(0);
127}
128
129void _exit_thread _P0()
130{
131 do_exit_thread(1);
132}
133
134#ifndef NO_EXIT_PROG
135static void do_exit_prog _P2(status, int status, no_cleanup, int no_cleanup)
136{
137 dprintf(("exit_prog(%d) called\n", status));
138 if (!initialized)
139 if (no_cleanup)
140 _exit(status);
141 else
142 exit(status);
143}
144
145void exit_prog _P1(status, int status)
146{
147 do_exit_prog(status, 0);
148}
149
150void _exit_prog _P1(status, int status)
151{
152 do_exit_prog(status, 1);
153}
154#endif /* NO_EXIT_PROG */
155
156/*
157 * Lock support.
158 */
159type_lock allocate_lock _P0()
160{
161 pthread_lock *lock;
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000162 int status, error = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000163
164 dprintf(("allocate_lock called\n"));
165 if (!initialized)
166 init_thread();
167
168 lock = (pthread_lock *) malloc(sizeof(pthread_lock));
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000169 if (lock) {
170 lock->locked = 0;
171
172 status = pthread_mutex_init(&lock->mut,
173 pthread_mutexattr_default);
174 CHECK_STATUS("pthread_mutex_init");
175
176 status = pthread_cond_init(&lock->lock_released,
177 pthread_condattr_default);
178 CHECK_STATUS("pthread_cond_init");
179
180 if (error) {
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000181 free((void *)lock);
182 lock = 0;
183 }
184 }
185
186 dprintf(("allocate_lock() -> %lx\n", (long)lock));
187 return (type_lock) lock;
188}
189
190void free_lock _P1(lock, type_lock lock)
191{
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000192 pthread_lock *thelock = (pthread_lock *)lock;
193 int status, error = 0;
194
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000195 dprintf(("free_lock(%lx) called\n", (long)lock));
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000196
197 status = pthread_mutex_destroy( &thelock->mut );
198 CHECK_STATUS("pthread_mutex_destroy");
199
200 status = pthread_cond_destroy( &thelock->lock_released );
201 CHECK_STATUS("pthread_cond_destroy");
202
203 free((void *)thelock);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000204}
205
206int acquire_lock _P2(lock, type_lock lock, waitflag, int waitflag)
207{
208 int success;
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000209 pthread_lock *thelock = (pthread_lock *)lock;
210 int status, error = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000211
212 dprintf(("acquire_lock(%lx, %d) called\n", (long)lock, waitflag));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000213
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000214 status = pthread_mutex_lock( &thelock->mut );
215 CHECK_STATUS("pthread_mutex_lock[1]");
216 success = thelock->locked == 0;
217 if (success) thelock->locked = 1;
218 status = pthread_mutex_unlock( &thelock->mut );
219 CHECK_STATUS("pthread_mutex_unlock[1]");
220
221 if ( !success && waitflag ) {
222 /* continue trying until we get the lock */
223
224 /* mut must be locked by me -- part of the condition
225 * protocol */
226 status = pthread_mutex_lock( &thelock->mut );
227 CHECK_STATUS("pthread_mutex_lock[2]");
228 while ( thelock->locked ) {
229 status = pthread_cond_wait(&thelock->lock_released,
230 &thelock->mut);
231 CHECK_STATUS("pthread_cond_wait");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000232 }
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000233 thelock->locked = 1;
234 status = pthread_mutex_unlock( &thelock->mut );
235 CHECK_STATUS("pthread_mutex_unlock[2]");
236 success = 1;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000237 }
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000238 if (error) success = 0;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000239 dprintf(("acquire_lock(%lx, %d) -> %d\n", (long)lock, waitflag, success));
240 return success;
241}
242
243void release_lock _P1(lock, type_lock lock)
244{
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000245 pthread_lock *thelock = (pthread_lock *)lock;
246 int status, error = 0;
247
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000248 dprintf(("release_lock(%lx) called\n", (long)lock));
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000249
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000250 status = pthread_mutex_lock( &thelock->mut );
251 CHECK_STATUS("pthread_mutex_lock[3]");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000252
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000253 thelock->locked = 0;
254
255 status = pthread_mutex_unlock( &thelock->mut );
256 CHECK_STATUS("pthread_mutex_unlock[3]");
257
258 /* wake up someone (anyone, if any) waiting on the lock */
259 status = pthread_cond_signal( &thelock->lock_released );
260 CHECK_STATUS("pthread_cond_signal");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000261}
262
263/*
264 * Semaphore support.
265 */
Guido van Rossum7af81301997-01-17 21:06:41 +0000266
267struct semaphore {
268 pthread_mutex_t mutex;
269 pthread_cond_t cond;
270 int value;
271};
Guido van Rossumb98b1b31994-05-11 08:42:04 +0000272
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000273type_sema allocate_sema _P1(value, int value)
274{
Guido van Rossum7af81301997-01-17 21:06:41 +0000275 struct semaphore *sema;
276 int status, error = 0;
277
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000278 dprintf(("allocate_sema called\n"));
279 if (!initialized)
280 init_thread();
281
Guido van Rossum7af81301997-01-17 21:06:41 +0000282 sema = (struct semaphore *) malloc(sizeof(struct semaphore));
283 if (sema != NULL) {
284 sema->value = value;
285 status = pthread_mutex_init(&sema->mutex,
286 pthread_mutexattr_default);
287 CHECK_STATUS("pthread_mutex_init");
288 status = pthread_cond_init(&sema->cond,
289 pthread_condattr_default);
290 CHECK_STATUS("pthread_cond_init");
291 if (error) {
292 free((void *) sema);
293 sema = NULL;
294 }
295 }
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000296 dprintf(("allocate_sema() -> %lx\n", (long) sema));
297 return (type_sema) sema;
298}
299
300void free_sema _P1(sema, type_sema sema)
301{
Guido van Rossum7af81301997-01-17 21:06:41 +0000302 int status, error = 0;
303 struct semaphore *thesema = (struct semaphore *) sema;
304
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000305 dprintf(("free_sema(%lx) called\n", (long) sema));
Guido van Rossum7af81301997-01-17 21:06:41 +0000306 status = pthread_cond_destroy(&thesema->cond);
307 CHECK_STATUS("pthread_cond_destroy");
308 status = pthread_mutex_destroy(&thesema->mutex);
309 CHECK_STATUS("pthread_mutex_destroy");
310 free((void *) thesema);
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000311}
312
Guido van Rossumcf1474b1996-10-08 14:17:53 +0000313int down_sema _P2(sema, type_sema sema, waitflag, int waitflag)
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000314{
Guido van Rossum7af81301997-01-17 21:06:41 +0000315 int status, error = 0, success;
316 struct semaphore *thesema = (struct semaphore *) sema;
317
Guido van Rossumcf1474b1996-10-08 14:17:53 +0000318 dprintf(("down_sema(%lx, %d) called\n", (long) sema, waitflag));
Guido van Rossum7af81301997-01-17 21:06:41 +0000319 status = pthread_mutex_lock(&thesema->mutex);
320 CHECK_STATUS("pthread_mutex_lock");
321 if (waitflag) {
322 while (!error && thesema->value <= 0) {
323 status = pthread_cond_wait(&thesema->cond,
324 &thesema->mutex);
325 CHECK_STATUS("pthread_cond_wait");
326 }
327 }
328 if (error)
329 success = 0;
330 else if (thesema->value > 0) {
331 thesema->value--;
332 success = 1;
333 }
334 else
335 success = 0;
336 status = pthread_mutex_unlock(&thesema->mutex);
337 CHECK_STATUS("pthread_mutex_unlock");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000338 dprintf(("down_sema(%lx) return\n", (long) sema));
Guido van Rossum7af81301997-01-17 21:06:41 +0000339 return success;
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000340}
341
342void up_sema _P1(sema, type_sema sema)
343{
Guido van Rossum7af81301997-01-17 21:06:41 +0000344 int status, error = 0;
345 struct semaphore *thesema = (struct semaphore *) sema;
346
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000347 dprintf(("up_sema(%lx)\n", (long) sema));
Guido van Rossum7af81301997-01-17 21:06:41 +0000348 status = pthread_mutex_lock(&thesema->mutex);
349 CHECK_STATUS("pthread_mutex_lock");
350 thesema->value++;
351 status = pthread_cond_signal(&thesema->cond);
352 CHECK_STATUS("pthread_cond_signal");
353 status = pthread_mutex_unlock(&thesema->mutex);
354 CHECK_STATUS("pthread_mutex_unlock");
Guido van Rossum2c8cb9f1994-05-09 15:12:46 +0000355}