Threads.linux.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. /*--------- threads support ------------------------- g.f. -----*/
  2. /*--------- lower half of the Oberon Threads module */
  3. #include <unistd.h>
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <limits.h>
  7. #include <signal.h>
  8. #include <semaphore.h>
  9. #include <errno.h>
  10. #include <bits/local_lim.h>
  11. #include "Threads.h"
  12. extern int suid_root;
  13. extern int debug;
  14. extern void SetSigaltstack();
  15. static o_thr_t mainthread = 0;
  16. static struct sched_param oldparam;
  17. static int oldpolicy;
  18. #define T_SIGSUSPEND SIGUSR1
  19. #define T_SIGRESUME SIGUSR2
  20. static struct sigaction sasuspend, saresume;
  21. static pthread_mutex_t suspend_mutex;
  22. static int suspend_done;
  23. static int resume_done;
  24. void
  25. o_thrSleep(int ms) {
  26. struct timespec sltime, rem;
  27. sltime.tv_sec = ms/1000;
  28. sltime.tv_nsec = 1000000*(ms%1000);
  29. while (nanosleep( &sltime, &rem ) < 0 && errno == EINTR)
  30. sltime = rem;
  31. }
  32. o_mtx_t
  33. o_mtxInit(int dummy) {
  34. o_mtx_t mtx;
  35. mtx = (o_mtx_t)malloc( sizeof(pthread_mutex_t) );
  36. pthread_mutex_init( mtx, NULL );
  37. return mtx;
  38. }
  39. void
  40. o_mtxDestroy(o_mtx_t mtx) {
  41. (void)pthread_mutex_destroy( mtx );
  42. free( mtx );
  43. }
  44. void
  45. o_mtxLock(o_mtx_t mtx) {
  46. (void)pthread_mutex_lock( mtx );
  47. }
  48. void
  49. o_mtxUnlock(o_mtx_t mtx) {
  50. (void)pthread_mutex_unlock( mtx );
  51. }
  52. o_con_t
  53. o_conInit(int dymmy) {
  54. o_con_t c;
  55. c = (o_con_t)malloc( sizeof(pthread_cond_t) );
  56. pthread_cond_init( c, NULL );
  57. return c;
  58. }
  59. void
  60. o_conDestroy(o_con_t c) {
  61. pthread_cond_destroy( c );
  62. free( c );
  63. }
  64. void
  65. o_conWait( o_con_t c, o_mtx_t m ) {
  66. pthread_cond_wait( c, m );
  67. }
  68. void
  69. o_conSignal( o_con_t c ) {
  70. pthread_cond_signal( c );
  71. }
  72. static void *
  73. starter(void *p) {
  74. o_thr_t me = pthread_self();
  75. oberon_proc proc = (oberon_proc)p;
  76. sigset_t old, new;
  77. struct sched_param param;
  78. SetSigaltstack();
  79. sigfillset( &new );
  80. sigdelset( &new, SIGILL );
  81. sigdelset( &new, SIGTRAP );
  82. sigdelset( &new, SIGFPE );
  83. sigdelset( &new, SIGBUS );
  84. sigdelset( &new, SIGSEGV );
  85. sigdelset( &new, SIGTERM );
  86. sigdelset( &new, T_SIGSUSPEND );
  87. //sigdelset( &new, T_SIGRESUME );
  88. pthread_sigmask( SIG_SETMASK, &new, &old );
  89. pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, NULL );
  90. pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NULL );
  91. param.sched_priority = 0;
  92. pthread_setschedparam( me, SCHED_OTHER, &param );
  93. proc();
  94. pthread_exit( NULL );
  95. return NULL;
  96. }
  97. o_thr_t
  98. o_thrStart( oberon_proc p, int len ) {
  99. o_thr_t id;
  100. pthread_attr_t attr;
  101. if (len < PTHREAD_STACK_MIN) len = PTHREAD_STACK_MIN;
  102. pthread_attr_init( &attr );
  103. pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
  104. pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );
  105. pthread_attr_setstacksize( &attr, len );
  106. if (pthread_create( &id, &attr, starter, p ) != 0) return 0;
  107. return id;
  108. }
  109. o_thr_t
  110. o_thrThis(int dummy) {
  111. return pthread_self();
  112. }
  113. void
  114. o_thrYield(int dummy) {
  115. o_thrSleep( 1 );
  116. }
  117. void
  118. o_thrExit(int dummy) {
  119. pthread_exit( 0 );
  120. }
  121. void
  122. o_thrSuspend(o_thr_t thr) {
  123. pthread_mutex_lock( &suspend_mutex );
  124. suspend_done = 0;
  125. pthread_kill( thr, T_SIGSUSPEND );
  126. while (suspend_done != 1) o_thrSleep( 1 );
  127. pthread_mutex_unlock( &suspend_mutex );
  128. }
  129. static void
  130. suspend_handler(int sig) {
  131. sigset_t block;
  132. sigfillset( &block );
  133. sigdelset( &block, T_SIGRESUME );
  134. suspend_done = 1;
  135. sigsuspend( &block ); /* await T_SIGRESUME */
  136. resume_done = 1;
  137. }
  138. static void
  139. resume_handler(int sig) {
  140. }
  141. void
  142. o_thrResume(o_thr_t thr) {
  143. int n;
  144. pthread_mutex_lock( &suspend_mutex );
  145. resume_done = 0; n = 1;
  146. pthread_kill( thr, T_SIGRESUME );
  147. while (resume_done != 1 && n < 50) { o_thrSleep( 1 ); n++; }
  148. pthread_mutex_unlock( &suspend_mutex );
  149. }
  150. void
  151. o_thrSetprio(o_thr_t thr, int prio) {
  152. struct sched_param param;
  153. int policy;
  154. pthread_getschedparam( thr, &policy, &param );
  155. param.sched_priority = prio;
  156. if (pthread_setschedparam( thr, SCHED_OTHER, &param ) != 0)
  157. perror("pthread_setschedparam");
  158. }
  159. int
  160. o_thrGetprio(o_thr_t thr) {
  161. struct sched_param param;
  162. int policy;
  163. pthread_getschedparam( thr, &policy, &param );
  164. return ( param.sched_priority );
  165. }
  166. void
  167. o_thrKill(o_thr_t thr, int sig) {
  168. pthread_kill( thr, sig );
  169. /* if (thr != mainthread) {
  170. pthread_detach( thr );
  171. if (thr == pthread_self())
  172. pthread_exit( 0 );
  173. else {
  174. pthread_cancel( thr );
  175. }
  176. } */
  177. }
  178. int
  179. o_thrInitialize( int *low, int* high ) {
  180. struct sched_param param;
  181. pthread_mutex_init( &suspend_mutex, NULL );
  182. mainthread = pthread_self();
  183. *high = sched_get_priority_max(SCHED_OTHER);
  184. *low = sched_get_priority_min(SCHED_OTHER);
  185. param.sched_priority = *high;
  186. pthread_setschedparam( mainthread, SCHED_OTHER, &param );
  187. sigemptyset( &sasuspend.sa_mask );
  188. sigaddset( &sasuspend.sa_mask, T_SIGRESUME );
  189. sasuspend.sa_flags = 0;
  190. sasuspend.sa_handler = suspend_handler;
  191. sigaction( T_SIGSUSPEND, &sasuspend, NULL );
  192. sigemptyset( &saresume.sa_mask );
  193. saresume.sa_flags = 0;
  194. saresume.sa_handler = resume_handler;
  195. sigaction( T_SIGRESUME, &saresume, NULL );
  196. return 1;
  197. }