1 /* Posix threads interface */
2
3 #include <stdlib.h>
4 #include <string.h>
5 #if defined(__APPLE__) || defined(HAVE_PTHREAD_DESTRUCTOR)
6 #define destructor xxdestructor
7 #endif
8 #include <pthread.h>
9 #if defined(__APPLE__) || defined(HAVE_PTHREAD_DESTRUCTOR)
10 #undef destructor
11 #endif
12 #include <signal.h>
13
14 /* The POSIX spec requires that use of pthread_attr_setstacksize
15 be conditional on _POSIX_THREAD_ATTR_STACKSIZE being defined. */
16 #ifdef _POSIX_THREAD_ATTR_STACKSIZE
17 #ifndef THREAD_STACK_SIZE
18 #define THREAD_STACK_SIZE 0 /* use default stack size */
19 #endif
20
21 #if (defined(__APPLE__) || defined(__FreeBSD__)) && defined(THREAD_STACK_SIZE) && THREAD_STACK_SIZE == 0
22 /* The default stack size for new threads on OSX is small enough that
23 * we'll get hard crashes instead of 'maximum recursion depth exceeded'
24 * exceptions.
25 *
26 * The default stack size below is the minimal stack size where a
27 * simple recursive function doesn't cause a hard crash.
28 */
29 #undef THREAD_STACK_SIZE
30 #define THREAD_STACK_SIZE 0x400000
31 #endif
32 /* for safety, ensure a viable minimum stacksize */
33 #define THREAD_STACK_MIN 0x8000 /* 32kB */
34 #else /* !_POSIX_THREAD_ATTR_STACKSIZE */
35 #ifdef THREAD_STACK_SIZE
36 #error "THREAD_STACK_SIZE defined but _POSIX_THREAD_ATTR_STACKSIZE undefined"
37 #endif
38 #endif
39
40 /* The POSIX spec says that implementations supporting the sem_*
41 family of functions must indicate this by defining
42 _POSIX_SEMAPHORES. */
43 #ifdef _POSIX_SEMAPHORES
44 /* On FreeBSD 4.x, _POSIX_SEMAPHORES is defined empty, so
45 we need to add 0 to make it work there as well. */
46 #if (_POSIX_SEMAPHORES+0) == -1
47 #define HAVE_BROKEN_POSIX_SEMAPHORES
48 #else
49 #include <semaphore.h>
50 #include <errno.h>
51 #endif
52 #endif
53
54 /* Before FreeBSD 5.4, system scope threads was very limited resource
55 in default setting. So the process scope is preferred to get
56 enough number of threads to work. */
57 #ifdef __FreeBSD__
58 #include <osreldate.h>
59 #if __FreeBSD_version >= 500000 && __FreeBSD_version < 504101
60 #undef PTHREAD_SYSTEM_SCHED_SUPPORTED
61 #endif
62 #endif
63
64 #if !defined(pthread_attr_default)
65 # define pthread_attr_default ((pthread_attr_t *)NULL)
66 #endif
67 #if !defined(pthread_mutexattr_default)
68 # define pthread_mutexattr_default ((pthread_mutexattr_t *)NULL)
69 #endif
70 #if !defined(pthread_condattr_default)
71 # define pthread_condattr_default ((pthread_condattr_t *)NULL)
72 #endif
73
74
75 /* Whether or not to use semaphores directly rather than emulating them with
76 * mutexes and condition variables:
77 */
78 #if defined(_POSIX_SEMAPHORES) && !defined(HAVE_BROKEN_POSIX_SEMAPHORES)
79 # define USE_SEMAPHORES
80 #else
81 # undef USE_SEMAPHORES
82 #endif
83
84
85 /* On platforms that don't use standard POSIX threads pthread_sigmask()
86 * isn't present. DEC threads uses sigprocmask() instead as do most
87 * other UNIX International compliant systems that don't have the full
88 * pthread implementation.
89 */
90 #if defined(HAVE_PTHREAD_SIGMASK) && !defined(HAVE_BROKEN_PTHREAD_SIGMASK)
91 # define SET_THREAD_SIGMASK pthread_sigmask
92 #else
93 # define SET_THREAD_SIGMASK sigprocmask
94 #endif
95
96
97 /* 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
104 * Python's locks regardless.
105 *
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
110 */
111
112 typedef struct {
113 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;
117 } pthread_lock;
118
119 #define CHECK_STATUS(name) if (status != 0) { perror(name); error = 1; }
120
121 /*
122 * Initialization.
123 */
124
125 #ifdef _HAVE_BSDI
126 static
127 void _noop(void)
128 {
129 }
130
131 static void
132 PyThread__init_thread(void)
133 {
134 /* DO AN INIT BY STARTING THE THREAD */
135 static int dummy = 0;
136 pthread_t thread1;
137 pthread_create(&thread1, NULL, (void *) _noop, &dummy);
138 pthread_join(thread1, NULL);
139 }
140
141 #else /* !_HAVE_BSDI */
142
143 static void
144 PyThread__init_thread(void)
145 {
146 #if defined(_AIX) && defined(__GNUC__)
147 pthread_init();
148 #endif
149 }
150
151 #endif /* !_HAVE_BSDI */
152
153 /*
154 * Thread support.
155 */
156
157
158 long
159 PyThread_start_new_thread(void (*func)(void *), void *arg)
160 {
161 pthread_t th;
162 int status;
163 #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
164 pthread_attr_t attrs;
165 #endif
166 #if defined(THREAD_STACK_SIZE)
167 size_t tss;
168 #endif
169
170 dprintf(("PyThread_start_new_thread called\n"));
171 if (!initialized)
172 PyThread_init_thread();
173
174 #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
175 if (pthread_attr_init(&attrs) != 0)
176 return -1;
177 #endif
178 #if defined(THREAD_STACK_SIZE)
179 tss = (_pythread_stacksize != 0) ? _pythread_stacksize
180 : THREAD_STACK_SIZE;
181 if (tss != 0) {
182 if (pthread_attr_setstacksize(&attrs, tss) != 0) {
183 pthread_attr_destroy(&attrs);
184 return -1;
185 }
186 }
187 #endif
188 #if defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
189 pthread_attr_setscope(&attrs, PTHREAD_SCOPE_SYSTEM);
190 #endif
191
192 status = pthread_create(&th,
193 #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
194 &attrs,
195 #else
196 (pthread_attr_t*)NULL,
197 #endif
198 (void* (*)(void *))func,
199 (void *)arg
200 );
201
202 #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
203 pthread_attr_destroy(&attrs);
204 #endif
205 if (status != 0)
206 return -1;
207
208 pthread_detach(th);
209
210 #if SIZEOF_PTHREAD_T <= SIZEOF_LONG
211 return (long) th;
212 #else
213 return (long) *(long *) &th;
214 #endif
215 }
216
217 /* XXX This implementation is considered (to quote Tim Peters) "inherently
218 hosed" because:
219 - It does not guarantee the promise that a non-zero integer is returned.
220 - The cast to long is inherently unsafe.
221 - It is not clear that the 'volatile' (for AIX?) and ugly casting in the
222 latter return statement (for Alpha OSF/1) are any longer necessary.
223 */
224 long
225 PyThread_get_thread_ident(void)
226 {
227 volatile pthread_t threadid;
228 if (!initialized)
229 PyThread_init_thread();
230 /* Jump through some hoops for Alpha OSF/1 */
231 threadid = pthread_self();
232 #if SIZEOF_PTHREAD_T <= SIZEOF_LONG
233 return (long) threadid;
234 #else
235 return (long) *(long *) &threadid;
236 #endif
237 }
238
239 void
240 PyThread_exit_thread(void)
241 {
242 dprintf(("PyThread_exit_thread called\n"));
243 if (!initialized) {
244 exit(0);
245 }
246 }
247
248 #ifdef USE_SEMAPHORES
249
250 /*
251 * Lock support.
252 */
253
254 PyThread_type_lock
255 PyThread_allocate_lock(void)
256 {
257 sem_t *lock;
258 int status, error = 0;
259
260 dprintf(("PyThread_allocate_lock called\n"));
261 if (!initialized)
262 PyThread_init_thread();
263
264 lock = (sem_t *)malloc(sizeof(sem_t));
265
266 if (lock) {
267 status = sem_init(lock,0,1);
268 CHECK_STATUS("sem_init");
269
270 if (error) {
271 free((void *)lock);
272 lock = NULL;
273 }
274 }
275
276 dprintf(("PyThread_allocate_lock() -> %p\n", lock));
277 return (PyThread_type_lock)lock;
278 }
279
280 void
281 PyThread_free_lock(PyThread_type_lock lock)
282 {
283 sem_t *thelock = (sem_t *)lock;
284 int status, error = 0;
285
variable 'error' set but not used
(emitted by gcc)
variable 'error' set but not used
(emitted by gcc)
286 dprintf(("PyThread_free_lock(%p) called\n", lock));
287
288 if (!thelock)
289 return;
290
291 status = sem_destroy(thelock);
292 CHECK_STATUS("sem_destroy");
293
294 free((void *)thelock);
295 }
296
297 /*
298 * As of February 2002, Cygwin thread implementations mistakenly report error
299 * codes in the return value of the sem_ calls (like the pthread_ functions).
300 * Correct implementations return -1 and put the code in errno. This supports
301 * either.
302 */
303 static int
304 fix_status(int status)
305 {
306 return (status == -1) ? errno : status;
307 }
308
309 int
310 PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
311 {
312 int success;
313 sem_t *thelock = (sem_t *)lock;
314 int status, error = 0;
315
variable 'error' set but not used
(emitted by gcc)
variable 'error' set but not used
(emitted by gcc)
316 dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
317
318 do {
319 if (waitflag)
320 status = fix_status(sem_wait(thelock));
321 else
322 status = fix_status(sem_trywait(thelock));
323 } while (status == EINTR); /* Retry if interrupted by a signal */
324
325 if (waitflag) {
326 CHECK_STATUS("sem_wait");
327 } else if (status != EAGAIN) {
328 CHECK_STATUS("sem_trywait");
329 }
330
331 success = (status == 0) ? 1 : 0;
332
333 dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
334 return success;
335 }
336
337 void
338 PyThread_release_lock(PyThread_type_lock lock)
339 {
340 sem_t *thelock = (sem_t *)lock;
341 int status, error = 0;
342
variable 'error' set but not used
(emitted by gcc)
variable 'error' set but not used
(emitted by gcc)
343 dprintf(("PyThread_release_lock(%p) called\n", lock));
344
345 status = sem_post(thelock);
346 CHECK_STATUS("sem_post");
347 }
348
349 #else /* USE_SEMAPHORES */
350
351 /*
352 * Lock support.
353 */
354 PyThread_type_lock
355 PyThread_allocate_lock(void)
356 {
357 pthread_lock *lock;
358 int status, error = 0;
359
360 dprintf(("PyThread_allocate_lock called\n"));
361 if (!initialized)
362 PyThread_init_thread();
363
364 lock = (pthread_lock *) malloc(sizeof(pthread_lock));
365 if (lock) {
366 memset((void *)lock, '\0', sizeof(pthread_lock));
367 lock->locked = 0;
368
369 status = pthread_mutex_init(&lock->mut,
370 pthread_mutexattr_default);
371 CHECK_STATUS("pthread_mutex_init");
372
373 status = pthread_cond_init(&lock->lock_released,
374 pthread_condattr_default);
375 CHECK_STATUS("pthread_cond_init");
376
377 if (error) {
378 free((void *)lock);
379 lock = 0;
380 }
381 }
382
383 dprintf(("PyThread_allocate_lock() -> %p\n", lock));
384 return (PyThread_type_lock) lock;
385 }
386
387 void
388 PyThread_free_lock(PyThread_type_lock lock)
389 {
390 pthread_lock *thelock = (pthread_lock *)lock;
391 int status, error = 0;
392
393 dprintf(("PyThread_free_lock(%p) called\n", lock));
394
395 status = pthread_mutex_destroy( &thelock->mut );
396 CHECK_STATUS("pthread_mutex_destroy");
397
398 status = pthread_cond_destroy( &thelock->lock_released );
399 CHECK_STATUS("pthread_cond_destroy");
400
401 free((void *)thelock);
402 }
403
404 int
405 PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
406 {
407 int success;
408 pthread_lock *thelock = (pthread_lock *)lock;
409 int status, error = 0;
410
411 dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
412
413 status = pthread_mutex_lock( &thelock->mut );
414 CHECK_STATUS("pthread_mutex_lock[1]");
415 success = thelock->locked == 0;
416
417 if ( !success && waitflag ) {
418 /* continue trying until we get the lock */
419
420 /* mut must be locked by me -- part of the condition
421 * protocol */
422 while ( thelock->locked ) {
423 status = pthread_cond_wait(&thelock->lock_released,
424 &thelock->mut);
425 CHECK_STATUS("pthread_cond_wait");
426 }
427 success = 1;
428 }
429 if (success) thelock->locked = 1;
430 status = pthread_mutex_unlock( &thelock->mut );
431 CHECK_STATUS("pthread_mutex_unlock[1]");
432
433 if (error) success = 0;
434 dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
435 return success;
436 }
437
438 void
439 PyThread_release_lock(PyThread_type_lock lock)
440 {
441 pthread_lock *thelock = (pthread_lock *)lock;
442 int status, error = 0;
443
444 dprintf(("PyThread_release_lock(%p) called\n", lock));
445
446 status = pthread_mutex_lock( &thelock->mut );
447 CHECK_STATUS("pthread_mutex_lock[3]");
448
449 thelock->locked = 0;
450
451 status = pthread_mutex_unlock( &thelock->mut );
452 CHECK_STATUS("pthread_mutex_unlock[3]");
453
454 /* wake up someone (anyone, if any) waiting on the lock */
455 status = pthread_cond_signal( &thelock->lock_released );
456 CHECK_STATUS("pthread_cond_signal");
457 }
458
459 #endif /* USE_SEMAPHORES */
460
461 /* set the thread stack size.
462 * Return 0 if size is valid, -1 if size is invalid,
463 * -2 if setting stack size is not supported.
464 */
465 static int
466 _pythread_pthread_set_stacksize(size_t size)
467 {
468 #if defined(THREAD_STACK_SIZE)
469 pthread_attr_t attrs;
470 size_t tss_min;
471 int rc = 0;
472 #endif
473
474 /* set to default */
475 if (size == 0) {
476 _pythread_stacksize = 0;
477 return 0;
478 }
479
480 #if defined(THREAD_STACK_SIZE)
481 #if defined(PTHREAD_STACK_MIN)
482 tss_min = PTHREAD_STACK_MIN > THREAD_STACK_MIN ? PTHREAD_STACK_MIN
483 : THREAD_STACK_MIN;
484 #else
485 tss_min = THREAD_STACK_MIN;
486 #endif
487 if (size >= tss_min) {
488 /* validate stack size by setting thread attribute */
489 if (pthread_attr_init(&attrs) == 0) {
490 rc = pthread_attr_setstacksize(&attrs, size);
491 pthread_attr_destroy(&attrs);
492 if (rc == 0) {
493 _pythread_stacksize = size;
494 return 0;
495 }
496 }
497 }
498 return -1;
499 #else
500 return -2;
501 #endif
502 }
503
504 #define THREAD_SET_STACKSIZE(x) _pythread_pthread_set_stacksize(x)