2
#include <support/SupportDefs.h>
5
/* ----------------------------------------------------------------------
6
* Fast locking mechanism described by Benoit Schillings (benoit@be.com)
7
* in the Be Developer's Newsletter, Issue #26 (http://www.be.com/).
9
typedef struct benaphore {
14
static status_t benaphore_create( const char *name, benaphore_t *ben );
15
static status_t benaphore_destroy( benaphore_t *ben );
16
static status_t benaphore_lock( benaphore_t *ben );
17
static status_t benaphore_timedlock( benaphore_t *ben, bigtime_t micros );
18
static status_t benaphore_unlock( benaphore_t *ben );
20
static status_t benaphore_create( const char *name, benaphore_t *ben )
24
ben->_sem = create_sem( 0, name );
26
if( ben->_sem < B_NO_ERROR ) {
36
static status_t benaphore_destroy( benaphore_t *ben )
38
if( ben->_sem >= B_NO_ERROR ) {
39
status_t retval = benaphore_timedlock( ben, 0 );
41
if( retval == EOK || retval == EWOULDBLOCK ) {
42
status_t del_retval = delete_sem( ben->_sem );
51
static status_t benaphore_lock( benaphore_t *ben )
53
int32 prev = atomic_add( &(ben->_atom), 1 );
56
return acquire_sem( ben->_sem );
62
static status_t benaphore_timedlock( benaphore_t *ben, bigtime_t micros )
64
int32 prev = atomic_add( &(ben->_atom), 1 );
67
status_t retval = acquire_sem_etc( ben->_sem, 1, B_TIMEOUT, micros );
70
case B_WOULD_BLOCK: /* Fall through... */
86
static status_t benaphore_unlock( benaphore_t *ben )
88
int32 prev = atomic_add( &(ben->_atom), -1 );
91
return release_sem( ben->_sem );
97
/* ----------------------------------------------------------------------
100
static void PyThread__init_thread( void )
106
/* ----------------------------------------------------------------------
109
* Only ANSI C, renamed functions here; you can't use K&R on BeOS,
110
* and there's no legacy thread module to support.
113
static int32 thread_count = 0;
115
long PyThread_start_new_thread( void (*func)(void *), void *arg )
117
status_t success = 0;
119
char name[B_OS_NAME_LENGTH];
122
dprintf(("PyThread_start_new_thread called\n"));
124
/* We are so very thread-safe... */
125
this_thread = atomic_add( &thread_count, 1 );
126
PyOS_snprintf(name, sizeof(name),
127
"python thread (%d)", this_thread );
129
tid = spawn_thread( (thread_func)func, name,
130
B_NORMAL_PRIORITY, arg );
131
if( tid > B_NO_ERROR ) {
132
success = resume_thread( tid );
135
return ( success == B_NO_ERROR ? tid : -1 );
138
long PyThread_get_thread_ident( void )
140
/* Presumed to return the current thread's ID... */
142
tid = find_thread( NULL );
144
return ( tid != B_NAME_NOT_FOUND ? tid : -1 );
147
static void do_PyThread_exit_thread( int no_cleanup )
151
dprintf(("PyThread_exit_thread called\n"));
153
/* Thread-safe way to read a variable without a mutex: */
154
threads = atomic_add( &thread_count, 0 );
157
/* No threads around, so exit main(). */
164
/* Oh, we're a thread, let's try to exit gracefully... */
165
exit_thread( B_NO_ERROR );
169
void PyThread_exit_thread( void )
171
do_PyThread_exit_thread(0);
174
void PyThread__exit_thread( void )
176
do_PyThread_exit_thread(1);
180
static void do_PyThread_exit_prog( int status, int no_cleanup )
182
dprintf(("PyThread_exit_prog(%d) called\n", status));
184
/* No need to do anything, the threads get torn down if main() exits. */
193
void PyThread_exit_prog( int status )
195
do_PyThread_exit_prog(status, 0);
198
void PyThread__exit_prog( int status )
200
do_PyThread_exit_prog(status, 1);
202
#endif /* NO_EXIT_PROG */
204
/* ----------------------------------------------------------------------
208
static int32 lock_count = 0;
210
PyThread_type_lock PyThread_allocate_lock( void )
214
char name[B_OS_NAME_LENGTH];
217
dprintf(("PyThread_allocate_lock called\n"));
219
lock = (benaphore_t *)malloc( sizeof( benaphore_t ) );
221
/* TODO: that's bad, raise MemoryError */
222
return (PyThread_type_lock)NULL;
225
this_lock = atomic_add( &lock_count, 1 );
226
PyOS_snprintf(name, sizeof(name), "python lock (%d)", this_lock);
228
retval = benaphore_create( name, lock );
229
if( retval != EOK ) {
230
/* TODO: that's bad, raise an exception */
231
return (PyThread_type_lock)NULL;
234
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
235
return (PyThread_type_lock) lock;
238
void PyThread_free_lock( PyThread_type_lock lock )
242
dprintf(("PyThread_free_lock(%p) called\n", lock));
244
retval = benaphore_destroy( (benaphore_t *)lock );
245
if( retval != EOK ) {
246
/* TODO: that's bad, raise an exception */
251
int PyThread_acquire_lock( PyThread_type_lock lock, int waitflag )
256
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
259
retval = benaphore_lock( (benaphore_t *)lock );
261
retval = benaphore_timedlock( (benaphore_t *)lock, 0 );
264
if( retval == EOK ) {
269
/* TODO: that's bad, raise an exception */
272
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
276
void PyThread_release_lock( PyThread_type_lock lock )
280
dprintf(("PyThread_release_lock(%p) called\n", lock));
282
retval = benaphore_unlock( (benaphore_t *)lock );
283
if( retval != EOK ) {
284
/* TODO: that's bad, raise an exception */