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 */