mthread_posix.c
Go to the documentation of this file.
1 #if PTHREAD
2 #include "eus.h"
3 #define ESUCCESS 0
4 
5 /*
6  * Most functions in thread library of Solaris2 return Zero on success.
7  */
8 
9 /* thread function for POSIX Thread */
10 struct {
11  int using;
12  thread_t tid;
13 } thread_table[MAXTHREAD];
14 
15 unsigned int thr_self()
16 {
17  int i;
18  thread_t tid;
19 
20  tid = pthread_self();
21  for( i = 0; i < MAXTHREAD && !pthread_equal(thread_table[i].tid,tid); i++ )
22  ;
23 
24  return( i );
25 }
26 
27 int thr_getprio( int tid, int *prio )
28 {
29  int policy,err;
30  struct sched_param param;
31  err = pthread_getschedparam( thread_table[tid].tid, &policy, &param );
32  if (err == 0){
33  *prio = param.sched_priority;
34  return ESUCCESS;
35  }else
36  return errno;
37 }
38 
39 int thr_setprio(int tid, int prio)
40 {
41  int err;
42  struct sched_param param;
43  param.sched_priority = prio;
44  err = pthread_setschedparam( thread_table[tid].tid, SCHED_RR, &param );
45  if (err == 0)
46  return ESUCCESS;
47  else
48  return errno;
49 }
50 
51 struct thr_arg {
52  int tid;
53  void (*func)();
54  void *args;
55 };
56 
57 static void thr_cleanup( struct thr_arg *arg )
58 {
59  thread_table[arg->tid].using = 0;
60 
61  free(arg);
62 }
63 
64 static int thr_create_lock=0;
65 
66 static void thr_startup( struct thr_arg *arg )
67 {
68  //if (debug) printf( "thr_startup:tid=%d\n", arg->tid );
69  /* this line causes SEGMENTATION FAULT, but why? R.Hanai */
70 
71  pthread_cleanup_push((void(*)(void *))thr_cleanup, arg );
72  if( !thread_table[arg->tid].tid )
73  thread_table[arg->tid].tid = pthread_self(); /* R.Hanai */
74 
75 /* Linuxthread is not supported */
76 #if !Linux && !Cygwin
77  pthread_setcancel( CANCEL_ON );
78  pthread_setasynccancel( CANCEL_ON );
79 #endif
80  while(thr_create_lock) usleep(1000);
81  (arg->func)( arg->args );
82 
83  pthread_cleanup_pop( 1 );
84 }
85 
86 int thr_create(void *base, size_t size, void (*func)(void *), void *args, long flags, int *tid )
87 /* base is not used */
88 /* size is not implemented */
89 /* flags is not used */
90 {
91  int i, stat;
92  struct thr_arg *arg;
93 
94  for( i = 0; i < MAXTHREAD && thread_table[i].using; i++ )
95  ;
96  if( i >= MAXTHREAD )
97  return -1;
98 
99  if( (arg = (struct thr_arg *)malloc( sizeof(struct thr_arg) )) == NULL )
100  return -1;
101 
102  arg->tid = i;
103  arg->func = func;
104  arg->args = args;
105  thr_create_lock=1;
106  stat = pthread_create( &thread_table[i].tid, NULL, (void*(*)(void *))thr_startup, arg );
107  if( stat == 0 )
108  thread_table[i].using = 1;
109  *tid = i;
110  thr_create_lock=0;
111  return( stat );
112 }
113 
114 #if Linux
115 #include <signal.h>
116 /*
117  thr_suspend() and thr_continue() are not implemented.
118  these routines are only defined to avoid prototype definition error.
119  */
120 pthread_mutex_t susp_the_mutex = PTHREAD_MUTEX_INITIALIZER;
121 pthread_mutex_t susp_mut = PTHREAD_MUTEX_INITIALIZER;
122 volatile int susp_sentinel = 0;
123 pthread_once_t susp_once = PTHREAD_ONCE_INIT;
124 pthread_t susp_null_pthread = {0};
125 pthread_t susp_array[MAXTHREAD];
126 int susp_bottom = MAXTHREAD;
127 int susp_inited = 0;
128 
129 /*
130  * Handle SIGUSR1 in the target thread, to suspend it until
131  * receiving SIGUSR2 (resume).
132  */
133 void
134 suspend_signal_handler (int sig)
135 {
136  sigset_t signal_set;
137 
138  /*
139  * Block all signals except SIGUSR2 while suspended.
140  */
141  sigfillset (&signal_set);
142  sigdelset (&signal_set, SIGUSR2);
143  susp_sentinel = 1;
144  sigsuspend (&signal_set);
145 
146  /*
147  * Once I'm here, I've been resumed, and the resume signal
148  * handler has been run to completion.
149  */
150  return;
151 }
152 
153 /*
154  * Handle SIGUSR2 in the target thread, to resume it. Note that
155  * the signal handler does nothing. It exists only because we need
156  * to cause sigsuspend() to return.
157  */
158 void
159 resume_signal_handler (int sig)
160 {
161  return;
162 }
163 
164 /*
165  * Dynamically initialize the "suspend package" when first used
166  * (called by pthread_once).
167  */
168 void
169 suspend_init_routine (void)
170 {
171  int status;
172  struct sigaction sigusr1, sigusr2;
173 
174  /*
175  * Allocate the suspended threads array. This array is used
176  * to guarentee idempotency
177  */
178  //susp_bottom = 10;
179 // susp_array = (pthread_t*) calloc (susp_bottom, sizeof (pthread_t));
180 
181  /*
182  * Install the signal handlers for suspend/resume.
183  */
184  sigusr1.sa_flags = 0;
185  sigusr1.sa_handler = suspend_signal_handler;
186 
187  sigemptyset (&sigusr1.sa_mask);
188  sigusr2.sa_flags = 0;
189  sigusr2.sa_handler = resume_signal_handler;
190  sigusr2.sa_mask = sigusr1.sa_mask;
191 
192  status = sigaction (SIGUSR1, &sigusr1, NULL);
193  if (status == -1)
194  {fprintf (stderr, "Installing suspend handler: %s\n", strerror(errno)); abort();}
195 
196  status = sigaction (SIGUSR2, &sigusr2, NULL);
197  if (status == -1)
198  {fprintf (stderr, "Installing resume handler : %s\n", strerror(errno)); abort(); }
199 
200  susp_inited = 1;
201  return;
202 }
203 
204 /*
205  * Suspend a thread by sending it a signal (SIGUSR1), which will
206  * block the thread until another signal (SIGUSR2) arrives.
207  *
208  * Multiple calls to thd_suspend for a single thread have no
209  * additional effect on the thread -- a single thd_continue
210  * call will cause it to resume execution.
211  */
212 int
213 //thd_suspend (pthread_t target_thread)
214 pthread_suspend (pthread_t target_thread)
215 {
216  int status;
217  int i = 0;
218 
219  /*
220  * The first call to thd_suspend will initialize the
221  * package.
222  */
223  status = pthread_once (&susp_once, suspend_init_routine);
224  if (status != 0)
225  return status;
226 
227  /*
228  * Serialize access to suspend, makes life easier
229  */
230  status = pthread_mutex_lock (&susp_mut);
231  if (status != 0)
232  return status;
233 
234  /*
235  * Threads that are suspended are added to the target_array;
236  * a request to suspend a thread already listed in the array
237  * is ignored. Sending a second SIGUSR1 would cause the
238  * thread to re-suspend itself as soon as it is resumed.
239  */
240  while (i < susp_bottom)
241  if (susp_array[i++] == target_thread) {
242  status = pthread_mutex_unlock (&susp_mut);
243  return status;
244  }
245 
246  /*
247  * Ok, we really need to suspend this thread. So, lets find
248  * the location in the array that we'll use. If we run off
249  * the end, realloc the array for more space.
250  */
251  i = 0;
252  while (susp_array[i] != 0)
253  i++;
254 
255  if (i == susp_bottom) {
256 // susp_array = (pthread_t*) realloc (
257 // susp_array, (++susp_bottom * sizeof (pthread_t)));
258 // if (susp_array == NULL) {
259  pthread_mutex_unlock (&susp_mut);
260  return errno;
261 // }
262 
263 // susp_array[susp_bottom] = susp_null_pthread; /* Clear new entry */
264  }
265 
266  /*
267  * Clear the sentinel and signal the thread to suspend.
268  */
269  susp_sentinel = 0;
270  status = pthread_kill (target_thread, SIGUSR1);
271  if (status != 0) {
272  pthread_mutex_unlock (&susp_mut);
273  return status;
274  }
275 
276  /*
277  * Wait for the sentinel to change.
278  */
279  while (susp_sentinel == 0)
280  sched_yield ();
281 
282  susp_array[i] = target_thread;
283 
284  status = pthread_mutex_unlock (&susp_mut);
285  return status;
286 }
287 
288 /*
289  * Resume a suspended thread by sending it SIGUSR2 to break
290  * it out of the sigsuspend() in which it's waiting. If the
291  * target thread isn't suspended, return with success.
292  */
293 int
294 //thd_continue (pthread_t target_thread)
295 pthread_continue (pthread_t target_thread)
296 {
297  int status;
298  int i = 0;
299  /*
300  * Serialize access to suspend, makes life easier
301  */
302  status = pthread_mutex_lock (&susp_mut);
303  if (status != 0)
304  return status;
305 
306  /*
307  * If we haven't been initialized, then the thread must be "resumed"
308  * it couldn't have been suspended!
309  */
310  if (!susp_inited) {
311  status = pthread_mutex_unlock (&susp_mut);
312  return status;
313  }
314 
315  /*
316  * Make sure the thread is in the suspend array. If not, it
317  * hasn't been suspended (or it has already been resumed) and
318  * we can just carry on.
319  */
320  while (susp_array[i] != target_thread && i < susp_bottom)
321  i++;
322 
323  if (i >= susp_bottom) {
324  pthread_mutex_unlock (&susp_mut);
325  return 0;
326  }
327 
328  /*
329  * Signal the thread to continue, and remove the thread from
330  * the suspended array.
331  */
332  status = pthread_kill (target_thread, SIGUSR2);
333  if (status != 0) {
334  pthread_mutex_unlock (&susp_mut);
335  return status;
336  }
337 
338  susp_array[i] = 0; /* Clear array element */
339  status = pthread_mutex_unlock (&susp_mut);
340  return status;
341 }
342 #endif
343 int thr_suspend( int tid ) {
344  return pthread_suspend ( thread_table[tid].tid );
345 }
346 
347 int thr_continue( int tid ) {
348  return pthread_continue ( thread_table[tid].tid );
349 }
350 
351 
352 int thr_kill( int tid, int sig )
353 /* sig is not used */
354 {
355  if( pthread_cancel( thread_table[tid].tid ) < 0 )
356  return errno;
357  else
358  return ESUCCESS;
359 }
360 
361 /* readers/writer lock functions for PISIX Thread */
362 int rwlock_init(rwlock_t *rwlp, int type, void *arg)
363 {
364  pthread_mutex_init(&(rwlp->lock), NULL);
365  pthread_cond_init(&(rwlp->r_cond), NULL);
366  pthread_cond_init(&(rwlp->w_cond), NULL);
367 
368  rwlp->readers = 0;
369 
370  return 0;
371 }
372 
373 int rwlock_destroy( rwlock_t *rwlp )
374 {
375  pthread_mutex_destroy( &(rwlp->lock) );
376  pthread_cond_destroy( &(rwlp->r_cond) );
377  pthread_cond_destroy( &(rwlp->w_cond) );
378 
379  return 0;
380 }
381 
382 int rw_rdlock( rwlock_t *rwlp )
383 {
384  pthread_mutex_lock( &(rwlp->lock) );
385  while( rwlp->readers == -1 )
386  pthread_cond_wait( &(rwlp->r_cond), &(rwlp->lock) );
387  rwlp->readers++;
388  pthread_mutex_unlock( &(rwlp->lock) );
389 
390  return 0;
391 }
392 
393 int rw_wrlock( rwlock_t *rwlp )
394 {
395  pthread_mutex_lock( &(rwlp->lock) );
396  while( rwlp->readers != 0 )
397  pthread_cond_wait( &(rwlp->w_cond), &(rwlp->lock) );
398  rwlp->readers=-1;
399  pthread_mutex_unlock( &(rwlp->lock) );
400 
401  return 0;
402 }
403 
404 int rw_unlock( rwlock_t *rwlp )
405 {
406  pthread_mutex_lock( &(rwlp->lock) );
407  if( rwlp->readers == -1 )
408  rwlp->readers = 0;
409  else
410  rwlp->readers--;
411  pthread_cond_broadcast( &(rwlp->w_cond) );
412  pthread_cond_broadcast( &(rwlp->r_cond) );
413  pthread_mutex_unlock( &(rwlp->lock) );
414 
415  return 0;
416 }
417 
418 /* semaphore function for POSIX Thread */
419 int sema_init(sema_t *sem, unsigned int c, int d, void *e)
420 /* c is not used */
421 /* d is not used */
422 /* e is not used */
423 {
424  pthread_mutex_init(&(sem->lock), NULL);
425  pthread_cond_init(&(sem->cond), NULL);
426  sem->count = 0;
427 
428  return 0;
429 }
430 
431 int sema_destroy(sema_t *sem)
432 {
433  pthread_mutex_destroy(&(sem->lock));
434  pthread_cond_destroy(&(sem->cond));
435 
436  return 0;
437 }
438 
439 int sema_wait(sema_t *sem)
440 {
441  pthread_mutex_lock(&(sem->lock));
442  while (sem->count == 0){
443  pthread_cond_wait(&(sem->cond), &(sem->lock));}
444  sem->count--;
445  pthread_mutex_unlock(&(sem->lock));
446 
447  return 0;
448 }
449 
450 int sema_trywait(sema_t *sem)
451 {
452  int ret;
453  pthread_mutex_lock(&(sem->lock));
454  if (sem->count == 0)
455  ret = EBUSY;
456  else{
457  sem->count--;
458  ret = 0;
459  }
460  pthread_mutex_unlock(&(sem->lock));
461  return (ret);
462 }
463 
464 int sema_post(sema_t *sem)
465 {
466  pthread_mutex_lock(&(sem->lock));
467  sem->count++;
468  pthread_cond_broadcast(&(sem->cond));
469  pthread_mutex_unlock(&(sem->lock));
470 
471  return 0;
472 }
473 
474 
475 void mthread_init( context *mainctx )
476 {
477  int i;
478  pthread_t tid;
479 
480  for( i = 0; i < MAXTHREAD; i++ )
481  thread_table[i].using = 0;
482 
483  thread_table[0].tid = pthread_self();
484  thread_table[0].using = 1;
485 
486  pthread_mutex_init(&mark_lock, NULL);
487  pthread_mutex_init(&alloc_lock, NULL);
488  pthread_mutex_init(&free_thread_lock, NULL);
489  pthread_mutex_init(&qthread_lock, NULL);
490  pthread_mutex_init(&qsort_lock, NULL);
491 
492  sema_init(&free_thread_sem, 0, 0, 0);
493  rwlock_init(&gc_lock, 0, 0);
494 }
495 
496 
497 #endif
rwlock_t gc_lock
Definition: mthread.c:18
Definition: eus.h:522
int rwlock_destroy(rwlock_t *)
Definition: pthreads.c:172
int thr_continue(int)
Definition: pthreads.c:58
int thr_setprio(int, int)
Definition: pthreads.c:30
cond_t w_cond
Definition: eus_thr.h:105
int sema_init(sema_t *, unsigned int, int, void *)
Definition: pthreads.c:111
cond_t cond
Definition: eus_thr.h:99
context * mainctx
Definition: eus.c:57
mutex_t qthread_lock
Definition: mthread.c:14
unsigned int count
Definition: eus_thr.h:97
Definition: eus_thr.h:96
int thr_kill(int, int)
Definition: pthreads.c:70
int rwlock_init(rwlock_t *, int, void *)
Definition: pthreads.c:164
mutex_t mark_lock
Definition: mthread.c:25
thread_t tid
Definition: collector.c:50
int thr_suspend(int)
Definition: pthreads.c:64
int rw_wrlock(rwlock_t *)
Definition: pthreads.c:188
int sema_wait(sema_t *)
Definition: pthreads.c:124
mutex_t free_thread_lock
Definition: mthread.c:13
static void abort(int sig)
struct @10 thread_table[]
cond_t r_cond
Definition: eus_thr.h:104
int sema_destroy(sema_t *)
Definition: pthreads.c:118
int thr_create(void *, size_t, void(*)(), void *, long, int *)
Definition: pthreads.c:43
int rw_rdlock(rwlock_t *)
Definition: pthreads.c:179
int sema_trywait(sema_t *)
Definition: pthreads.c:133
sema_t free_thread_sem
Definition: mthread.c:11
mutex_t qsort_lock
Definition: mthread.c:21
int rw_unlock(rwlock_t *)
Definition: pthreads.c:197
int thr_getprio(int tid, int *prio)
Definition: pthreads.c:21
unsigned int readers
Definition: eus_thr.h:102
#define NULL
Definition: transargv.c:8
int errno
int sema_post(sema_t *sem)
Definition: pthreads.c:148
unsigned int thr_self()
Definition: eus.c:25
mutex_t lock
Definition: eus_thr.h:98
mutex_t lock
Definition: eus_thr.h:103
mutex_t alloc_lock
Definition: memory.mutex.c:42


euslisp
Author(s): Toshihiro Matsui
autogenerated on Fri Feb 21 2020 03:20:54