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 int 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 sprintf( name
, "python thread (%d)", this_thread
);
128 tid
= spawn_thread( (thread_func
)func
, name
,
129 B_NORMAL_PRIORITY
, arg
);
130 if( tid
> B_NO_ERROR
) {
131 success
= resume_thread( tid
);
134 return ( success
== B_NO_ERROR
? 1 : 0 );
137 long PyThread_get_thread_ident( void )
139 /* Presumed to return the current thread's ID... */
141 tid
= find_thread( NULL
);
143 return ( tid
!= B_NAME_NOT_FOUND
? tid
: -1 );
146 static void do_PyThread_exit_thread( int no_cleanup
)
150 dprintf(("PyThread_exit_thread called\n"));
152 /* Thread-safe way to read a variable without a mutex: */
153 threads
= atomic_add( &thread_count
, 0 );
156 /* No threads around, so exit main(). */
163 /* Oh, we're a thread, let's try to exit gracefully... */
164 exit_thread( B_NO_ERROR
);
168 void PyThread_exit_thread( void )
170 do_PyThread_exit_thread(0);
173 void PyThread__exit_thread( void )
175 do_PyThread_exit_thread(1);
179 static void do_PyThread_exit_prog( int status
, int no_cleanup
)
181 dprintf(("PyThread_exit_prog(%d) called\n", status
));
183 /* No need to do anything, the threads get torn down if main() exits. */
192 void PyThread_exit_prog( int status
)
194 do_PyThread_exit_prog(status
, 0);
197 void PyThread__exit_prog( int status
)
199 do_PyThread_exit_prog(status
, 1);
201 #endif /* NO_EXIT_PROG */
203 /* ----------------------------------------------------------------------
207 static int32 lock_count
= 0;
209 PyThread_type_lock
PyThread_allocate_lock( void )
213 char name
[B_OS_NAME_LENGTH
];
216 dprintf(("PyThread_allocate_lock called\n"));
218 lock
= (benaphore_t
*)malloc( sizeof( benaphore_t
) );
220 /* TODO: that's bad, raise MemoryError */
221 return (PyThread_type_lock
)NULL
;
224 this_lock
= atomic_add( &lock_count
, 1 );
225 sprintf( name
, "python lock (%d)", this_lock
);
227 retval
= benaphore_create( name
, lock
);
228 if( retval
!= EOK
) {
229 /* TODO: that's bad, raise an exception */
230 return (PyThread_type_lock
)NULL
;
233 dprintf(("PyThread_allocate_lock() -> %p\n", lock
));
234 return (PyThread_type_lock
) lock
;
237 void PyThread_free_lock( PyThread_type_lock lock
)
241 dprintf(("PyThread_free_lock(%p) called\n", lock
));
243 retval
= benaphore_destroy( (benaphore_t
*)lock
);
244 if( retval
!= EOK
) {
245 /* TODO: that's bad, raise an exception */
250 int PyThread_acquire_lock( PyThread_type_lock lock
, int waitflag
)
255 dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock
, waitflag
));
258 retval
= benaphore_lock( (benaphore_t
*)lock
);
260 retval
= benaphore_timedlock( (benaphore_t
*)lock
, 0 );
263 if( retval
== EOK
) {
268 /* TODO: that's bad, raise an exception */
271 dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock
, waitflag
, success
));
275 void PyThread_release_lock( PyThread_type_lock lock
)
279 dprintf(("PyThread_release_lock(%p) called\n", lock
));
281 retval
= benaphore_unlock( (benaphore_t
*)lock
);
282 if( retval
!= EOK
) {
283 /* TODO: that's bad, raise an exception */
288 /* ----------------------------------------------------------------------
291 * Guido says not to implement this because it's not used anywhere;
292 * I'll do it anyway, you never know when it might be handy, and it's
295 PyThread_type_sema
PyThread_allocate_sema( int value
)
299 dprintf(("PyThread_allocate_sema called\n"));
301 sema
= create_sem( value
, "python semaphore" );
302 if( sema
< B_NO_ERROR
) {
303 /* TODO: that's bad, raise an exception */
307 dprintf(("PyThread_allocate_sema() -> %p\n", sema
));
308 return (PyThread_type_sema
) sema
;
311 void PyThread_free_sema( PyThread_type_sema sema
)
315 dprintf(("PyThread_free_sema(%p) called\n", sema
));
317 retval
= delete_sem( (sem_id
)sema
);
318 if( retval
!= B_NO_ERROR
) {
319 /* TODO: that's bad, raise an exception */
324 int PyThread_down_sema( PyThread_type_sema sema
, int waitflag
)
328 dprintf(("PyThread_down_sema(%p, %d) called\n", sema
, waitflag
));
331 retval
= acquire_sem( (sem_id
)sema
);
333 retval
= acquire_sem_etc( (sem_id
)sema
, 1, B_TIMEOUT
, 0 );
336 if( retval
!= B_NO_ERROR
) {
337 /* TODO: that's bad, raise an exception */
341 dprintf(("PyThread_down_sema(%p) return\n", sema
));
345 void PyThread_up_sema( PyThread_type_sema sema
)
349 dprintf(("PyThread_up_sema(%p)\n", sema
));
351 retval
= release_sem( (sem_id
)sema
);
352 if( retval
!= B_NO_ERROR
) {
353 /* TODO: that's bad, raise an exception */