threads.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. #include <brl.mod/blitz.mod/blitz.h>
  2. //***** Threads *****
  3. BBThread *threads_CreateThread( BBThreadProc entry,BBObject *data ){
  4. BBThread *thread=bbThreadCreate( entry,data );
  5. bbThreadResume( thread );
  6. return thread;
  7. }
  8. void threads_DetachThread( BBThread *thread ){
  9. bbThreadDetach( thread );
  10. }
  11. BBObject *threads_WaitThread( BBThread *thread ){
  12. return bbThreadWait( thread );
  13. }
  14. //***** Mutexes *****
  15. bb_mutex_t *threads_CreateMutex(){
  16. bb_mutex_t *mutex=malloc( sizeof(bb_mutex_t) );
  17. if( bb_mutex_init( mutex ) ) return mutex;
  18. free( mutex );
  19. return 0;
  20. }
  21. void threads_CloseMutex( bb_mutex_t *mutex ){
  22. bb_mutex_destroy( mutex );
  23. free( mutex );
  24. }
  25. void threads_LockMutex( bb_mutex_t *mutex ){
  26. bb_mutex_lock( mutex );
  27. }
  28. void threads_UnlockMutex( bb_mutex_t *mutex ){
  29. bb_mutex_unlock( mutex );
  30. }
  31. int threads_TryLockMutex( bb_mutex_t *mutex ){
  32. return bb_mutex_trylock( mutex );
  33. }
  34. //***** Semaphores *****
  35. #ifndef __APPLE__
  36. bb_sem_t *threads_CreateSemaphore( int count ){
  37. bb_sem_t *sem=malloc( sizeof(bb_sem_t) );
  38. if( bb_sem_init( sem,count ) ) return sem;
  39. free( sem );
  40. return 0;
  41. }
  42. void threads_CloseSemaphore( bb_sem_t *sem ){
  43. bb_sem_destroy( sem );
  44. free( sem );
  45. }
  46. void threads_WaitSemaphore( bb_sem_t *sem ){
  47. bb_sem_wait( sem );
  48. }
  49. void threads_PostSemaphore( bb_sem_t *sem ){
  50. bb_sem_post( sem );
  51. }
  52. #endif
  53. //***** CondVars *****
  54. #ifdef _WIN32
  55. int threads_TimedWaitSemaphore( bb_sem_t *sem, int millisecs ){
  56. int res = bb_sem_timed_wait( sem, millisecs );
  57. if (res == WAIT_TIMEOUT) {
  58. return 1;
  59. } else if (res == WAIT_FAILED) {
  60. return -1;
  61. }
  62. return 0;
  63. }
  64. typedef struct BBCond BBCond;
  65. struct BBCond{
  66. int waiters;
  67. bb_sem_t sema;
  68. };
  69. BBCond *threads_CreateCond(){
  70. BBCond *cond=(BBCond*)malloc( sizeof( BBCond ) );
  71. cond->waiters=0;
  72. bb_sem_init( &cond->sema,0 );
  73. return cond;
  74. }
  75. void threads_CloseCond( BBCond *cond ){
  76. bb_sem_destroy( &cond->sema );
  77. free( cond );
  78. }
  79. void threads_WaitCond( BBCond *cond,bb_mutex_t *mutex ){
  80. bbAtomicAdd( &cond->waiters,1 );
  81. //Ok, the below is not strictly speaking 'fair'.
  82. //A context switch below the mutex_unlock and sem_wait could end up
  83. //starving this thread (I think). Possibly not a problem unless app is
  84. //really thrashing, but should be fixed none-the-less.
  85. //
  86. bb_mutex_unlock( mutex );
  87. bb_sem_wait( &cond->sema );
  88. bb_mutex_lock( mutex );
  89. }
  90. int threads_TimedWaitCond( BBCond *cond,bb_mutex_t *mutex, int millisecs ){
  91. bbAtomicAdd( &cond->waiters,1 );
  92. //Ok, the below is not strictly speaking 'fair'.
  93. //A context switch below the mutex_unlock and sem_wait could end up
  94. //starving this thread (I think). Possibly not a problem unless app is
  95. //really thrashing, but should be fixed none-the-less.
  96. //
  97. bb_mutex_unlock( mutex );
  98. int res = bb_sem_timed_wait( &cond->sema, millisecs );
  99. bb_mutex_lock( mutex );
  100. if (res == WAIT_TIMEOUT) {
  101. return 1;
  102. } else if (res == WAIT_FAILED) {
  103. return -1;
  104. }
  105. return 0;
  106. }
  107. void threads_SignalCond( BBCond *cond ){
  108. int waiters;
  109. while( waiters=cond->waiters ){
  110. if( bbAtomicCAS( &cond->waiters,waiters,waiters-1 ) ){
  111. bb_sem_post( &cond->sema );
  112. return;
  113. }
  114. }
  115. }
  116. void threads_BroadcastCond( BBCond *cond ){
  117. int waiters;
  118. while( waiters=cond->waiters ){
  119. if( bbAtomicCAS( &cond->waiters,waiters,0 ) ){
  120. while( waiters-- ){
  121. bb_sem_post( &cond->sema );
  122. }
  123. return;
  124. }
  125. }
  126. }
  127. #elif __SWITCH__
  128. cnd_t *threads_CreateCond(){
  129. cnd_t *cond=malloc( sizeof(cnd_t) );
  130. if( cnd_init( cond )==thrd_success ) return cond;
  131. free( cond );
  132. return 0;
  133. }
  134. void threads_CloseCond( cnd_t *cond ){
  135. free( cond );
  136. }
  137. void threads_WaitCond( cnd_t *cond,bb_mutex_t *mutex ){
  138. cnd_wait( cond,mutex );
  139. }
  140. void threads_SignalCond( cnd_t *cond ){
  141. cnd_signal( cond );
  142. }
  143. void threads_BroadcastCond( cnd_t *cond ){
  144. cnd_broadcast( cond );
  145. }
  146. #else
  147. #include <errno.h>
  148. pthread_cond_t *threads_CreateCond(){
  149. pthread_cond_t *cond=malloc( sizeof( pthread_cond_t ) );
  150. if( pthread_cond_init( cond,0 )>=0 ) return cond;
  151. free( cond );
  152. return 0;
  153. }
  154. void threads_CloseCond( pthread_cond_t *cond ){
  155. pthread_cond_destroy( cond );
  156. free( cond );
  157. }
  158. void threads_WaitCond( pthread_cond_t *cond,bb_mutex_t *mutex ){
  159. pthread_cond_wait( cond,mutex );
  160. }
  161. void threads_SignalCond( pthread_cond_t *cond ){
  162. pthread_cond_signal( cond );
  163. }
  164. void threads_BroadcastCond( pthread_cond_t *cond ){
  165. pthread_cond_broadcast( cond );
  166. }
  167. int threads_TimedWaitCond(pthread_cond_t *cond,bb_mutex_t *mutex, int millisecs) {
  168. struct timespec ts;
  169. if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
  170. return -1;
  171. }
  172. ts.tv_sec += millisecs / 1000;
  173. BBInt64 nsec = ts.tv_nsec + ((millisecs % 1000) * 1000000L);
  174. if (nsec <= 999999999L) {
  175. ts.tv_nsec = nsec;
  176. } else {
  177. ts.tv_sec += 1;
  178. ts.tv_nsec = nsec - 999999999L;
  179. }
  180. int res = pthread_cond_timedwait(cond, mutex, &ts);
  181. if (res == 0) {
  182. return 0;
  183. } else if (res == ETIMEDOUT) {
  184. return 1;
  185. }
  186. return -1;
  187. }
  188. #endif
  189. #if __linux__ || __HAIKU__
  190. int threads_TimedWaitSemaphore( bb_sem_t *sem, int millisecs ){
  191. struct timespec ts;
  192. if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
  193. return -1;
  194. }
  195. ts.tv_sec += millisecs / 1000;
  196. ts.tv_nsec += (millisecs % 1000) * 1000000L;
  197. int res = sem_timedwait(sem, &ts);
  198. if (res == 0) {
  199. return 0;
  200. } else if (res == ETIMEDOUT) {
  201. return 1;
  202. }
  203. return -1;
  204. }
  205. #endif