mthread_posix.c
Go to the documentation of this file.
00001 #if PTHREAD
00002 #include "eus.h"
00003 #define ESUCCESS 0
00004 
00005 /*
00006  * Most functions in thread library of Solaris2 return Zero on success.
00007  */
00008 
00009 /* thread function for POSIX Thread */
00010 struct {
00011     int using;
00012     thread_t tid;
00013 } thread_table[MAXTHREAD];
00014 
00015 unsigned int thr_self()
00016 {
00017     int i;
00018     thread_t tid;
00019 
00020     tid = pthread_self();
00021     for( i = 0; i < MAXTHREAD && !pthread_equal(thread_table[i].tid,tid); i++ )
00022       ;
00023 
00024     return( i );
00025 }
00026 
00027 int thr_getprio( int tid, int *prio )
00028 {
00029     int policy,err;
00030     struct  sched_param param;
00031     err = pthread_getschedparam( thread_table[tid].tid, &policy, &param );
00032     if (err == 0){
00033       *prio = param.sched_priority;
00034       return ESUCCESS;
00035     }else
00036       return errno;
00037 }
00038 
00039 int thr_setprio(int tid, int prio)
00040 {
00041     int err;
00042     struct  sched_param param;
00043     param.sched_priority = prio;
00044     err = pthread_setschedparam( thread_table[tid].tid, SCHED_RR, &param );
00045     if (err == 0)
00046       return ESUCCESS;
00047     else
00048       return errno;
00049 }
00050 
00051 struct thr_arg {
00052     int tid;
00053     void (*func)();
00054     void *args;
00055 };
00056 
00057 static void thr_cleanup( struct thr_arg *arg )
00058 {
00059     thread_table[arg->tid].using = 0;
00060 
00061     free(arg);
00062 }
00063 
00064 static int thr_create_lock=0;
00065 
00066 static void thr_startup( struct thr_arg *arg )
00067 {
00068     //if (debug) printf( "thr_startup:tid=%d\n", arg->tid ); 
00069     /* this line causes SEGMENTATION FAULT, but why? R.Hanai */
00070 
00071   pthread_cleanup_push((void(*)(void *))thr_cleanup, arg );
00072     if( !thread_table[arg->tid].tid ) 
00073       thread_table[arg->tid].tid = pthread_self(); /* R.Hanai */
00074 
00075 /*  Linuxthread is not supported */
00076 #if !Linux && !Cygwin
00077     pthread_setcancel( CANCEL_ON );
00078     pthread_setasynccancel( CANCEL_ON );
00079 #endif
00080     while(thr_create_lock) usleep(1000);
00081     (arg->func)( arg->args );
00082 
00083     pthread_cleanup_pop( 1 );
00084 }
00085 
00086 int thr_create(void *base, size_t size, void (*func)(void *), void *args, long flags, int *tid )
00087 /* base is not used */
00088 /* size is not implemented */
00089 /* flags is not used */
00090 {
00091     int i, stat;
00092     struct thr_arg *arg;
00093 
00094     for( i = 0; i < MAXTHREAD && thread_table[i].using; i++ )
00095       ;
00096     if( i >= MAXTHREAD )
00097       return -1;
00098 
00099     if( (arg = (struct thr_arg *)malloc( sizeof(struct thr_arg) )) == NULL )
00100       return -1;
00101 
00102     arg->tid = i;
00103     arg->func = func;
00104     arg->args = args;
00105     thr_create_lock=1;
00106     stat = pthread_create( &thread_table[i].tid, NULL, (void*(*)(void *))thr_startup, arg );
00107     if( stat == 0 )
00108       thread_table[i].using = 1;
00109     *tid = i;
00110     thr_create_lock=0;
00111     return( stat );
00112 }
00113 
00114 #if Linux
00115 #include <signal.h>
00116 /*
00117    thr_suspend() and thr_continue() are not implemented.
00118    these routines are only defined to avoid prototype definition error.
00119  */
00120 pthread_mutex_t susp_the_mutex = PTHREAD_MUTEX_INITIALIZER;
00121 pthread_mutex_t susp_mut = PTHREAD_MUTEX_INITIALIZER;
00122 volatile int susp_sentinel = 0;
00123 pthread_once_t susp_once = PTHREAD_ONCE_INIT;
00124 pthread_t susp_null_pthread = {0};
00125 pthread_t susp_array[MAXTHREAD]; 
00126 int susp_bottom = MAXTHREAD;
00127 int susp_inited = 0;
00128 
00129 /*
00130  * Handle SIGUSR1 in the target thread, to suspend it until
00131  * receiving SIGUSR2 (resume).
00132  */
00133 void
00134 suspend_signal_handler (int sig)
00135 {
00136     sigset_t signal_set;
00137 
00138     /*
00139      * Block all signals except SIGUSR2 while suspended.
00140      */
00141     sigfillset (&signal_set);
00142     sigdelset (&signal_set, SIGUSR2);
00143     susp_sentinel = 1;
00144     sigsuspend (&signal_set);
00145 
00146     /*
00147      * Once I'm here, I've been resumed, and the resume signal
00148      * handler has been run to completion.
00149      */
00150     return;
00151 }
00152 
00153 /*
00154  * Handle SIGUSR2 in the target thread, to resume it. Note that
00155  * the signal handler does nothing. It exists only because we need
00156  * to cause sigsuspend() to return.
00157  */
00158 void
00159 resume_signal_handler (int sig)
00160 {
00161     return;
00162 }
00163 
00164 /*
00165  * Dynamically initialize the "suspend package" when first used
00166  * (called by pthread_once).
00167  */
00168 void
00169 suspend_init_routine (void)
00170 {
00171     int status;
00172     struct sigaction sigusr1, sigusr2;
00173 
00174     /*
00175      * Allocate the suspended threads array. This array is used
00176      * to guarentee idempotency
00177      */
00178     //susp_bottom = 10;
00179 //    susp_array = (pthread_t*) calloc (susp_bottom, sizeof (pthread_t));
00180 
00181     /*
00182      * Install the signal handlers for suspend/resume.
00183      */
00184     sigusr1.sa_flags = 0;
00185     sigusr1.sa_handler = suspend_signal_handler;
00186 
00187     sigemptyset (&sigusr1.sa_mask);
00188     sigusr2.sa_flags = 0;
00189     sigusr2.sa_handler = resume_signal_handler;
00190     sigusr2.sa_mask = sigusr1.sa_mask;
00191 
00192     status = sigaction (SIGUSR1, &sigusr1, NULL);
00193     if (status == -1)
00194       {fprintf (stderr, "Installing suspend handler: %s\n", strerror(errno)); abort();}
00195     
00196     status = sigaction (SIGUSR2, &sigusr2, NULL);
00197     if (status == -1)
00198       {fprintf (stderr, "Installing resume handler : %s\n", strerror(errno)); abort(); }
00199     
00200     susp_inited = 1;
00201     return;
00202 }
00203 
00204 /*
00205  * Suspend a thread by sending it a signal (SIGUSR1), which will
00206  * block the thread until another signal (SIGUSR2) arrives.
00207  *
00208  * Multiple calls to thd_suspend for a single thread have no
00209  * additional effect on the thread -- a single thd_continue
00210  * call will cause it to resume execution.
00211  */
00212 int 
00213 //thd_suspend (pthread_t target_thread)
00214 pthread_suspend (pthread_t target_thread)
00215 {
00216     int status;
00217     int i = 0;
00218 
00219     /*
00220      * The first call to thd_suspend will initialize the
00221      * package.
00222      */
00223     status = pthread_once (&susp_once, suspend_init_routine);
00224     if (status != 0)
00225         return status;
00226 
00227     /* 
00228      * Serialize access to suspend, makes life easier
00229      */
00230     status = pthread_mutex_lock (&susp_mut);
00231     if (status != 0)
00232         return status;
00233 
00234     /*
00235      * Threads that are suspended are added to the target_array;
00236      * a request to suspend a thread already listed in the array
00237      * is ignored. Sending a second SIGUSR1 would cause the
00238      * thread to re-suspend itself as soon as it is resumed.
00239      */
00240     while (i < susp_bottom) 
00241         if (susp_array[i++] == target_thread) {
00242             status = pthread_mutex_unlock (&susp_mut);
00243             return status;
00244         }
00245 
00246     /*
00247      * Ok, we really need to suspend this thread. So, lets find
00248      * the location in the array that we'll use. If we run off
00249      * the end, realloc the array for more space.
00250      */
00251     i = 0;
00252     while (susp_array[i] != 0)
00253         i++;
00254 
00255     if (i == susp_bottom) {
00256 //        susp_array = (pthread_t*) realloc (
00257 //            susp_array, (++susp_bottom * sizeof (pthread_t)));
00258 //        if (susp_array == NULL) {
00259             pthread_mutex_unlock (&susp_mut);
00260             return errno;
00261 //        }
00262 
00263 //        susp_array[susp_bottom] = susp_null_pthread;   /* Clear new entry */
00264     }
00265 
00266     /*
00267      * Clear the sentinel and signal the thread to suspend.
00268      */
00269     susp_sentinel = 0;
00270     status = pthread_kill (target_thread, SIGUSR1);
00271     if (status != 0) {
00272         pthread_mutex_unlock (&susp_mut);
00273         return status;
00274     }
00275 
00276     /*
00277      * Wait for the sentinel to change.
00278      */
00279     while (susp_sentinel == 0)
00280         sched_yield ();
00281     
00282     susp_array[i] = target_thread;
00283 
00284     status = pthread_mutex_unlock (&susp_mut);
00285     return status;
00286 }
00287 
00288 /*
00289  * Resume a suspended thread by sending it SIGUSR2 to break
00290  * it out of the sigsuspend() in which it's waiting. If the
00291  * target thread isn't suspended, return with success.
00292  */
00293 int 
00294 //thd_continue (pthread_t target_thread)
00295 pthread_continue (pthread_t target_thread)
00296 {
00297     int status;
00298     int i = 0;
00299     /* 
00300      * Serialize access to suspend, makes life easier
00301      */
00302     status = pthread_mutex_lock (&susp_mut);
00303     if (status != 0)
00304         return status;
00305 
00306     /*
00307      * If we haven't been initialized, then the thread must be "resumed"
00308      * it couldn't have been suspended!
00309      */
00310     if (!susp_inited) {
00311         status = pthread_mutex_unlock (&susp_mut);
00312         return status;
00313     }
00314 
00315     /*
00316      * Make sure the thread is in the suspend array. If not, it
00317      * hasn't been suspended (or it has already been resumed) and
00318      * we can just carry on.
00319      */
00320     while (susp_array[i] != target_thread && i < susp_bottom) 
00321         i++;
00322 
00323     if (i >= susp_bottom) {
00324         pthread_mutex_unlock (&susp_mut);
00325         return 0;
00326     }
00327 
00328     /*
00329      * Signal the thread to continue, and remove the thread from
00330      * the suspended array.
00331      */
00332     status = pthread_kill (target_thread, SIGUSR2);
00333     if (status != 0) {
00334         pthread_mutex_unlock (&susp_mut);
00335         return status;
00336     }
00337 
00338     susp_array[i] = 0;               /* Clear array element */
00339     status = pthread_mutex_unlock (&susp_mut);
00340     return status;
00341 }
00342 #endif
00343 int thr_suspend( int tid ) { 
00344   return pthread_suspend ( thread_table[tid].tid );
00345 }
00346 
00347 int thr_continue( int tid ) {
00348   return pthread_continue ( thread_table[tid].tid );
00349 }
00350 
00351 
00352 int thr_kill( int tid, int sig )
00353 /* sig is not used */
00354 {
00355     if( pthread_cancel( thread_table[tid].tid ) < 0 )
00356       return errno;
00357     else
00358       return ESUCCESS;
00359 }
00360 
00361 /* readers/writer lock functions for PISIX Thread */
00362 int rwlock_init(rwlock_t *rwlp, int type, void *arg)
00363 {
00364     pthread_mutex_init(&(rwlp->lock), NULL);
00365     pthread_cond_init(&(rwlp->r_cond), NULL);
00366     pthread_cond_init(&(rwlp->w_cond), NULL);
00367 
00368     rwlp->readers = 0;
00369 
00370     return 0;
00371 }
00372 
00373 int rwlock_destroy( rwlock_t *rwlp )
00374 {
00375     pthread_mutex_destroy( &(rwlp->lock) );
00376     pthread_cond_destroy( &(rwlp->r_cond) );
00377     pthread_cond_destroy( &(rwlp->w_cond) );
00378 
00379     return 0;
00380 }
00381 
00382 int rw_rdlock( rwlock_t *rwlp )
00383 {
00384     pthread_mutex_lock( &(rwlp->lock) );
00385     while( rwlp->readers == -1 )
00386       pthread_cond_wait( &(rwlp->r_cond), &(rwlp->lock) );
00387     rwlp->readers++;
00388     pthread_mutex_unlock( &(rwlp->lock) );
00389 
00390     return 0;
00391 }
00392 
00393 int rw_wrlock( rwlock_t *rwlp )
00394 {
00395     pthread_mutex_lock( &(rwlp->lock) );
00396     while( rwlp->readers != 0 )
00397       pthread_cond_wait( &(rwlp->w_cond), &(rwlp->lock) );
00398     rwlp->readers=-1;
00399     pthread_mutex_unlock( &(rwlp->lock) );
00400 
00401     return 0;
00402 }
00403 
00404 int rw_unlock( rwlock_t *rwlp )
00405 {
00406     pthread_mutex_lock( &(rwlp->lock) );
00407     if( rwlp->readers == -1 )
00408       rwlp->readers = 0;
00409     else
00410       rwlp->readers--;
00411     pthread_cond_broadcast( &(rwlp->w_cond) );
00412     pthread_cond_broadcast( &(rwlp->r_cond) );
00413     pthread_mutex_unlock( &(rwlp->lock) );
00414 
00415     return 0;
00416 }
00417 
00418 /* semaphore function for POSIX Thread */
00419 int sema_init(sema_t *sem, unsigned int c, int d, void *e)
00420 /* c is not used */
00421 /* d is not used */
00422 /* e is not used */
00423 {
00424   pthread_mutex_init(&(sem->lock), NULL);
00425   pthread_cond_init(&(sem->cond), NULL);
00426   sem->count = 0;
00427 
00428     return 0;
00429 }
00430 
00431 int sema_destroy(sema_t *sem)
00432 {
00433   pthread_mutex_destroy(&(sem->lock));
00434   pthread_cond_destroy(&(sem->cond));
00435 
00436     return 0;
00437 }
00438 
00439 int sema_wait(sema_t *sem)
00440 {
00441   pthread_mutex_lock(&(sem->lock));
00442   while (sem->count == 0){
00443     pthread_cond_wait(&(sem->cond), &(sem->lock));}
00444   sem->count--;
00445   pthread_mutex_unlock(&(sem->lock));
00446 
00447     return 0;
00448 }
00449 
00450 int sema_trywait(sema_t *sem)
00451 {
00452   int ret;
00453   pthread_mutex_lock(&(sem->lock));
00454   if (sem->count == 0)
00455     ret = EBUSY;
00456   else{
00457     sem->count--;
00458     ret = 0;
00459   }
00460   pthread_mutex_unlock(&(sem->lock));
00461   return (ret);
00462 }
00463   
00464 int sema_post(sema_t *sem)
00465 {
00466   pthread_mutex_lock(&(sem->lock));
00467   sem->count++;
00468   pthread_cond_broadcast(&(sem->cond));
00469   pthread_mutex_unlock(&(sem->lock));
00470 
00471     return 0;
00472 }
00473 
00474 
00475 void mthread_init( context *mainctx )
00476 {
00477     int i;
00478     pthread_t tid;
00479 
00480     for( i = 0; i < MAXTHREAD; i++ )
00481       thread_table[i].using = 0;
00482 
00483     thread_table[0].tid = pthread_self();
00484     thread_table[0].using = 1;
00485 
00486     pthread_mutex_init(&mark_lock, NULL);
00487     pthread_mutex_init(&alloc_lock, NULL);
00488     pthread_mutex_init(&free_thread_lock, NULL);
00489     pthread_mutex_init(&qthread_lock, NULL);
00490     pthread_mutex_init(&qsort_lock, NULL);
00491     
00492     sema_init(&free_thread_sem, 0, 0, 0);
00493     rwlock_init(&gc_lock, 0, 0);
00494 }
00495 
00496 
00497 #endif


euslisp
Author(s): Toshihiro Matsui
autogenerated on Thu Mar 9 2017 04:57:50