1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
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
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>
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
{
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
)
56 ben
->_sem
= create_sem( 0, name
);
58 if( ben
->_sem
< B_NO_ERROR
) {
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
);
83 static status_t
benaphore_lock( benaphore_t
*ben
)
85 int32 prev
= atomic_add( &(ben
->_atom
), 1 );
88 return acquire_sem( ben
->_sem
);
94 static status_t
benaphore_timedlock( benaphore_t
*ben
, bigtime_t micros
)
96 int32 prev
= atomic_add( &(ben
->_atom
), 1 );
99 status_t retval
= acquire_sem_etc( ben
->_sem
, 1, B_TIMEOUT
, micros
);
102 case B_WOULD_BLOCK
: /* Fall through... */
118 static status_t
benaphore_unlock( benaphore_t
*ben
)
120 int32 prev
= atomic_add( &(ben
->_atom
), -1 );
123 return release_sem( ben
->_sem
);
129 /* ----------------------------------------------------------------------
132 static void PyThread__init_thread( void )
138 /* ----------------------------------------------------------------------
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;
151 char name
[B_OS_NAME_LENGTH
];
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... */
173 tid
= find_thread( NULL
);
175 return ( tid
!= B_NAME_NOT_FOUND
? tid
: -1 );
178 static void do_PyThread_exit_thread( int no_cleanup
)
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 );
188 /* No threads around, so exit main(). */
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);
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. */
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 /* ----------------------------------------------------------------------
239 static int32 lock_count
= 0;
241 PyThread_type_lock
PyThread_allocate_lock( void )
245 char name
[B_OS_NAME_LENGTH
];
248 dprintf(("PyThread_allocate_lock called\n"));
250 lock
= (benaphore_t
*)malloc( sizeof( benaphore_t
) );
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
)
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 */
282 int PyThread_acquire_lock( PyThread_type_lock lock
, int waitflag
)
287 dprintf(("PyThread_acquire_lock(%lx, %d) called\n", (long)lock
, waitflag
));
290 retval
= benaphore_lock( (benaphore_t
*)lock
);
292 retval
= benaphore_timedlock( (benaphore_t
*)lock
, 0 );
295 if( retval
== EOK
) {
300 /* TODO: that's bad, raise an exception */
303 dprintf(("PyThread_acquire_lock(%lx, %d) -> %d\n", (long)lock
, waitflag
, success
));
307 void PyThread_release_lock( PyThread_type_lock lock
)
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 */
320 /* ----------------------------------------------------------------------
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
327 PyThread_type_sema
PyThread_allocate_sema( int value
)
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 */
339 dprintf(("PyThread_allocate_sema() -> %lx\n", (long) sema
));
340 return (PyThread_type_sema
) sema
;
343 void PyThread_free_sema( PyThread_type_sema sema
)
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 */
356 int PyThread_down_sema( PyThread_type_sema sema
, int waitflag
)
360 dprintf(("PyThread_down_sema(%lx, %d) called\n", (long) sema
, waitflag
));
363 retval
= acquire_sem( (sem_id
)sema
);
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 */
373 dprintf(("PyThread_down_sema(%lx) return\n", (long) sema
));
377 void PyThread_up_sema( PyThread_type_sema sema
)
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 */