Added 'list_only' option (and modified 'run()' to respect it).
[python/dscho.git] / Python / thread_beos.h
blob0dff786436cb160cb29575343c916473b36b2395
1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3 The Netherlands.
5 All Rights Reserved
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI or Corporation for National Research Initiatives or
13 CNRI not be used in advertising or publicity pertaining to
14 distribution of the software without specific, written prior
15 permission.
17 While CWI is the initial source for this software, a modified version
18 is made available by the Corporation for National Research Initiatives
19 (CNRI) at the Internet address ftp://ftp.python.org.
21 STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22 REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23 MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24 CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28 PERFORMANCE OF THIS SOFTWARE.
30 BeOS thread support by Chris Herborth (chrish@qnx.com)
31 ******************************************************************/
33 #include <kernel/OS.h>
34 #include <support/SupportDefs.h>
35 #include <errno.h>
37 /* ----------------------------------------------------------------------
38 * Fast locking mechanism described by Benoit Schillings (benoit@be.com)
39 * in the Be Developer's Newsletter, Issue #26 (http://www.be.com/).
41 typedef struct benaphore {
42 sem_id _sem;
43 int32 _atom;
44 } benaphore_t;
46 static status_t benaphore_create( const char *name, benaphore_t *ben );
47 static status_t benaphore_destroy( benaphore_t *ben );
48 static status_t benaphore_lock( benaphore_t *ben );
49 static status_t benaphore_timedlock( benaphore_t *ben, bigtime_t micros );
50 static status_t benaphore_unlock( benaphore_t *ben );
52 static status_t benaphore_create( const char *name, benaphore_t *ben )
54 if( ben != NULL ) {
55 ben->_atom = 0;
56 ben->_sem = create_sem( 0, name );
58 if( ben->_sem < B_NO_ERROR ) {
59 return B_BAD_SEM_ID;
61 } else {
62 return EFAULT;
65 return EOK;
68 static status_t benaphore_destroy( benaphore_t *ben )
70 if( ben->_sem >= B_NO_ERROR ) {
71 status_t retval = benaphore_timedlock( ben, 0 );
73 if( retval == EOK || retval == EWOULDBLOCK ) {
74 status_t del_retval = delete_sem( ben->_sem );
76 return del_retval;
80 return B_BAD_SEM_ID;
83 static status_t benaphore_lock( benaphore_t *ben )
85 int32 prev = atomic_add( &(ben->_atom), 1 );
87 if( prev > 0 ) {
88 return acquire_sem( ben->_sem );
91 return EOK;
94 static status_t benaphore_timedlock( benaphore_t *ben, bigtime_t micros )
96 int32 prev = atomic_add( &(ben->_atom), 1 );
98 if( prev > 0 ) {
99 status_t retval = acquire_sem_etc( ben->_sem, 1, B_TIMEOUT, micros );
101 switch( retval ) {
102 case B_WOULD_BLOCK: /* Fall through... */
103 case B_TIMED_OUT:
104 return EWOULDBLOCK;
105 break;
106 case B_OK:
107 return EOK;
108 break;
109 default:
110 return retval;
111 break;
115 return EOK;
118 static status_t benaphore_unlock( benaphore_t *ben )
120 int32 prev = atomic_add( &(ben->_atom), -1 );
122 if( prev > 1 ) {
123 return release_sem( ben->_sem );
126 return EOK;
129 /* ----------------------------------------------------------------------
130 * Initialization.
132 static void PyThread__init_thread( void )
134 /* Do nothing. */
135 return;
138 /* ----------------------------------------------------------------------
139 * Thread support.
141 * Only ANSI C, renamed functions here; you can't use K&R on BeOS,
142 * and there's no legacy thread module to support.
145 static int32 thread_count = 0;
147 int PyThread_start_new_thread( void (*func)(void *), void *arg )
149 status_t success = 0;
150 thread_id tid;
151 char name[B_OS_NAME_LENGTH];
152 int32 this_thread;
154 dprintf(("PyThread_start_new_thread called\n"));
156 /* We are so very thread-safe... */
157 this_thread = atomic_add( &thread_count, 1 );
158 sprintf( name, "python thread (%d)", this_thread );
160 tid = spawn_thread( (thread_func)func, name,
161 B_NORMAL_PRIORITY, arg );
162 if( tid > B_NO_ERROR ) {
163 success = resume_thread( tid );
166 return ( success == B_NO_ERROR ? 1 : 0 );
169 long PyThread_get_thread_ident( void )
171 /* Presumed to return the current thread's ID... */
172 thread_id tid;
173 tid = find_thread( NULL );
175 return ( tid != B_NAME_NOT_FOUND ? tid : -1 );
178 static void do_PyThread_exit_thread( int no_cleanup )
180 int32 threads;
182 dprintf(("PyThread_exit_thread called\n"));
184 /* Thread-safe way to read a variable without a mutex: */
185 threads = atomic_add( &thread_count, 0 );
187 if( threads == 0 ) {
188 /* No threads around, so exit main(). */
189 if( no_cleanup ) {
190 _exit(0);
191 } else {
192 exit(0);
194 } else {
195 /* Oh, we're a thread, let's try to exit gracefully... */
196 exit_thread( B_NO_ERROR );
200 void PyThread_exit_thread( void )
202 do_PyThread_exit_thread(0);
205 void PyThread__exit_thread( void )
207 do_PyThread_exit_thread(1);
210 #ifndef NO_EXIT_PROG
211 static void do_PyThread_exit_prog( int status, int no_cleanup )
213 dprintf(("PyThread_exit_prog(%d) called\n", status));
215 /* No need to do anything, the threads get torn down if main() exits. */
217 if (no_cleanup) {
218 _exit(status);
219 } else {
220 exit(status);
224 void PyThread_exit_prog( int status )
226 do_PyThread_exit_prog(status, 0);
229 void PyThread__exit_prog( int status )
231 do_PyThread_exit_prog(status, 1);
233 #endif /* NO_EXIT_PROG */
235 /* ----------------------------------------------------------------------
236 * Lock support.
239 static int32 lock_count = 0;
241 PyThread_type_lock PyThread_allocate_lock( void )
243 benaphore_t *lock;
244 status_t retval;
245 char name[B_OS_NAME_LENGTH];
246 int32 this_lock;
248 dprintf(("PyThread_allocate_lock called\n"));
250 lock = (benaphore_t *)malloc( sizeof( benaphore_t ) );
251 if( lock == NULL ) {
252 /* TODO: that's bad, raise MemoryError */
253 return (PyThread_type_lock)NULL;
256 this_lock = atomic_add( &lock_count, 1 );
257 sprintf( name, "python lock (%d)", this_lock );
259 retval = benaphore_create( name, lock );
260 if( retval != EOK ) {
261 /* TODO: that's bad, raise an exception */
262 return (PyThread_type_lock)NULL;
265 dprintf(("PyThread_allocate_lock() -> %lx\n", (long)lock));
266 return (PyThread_type_lock) lock;
269 void PyThread_free_lock( PyThread_type_lock lock )
271 status_t retval;
273 dprintf(("PyThread_free_lock(%lx) called\n", (long)lock));
275 retval = benaphore_destroy( (benaphore_t *)lock );
276 if( retval != EOK ) {
277 /* TODO: that's bad, raise an exception */
278 return;
282 int PyThread_acquire_lock( PyThread_type_lock lock, int waitflag )
284 int success;
285 status_t retval;
287 dprintf(("PyThread_acquire_lock(%lx, %d) called\n", (long)lock, waitflag));
289 if( waitflag ) {
290 retval = benaphore_lock( (benaphore_t *)lock );
291 } else {
292 retval = benaphore_timedlock( (benaphore_t *)lock, 0 );
295 if( retval == EOK ) {
296 success = 1;
297 } else {
298 success = 0;
300 /* TODO: that's bad, raise an exception */
303 dprintf(("PyThread_acquire_lock(%lx, %d) -> %d\n", (long)lock, waitflag, success));
304 return success;
307 void PyThread_release_lock( PyThread_type_lock lock )
309 status_t retval;
311 dprintf(("PyThread_release_lock(%lx) called\n", (long)lock));
313 retval = benaphore_unlock( (benaphore_t *)lock );
314 if( retval != EOK ) {
315 /* TODO: that's bad, raise an exception */
316 return;
320 /* ----------------------------------------------------------------------
321 * Semaphore support.
323 * Guido says not to implement this because it's not used anywhere;
324 * I'll do it anyway, you never know when it might be handy, and it's
325 * easy...
327 PyThread_type_sema PyThread_allocate_sema( int value )
329 sem_id sema;
331 dprintf(("PyThread_allocate_sema called\n"));
333 sema = create_sem( value, "python semaphore" );
334 if( sema < B_NO_ERROR ) {
335 /* TODO: that's bad, raise an exception */
336 return 0;
339 dprintf(("PyThread_allocate_sema() -> %lx\n", (long) sema));
340 return (PyThread_type_sema) sema;
343 void PyThread_free_sema( PyThread_type_sema sema )
345 status_t retval;
347 dprintf(("PyThread_free_sema(%lx) called\n", (long) sema));
349 retval = delete_sem( (sem_id)sema );
350 if( retval != B_NO_ERROR ) {
351 /* TODO: that's bad, raise an exception */
352 return;
356 int PyThread_down_sema( PyThread_type_sema sema, int waitflag )
358 status_t retval;
360 dprintf(("PyThread_down_sema(%lx, %d) called\n", (long) sema, waitflag));
362 if( waitflag ) {
363 retval = acquire_sem( (sem_id)sema );
364 } else {
365 retval = acquire_sem_etc( (sem_id)sema, 1, B_TIMEOUT, 0 );
368 if( retval != B_NO_ERROR ) {
369 /* TODO: that's bad, raise an exception */
370 return 0;
373 dprintf(("PyThread_down_sema(%lx) return\n", (long) sema));
374 return -1;
377 void PyThread_up_sema( PyThread_type_sema sema )
379 status_t retval;
381 dprintf(("PyThread_up_sema(%lx)\n", (long) sema));
383 retval = release_sem( (sem_id)sema );
384 if( retval != B_NO_ERROR ) {
385 /* TODO: that's bad, raise an exception */
386 return;