Ruby  1.9.3p385(2013-02-06revision39114)
thread.c
Go to the documentation of this file.
00001 /**********************************************************************
00002 
00003   thread.c -
00004 
00005   $Author: usa $
00006 
00007   Copyright (C) 2004-2007 Koichi Sasada
00008 
00009 **********************************************************************/
00010 
00011 /*
00012   YARV Thread Design
00013 
00014   model 1: Userlevel Thread
00015     Same as traditional ruby thread.
00016 
00017   model 2: Native Thread with Global VM lock
00018     Using pthread (or Windows thread) and Ruby threads run concurrent.
00019 
00020   model 3: Native Thread with fine grain lock
00021     Using pthread and Ruby threads run concurrent or parallel.
00022 
00023 ------------------------------------------------------------------------
00024 
00025   model 2:
00026     A thread has mutex (GVL: Global VM Lock or Giant VM Lock) can run.
00027     When thread scheduling, running thread release GVL.  If running thread
00028     try blocking operation, this thread must release GVL and another
00029     thread can continue this flow.  After blocking operation, thread
00030     must check interrupt (RUBY_VM_CHECK_INTS).
00031 
00032     Every VM can run parallel.
00033 
00034     Ruby threads are scheduled by OS thread scheduler.
00035 
00036 ------------------------------------------------------------------------
00037 
00038   model 3:
00039     Every threads run concurrent or parallel and to access shared object
00040     exclusive access control is needed.  For example, to access String
00041     object or Array object, fine grain lock must be locked every time.
00042  */
00043 
00044 
00045 /* for model 2 */
00046 
00047 #include "eval_intern.h"
00048 #include "gc.h"
00049 #include "internal.h"
00050 #include "ruby/io.h"
00051 
00052 #ifndef USE_NATIVE_THREAD_PRIORITY
00053 #define USE_NATIVE_THREAD_PRIORITY 0
00054 #define RUBY_THREAD_PRIORITY_MAX 3
00055 #define RUBY_THREAD_PRIORITY_MIN -3
00056 #endif
00057 
00058 #ifndef THREAD_DEBUG
00059 #define THREAD_DEBUG 0
00060 #endif
00061 
00062 VALUE rb_cMutex;
00063 VALUE rb_cBarrier;
00064 
00065 static void sleep_timeval(rb_thread_t *th, struct timeval time);
00066 static void sleep_wait_for_interrupt(rb_thread_t *th, double sleepsec);
00067 static void sleep_forever(rb_thread_t *th, int nodeadlock);
00068 static double timeofday(void);
00069 static int rb_threadptr_dead(rb_thread_t *th);
00070 
00071 static void rb_check_deadlock(rb_vm_t *vm);
00072 
00073 #define eKillSignal INT2FIX(0)
00074 #define eTerminateSignal INT2FIX(1)
00075 static volatile int system_working = 1;
00076 
00077 #define closed_stream_error GET_VM()->special_exceptions[ruby_error_closed_stream]
00078 
00079 inline static void
00080 st_delete_wrap(st_table *table, st_data_t key)
00081 {
00082     st_delete(table, &key, 0);
00083 }
00084 
00085 /********************************************************************************/
00086 
00087 #define THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION
00088 
00089 struct rb_blocking_region_buffer {
00090     enum rb_thread_status prev_status;
00091     struct rb_unblock_callback oldubf;
00092 };
00093 
00094 static void set_unblock_function(rb_thread_t *th, rb_unblock_function_t *func, void *arg,
00095                                  struct rb_unblock_callback *old);
00096 static void reset_unblock_function(rb_thread_t *th, const struct rb_unblock_callback *old);
00097 
00098 static inline void blocking_region_end(rb_thread_t *th, struct rb_blocking_region_buffer *region);
00099 
00100 #define RB_GC_SAVE_MACHINE_CONTEXT(th) \
00101   do { \
00102     rb_gc_save_machine_context(th); \
00103     SET_MACHINE_STACK_END(&(th)->machine_stack_end); \
00104   } while (0)
00105 
00106 #define GVL_UNLOCK_BEGIN() do { \
00107   rb_thread_t *_th_stored = GET_THREAD(); \
00108   RB_GC_SAVE_MACHINE_CONTEXT(_th_stored); \
00109   gvl_release(_th_stored->vm);
00110 
00111 #define GVL_UNLOCK_END() \
00112   gvl_acquire(_th_stored->vm, _th_stored); \
00113   rb_thread_set_current(_th_stored); \
00114 } while(0)
00115 
00116 #define blocking_region_begin(th, region, func, arg) \
00117   do { \
00118     (region)->prev_status = (th)->status; \
00119     set_unblock_function((th), (func), (arg), &(region)->oldubf); \
00120     (th)->blocking_region_buffer = (region); \
00121     (th)->status = THREAD_STOPPED; \
00122     thread_debug("enter blocking region (%p)\n", (void *)(th)); \
00123     RB_GC_SAVE_MACHINE_CONTEXT(th); \
00124     gvl_release((th)->vm); \
00125   } while (0)
00126 
00127 #define BLOCKING_REGION(exec, ubf, ubfarg) do { \
00128     rb_thread_t *__th = GET_THREAD(); \
00129     struct rb_blocking_region_buffer __region; \
00130     blocking_region_begin(__th, &__region, (ubf), (ubfarg)); \
00131     exec; \
00132     blocking_region_end(__th, &__region); \
00133     RUBY_VM_CHECK_INTS(); \
00134 } while(0)
00135 
00136 #if THREAD_DEBUG
00137 #ifdef HAVE_VA_ARGS_MACRO
00138 void rb_thread_debug(const char *file, int line, const char *fmt, ...);
00139 #define thread_debug(fmt, ...) rb_thread_debug(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
00140 #define POSITION_FORMAT "%s:%d:"
00141 #define POSITION_ARGS ,file, line
00142 #else
00143 void rb_thread_debug(const char *fmt, ...);
00144 #define thread_debug rb_thread_debug
00145 #define POSITION_FORMAT
00146 #define POSITION_ARGS
00147 #endif
00148 
00149 # if THREAD_DEBUG < 0
00150 static int rb_thread_debug_enabled;
00151 
00152 /*
00153  *  call-seq:
00154  *     Thread.DEBUG     -> num
00155  *
00156  *  Returns the thread debug level.  Available only if compiled with
00157  *  THREAD_DEBUG=-1.
00158  */
00159 
00160 static VALUE
00161 rb_thread_s_debug(void)
00162 {
00163     return INT2NUM(rb_thread_debug_enabled);
00164 }
00165 
00166 /*
00167  *  call-seq:
00168  *     Thread.DEBUG = num
00169  *
00170  *  Sets the thread debug level.  Available only if compiled with
00171  *  THREAD_DEBUG=-1.
00172  */
00173 
00174 static VALUE
00175 rb_thread_s_debug_set(VALUE self, VALUE val)
00176 {
00177     rb_thread_debug_enabled = RTEST(val) ? NUM2INT(val) : 0;
00178     return val;
00179 }
00180 # else
00181 # define rb_thread_debug_enabled THREAD_DEBUG
00182 # endif
00183 #else
00184 #define thread_debug if(0)printf
00185 #endif
00186 
00187 #ifndef __ia64
00188 #define thread_start_func_2(th, st, rst) thread_start_func_2(th, st)
00189 #endif
00190 NOINLINE(static int thread_start_func_2(rb_thread_t *th, VALUE *stack_start,
00191                                         VALUE *register_stack_start));
00192 static void timer_thread_function(void *);
00193 
00194 #if   defined(_WIN32)
00195 #include "thread_win32.c"
00196 
00197 #define DEBUG_OUT() \
00198   WaitForSingleObject(&debug_mutex, INFINITE); \
00199   printf(POSITION_FORMAT"%p - %s" POSITION_ARGS, GetCurrentThreadId(), buf); \
00200   fflush(stdout); \
00201   ReleaseMutex(&debug_mutex);
00202 
00203 #elif defined(HAVE_PTHREAD_H)
00204 #include "thread_pthread.c"
00205 
00206 #define DEBUG_OUT() \
00207   pthread_mutex_lock(&debug_mutex); \
00208   printf(POSITION_FORMAT"%#"PRIxVALUE" - %s" POSITION_ARGS, (VALUE)pthread_self(), buf); \
00209   fflush(stdout); \
00210   pthread_mutex_unlock(&debug_mutex);
00211 
00212 #else
00213 #error "unsupported thread type"
00214 #endif
00215 
00216 #if THREAD_DEBUG
00217 static int debug_mutex_initialized = 1;
00218 static rb_thread_lock_t debug_mutex;
00219 
00220 void
00221 rb_thread_debug(
00222 #ifdef HAVE_VA_ARGS_MACRO
00223     const char *file, int line,
00224 #endif
00225     const char *fmt, ...)
00226 {
00227     va_list args;
00228     char buf[BUFSIZ];
00229 
00230     if (!rb_thread_debug_enabled) return;
00231 
00232     if (debug_mutex_initialized == 1) {
00233         debug_mutex_initialized = 0;
00234         native_mutex_initialize(&debug_mutex);
00235     }
00236 
00237     va_start(args, fmt);
00238     vsnprintf(buf, BUFSIZ, fmt, args);
00239     va_end(args);
00240 
00241     DEBUG_OUT();
00242 }
00243 #endif
00244 
00245 void
00246 rb_vm_gvl_destroy(rb_vm_t *vm)
00247 {
00248     gvl_release(vm);
00249     gvl_destroy(vm);
00250 }
00251 
00252 void
00253 rb_thread_lock_unlock(rb_thread_lock_t *lock)
00254 {
00255     native_mutex_unlock(lock);
00256 }
00257 
00258 void
00259 rb_thread_lock_destroy(rb_thread_lock_t *lock)
00260 {
00261     native_mutex_destroy(lock);
00262 }
00263 
00264 static void
00265 set_unblock_function(rb_thread_t *th, rb_unblock_function_t *func, void *arg,
00266                      struct rb_unblock_callback *old)
00267 {
00268   check_ints:
00269     RUBY_VM_CHECK_INTS(); /* check signal or so */
00270     native_mutex_lock(&th->interrupt_lock);
00271     if (th->interrupt_flag) {
00272         native_mutex_unlock(&th->interrupt_lock);
00273         goto check_ints;
00274     }
00275     else {
00276         if (old) *old = th->unblock;
00277         th->unblock.func = func;
00278         th->unblock.arg = arg;
00279     }
00280     native_mutex_unlock(&th->interrupt_lock);
00281 }
00282 
00283 static void
00284 reset_unblock_function(rb_thread_t *th, const struct rb_unblock_callback *old)
00285 {
00286     native_mutex_lock(&th->interrupt_lock);
00287     th->unblock = *old;
00288     native_mutex_unlock(&th->interrupt_lock);
00289 }
00290 
00291 void
00292 rb_threadptr_interrupt(rb_thread_t *th)
00293 {
00294     native_mutex_lock(&th->interrupt_lock);
00295     RUBY_VM_SET_INTERRUPT(th);
00296     if (th->unblock.func) {
00297         (th->unblock.func)(th->unblock.arg);
00298     }
00299     else {
00300         /* none */
00301     }
00302     native_mutex_unlock(&th->interrupt_lock);
00303 }
00304 
00305 
00306 static int
00307 terminate_i(st_data_t key, st_data_t val, rb_thread_t *main_thread)
00308 {
00309     VALUE thval = key;
00310     rb_thread_t *th;
00311     GetThreadPtr(thval, th);
00312 
00313     if (th != main_thread) {
00314         thread_debug("terminate_i: %p\n", (void *)th);
00315         rb_threadptr_interrupt(th);
00316         th->thrown_errinfo = eTerminateSignal;
00317         th->status = THREAD_TO_KILL;
00318     }
00319     else {
00320         thread_debug("terminate_i: main thread (%p)\n", (void *)th);
00321     }
00322     return ST_CONTINUE;
00323 }
00324 
00325 typedef struct rb_mutex_struct
00326 {
00327     rb_thread_lock_t lock;
00328     rb_thread_cond_t cond;
00329     struct rb_thread_struct volatile *th;
00330     int cond_waiting;
00331     struct rb_mutex_struct *next_mutex;
00332 } rb_mutex_t;
00333 
00334 static void rb_mutex_abandon_all(rb_mutex_t *mutexes);
00335 static const char* rb_mutex_unlock_th(rb_mutex_t *mutex, rb_thread_t volatile *th);
00336 
00337 void
00338 rb_threadptr_unlock_all_locking_mutexes(rb_thread_t *th)
00339 {
00340     const char *err;
00341     rb_mutex_t *mutex;
00342     rb_mutex_t *mutexes = th->keeping_mutexes;
00343 
00344     while (mutexes) {
00345         mutex = mutexes;
00346         /* rb_warn("mutex #<%p> remains to be locked by terminated thread",
00347                 mutexes); */
00348         mutexes = mutex->next_mutex;
00349         err = rb_mutex_unlock_th(mutex, th);
00350         if (err) rb_bug("invalid keeping_mutexes: %s", err);
00351     }
00352 }
00353 
00354 void
00355 rb_thread_terminate_all(void)
00356 {
00357     rb_thread_t *th = GET_THREAD(); /* main thread */
00358     rb_vm_t *vm = th->vm;
00359 
00360     if (vm->main_thread != th) {
00361         rb_bug("rb_thread_terminate_all: called by child thread (%p, %p)",
00362                (void *)vm->main_thread, (void *)th);
00363     }
00364 
00365     /* unlock all locking mutexes */
00366     rb_threadptr_unlock_all_locking_mutexes(th);
00367 
00368     thread_debug("rb_thread_terminate_all (main thread: %p)\n", (void *)th);
00369     st_foreach(vm->living_threads, terminate_i, (st_data_t)th);
00370     vm->inhibit_thread_creation = 1;
00371 
00372     while (!rb_thread_alone()) {
00373         PUSH_TAG();
00374         if (EXEC_TAG() == 0) {
00375             rb_thread_schedule();
00376         }
00377         else {
00378             /* ignore exception */
00379         }
00380         POP_TAG();
00381     }
00382 }
00383 
00384 static void
00385 thread_cleanup_func_before_exec(void *th_ptr)
00386 {
00387     rb_thread_t *th = th_ptr;
00388     th->status = THREAD_KILLED;
00389     th->machine_stack_start = th->machine_stack_end = 0;
00390 #ifdef __ia64
00391     th->machine_register_stack_start = th->machine_register_stack_end = 0;
00392 #endif
00393 }
00394 
00395 static void
00396 thread_cleanup_func(void *th_ptr, int atfork)
00397 {
00398     rb_thread_t *th = th_ptr;
00399 
00400     th->locking_mutex = Qfalse;
00401     thread_cleanup_func_before_exec(th_ptr);
00402 
00403     /*
00404      * Unfortunately, we can't release native threading resource at fork
00405      * because libc may have unstable locking state therefore touching
00406      * a threading resource may cause a deadlock.
00407      */
00408     if (atfork)
00409         return;
00410 
00411     native_mutex_destroy(&th->interrupt_lock);
00412     native_thread_destroy(th);
00413 }
00414 
00415 static VALUE rb_threadptr_raise(rb_thread_t *, int, VALUE *);
00416 
00417 void
00418 ruby_thread_init_stack(rb_thread_t *th)
00419 {
00420     native_thread_init_stack(th);
00421 }
00422 
00423 static int
00424 thread_start_func_2(rb_thread_t *th, VALUE *stack_start, VALUE *register_stack_start)
00425 {
00426     int state;
00427     VALUE args = th->first_args;
00428     rb_proc_t *proc;
00429     rb_thread_t *join_th;
00430     rb_thread_t *main_th;
00431     VALUE errinfo = Qnil;
00432 # ifdef USE_SIGALTSTACK
00433     void rb_register_sigaltstack(rb_thread_t *th);
00434 
00435     rb_register_sigaltstack(th);
00436 # endif
00437 
00438     ruby_thread_set_native(th);
00439 
00440     th->machine_stack_start = stack_start;
00441 #ifdef __ia64
00442     th->machine_register_stack_start = register_stack_start;
00443 #endif
00444     thread_debug("thread start: %p\n", (void *)th);
00445 
00446     gvl_acquire(th->vm, th);
00447     {
00448         thread_debug("thread start (get lock): %p\n", (void *)th);
00449         rb_thread_set_current(th);
00450 
00451         TH_PUSH_TAG(th);
00452         if ((state = EXEC_TAG()) == 0) {
00453             SAVE_ROOT_JMPBUF(th, {
00454                 if (!th->first_func) {
00455                     GetProcPtr(th->first_proc, proc);
00456                     th->errinfo = Qnil;
00457                     th->local_lfp = proc->block.lfp;
00458                     th->local_svar = Qnil;
00459                     th->value = rb_vm_invoke_proc(th, proc, proc->block.self,
00460                                                   (int)RARRAY_LEN(args), RARRAY_PTR(args), 0);
00461                 }
00462                 else {
00463                     th->value = (*th->first_func)((void *)args);
00464                 }
00465             });
00466         }
00467         else {
00468             errinfo = th->errinfo;
00469             if (NIL_P(errinfo)) errinfo = rb_errinfo();
00470             if (state == TAG_FATAL) {
00471                 /* fatal error within this thread, need to stop whole script */
00472             }
00473             else if (rb_obj_is_kind_of(errinfo, rb_eSystemExit)) {
00474                 if (th->safe_level >= 4) {
00475                     th->errinfo = rb_exc_new3(rb_eSecurityError,
00476                                               rb_sprintf("Insecure exit at level %d", th->safe_level));
00477                     errinfo = Qnil;
00478                 }
00479             }
00480             else if (th->safe_level < 4 &&
00481                      (th->vm->thread_abort_on_exception ||
00482                       th->abort_on_exception || RTEST(ruby_debug))) {
00483                 /* exit on main_thread */
00484             }
00485             else {
00486                 errinfo = Qnil;
00487             }
00488             th->value = Qnil;
00489         }
00490 
00491         th->status = THREAD_KILLED;
00492         thread_debug("thread end: %p\n", (void *)th);
00493 
00494         main_th = th->vm->main_thread;
00495         if (th != main_th) {
00496             if (TYPE(errinfo) == T_OBJECT) {
00497                 /* treat with normal error object */
00498                 rb_threadptr_raise(main_th, 1, &errinfo);
00499             }
00500         }
00501         TH_POP_TAG();
00502 
00503         /* locking_mutex must be Qfalse */
00504         if (th->locking_mutex != Qfalse) {
00505             rb_bug("thread_start_func_2: locking_mutex must not be set (%p:%"PRIxVALUE")",
00506                    (void *)th, th->locking_mutex);
00507         }
00508 
00509         /* delete self other than main thread from living_threads */
00510         if (th != main_th) {
00511             st_delete_wrap(th->vm->living_threads, th->self);
00512         }
00513 
00514         /* wake up joining threads */
00515         join_th = th->join_list_head;
00516         while (join_th) {
00517             if (join_th == main_th) errinfo = Qnil;
00518             rb_threadptr_interrupt(join_th);
00519             switch (join_th->status) {
00520               case THREAD_STOPPED: case THREAD_STOPPED_FOREVER:
00521                 join_th->status = THREAD_RUNNABLE;
00522               default: break;
00523             }
00524             join_th = join_th->join_list_next;
00525         }
00526 
00527         rb_threadptr_unlock_all_locking_mutexes(th);
00528         if (th != main_th) rb_check_deadlock(th->vm);
00529 
00530         if (!th->root_fiber) {
00531             rb_thread_recycle_stack_release(th->stack);
00532             th->stack = 0;
00533         }
00534     }
00535     if (th->vm->main_thread == th) {
00536         ruby_cleanup(state);
00537     }
00538     else {
00539         thread_cleanup_func(th, FALSE);
00540         gvl_release(th->vm);
00541     }
00542 
00543     return 0;
00544 }
00545 
00546 static VALUE
00547 thread_create_core(VALUE thval, VALUE args, VALUE (*fn)(ANYARGS))
00548 {
00549     rb_thread_t *th;
00550     int err;
00551 
00552     if (OBJ_FROZEN(GET_THREAD()->thgroup)) {
00553         rb_raise(rb_eThreadError,
00554                  "can't start a new thread (frozen ThreadGroup)");
00555     }
00556     GetThreadPtr(thval, th);
00557 
00558     /* setup thread environment */
00559     th->first_func = fn;
00560     th->first_proc = fn ? Qfalse : rb_block_proc();
00561     th->first_args = args; /* GC: shouldn't put before above line */
00562 
00563     th->priority = GET_THREAD()->priority;
00564     th->thgroup = GET_THREAD()->thgroup;
00565 
00566     native_mutex_initialize(&th->interrupt_lock);
00567     if (GET_VM()->event_hooks != NULL)
00568         th->event_flags |= RUBY_EVENT_VM;
00569 
00570     /* kick thread */
00571     st_insert(th->vm->living_threads, thval, (st_data_t) th->thread_id);
00572     err = native_thread_create(th);
00573     if (err) {
00574         st_delete_wrap(th->vm->living_threads, th->self);
00575         th->status = THREAD_KILLED;
00576         rb_raise(rb_eThreadError, "can't create Thread (%d)", err);
00577     }
00578     return thval;
00579 }
00580 
00581 /* :nodoc: */
00582 static VALUE
00583 thread_s_new(int argc, VALUE *argv, VALUE klass)
00584 {
00585     rb_thread_t *th;
00586     VALUE thread = rb_thread_alloc(klass);
00587 
00588     if (GET_VM()->inhibit_thread_creation)
00589         rb_raise(rb_eThreadError, "can't alloc thread");
00590 
00591     rb_obj_call_init(thread, argc, argv);
00592     GetThreadPtr(thread, th);
00593     if (!th->first_args) {
00594         rb_raise(rb_eThreadError, "uninitialized thread - check `%s#initialize'",
00595                  rb_class2name(klass));
00596     }
00597     return thread;
00598 }
00599 
00600 /*
00601  *  call-seq:
00602  *     Thread.start([args]*) {|args| block }   -> thread
00603  *     Thread.fork([args]*) {|args| block }    -> thread
00604  *
00605  *  Basically the same as <code>Thread::new</code>. However, if class
00606  *  <code>Thread</code> is subclassed, then calling <code>start</code> in that
00607  *  subclass will not invoke the subclass's <code>initialize</code> method.
00608  */
00609 
00610 static VALUE
00611 thread_start(VALUE klass, VALUE args)
00612 {
00613     return thread_create_core(rb_thread_alloc(klass), args, 0);
00614 }
00615 
00616 /* :nodoc: */
00617 static VALUE
00618 thread_initialize(VALUE thread, VALUE args)
00619 {
00620     rb_thread_t *th;
00621     if (!rb_block_given_p()) {
00622         rb_raise(rb_eThreadError, "must be called with a block");
00623     }
00624     GetThreadPtr(thread, th);
00625     if (th->first_args) {
00626         VALUE proc = th->first_proc, line, loc;
00627         const char *file;
00628         if (!proc || !RTEST(loc = rb_proc_location(proc))) {
00629             rb_raise(rb_eThreadError, "already initialized thread");
00630         }
00631         file = RSTRING_PTR(RARRAY_PTR(loc)[0]);
00632         if (NIL_P(line = RARRAY_PTR(loc)[1])) {
00633             rb_raise(rb_eThreadError, "already initialized thread - %s",
00634                      file);
00635         }
00636         rb_raise(rb_eThreadError, "already initialized thread - %s:%d",
00637                  file, NUM2INT(line));
00638     }
00639     return thread_create_core(thread, args, 0);
00640 }
00641 
00642 VALUE
00643 rb_thread_create(VALUE (*fn)(ANYARGS), void *arg)
00644 {
00645     return thread_create_core(rb_thread_alloc(rb_cThread), (VALUE)arg, fn);
00646 }
00647 
00648 
00649 /* +infty, for this purpose */
00650 #define DELAY_INFTY 1E30
00651 
00652 struct join_arg {
00653     rb_thread_t *target, *waiting;
00654     double limit;
00655     int forever;
00656 };
00657 
00658 static VALUE
00659 remove_from_join_list(VALUE arg)
00660 {
00661     struct join_arg *p = (struct join_arg *)arg;
00662     rb_thread_t *target_th = p->target, *th = p->waiting;
00663 
00664     if (target_th->status != THREAD_KILLED) {
00665         rb_thread_t **pth = &target_th->join_list_head;
00666 
00667         while (*pth) {
00668             if (*pth == th) {
00669                 *pth = th->join_list_next;
00670                 break;
00671             }
00672             pth = &(*pth)->join_list_next;
00673         }
00674     }
00675 
00676     return Qnil;
00677 }
00678 
00679 static VALUE
00680 thread_join_sleep(VALUE arg)
00681 {
00682     struct join_arg *p = (struct join_arg *)arg;
00683     rb_thread_t *target_th = p->target, *th = p->waiting;
00684     double now, limit = p->limit;
00685 
00686     while (target_th->status != THREAD_KILLED) {
00687         if (p->forever) {
00688             sleep_forever(th, 1);
00689         }
00690         else {
00691             now = timeofday();
00692             if (now > limit) {
00693                 thread_debug("thread_join: timeout (thid: %p)\n",
00694                              (void *)target_th->thread_id);
00695                 return Qfalse;
00696             }
00697             sleep_wait_for_interrupt(th, limit - now);
00698         }
00699         thread_debug("thread_join: interrupted (thid: %p)\n",
00700                      (void *)target_th->thread_id);
00701     }
00702     return Qtrue;
00703 }
00704 
00705 static VALUE
00706 thread_join(rb_thread_t *target_th, double delay)
00707 {
00708     rb_thread_t *th = GET_THREAD();
00709     struct join_arg arg;
00710 
00711     arg.target = target_th;
00712     arg.waiting = th;
00713     arg.limit = timeofday() + delay;
00714     arg.forever = delay == DELAY_INFTY;
00715 
00716     thread_debug("thread_join (thid: %p)\n", (void *)target_th->thread_id);
00717 
00718     if (target_th->status != THREAD_KILLED) {
00719         th->join_list_next = target_th->join_list_head;
00720         target_th->join_list_head = th;
00721         if (!rb_ensure(thread_join_sleep, (VALUE)&arg,
00722                        remove_from_join_list, (VALUE)&arg)) {
00723             return Qnil;
00724         }
00725     }
00726 
00727     thread_debug("thread_join: success (thid: %p)\n",
00728                  (void *)target_th->thread_id);
00729 
00730     if (target_th->errinfo != Qnil) {
00731         VALUE err = target_th->errinfo;
00732 
00733         if (FIXNUM_P(err)) {
00734             /* */
00735         }
00736         else if (TYPE(target_th->errinfo) == T_NODE) {
00737             rb_exc_raise(rb_vm_make_jump_tag_but_local_jump(
00738                 GET_THROWOBJ_STATE(err), GET_THROWOBJ_VAL(err)));
00739         }
00740         else {
00741             /* normal exception */
00742             rb_exc_raise(err);
00743         }
00744     }
00745     return target_th->self;
00746 }
00747 
00748 /*
00749  *  call-seq:
00750  *     thr.join          -> thr
00751  *     thr.join(limit)   -> thr
00752  *
00753  *  The calling thread will suspend execution and run <i>thr</i>. Does not
00754  *  return until <i>thr</i> exits or until <i>limit</i> seconds have passed. If
00755  *  the time limit expires, <code>nil</code> will be returned, otherwise
00756  *  <i>thr</i> is returned.
00757  *
00758  *  Any threads not joined will be killed when the main program exits.  If
00759  *  <i>thr</i> had previously raised an exception and the
00760  *  <code>abort_on_exception</code> and <code>$DEBUG</code> flags are not set
00761  *  (so the exception has not yet been processed) it will be processed at this
00762  *  time.
00763  *
00764  *     a = Thread.new { print "a"; sleep(10); print "b"; print "c" }
00765  *     x = Thread.new { print "x"; Thread.pass; print "y"; print "z" }
00766  *     x.join # Let x thread finish, a will be killed on exit.
00767  *
00768  *  <em>produces:</em>
00769  *
00770  *     axyz
00771  *
00772  *  The following example illustrates the <i>limit</i> parameter.
00773  *
00774  *     y = Thread.new { 4.times { sleep 0.1; puts 'tick... ' }}
00775  *     puts "Waiting" until y.join(0.15)
00776  *
00777  *  <em>produces:</em>
00778  *
00779  *     tick...
00780  *     Waiting
00781  *     tick...
00782  *     Waitingtick...
00783  *
00784  *
00785  *     tick...
00786  */
00787 
00788 static VALUE
00789 thread_join_m(int argc, VALUE *argv, VALUE self)
00790 {
00791     rb_thread_t *target_th;
00792     double delay = DELAY_INFTY;
00793     VALUE limit;
00794 
00795     GetThreadPtr(self, target_th);
00796 
00797     rb_scan_args(argc, argv, "01", &limit);
00798     if (!NIL_P(limit)) {
00799         delay = rb_num2dbl(limit);
00800     }
00801 
00802     return thread_join(target_th, delay);
00803 }
00804 
00805 /*
00806  *  call-seq:
00807  *     thr.value   -> obj
00808  *
00809  *  Waits for <i>thr</i> to complete (via <code>Thread#join</code>) and returns
00810  *  its value.
00811  *
00812  *     a = Thread.new { 2 + 2 }
00813  *     a.value   #=> 4
00814  */
00815 
00816 static VALUE
00817 thread_value(VALUE self)
00818 {
00819     rb_thread_t *th;
00820     GetThreadPtr(self, th);
00821     thread_join(th, DELAY_INFTY);
00822     return th->value;
00823 }
00824 
00825 /*
00826  * Thread Scheduling
00827  */
00828 
00829 static struct timeval
00830 double2timeval(double d)
00831 {
00832     struct timeval time;
00833 
00834     time.tv_sec = (int)d;
00835     time.tv_usec = (int)((d - (int)d) * 1e6);
00836     if (time.tv_usec < 0) {
00837         time.tv_usec += (int)1e6;
00838         time.tv_sec -= 1;
00839     }
00840     return time;
00841 }
00842 
00843 static void
00844 sleep_forever(rb_thread_t *th, int deadlockable)
00845 {
00846     enum rb_thread_status prev_status = th->status;
00847     enum rb_thread_status status = deadlockable ? THREAD_STOPPED_FOREVER : THREAD_STOPPED;
00848 
00849     th->status = status;
00850     do {
00851         if (deadlockable) {
00852             th->vm->sleeper++;
00853             rb_check_deadlock(th->vm);
00854         }
00855         native_sleep(th, 0);
00856         if (deadlockable) {
00857             th->vm->sleeper--;
00858         }
00859         RUBY_VM_CHECK_INTS();
00860     } while (th->status == status);
00861     th->status = prev_status;
00862 }
00863 
00864 static void
00865 getclockofday(struct timeval *tp)
00866 {
00867 #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
00868     struct timespec ts;
00869 
00870     if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
00871         tp->tv_sec = ts.tv_sec;
00872         tp->tv_usec = ts.tv_nsec / 1000;
00873     } else
00874 #endif
00875     {
00876         gettimeofday(tp, NULL);
00877     }
00878 }
00879 
00880 static void
00881 sleep_timeval(rb_thread_t *th, struct timeval tv)
00882 {
00883     struct timeval to, tvn;
00884     enum rb_thread_status prev_status = th->status;
00885 
00886     getclockofday(&to);
00887     to.tv_sec += tv.tv_sec;
00888     if ((to.tv_usec += tv.tv_usec) >= 1000000) {
00889         to.tv_sec++;
00890         to.tv_usec -= 1000000;
00891     }
00892 
00893     th->status = THREAD_STOPPED;
00894     do {
00895         native_sleep(th, &tv);
00896         RUBY_VM_CHECK_INTS();
00897         getclockofday(&tvn);
00898         if (to.tv_sec < tvn.tv_sec) break;
00899         if (to.tv_sec == tvn.tv_sec && to.tv_usec <= tvn.tv_usec) break;
00900         thread_debug("sleep_timeval: %ld.%.6ld > %ld.%.6ld\n",
00901                      (long)to.tv_sec, (long)to.tv_usec,
00902                      (long)tvn.tv_sec, (long)tvn.tv_usec);
00903         tv.tv_sec = to.tv_sec - tvn.tv_sec;
00904         if ((tv.tv_usec = to.tv_usec - tvn.tv_usec) < 0) {
00905             --tv.tv_sec;
00906             tv.tv_usec += 1000000;
00907         }
00908     } while (th->status == THREAD_STOPPED);
00909     th->status = prev_status;
00910 }
00911 
00912 void
00913 rb_thread_sleep_forever(void)
00914 {
00915     thread_debug("rb_thread_sleep_forever\n");
00916     sleep_forever(GET_THREAD(), 0);
00917 }
00918 
00919 static void
00920 rb_thread_sleep_deadly(void)
00921 {
00922     thread_debug("rb_thread_sleep_deadly\n");
00923     sleep_forever(GET_THREAD(), 1);
00924 }
00925 
00926 static double
00927 timeofday(void)
00928 {
00929 #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
00930     struct timespec tp;
00931 
00932     if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) {
00933         return (double)tp.tv_sec + (double)tp.tv_nsec * 1e-9;
00934     } else
00935 #endif
00936     {
00937         struct timeval tv;
00938         gettimeofday(&tv, NULL);
00939         return (double)tv.tv_sec + (double)tv.tv_usec * 1e-6;
00940     }
00941 }
00942 
00943 static void
00944 sleep_wait_for_interrupt(rb_thread_t *th, double sleepsec)
00945 {
00946     sleep_timeval(th, double2timeval(sleepsec));
00947 }
00948 
00949 static void
00950 sleep_for_polling(rb_thread_t *th)
00951 {
00952     struct timeval time;
00953     time.tv_sec = 0;
00954     time.tv_usec = 100 * 1000;  /* 0.1 sec */
00955     sleep_timeval(th, time);
00956 }
00957 
00958 void
00959 rb_thread_wait_for(struct timeval time)
00960 {
00961     rb_thread_t *th = GET_THREAD();
00962     sleep_timeval(th, time);
00963 }
00964 
00965 void
00966 rb_thread_polling(void)
00967 {
00968     RUBY_VM_CHECK_INTS();
00969     if (!rb_thread_alone()) {
00970         rb_thread_t *th = GET_THREAD();
00971         sleep_for_polling(th);
00972     }
00973 }
00974 
00975 /*
00976  * CAUTION: This function causes thread switching.
00977  *          rb_thread_check_ints() check ruby's interrupts.
00978  *          some interrupt needs thread switching/invoke handlers,
00979  *          and so on.
00980  */
00981 
00982 void
00983 rb_thread_check_ints(void)
00984 {
00985     RUBY_VM_CHECK_INTS();
00986 }
00987 
00988 /*
00989  * Hidden API for tcl/tk wrapper.
00990  * There is no guarantee to perpetuate it.
00991  */
00992 int
00993 rb_thread_check_trap_pending(void)
00994 {
00995     return rb_signal_buff_size() != 0;
00996 }
00997 
00998 /* This function can be called in blocking region. */
00999 int
01000 rb_thread_interrupted(VALUE thval)
01001 {
01002     rb_thread_t *th;
01003     GetThreadPtr(thval, th);
01004     return RUBY_VM_INTERRUPTED(th);
01005 }
01006 
01007 void
01008 rb_thread_sleep(int sec)
01009 {
01010     rb_thread_wait_for(rb_time_timeval(INT2FIX(sec)));
01011 }
01012 
01013 static void rb_threadptr_execute_interrupts_common(rb_thread_t *);
01014 
01015 static void
01016 rb_thread_schedule_limits(unsigned long limits_us)
01017 {
01018     thread_debug("rb_thread_schedule\n");
01019     if (!rb_thread_alone()) {
01020         rb_thread_t *th = GET_THREAD();
01021 
01022         if (th->running_time_us >= limits_us) {
01023             thread_debug("rb_thread_schedule/switch start\n");
01024             RB_GC_SAVE_MACHINE_CONTEXT(th);
01025             gvl_yield(th->vm, th);
01026             rb_thread_set_current(th);
01027             thread_debug("rb_thread_schedule/switch done\n");
01028         }
01029     }
01030 }
01031 
01032 void
01033 rb_thread_schedule(void)
01034 {
01035     rb_thread_schedule_limits(0);
01036 
01037     if (UNLIKELY(GET_THREAD()->interrupt_flag)) {
01038         rb_threadptr_execute_interrupts_common(GET_THREAD());
01039     }
01040 }
01041 
01042 /* blocking region */
01043 
01044 static inline void
01045 blocking_region_end(rb_thread_t *th, struct rb_blocking_region_buffer *region)
01046 {
01047     gvl_acquire(th->vm, th);
01048     rb_thread_set_current(th);
01049     thread_debug("leave blocking region (%p)\n", (void *)th);
01050     remove_signal_thread_list(th);
01051     th->blocking_region_buffer = 0;
01052     reset_unblock_function(th, &region->oldubf);
01053     if (th->status == THREAD_STOPPED) {
01054         th->status = region->prev_status;
01055     }
01056 }
01057 
01058 struct rb_blocking_region_buffer *
01059 rb_thread_blocking_region_begin(void)
01060 {
01061     rb_thread_t *th = GET_THREAD();
01062     struct rb_blocking_region_buffer *region = ALLOC(struct rb_blocking_region_buffer);
01063     blocking_region_begin(th, region, ubf_select, th);
01064     return region;
01065 }
01066 
01067 void
01068 rb_thread_blocking_region_end(struct rb_blocking_region_buffer *region)
01069 {
01070     int saved_errno = errno;
01071     rb_thread_t *th = GET_THREAD();
01072     blocking_region_end(th, region);
01073     xfree(region);
01074     RUBY_VM_CHECK_INTS();
01075     errno = saved_errno;
01076 }
01077 
01078 /*
01079  * rb_thread_blocking_region - permit concurrent/parallel execution.
01080  *
01081  * This function does:
01082  *   (1) release GVL.
01083  *       Other Ruby threads may run in parallel.
01084  *   (2) call func with data1.
01085  *   (3) acquire GVL.
01086  *       Other Ruby threads can not run in parallel any more.
01087  *
01088  *   If another thread interrupts this thread (Thread#kill, signal delivery,
01089  *   VM-shutdown request, and so on), `ubf()' is called (`ubf()' means
01090  *   "un-blocking function").  `ubf()' should interrupt `func()' execution.
01091  *
01092  *   There are built-in ubfs and you can specify these ubfs.
01093  *   However, we can not guarantee our built-in ubfs interrupt
01094  *   your `func()' correctly.  Be careful to use rb_thread_blocking_region().
01095  *
01096  *     * RUBY_UBF_IO: ubf for IO operation
01097  *     * RUBY_UBF_PROCESS: ubf for process operation
01098  *
01099  *   NOTE: You can not execute most of Ruby C API and touch Ruby
01100  *         objects in `func()' and `ubf()', including raising an
01101  *         exception, because current thread doesn't acquire GVL
01102  *         (cause synchronization problem).  If you need to do it,
01103  *         read source code of C APIs and confirm by yourself.
01104  *
01105  *   NOTE: In short, this API is difficult to use safely.  I recommend you
01106  *         use other ways if you have.  We lack experiences to use this API.
01107  *         Please report your problem related on it.
01108  *
01109  *   Safe C API:
01110  *     * rb_thread_interrupted() - check interrupt flag
01111  *     * ruby_xalloc(), ruby_xrealloc(), ruby_xfree() -
01112  *         if they called without GVL, acquire GVL automatically.
01113  */
01114 VALUE
01115 rb_thread_blocking_region(
01116     rb_blocking_function_t *func, void *data1,
01117     rb_unblock_function_t *ubf, void *data2)
01118 {
01119     VALUE val;
01120     rb_thread_t *th = GET_THREAD();
01121     int saved_errno = 0;
01122 
01123     th->waiting_fd = -1;
01124     if (ubf == RUBY_UBF_IO || ubf == RUBY_UBF_PROCESS) {
01125         ubf = ubf_select;
01126         data2 = th;
01127     }
01128 
01129     BLOCKING_REGION({
01130         val = func(data1);
01131         saved_errno = errno;
01132     }, ubf, data2);
01133     errno = saved_errno;
01134 
01135     return val;
01136 }
01137 
01138 VALUE
01139 rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd)
01140 {
01141     VALUE val;
01142     rb_thread_t *th = GET_THREAD();
01143     int saved_errno = 0;
01144 
01145     th->waiting_fd = fd;
01146     BLOCKING_REGION({
01147         val = func(data1);
01148         saved_errno = errno;
01149     }, ubf_select, th);
01150     th->waiting_fd = -1;
01151     errno = saved_errno;
01152 
01153     return val;
01154 }
01155 
01156 /* alias of rb_thread_blocking_region() */
01157 
01158 VALUE
01159 rb_thread_call_without_gvl(
01160     rb_blocking_function_t *func, void *data1,
01161     rb_unblock_function_t *ubf, void *data2)
01162 {
01163     return rb_thread_blocking_region(func, data1, ubf, data2);
01164 }
01165 
01166 /*
01167  * rb_thread_call_with_gvl - re-enter into Ruby world while releasing GVL.
01168  *
01169  ***
01170  *** This API is EXPERIMENTAL!
01171  *** We do not guarantee that this API remains in ruby 1.9.2 or later.
01172  ***
01173  *
01174  * While releasing GVL using rb_thread_blocking_region() or
01175  * rb_thread_call_without_gvl(), you can not access Ruby values or invoke methods.
01176  * If you need to access it, you must use this function rb_thread_call_with_gvl().
01177  *
01178  * This function rb_thread_call_with_gvl() does:
01179  * (1) acquire GVL.
01180  * (2) call passed function `func'.
01181  * (3) release GVL.
01182  * (4) return a value which is returned at (2).
01183  *
01184  * NOTE: You should not return Ruby object at (2) because such Object
01185  *       will not marked.
01186  *
01187  * NOTE: If an exception is raised in `func', this function "DOES NOT"
01188  *       protect (catch) the exception.  If you have any resources
01189  *       which should free before throwing exception, you need use
01190  *       rb_protect() in `func' and return a value which represents
01191  *       exception is raised.
01192  *
01193  * NOTE: This functions should not be called by a thread which
01194  *       is not created as Ruby thread (created by Thread.new or so).
01195  *       In other words, this function *DOES NOT* associate
01196  *       NON-Ruby thread to Ruby thread.
01197  */
01198 void *
01199 rb_thread_call_with_gvl(void *(*func)(void *), void *data1)
01200 {
01201     rb_thread_t *th = ruby_thread_from_native();
01202     struct rb_blocking_region_buffer *brb;
01203     struct rb_unblock_callback prev_unblock;
01204     void *r;
01205 
01206     if (th == 0) {
01207         /* Error is occurred, but we can't use rb_bug()
01208          * because this thread is not Ruby's thread.
01209          * What should we do?
01210          */
01211 
01212         fprintf(stderr, "[BUG] rb_thread_call_with_gvl() is called by non-ruby thread\n");
01213         exit(EXIT_FAILURE);
01214     }
01215 
01216     brb = (struct rb_blocking_region_buffer *)th->blocking_region_buffer;
01217     prev_unblock = th->unblock;
01218 
01219     if (brb == 0) {
01220         rb_bug("rb_thread_call_with_gvl: called by a thread which has GVL.");
01221     }
01222 
01223     blocking_region_end(th, brb);
01224     /* enter to Ruby world: You can access Ruby values, methods and so on. */
01225     r = (*func)(data1);
01226     /* leave from Ruby world: You can not access Ruby values, etc. */
01227     blocking_region_begin(th, brb, prev_unblock.func, prev_unblock.arg);
01228     return r;
01229 }
01230 
01231 /*
01232  * ruby_thread_has_gvl_p - check if current native thread has GVL.
01233  *
01234  ***
01235  *** This API is EXPERIMENTAL!
01236  *** We do not guarantee that this API remains in ruby 1.9.2 or later.
01237  ***
01238  */
01239 
01240 int
01241 ruby_thread_has_gvl_p(void)
01242 {
01243     rb_thread_t *th = ruby_thread_from_native();
01244 
01245     if (th && th->blocking_region_buffer == 0) {
01246         return 1;
01247     }
01248     else {
01249         return 0;
01250     }
01251 }
01252 
01253 /*
01254  * call-seq:
01255  *    Thread.pass   -> nil
01256  *
01257  * Give the thread scheduler a hint to pass execution to another thread.
01258  * A running thread may or may not switch, it depends on OS and processor.
01259  */
01260 
01261 static VALUE
01262 thread_s_pass(VALUE klass)
01263 {
01264     rb_thread_schedule();
01265     return Qnil;
01266 }
01267 
01268 /*
01269  *
01270  */
01271 
01272 static void
01273 rb_threadptr_execute_interrupts_common(rb_thread_t *th)
01274 {
01275     rb_atomic_t interrupt;
01276 
01277     if (th->raised_flag) return;
01278 
01279     while ((interrupt = ATOMIC_EXCHANGE(th->interrupt_flag, 0)) != 0) {
01280         enum rb_thread_status status = th->status;
01281         int timer_interrupt = interrupt & 0x01;
01282         int finalizer_interrupt = interrupt & 0x04;
01283         int sig;
01284 
01285         th->status = THREAD_RUNNABLE;
01286 
01287         /* signal handling */
01288         if (th == th->vm->main_thread) {
01289             while ((sig = rb_get_next_signal()) != 0) {
01290                 rb_signal_exec(th, sig);
01291             }
01292         }
01293 
01294         /* exception from another thread */
01295         if (th->thrown_errinfo) {
01296             VALUE err = th->thrown_errinfo;
01297             th->thrown_errinfo = 0;
01298             thread_debug("rb_thread_execute_interrupts: %"PRIdVALUE"\n", err);
01299 
01300             if (err == eKillSignal || err == eTerminateSignal) {
01301                 th->errinfo = INT2FIX(TAG_FATAL);
01302                 TH_JUMP_TAG(th, TAG_FATAL);
01303             }
01304             else {
01305                 rb_exc_raise(err);
01306             }
01307         }
01308         th->status = status;
01309 
01310         if (finalizer_interrupt) {
01311             rb_gc_finalize_deferred();
01312         }
01313 
01314         if (timer_interrupt) {
01315             unsigned long limits_us = 250 * 1000;
01316 
01317             if (th->priority > 0)
01318                 limits_us <<= th->priority;
01319             else
01320                 limits_us >>= -th->priority;
01321 
01322             if (status == THREAD_RUNNABLE)
01323                 th->running_time_us += TIME_QUANTUM_USEC;
01324 
01325             EXEC_EVENT_HOOK(th, RUBY_EVENT_SWITCH, th->cfp->self, 0, 0);
01326 
01327             rb_thread_schedule_limits(limits_us);
01328         }
01329     }
01330 }
01331 
01332 void
01333 rb_threadptr_execute_interrupts(rb_thread_t *th)
01334 {
01335     rb_threadptr_execute_interrupts_common(th);
01336 }
01337 
01338 void
01339 rb_thread_execute_interrupts(VALUE thval)
01340 {
01341     rb_thread_t *th;
01342     GetThreadPtr(thval, th);
01343     rb_threadptr_execute_interrupts_common(th);
01344 }
01345 
01346 void
01347 rb_gc_mark_threads(void)
01348 {
01349     rb_bug("deprecated function rb_gc_mark_threads is called");
01350 }
01351 
01352 /*****************************************************/
01353 
01354 static void
01355 rb_threadptr_ready(rb_thread_t *th)
01356 {
01357     rb_threadptr_interrupt(th);
01358 }
01359 
01360 static VALUE
01361 rb_threadptr_raise(rb_thread_t *th, int argc, VALUE *argv)
01362 {
01363     VALUE exc;
01364 
01365   again:
01366     if (rb_threadptr_dead(th)) {
01367         return Qnil;
01368     }
01369 
01370     if (th->thrown_errinfo != 0 || th->raised_flag) {
01371         rb_thread_schedule();
01372         goto again;
01373     }
01374 
01375     exc = rb_make_exception(argc, argv);
01376     th->thrown_errinfo = exc;
01377     rb_threadptr_ready(th);
01378     return Qnil;
01379 }
01380 
01381 void
01382 rb_threadptr_signal_raise(rb_thread_t *th, int sig)
01383 {
01384     VALUE argv[2];
01385 
01386     argv[0] = rb_eSignal;
01387     argv[1] = INT2FIX(sig);
01388     rb_threadptr_raise(th->vm->main_thread, 2, argv);
01389 }
01390 
01391 void
01392 rb_threadptr_signal_exit(rb_thread_t *th)
01393 {
01394     VALUE argv[2];
01395 
01396     argv[0] = rb_eSystemExit;
01397     argv[1] = rb_str_new2("exit");
01398     rb_threadptr_raise(th->vm->main_thread, 2, argv);
01399 }
01400 
01401 #if defined(POSIX_SIGNAL) && defined(SIGSEGV) && defined(HAVE_SIGALTSTACK)
01402 #define USE_SIGALTSTACK
01403 #endif
01404 
01405 void
01406 ruby_thread_stack_overflow(rb_thread_t *th)
01407 {
01408     th->raised_flag = 0;
01409 #ifdef USE_SIGALTSTACK
01410     rb_exc_raise(sysstack_error);
01411 #else
01412     th->errinfo = sysstack_error;
01413     TH_JUMP_TAG(th, TAG_RAISE);
01414 #endif
01415 }
01416 
01417 int
01418 rb_threadptr_set_raised(rb_thread_t *th)
01419 {
01420     if (th->raised_flag & RAISED_EXCEPTION) {
01421         return 1;
01422     }
01423     th->raised_flag |= RAISED_EXCEPTION;
01424     return 0;
01425 }
01426 
01427 int
01428 rb_threadptr_reset_raised(rb_thread_t *th)
01429 {
01430     if (!(th->raised_flag & RAISED_EXCEPTION)) {
01431         return 0;
01432     }
01433     th->raised_flag &= ~RAISED_EXCEPTION;
01434     return 1;
01435 }
01436 
01437 #define THREAD_IO_WAITING_P(th) (                       \
01438         ((th)->status == THREAD_STOPPED ||              \
01439          (th)->status == THREAD_STOPPED_FOREVER) &&     \
01440         (th)->blocking_region_buffer &&                 \
01441         (th)->unblock.func == ubf_select &&             \
01442         1)
01443 
01444 static int
01445 thread_fd_close_i(st_data_t key, st_data_t val, st_data_t data)
01446 {
01447     int fd = (int)data;
01448     rb_thread_t *th;
01449     GetThreadPtr((VALUE)key, th);
01450 
01451     if (THREAD_IO_WAITING_P(th)) {
01452         native_mutex_lock(&th->interrupt_lock);
01453         if (THREAD_IO_WAITING_P(th) && th->waiting_fd == fd) {
01454             th->thrown_errinfo = th->vm->special_exceptions[ruby_error_closed_stream];
01455             RUBY_VM_SET_INTERRUPT(th);
01456             (th->unblock.func)(th->unblock.arg);
01457         }
01458         native_mutex_unlock(&th->interrupt_lock);
01459     }
01460     return ST_CONTINUE;
01461 }
01462 
01463 void
01464 rb_thread_fd_close(int fd)
01465 {
01466     st_foreach(GET_THREAD()->vm->living_threads, thread_fd_close_i, (st_index_t)fd);
01467 }
01468 
01469 /*
01470  *  call-seq:
01471  *     thr.raise
01472  *     thr.raise(string)
01473  *     thr.raise(exception [, string [, array]])
01474  *
01475  *  Raises an exception (see <code>Kernel::raise</code>) from <i>thr</i>. The
01476  *  caller does not have to be <i>thr</i>.
01477  *
01478  *     Thread.abort_on_exception = true
01479  *     a = Thread.new { sleep(200) }
01480  *     a.raise("Gotcha")
01481  *
01482  *  <em>produces:</em>
01483  *
01484  *     prog.rb:3: Gotcha (RuntimeError)
01485  *      from prog.rb:2:in `initialize'
01486  *      from prog.rb:2:in `new'
01487  *      from prog.rb:2
01488  */
01489 
01490 static VALUE
01491 thread_raise_m(int argc, VALUE *argv, VALUE self)
01492 {
01493     rb_thread_t *th;
01494     GetThreadPtr(self, th);
01495     rb_threadptr_raise(th, argc, argv);
01496     return Qnil;
01497 }
01498 
01499 
01500 /*
01501  *  call-seq:
01502  *     thr.exit        -> thr or nil
01503  *     thr.kill        -> thr or nil
01504  *     thr.terminate   -> thr or nil
01505  *
01506  *  Terminates <i>thr</i> and schedules another thread to be run. If this thread
01507  *  is already marked to be killed, <code>exit</code> returns the
01508  *  <code>Thread</code>. If this is the main thread, or the last thread, exits
01509  *  the process.
01510  */
01511 
01512 VALUE
01513 rb_thread_kill(VALUE thread)
01514 {
01515     rb_thread_t *th;
01516 
01517     GetThreadPtr(thread, th);
01518 
01519     if (th != GET_THREAD() && th->safe_level < 4) {
01520         rb_secure(4);
01521     }
01522     if (th->status == THREAD_TO_KILL || th->status == THREAD_KILLED) {
01523         return thread;
01524     }
01525     if (th == th->vm->main_thread) {
01526         rb_exit(EXIT_SUCCESS);
01527     }
01528 
01529     thread_debug("rb_thread_kill: %p (%p)\n", (void *)th, (void *)th->thread_id);
01530 
01531     rb_threadptr_interrupt(th);
01532     th->thrown_errinfo = eKillSignal;
01533     th->status = THREAD_TO_KILL;
01534 
01535     return thread;
01536 }
01537 
01538 
01539 /*
01540  *  call-seq:
01541  *     Thread.kill(thread)   -> thread
01542  *
01543  *  Causes the given <em>thread</em> to exit (see <code>Thread::exit</code>).
01544  *
01545  *     count = 0
01546  *     a = Thread.new { loop { count += 1 } }
01547  *     sleep(0.1)       #=> 0
01548  *     Thread.kill(a)   #=> #<Thread:0x401b3d30 dead>
01549  *     count            #=> 93947
01550  *     a.alive?         #=> false
01551  */
01552 
01553 static VALUE
01554 rb_thread_s_kill(VALUE obj, VALUE th)
01555 {
01556     return rb_thread_kill(th);
01557 }
01558 
01559 
01560 /*
01561  *  call-seq:
01562  *     Thread.exit   -> thread
01563  *
01564  *  Terminates the currently running thread and schedules another thread to be
01565  *  run. If this thread is already marked to be killed, <code>exit</code>
01566  *  returns the <code>Thread</code>. If this is the main thread, or the last
01567  *  thread, exit the process.
01568  */
01569 
01570 static VALUE
01571 rb_thread_exit(void)
01572 {
01573     return rb_thread_kill(GET_THREAD()->self);
01574 }
01575 
01576 
01577 /*
01578  *  call-seq:
01579  *     thr.wakeup   -> thr
01580  *
01581  *  Marks <i>thr</i> as eligible for scheduling (it may still remain blocked on
01582  *  I/O, however). Does not invoke the scheduler (see <code>Thread#run</code>).
01583  *
01584  *     c = Thread.new { Thread.stop; puts "hey!" }
01585  *     sleep 0.1 while c.status!='sleep'
01586  *     c.wakeup
01587  *     c.join
01588  *
01589  *  <em>produces:</em>
01590  *
01591  *     hey!
01592  */
01593 
01594 VALUE
01595 rb_thread_wakeup(VALUE thread)
01596 {
01597     if (!RTEST(rb_thread_wakeup_alive(thread))) {
01598         rb_raise(rb_eThreadError, "killed thread");
01599     }
01600     return thread;
01601 }
01602 
01603 VALUE
01604 rb_thread_wakeup_alive(VALUE thread)
01605 {
01606     rb_thread_t *th;
01607     GetThreadPtr(thread, th);
01608 
01609     if (th->status == THREAD_KILLED) {
01610         return Qnil;
01611     }
01612     rb_threadptr_ready(th);
01613     if (th->status != THREAD_TO_KILL) {
01614         th->status = THREAD_RUNNABLE;
01615     }
01616     return thread;
01617 }
01618 
01619 
01620 /*
01621  *  call-seq:
01622  *     thr.run   -> thr
01623  *
01624  *  Wakes up <i>thr</i>, making it eligible for scheduling.
01625  *
01626  *     a = Thread.new { puts "a"; Thread.stop; puts "c" }
01627  *     sleep 0.1 while a.status!='sleep'
01628  *     puts "Got here"
01629  *     a.run
01630  *     a.join
01631  *
01632  *  <em>produces:</em>
01633  *
01634  *     a
01635  *     Got here
01636  *     c
01637  */
01638 
01639 VALUE
01640 rb_thread_run(VALUE thread)
01641 {
01642     rb_thread_wakeup(thread);
01643     rb_thread_schedule();
01644     return thread;
01645 }
01646 
01647 
01648 /*
01649  *  call-seq:
01650  *     Thread.stop   -> nil
01651  *
01652  *  Stops execution of the current thread, putting it into a ``sleep'' state,
01653  *  and schedules execution of another thread.
01654  *
01655  *     a = Thread.new { print "a"; Thread.stop; print "c" }
01656  *     sleep 0.1 while a.status!='sleep'
01657  *     print "b"
01658  *     a.run
01659  *     a.join
01660  *
01661  *  <em>produces:</em>
01662  *
01663  *     abc
01664  */
01665 
01666 VALUE
01667 rb_thread_stop(void)
01668 {
01669     if (rb_thread_alone()) {
01670         rb_raise(rb_eThreadError,
01671                  "stopping only thread\n\tnote: use sleep to stop forever");
01672     }
01673     rb_thread_sleep_deadly();
01674     return Qnil;
01675 }
01676 
01677 static int
01678 thread_list_i(st_data_t key, st_data_t val, void *data)
01679 {
01680     VALUE ary = (VALUE)data;
01681     rb_thread_t *th;
01682     GetThreadPtr((VALUE)key, th);
01683 
01684     switch (th->status) {
01685       case THREAD_RUNNABLE:
01686       case THREAD_STOPPED:
01687       case THREAD_STOPPED_FOREVER:
01688       case THREAD_TO_KILL:
01689         rb_ary_push(ary, th->self);
01690       default:
01691         break;
01692     }
01693     return ST_CONTINUE;
01694 }
01695 
01696 /********************************************************************/
01697 
01698 /*
01699  *  call-seq:
01700  *     Thread.list   -> array
01701  *
01702  *  Returns an array of <code>Thread</code> objects for all threads that are
01703  *  either runnable or stopped.
01704  *
01705  *     Thread.new { sleep(200) }
01706  *     Thread.new { 1000000.times {|i| i*i } }
01707  *     Thread.new { Thread.stop }
01708  *     Thread.list.each {|t| p t}
01709  *
01710  *  <em>produces:</em>
01711  *
01712  *     #<Thread:0x401b3e84 sleep>
01713  *     #<Thread:0x401b3f38 run>
01714  *     #<Thread:0x401b3fb0 sleep>
01715  *     #<Thread:0x401bdf4c run>
01716  */
01717 
01718 VALUE
01719 rb_thread_list(void)
01720 {
01721     VALUE ary = rb_ary_new();
01722     st_foreach(GET_THREAD()->vm->living_threads, thread_list_i, ary);
01723     return ary;
01724 }
01725 
01726 VALUE
01727 rb_thread_current(void)
01728 {
01729     return GET_THREAD()->self;
01730 }
01731 
01732 /*
01733  *  call-seq:
01734  *     Thread.current   -> thread
01735  *
01736  *  Returns the currently executing thread.
01737  *
01738  *     Thread.current   #=> #<Thread:0x401bdf4c run>
01739  */
01740 
01741 static VALUE
01742 thread_s_current(VALUE klass)
01743 {
01744     return rb_thread_current();
01745 }
01746 
01747 VALUE
01748 rb_thread_main(void)
01749 {
01750     return GET_THREAD()->vm->main_thread->self;
01751 }
01752 
01753 /*
01754  *  call-seq:
01755  *     Thread.main   -> thread
01756  *
01757  *  Returns the main thread.
01758  */
01759 
01760 static VALUE
01761 rb_thread_s_main(VALUE klass)
01762 {
01763     return rb_thread_main();
01764 }
01765 
01766 
01767 /*
01768  *  call-seq:
01769  *     Thread.abort_on_exception   -> true or false
01770  *
01771  *  Returns the status of the global ``abort on exception'' condition.  The
01772  *  default is <code>false</code>. When set to <code>true</code>, or if the
01773  *  global <code>$DEBUG</code> flag is <code>true</code> (perhaps because the
01774  *  command line option <code>-d</code> was specified) all threads will abort
01775  *  (the process will <code>exit(0)</code>) if an exception is raised in any
01776  *  thread. See also <code>Thread::abort_on_exception=</code>.
01777  */
01778 
01779 static VALUE
01780 rb_thread_s_abort_exc(void)
01781 {
01782     return GET_THREAD()->vm->thread_abort_on_exception ? Qtrue : Qfalse;
01783 }
01784 
01785 
01786 /*
01787  *  call-seq:
01788  *     Thread.abort_on_exception= boolean   -> true or false
01789  *
01790  *  When set to <code>true</code>, all threads will abort if an exception is
01791  *  raised. Returns the new state.
01792  *
01793  *     Thread.abort_on_exception = true
01794  *     t1 = Thread.new do
01795  *       puts  "In new thread"
01796  *       raise "Exception from thread"
01797  *     end
01798  *     sleep(1)
01799  *     puts "not reached"
01800  *
01801  *  <em>produces:</em>
01802  *
01803  *     In new thread
01804  *     prog.rb:4: Exception from thread (RuntimeError)
01805  *      from prog.rb:2:in `initialize'
01806  *      from prog.rb:2:in `new'
01807  *      from prog.rb:2
01808  */
01809 
01810 static VALUE
01811 rb_thread_s_abort_exc_set(VALUE self, VALUE val)
01812 {
01813     rb_secure(4);
01814     GET_THREAD()->vm->thread_abort_on_exception = RTEST(val);
01815     return val;
01816 }
01817 
01818 
01819 /*
01820  *  call-seq:
01821  *     thr.abort_on_exception   -> true or false
01822  *
01823  *  Returns the status of the thread-local ``abort on exception'' condition for
01824  *  <i>thr</i>. The default is <code>false</code>. See also
01825  *  <code>Thread::abort_on_exception=</code>.
01826  */
01827 
01828 static VALUE
01829 rb_thread_abort_exc(VALUE thread)
01830 {
01831     rb_thread_t *th;
01832     GetThreadPtr(thread, th);
01833     return th->abort_on_exception ? Qtrue : Qfalse;
01834 }
01835 
01836 
01837 /*
01838  *  call-seq:
01839  *     thr.abort_on_exception= boolean   -> true or false
01840  *
01841  *  When set to <code>true</code>, causes all threads (including the main
01842  *  program) to abort if an exception is raised in <i>thr</i>. The process will
01843  *  effectively <code>exit(0)</code>.
01844  */
01845 
01846 static VALUE
01847 rb_thread_abort_exc_set(VALUE thread, VALUE val)
01848 {
01849     rb_thread_t *th;
01850     rb_secure(4);
01851 
01852     GetThreadPtr(thread, th);
01853     th->abort_on_exception = RTEST(val);
01854     return val;
01855 }
01856 
01857 
01858 /*
01859  *  call-seq:
01860  *     thr.group   -> thgrp or nil
01861  *
01862  *  Returns the <code>ThreadGroup</code> which contains <i>thr</i>, or nil if
01863  *  the thread is not a member of any group.
01864  *
01865  *     Thread.main.group   #=> #<ThreadGroup:0x4029d914>
01866  */
01867 
01868 VALUE
01869 rb_thread_group(VALUE thread)
01870 {
01871     rb_thread_t *th;
01872     VALUE group;
01873     GetThreadPtr(thread, th);
01874     group = th->thgroup;
01875 
01876     if (!group) {
01877         group = Qnil;
01878     }
01879     return group;
01880 }
01881 
01882 static const char *
01883 thread_status_name(enum rb_thread_status status)
01884 {
01885     switch (status) {
01886       case THREAD_RUNNABLE:
01887         return "run";
01888       case THREAD_STOPPED:
01889       case THREAD_STOPPED_FOREVER:
01890         return "sleep";
01891       case THREAD_TO_KILL:
01892         return "aborting";
01893       case THREAD_KILLED:
01894         return "dead";
01895       default:
01896         return "unknown";
01897     }
01898 }
01899 
01900 static int
01901 rb_threadptr_dead(rb_thread_t *th)
01902 {
01903     return th->status == THREAD_KILLED;
01904 }
01905 
01906 
01907 /*
01908  *  call-seq:
01909  *     thr.status   -> string, false or nil
01910  *
01911  *  Returns the status of <i>thr</i>: ``<code>sleep</code>'' if <i>thr</i> is
01912  *  sleeping or waiting on I/O, ``<code>run</code>'' if <i>thr</i> is executing,
01913  *  ``<code>aborting</code>'' if <i>thr</i> is aborting, <code>false</code> if
01914  *  <i>thr</i> terminated normally, and <code>nil</code> if <i>thr</i>
01915  *  terminated with an exception.
01916  *
01917  *     a = Thread.new { raise("die now") }
01918  *     b = Thread.new { Thread.stop }
01919  *     c = Thread.new { Thread.exit }
01920  *     d = Thread.new { sleep }
01921  *     d.kill                  #=> #<Thread:0x401b3678 aborting>
01922  *     a.status                #=> nil
01923  *     b.status                #=> "sleep"
01924  *     c.status                #=> false
01925  *     d.status                #=> "aborting"
01926  *     Thread.current.status   #=> "run"
01927  */
01928 
01929 static VALUE
01930 rb_thread_status(VALUE thread)
01931 {
01932     rb_thread_t *th;
01933     GetThreadPtr(thread, th);
01934 
01935     if (rb_threadptr_dead(th)) {
01936         if (!NIL_P(th->errinfo) && !FIXNUM_P(th->errinfo)
01937             /* TODO */ ) {
01938             return Qnil;
01939         }
01940         return Qfalse;
01941     }
01942     return rb_str_new2(thread_status_name(th->status));
01943 }
01944 
01945 
01946 /*
01947  *  call-seq:
01948  *     thr.alive?   -> true or false
01949  *
01950  *  Returns <code>true</code> if <i>thr</i> is running or sleeping.
01951  *
01952  *     thr = Thread.new { }
01953  *     thr.join                #=> #<Thread:0x401b3fb0 dead>
01954  *     Thread.current.alive?   #=> true
01955  *     thr.alive?              #=> false
01956  */
01957 
01958 static VALUE
01959 rb_thread_alive_p(VALUE thread)
01960 {
01961     rb_thread_t *th;
01962     GetThreadPtr(thread, th);
01963 
01964     if (rb_threadptr_dead(th))
01965         return Qfalse;
01966     return Qtrue;
01967 }
01968 
01969 /*
01970  *  call-seq:
01971  *     thr.stop?   -> true or false
01972  *
01973  *  Returns <code>true</code> if <i>thr</i> is dead or sleeping.
01974  *
01975  *     a = Thread.new { Thread.stop }
01976  *     b = Thread.current
01977  *     a.stop?   #=> true
01978  *     b.stop?   #=> false
01979  */
01980 
01981 static VALUE
01982 rb_thread_stop_p(VALUE thread)
01983 {
01984     rb_thread_t *th;
01985     GetThreadPtr(thread, th);
01986 
01987     if (rb_threadptr_dead(th))
01988         return Qtrue;
01989     if (th->status == THREAD_STOPPED || th->status == THREAD_STOPPED_FOREVER)
01990         return Qtrue;
01991     return Qfalse;
01992 }
01993 
01994 /*
01995  *  call-seq:
01996  *     thr.safe_level   -> integer
01997  *
01998  *  Returns the safe level in effect for <i>thr</i>. Setting thread-local safe
01999  *  levels can help when implementing sandboxes which run insecure code.
02000  *
02001  *     thr = Thread.new { $SAFE = 3; sleep }
02002  *     Thread.current.safe_level   #=> 0
02003  *     thr.safe_level              #=> 3
02004  */
02005 
02006 static VALUE
02007 rb_thread_safe_level(VALUE thread)
02008 {
02009     rb_thread_t *th;
02010     GetThreadPtr(thread, th);
02011 
02012     return INT2NUM(th->safe_level);
02013 }
02014 
02015 /*
02016  * call-seq:
02017  *   thr.inspect   -> string
02018  *
02019  * Dump the name, id, and status of _thr_ to a string.
02020  */
02021 
02022 static VALUE
02023 rb_thread_inspect(VALUE thread)
02024 {
02025     const char *cname = rb_obj_classname(thread);
02026     rb_thread_t *th;
02027     const char *status;
02028     VALUE str;
02029 
02030     GetThreadPtr(thread, th);
02031     status = thread_status_name(th->status);
02032     str = rb_sprintf("#<%s:%p %s>", cname, (void *)thread, status);
02033     OBJ_INFECT(str, thread);
02034 
02035     return str;
02036 }
02037 
02038 VALUE
02039 rb_thread_local_aref(VALUE thread, ID id)
02040 {
02041     rb_thread_t *th;
02042     st_data_t val;
02043 
02044     GetThreadPtr(thread, th);
02045     if (rb_safe_level() >= 4 && th != GET_THREAD()) {
02046         rb_raise(rb_eSecurityError, "Insecure: thread locals");
02047     }
02048     if (!th->local_storage) {
02049         return Qnil;
02050     }
02051     if (st_lookup(th->local_storage, id, &val)) {
02052         return (VALUE)val;
02053     }
02054     return Qnil;
02055 }
02056 
02057 /*
02058  *  call-seq:
02059  *      thr[sym]   -> obj or nil
02060  *
02061  *  Attribute Reference---Returns the value of a thread-local variable, using
02062  *  either a symbol or a string name. If the specified variable does not exist,
02063  *  returns <code>nil</code>.
02064  *
02065  *     [
02066  *       Thread.new { Thread.current["name"] = "A" },
02067  *       Thread.new { Thread.current[:name]  = "B" },
02068  *       Thread.new { Thread.current["name"] = "C" }
02069  *     ].each do |th|
02070  *       th.join
02071  *       puts "#{th.inspect}: #{th[:name]}"
02072  *     end
02073  *
02074  *  <em>produces:</em>
02075  *
02076  *     #<Thread:0x00000002a54220 dead>: A
02077  *     #<Thread:0x00000002a541a8 dead>: B
02078  *     #<Thread:0x00000002a54130 dead>: C
02079  */
02080 
02081 static VALUE
02082 rb_thread_aref(VALUE thread, VALUE id)
02083 {
02084     return rb_thread_local_aref(thread, rb_to_id(id));
02085 }
02086 
02087 VALUE
02088 rb_thread_local_aset(VALUE thread, ID id, VALUE val)
02089 {
02090     rb_thread_t *th;
02091     GetThreadPtr(thread, th);
02092 
02093     if (rb_safe_level() >= 4 && th != GET_THREAD()) {
02094         rb_raise(rb_eSecurityError, "Insecure: can't modify thread locals");
02095     }
02096     if (OBJ_FROZEN(thread)) {
02097         rb_error_frozen("thread locals");
02098     }
02099     if (!th->local_storage) {
02100         th->local_storage = st_init_numtable();
02101     }
02102     if (NIL_P(val)) {
02103         st_delete_wrap(th->local_storage, id);
02104         return Qnil;
02105     }
02106     st_insert(th->local_storage, id, val);
02107     return val;
02108 }
02109 
02110 /*
02111  *  call-seq:
02112  *      thr[sym] = obj   -> obj
02113  *
02114  *  Attribute Assignment---Sets or creates the value of a thread-local variable,
02115  *  using either a symbol or a string. See also <code>Thread#[]</code>.
02116  */
02117 
02118 static VALUE
02119 rb_thread_aset(VALUE self, VALUE id, VALUE val)
02120 {
02121     return rb_thread_local_aset(self, rb_to_id(id), val);
02122 }
02123 
02124 /*
02125  *  call-seq:
02126  *     thr.key?(sym)   -> true or false
02127  *
02128  *  Returns <code>true</code> if the given string (or symbol) exists as a
02129  *  thread-local variable.
02130  *
02131  *     me = Thread.current
02132  *     me[:oliver] = "a"
02133  *     me.key?(:oliver)    #=> true
02134  *     me.key?(:stanley)   #=> false
02135  */
02136 
02137 static VALUE
02138 rb_thread_key_p(VALUE self, VALUE key)
02139 {
02140     rb_thread_t *th;
02141     ID id = rb_to_id(key);
02142 
02143     GetThreadPtr(self, th);
02144 
02145     if (!th->local_storage) {
02146         return Qfalse;
02147     }
02148     if (st_lookup(th->local_storage, id, 0)) {
02149         return Qtrue;
02150     }
02151     return Qfalse;
02152 }
02153 
02154 static int
02155 thread_keys_i(ID key, VALUE value, VALUE ary)
02156 {
02157     rb_ary_push(ary, ID2SYM(key));
02158     return ST_CONTINUE;
02159 }
02160 
02161 static int
02162 vm_living_thread_num(rb_vm_t *vm)
02163 {
02164     return vm->living_threads->num_entries;
02165 }
02166 
02167 int
02168 rb_thread_alone(void)
02169 {
02170     int num = 1;
02171     if (GET_THREAD()->vm->living_threads) {
02172         num = vm_living_thread_num(GET_THREAD()->vm);
02173         thread_debug("rb_thread_alone: %d\n", num);
02174     }
02175     return num == 1;
02176 }
02177 
02178 /*
02179  *  call-seq:
02180  *     thr.keys   -> array
02181  *
02182  *  Returns an an array of the names of the thread-local variables (as Symbols).
02183  *
02184  *     thr = Thread.new do
02185  *       Thread.current[:cat] = 'meow'
02186  *       Thread.current["dog"] = 'woof'
02187  *     end
02188  *     thr.join   #=> #<Thread:0x401b3f10 dead>
02189  *     thr.keys   #=> [:dog, :cat]
02190  */
02191 
02192 static VALUE
02193 rb_thread_keys(VALUE self)
02194 {
02195     rb_thread_t *th;
02196     VALUE ary = rb_ary_new();
02197     GetThreadPtr(self, th);
02198 
02199     if (th->local_storage) {
02200         st_foreach(th->local_storage, thread_keys_i, ary);
02201     }
02202     return ary;
02203 }
02204 
02205 /*
02206  *  call-seq:
02207  *     thr.priority   -> integer
02208  *
02209  *  Returns the priority of <i>thr</i>. Default is inherited from the
02210  *  current thread which creating the new thread, or zero for the
02211  *  initial main thread; higher-priority thread will run more frequently
02212  *  than lower-priority threads (but lower-priority threads can also run).
02213  *
02214  *  This is just hint for Ruby thread scheduler.  It may be ignored on some
02215  *  platform.
02216  *
02217  *     Thread.current.priority   #=> 0
02218  */
02219 
02220 static VALUE
02221 rb_thread_priority(VALUE thread)
02222 {
02223     rb_thread_t *th;
02224     GetThreadPtr(thread, th);
02225     return INT2NUM(th->priority);
02226 }
02227 
02228 
02229 /*
02230  *  call-seq:
02231  *     thr.priority= integer   -> thr
02232  *
02233  *  Sets the priority of <i>thr</i> to <i>integer</i>. Higher-priority threads
02234  *  will run more frequently than lower-priority threads (but lower-priority
02235  *  threads can also run).
02236  *
02237  *  This is just hint for Ruby thread scheduler.  It may be ignored on some
02238  *  platform.
02239  *
02240  *     count1 = count2 = 0
02241  *     a = Thread.new do
02242  *           loop { count1 += 1 }
02243  *         end
02244  *     a.priority = -1
02245  *
02246  *     b = Thread.new do
02247  *           loop { count2 += 1 }
02248  *         end
02249  *     b.priority = -2
02250  *     sleep 1   #=> 1
02251  *     count1    #=> 622504
02252  *     count2    #=> 5832
02253  */
02254 
02255 static VALUE
02256 rb_thread_priority_set(VALUE thread, VALUE prio)
02257 {
02258     rb_thread_t *th;
02259     int priority;
02260     GetThreadPtr(thread, th);
02261 
02262     rb_secure(4);
02263 
02264 #if USE_NATIVE_THREAD_PRIORITY
02265     th->priority = NUM2INT(prio);
02266     native_thread_apply_priority(th);
02267 #else
02268     priority = NUM2INT(prio);
02269     if (priority > RUBY_THREAD_PRIORITY_MAX) {
02270         priority = RUBY_THREAD_PRIORITY_MAX;
02271     }
02272     else if (priority < RUBY_THREAD_PRIORITY_MIN) {
02273         priority = RUBY_THREAD_PRIORITY_MIN;
02274     }
02275     th->priority = priority;
02276 #endif
02277     return INT2NUM(th->priority);
02278 }
02279 
02280 /* for IO */
02281 
02282 #if defined(NFDBITS) && defined(HAVE_RB_FD_INIT)
02283 
02284 /*
02285  * several Unix platforms support file descriptors bigger than FD_SETSIZE
02286  * in select(2) system call.
02287  *
02288  * - Linux 2.2.12 (?)
02289  * - NetBSD 1.2 (src/sys/kern/sys_generic.c:1.25)
02290  *   select(2) documents how to allocate fd_set dynamically.
02291  *   http://netbsd.gw.com/cgi-bin/man-cgi?select++NetBSD-4.0
02292  * - FreeBSD 2.2 (src/sys/kern/sys_generic.c:1.19)
02293  * - OpenBSD 2.0 (src/sys/kern/sys_generic.c:1.4)
02294  *   select(2) documents how to allocate fd_set dynamically.
02295  *   http://www.openbsd.org/cgi-bin/man.cgi?query=select&manpath=OpenBSD+4.4
02296  * - HP-UX documents how to allocate fd_set dynamically.
02297  *   http://docs.hp.com/en/B2355-60105/select.2.html
02298  * - Solaris 8 has select_large_fdset
02299  *
02300  * When fd_set is not big enough to hold big file descriptors,
02301  * it should be allocated dynamically.
02302  * Note that this assumes fd_set is structured as bitmap.
02303  *
02304  * rb_fd_init allocates the memory.
02305  * rb_fd_term free the memory.
02306  * rb_fd_set may re-allocates bitmap.
02307  *
02308  * So rb_fd_set doesn't reject file descriptors bigger than FD_SETSIZE.
02309  */
02310 
02311 void
02312 rb_fd_init(rb_fdset_t *fds)
02313 {
02314     fds->maxfd = 0;
02315     fds->fdset = ALLOC(fd_set);
02316     FD_ZERO(fds->fdset);
02317 }
02318 
02319 void
02320 rb_fd_init_copy(rb_fdset_t *dst, rb_fdset_t *src)
02321 {
02322     size_t size = howmany(rb_fd_max(src), NFDBITS) * sizeof(fd_mask);
02323 
02324     if (size < sizeof(fd_set))
02325         size = sizeof(fd_set);
02326     dst->maxfd = src->maxfd;
02327     dst->fdset = xmalloc(size);
02328     memcpy(dst->fdset, src->fdset, size);
02329 }
02330 
02331 void
02332 rb_fd_term(rb_fdset_t *fds)
02333 {
02334     if (fds->fdset) xfree(fds->fdset);
02335     fds->maxfd = 0;
02336     fds->fdset = 0;
02337 }
02338 
02339 void
02340 rb_fd_zero(rb_fdset_t *fds)
02341 {
02342     if (fds->fdset)
02343         MEMZERO(fds->fdset, fd_mask, howmany(fds->maxfd, NFDBITS));
02344 }
02345 
02346 static void
02347 rb_fd_resize(int n, rb_fdset_t *fds)
02348 {
02349     size_t m = howmany(n + 1, NFDBITS) * sizeof(fd_mask);
02350     size_t o = howmany(fds->maxfd, NFDBITS) * sizeof(fd_mask);
02351 
02352     if (m < sizeof(fd_set)) m = sizeof(fd_set);
02353     if (o < sizeof(fd_set)) o = sizeof(fd_set);
02354 
02355     if (m > o) {
02356         fds->fdset = xrealloc(fds->fdset, m);
02357         memset((char *)fds->fdset + o, 0, m - o);
02358     }
02359     if (n >= fds->maxfd) fds->maxfd = n + 1;
02360 }
02361 
02362 void
02363 rb_fd_set(int n, rb_fdset_t *fds)
02364 {
02365     rb_fd_resize(n, fds);
02366     FD_SET(n, fds->fdset);
02367 }
02368 
02369 void
02370 rb_fd_clr(int n, rb_fdset_t *fds)
02371 {
02372     if (n >= fds->maxfd) return;
02373     FD_CLR(n, fds->fdset);
02374 }
02375 
02376 int
02377 rb_fd_isset(int n, const rb_fdset_t *fds)
02378 {
02379     if (n >= fds->maxfd) return 0;
02380     return FD_ISSET(n, fds->fdset) != 0; /* "!= 0" avoids FreeBSD PR 91421 */
02381 }
02382 
02383 void
02384 rb_fd_copy(rb_fdset_t *dst, const fd_set *src, int max)
02385 {
02386     size_t size = howmany(max, NFDBITS) * sizeof(fd_mask);
02387 
02388     if (size < sizeof(fd_set)) size = sizeof(fd_set);
02389     dst->maxfd = max;
02390     dst->fdset = xrealloc(dst->fdset, size);
02391     memcpy(dst->fdset, src, size);
02392 }
02393 
02394 static void
02395 rb_fd_rcopy(fd_set *dst, rb_fdset_t *src)
02396 {
02397     size_t size = howmany(rb_fd_max(src), NFDBITS) * sizeof(fd_mask);
02398 
02399     if (size > sizeof(fd_set)) {
02400         rb_raise(rb_eArgError, "too large fdsets");
02401     }
02402     memcpy(dst, rb_fd_ptr(src), sizeof(fd_set));
02403 }
02404 
02405 void
02406 rb_fd_dup(rb_fdset_t *dst, const rb_fdset_t *src)
02407 {
02408     size_t size = howmany(rb_fd_max(src), NFDBITS) * sizeof(fd_mask);
02409 
02410     if (size < sizeof(fd_set))
02411         size = sizeof(fd_set);
02412     dst->maxfd = src->maxfd;
02413     dst->fdset = xrealloc(dst->fdset, size);
02414     memcpy(dst->fdset, src->fdset, size);
02415 }
02416 
02417 int
02418 rb_fd_select(int n, rb_fdset_t *readfds, rb_fdset_t *writefds, rb_fdset_t *exceptfds, struct timeval *timeout)
02419 {
02420     fd_set *r = NULL, *w = NULL, *e = NULL;
02421     if (readfds) {
02422         rb_fd_resize(n - 1, readfds);
02423         r = rb_fd_ptr(readfds);
02424     }
02425     if (writefds) {
02426         rb_fd_resize(n - 1, writefds);
02427         w = rb_fd_ptr(writefds);
02428     }
02429     if (exceptfds) {
02430         rb_fd_resize(n - 1, exceptfds);
02431         e = rb_fd_ptr(exceptfds);
02432     }
02433     return select(n, r, w, e, timeout);
02434 }
02435 
02436 #undef FD_ZERO
02437 #undef FD_SET
02438 #undef FD_CLR
02439 #undef FD_ISSET
02440 
02441 #define FD_ZERO(f)      rb_fd_zero(f)
02442 #define FD_SET(i, f)    rb_fd_set((i), (f))
02443 #define FD_CLR(i, f)    rb_fd_clr((i), (f))
02444 #define FD_ISSET(i, f)  rb_fd_isset((i), (f))
02445 
02446 #elif defined(_WIN32)
02447 
02448 void
02449 rb_fd_init(rb_fdset_t *set)
02450 {
02451     set->capa = FD_SETSIZE;
02452     set->fdset = ALLOC(fd_set);
02453     FD_ZERO(set->fdset);
02454 }
02455 
02456 void
02457 rb_fd_init_copy(rb_fdset_t *dst, rb_fdset_t *src)
02458 {
02459     rb_fd_init(dst);
02460     rb_fd_dup(dst, src);
02461 }
02462 
02463 static void
02464 rb_fd_rcopy(fd_set *dst, rb_fdset_t *src)
02465 {
02466     int max = rb_fd_max(src);
02467 
02468     /* we assume src is the result of select() with dst, so dst should be
02469      * larger or equal than src. */
02470     if (max > FD_SETSIZE || max > dst->fd_count) {
02471         rb_raise(rb_eArgError, "too large fdsets");
02472     }
02473 
02474     memcpy(dst->fd_array, src->fdset->fd_array, max);
02475     dst->fd_count = max;
02476 }
02477 
02478 void
02479 rb_fd_term(rb_fdset_t *set)
02480 {
02481     xfree(set->fdset);
02482     set->fdset = NULL;
02483     set->capa = 0;
02484 }
02485 
02486 void
02487 rb_fd_set(int fd, rb_fdset_t *set)
02488 {
02489     unsigned int i;
02490     SOCKET s = rb_w32_get_osfhandle(fd);
02491 
02492     for (i = 0; i < set->fdset->fd_count; i++) {
02493         if (set->fdset->fd_array[i] == s) {
02494             return;
02495         }
02496     }
02497     if (set->fdset->fd_count >= (unsigned)set->capa) {
02498         set->capa = (set->fdset->fd_count / FD_SETSIZE + 1) * FD_SETSIZE;
02499         set->fdset = xrealloc(set->fdset, sizeof(unsigned int) + sizeof(SOCKET) * set->capa);
02500     }
02501     set->fdset->fd_array[set->fdset->fd_count++] = s;
02502 }
02503 
02504 #undef FD_ZERO
02505 #undef FD_SET
02506 #undef FD_CLR
02507 #undef FD_ISSET
02508 
02509 #define FD_ZERO(f)      rb_fd_zero(f)
02510 #define FD_SET(i, f)    rb_fd_set((i), (f))
02511 #define FD_CLR(i, f)    rb_fd_clr((i), (f))
02512 #define FD_ISSET(i, f)  rb_fd_isset((i), (f))
02513 
02514 #else
02515 #define rb_fd_rcopy(d, s) (*(d) = *(s))
02516 #endif
02517 
02518 #if defined(__CYGWIN__)
02519 static long
02520 cmp_tv(const struct timeval *a, const struct timeval *b)
02521 {
02522     long d = (a->tv_sec - b->tv_sec);
02523     return (d != 0) ? d : (a->tv_usec - b->tv_usec);
02524 }
02525 
02526 static int
02527 subtract_tv(struct timeval *rest, const struct timeval *wait)
02528 {
02529     if (rest->tv_sec < wait->tv_sec) {
02530         return 0;
02531     }
02532     while (rest->tv_usec < wait->tv_usec) {
02533         if (rest->tv_sec <= wait->tv_sec) {
02534             return 0;
02535         }
02536         rest->tv_sec -= 1;
02537         rest->tv_usec += 1000 * 1000;
02538     }
02539     rest->tv_sec -= wait->tv_sec;
02540     rest->tv_usec -= wait->tv_usec;
02541     return rest->tv_sec != 0 || rest->tv_usec != 0;
02542 }
02543 #endif
02544 
02545 static int
02546 do_select(int n, rb_fdset_t *read, rb_fdset_t *write, rb_fdset_t *except,
02547           struct timeval *timeout)
02548 {
02549     int result, lerrno;
02550     rb_fdset_t UNINITIALIZED_VAR(orig_read);
02551     rb_fdset_t UNINITIALIZED_VAR(orig_write);
02552     rb_fdset_t UNINITIALIZED_VAR(orig_except);
02553     double limit = 0;
02554     struct timeval wait_rest;
02555 # if defined(__CYGWIN__)
02556     struct timeval start_time;
02557 # endif
02558 
02559     if (timeout) {
02560 # if defined(__CYGWIN__)
02561         gettimeofday(&start_time, NULL);
02562         limit = (double)start_time.tv_sec + (double)start_time.tv_usec*1e-6;
02563 # else
02564         limit = timeofday();
02565 # endif
02566         limit += (double)timeout->tv_sec+(double)timeout->tv_usec*1e-6;
02567         wait_rest = *timeout;
02568         timeout = &wait_rest;
02569     }
02570 
02571     if (read)
02572         rb_fd_init_copy(&orig_read, read);
02573     if (write)
02574         rb_fd_init_copy(&orig_write, write);
02575     if (except)
02576         rb_fd_init_copy(&orig_except, except);
02577 
02578   retry:
02579     lerrno = 0;
02580 
02581 #if defined(__CYGWIN__)
02582     {
02583         int finish = 0;
02584         /* polling duration: 100ms */
02585         struct timeval wait_100ms, *wait;
02586         wait_100ms.tv_sec = 0;
02587         wait_100ms.tv_usec = 100 * 1000; /* 100 ms */
02588 
02589         do {
02590             wait = (timeout == 0 || cmp_tv(&wait_100ms, timeout) < 0) ? &wait_100ms : timeout;
02591             BLOCKING_REGION({
02592                 do {
02593                     result = rb_fd_select(n, read, write, except, wait);
02594                     if (result < 0) lerrno = errno;
02595                     if (result != 0) break;
02596 
02597                     if (read)
02598                         rb_fd_dup(read, &orig_read);
02599                     if (write)
02600                         rb_fd_dup(write, &orig_write);
02601                     if (except)
02602                         rb_fd_dup(except, &orig_except);
02603                     if (timeout) {
02604                         struct timeval elapsed;
02605                         gettimeofday(&elapsed, NULL);
02606                         subtract_tv(&elapsed, &start_time);
02607                         gettimeofday(&start_time, NULL);
02608                         if (!subtract_tv(timeout, &elapsed)) {
02609                             finish = 1;
02610                             break;
02611                         }
02612                         if (cmp_tv(&wait_100ms, timeout) > 0) wait = timeout;
02613                     }
02614                 } while (__th->interrupt_flag == 0);
02615             }, 0, 0);
02616         } while (result == 0 && !finish);
02617     }
02618 #elif defined(_WIN32)
02619     {
02620         rb_thread_t *th = GET_THREAD();
02621         BLOCKING_REGION({
02622             result = native_fd_select(n, read, write, except, timeout, th);
02623             if (result < 0) lerrno = errno;
02624         }, ubf_select, th);
02625     }
02626 #else
02627     BLOCKING_REGION({
02628         result = rb_fd_select(n, read, write, except, timeout);
02629         if (result < 0) lerrno = errno;
02630     }, ubf_select, GET_THREAD());
02631 #endif
02632 
02633     errno = lerrno;
02634 
02635     if (result < 0) {
02636         switch (errno) {
02637           case EINTR:
02638 #ifdef ERESTART
02639           case ERESTART:
02640 #endif
02641             if (read)
02642                 rb_fd_dup(read, &orig_read);
02643             if (write)
02644                 rb_fd_dup(write, &orig_write);
02645             if (except)
02646                 rb_fd_dup(except, &orig_except);
02647 
02648             if (timeout) {
02649                 double d = limit - timeofday();
02650 
02651                 wait_rest.tv_sec = (unsigned int)d;
02652                 wait_rest.tv_usec = (int)((d-(double)wait_rest.tv_sec)*1e6);
02653                 if (wait_rest.tv_sec < 0)  wait_rest.tv_sec = 0;
02654                 if (wait_rest.tv_usec < 0) wait_rest.tv_usec = 0;
02655             }
02656 
02657             goto retry;
02658           default:
02659             break;
02660         }
02661     }
02662 
02663     if (read)
02664         rb_fd_term(&orig_read);
02665     if (write)
02666         rb_fd_term(&orig_write);
02667     if (except)
02668         rb_fd_term(&orig_except);
02669 
02670     return result;
02671 }
02672 
02673 static void
02674 rb_thread_wait_fd_rw(int fd, int read)
02675 {
02676     int result = 0;
02677     int events = read ? RB_WAITFD_IN : RB_WAITFD_OUT;
02678 
02679     thread_debug("rb_thread_wait_fd_rw(%d, %s)\n", fd, read ? "read" : "write");
02680 
02681     if (fd < 0) {
02682         rb_raise(rb_eIOError, "closed stream");
02683     }
02684     if (rb_thread_alone()) return;
02685     while (result <= 0) {
02686         result = rb_wait_for_single_fd(fd, events, NULL);
02687 
02688         if (result < 0) {
02689             rb_sys_fail(0);
02690         }
02691     }
02692 
02693     thread_debug("rb_thread_wait_fd_rw(%d, %s): done\n", fd, read ? "read" : "write");
02694 }
02695 
02696 void
02697 rb_thread_wait_fd(int fd)
02698 {
02699     rb_thread_wait_fd_rw(fd, 1);
02700 }
02701 
02702 int
02703 rb_thread_fd_writable(int fd)
02704 {
02705     rb_thread_wait_fd_rw(fd, 0);
02706     return TRUE;
02707 }
02708 
02709 int
02710 rb_thread_select(int max, fd_set * read, fd_set * write, fd_set * except,
02711                  struct timeval *timeout)
02712 {
02713     rb_fdset_t fdsets[3];
02714     rb_fdset_t *rfds = NULL;
02715     rb_fdset_t *wfds = NULL;
02716     rb_fdset_t *efds = NULL;
02717     int retval;
02718 
02719     if (read) {
02720         rfds = &fdsets[0];
02721         rb_fd_init(rfds);
02722         rb_fd_copy(rfds, read, max);
02723     }
02724     if (write) {
02725         wfds = &fdsets[1];
02726         rb_fd_init(wfds);
02727         rb_fd_copy(wfds, write, max);
02728     }
02729     if (except) {
02730         efds = &fdsets[2];
02731         rb_fd_init(efds);
02732         rb_fd_copy(efds, except, max);
02733     }
02734 
02735     retval = rb_thread_fd_select(max, rfds, wfds, efds, timeout);
02736 
02737     if (rfds) {
02738         rb_fd_rcopy(read, rfds);
02739         rb_fd_term(rfds);
02740     }
02741     if (wfds) {
02742         rb_fd_rcopy(write, wfds);
02743         rb_fd_term(wfds);
02744     }
02745     if (efds) {
02746         rb_fd_rcopy(except, efds);
02747         rb_fd_term(efds);
02748     }
02749 
02750     return retval;
02751 }
02752 
02753 int
02754 rb_thread_fd_select(int max, rb_fdset_t * read, rb_fdset_t * write, rb_fdset_t * except,
02755                     struct timeval *timeout)
02756 {
02757     if (!read && !write && !except) {
02758         if (!timeout) {
02759             rb_thread_sleep_forever();
02760             return 0;
02761         }
02762         rb_thread_wait_for(*timeout);
02763         return 0;
02764     }
02765 
02766     if (read) {
02767         rb_fd_resize(max - 1, read);
02768     }
02769     if (write) {
02770         rb_fd_resize(max - 1, write);
02771     }
02772     if (except) {
02773         rb_fd_resize(max - 1, except);
02774     }
02775     return do_select(max, read, write, except, timeout);
02776 }
02777 
02778 /*
02779  * poll() is supported by many OSes, but so far Linux is the only
02780  * one we know of that supports using poll() in all places select()
02781  * would work.
02782  */
02783 #if defined(HAVE_POLL) && defined(linux)
02784 #  define USE_POLL
02785 #endif
02786 
02787 #ifdef USE_POLL
02788 
02789 /* The same with linux kernel. TODO: make platform independent definition. */
02790 #define POLLIN_SET (POLLRDNORM | POLLRDBAND | POLLIN | POLLHUP | POLLERR)
02791 #define POLLOUT_SET (POLLWRBAND | POLLWRNORM | POLLOUT | POLLERR)
02792 #define POLLEX_SET (POLLPRI)
02793 
02794 #define TIMET_MAX (~(time_t)0 <= 0 ? (time_t)((~(unsigned_time_t)0) >> 1) : (time_t)(~(unsigned_time_t)0))
02795 #define TIMET_MIN (~(time_t)0 <= 0 ? (time_t)(((unsigned_time_t)1) << (sizeof(time_t) * CHAR_BIT - 1)) : (time_t)0)
02796 
02797 #ifndef HAVE_PPOLL
02798 /* TODO: don't ignore sigmask */
02799 int ppoll(struct pollfd *fds, nfds_t nfds,
02800           const struct timespec *ts, const sigset_t *sigmask)
02801 {
02802     int timeout_ms;
02803 
02804     if (ts) {
02805         int tmp, tmp2;
02806 
02807         if (ts->tv_sec > TIMET_MAX/1000)
02808             timeout_ms = -1;
02809         else {
02810             tmp = ts->tv_sec * 1000;
02811             tmp2 = ts->tv_nsec / (1000 * 1000);
02812             if (TIMET_MAX - tmp < tmp2)
02813                 timeout_ms = -1;
02814             else
02815                 timeout_ms = tmp + tmp2;
02816         }
02817     } else
02818         timeout_ms = -1;
02819 
02820     return poll(fds, nfds, timeout_ms);
02821 }
02822 #endif
02823 
02824 /*
02825  * returns a mask of events
02826  */
02827 int
02828 rb_wait_for_single_fd(int fd, int events, struct timeval *tv)
02829 {
02830     struct pollfd fds;
02831     int result, lerrno;
02832     double limit = 0;
02833     struct timespec ts;
02834     struct timespec *timeout = NULL;
02835 
02836     if (tv) {
02837         ts.tv_sec = tv->tv_sec;
02838         ts.tv_nsec = tv->tv_usec * 1000;
02839         limit = timeofday();
02840         limit += (double)tv->tv_sec + (double)tv->tv_usec * 1e-6;
02841         timeout = &ts;
02842     }
02843 
02844     fds.fd = fd;
02845     fds.events = (short)events;
02846 
02847 retry:
02848     lerrno = 0;
02849     BLOCKING_REGION({
02850         result = ppoll(&fds, 1, timeout, NULL);
02851         if (result < 0) lerrno = errno;
02852     }, ubf_select, GET_THREAD());
02853 
02854     if (result < 0) {
02855         errno = lerrno;
02856         switch (errno) {
02857           case EINTR:
02858 #ifdef ERESTART
02859           case ERESTART:
02860 #endif
02861             if (timeout) {
02862                 double d = limit - timeofday();
02863 
02864                 ts.tv_sec = (long)d;
02865                 ts.tv_nsec = (long)((d - (double)ts.tv_sec) * 1e9);
02866                 if (ts.tv_sec < 0)
02867                     ts.tv_sec = 0;
02868                 if (ts.tv_nsec < 0)
02869                     ts.tv_nsec = 0;
02870             }
02871             goto retry;
02872         }
02873         return -1;
02874     }
02875 
02876     if (fds.revents & POLLNVAL) {
02877         errno = EBADF;
02878         return -1;
02879     }
02880 
02881     /*
02882      * POLLIN, POLLOUT have a different meanings from select(2)'s read/write bit.
02883      * Therefore we need fix it up.
02884      */
02885     result = 0;
02886     if (fds.revents & POLLIN_SET)
02887         result |= RB_WAITFD_IN;
02888     if (fds.revents & POLLOUT_SET)
02889         result |= RB_WAITFD_OUT;
02890     if (fds.revents & POLLEX_SET)
02891         result |= RB_WAITFD_PRI;
02892 
02893     return result;
02894 }
02895 #else /* ! USE_POLL - implement rb_io_poll_fd() using select() */
02896 static rb_fdset_t *init_set_fd(int fd, rb_fdset_t *fds)
02897 {
02898     rb_fd_init(fds);
02899     rb_fd_set(fd, fds);
02900 
02901     return fds;
02902 }
02903 
02904 struct select_args {
02905     union {
02906         int fd;
02907         int error;
02908     } as;
02909     rb_fdset_t *read;
02910     rb_fdset_t *write;
02911     rb_fdset_t *except;
02912     struct timeval *tv;
02913 };
02914 
02915 static VALUE
02916 select_single(VALUE ptr)
02917 {
02918     struct select_args *args = (struct select_args *)ptr;
02919     int r;
02920 
02921     r = rb_thread_fd_select(args->as.fd + 1,
02922                             args->read, args->write, args->except, args->tv);
02923     if (r == -1)
02924         args->as.error = errno;
02925     if (r > 0) {
02926         r = 0;
02927         if (args->read && rb_fd_isset(args->as.fd, args->read))
02928             r |= RB_WAITFD_IN;
02929         if (args->write && rb_fd_isset(args->as.fd, args->write))
02930             r |= RB_WAITFD_OUT;
02931         if (args->except && rb_fd_isset(args->as.fd, args->except))
02932             r |= RB_WAITFD_PRI;
02933     }
02934     return (VALUE)r;
02935 }
02936 
02937 static VALUE
02938 select_single_cleanup(VALUE ptr)
02939 {
02940     struct select_args *args = (struct select_args *)ptr;
02941 
02942     if (args->read) rb_fd_term(args->read);
02943     if (args->write) rb_fd_term(args->write);
02944     if (args->except) rb_fd_term(args->except);
02945 
02946     return (VALUE)-1;
02947 }
02948 
02949 int
02950 rb_wait_for_single_fd(int fd, int events, struct timeval *tv)
02951 {
02952     rb_fdset_t rfds, wfds, efds;
02953     struct select_args args;
02954     int r;
02955     VALUE ptr = (VALUE)&args;
02956 
02957     args.as.fd = fd;
02958     args.read = (events & RB_WAITFD_IN) ? init_set_fd(fd, &rfds) : NULL;
02959     args.write = (events & RB_WAITFD_OUT) ? init_set_fd(fd, &wfds) : NULL;
02960     args.except = (events & RB_WAITFD_PRI) ? init_set_fd(fd, &efds) : NULL;
02961     args.tv = tv;
02962 
02963     r = (int)rb_ensure(select_single, ptr, select_single_cleanup, ptr);
02964     if (r == -1)
02965         errno = args.as.error;
02966 
02967     return r;
02968 }
02969 #endif /* ! USE_POLL */
02970 
02971 /*
02972  * for GC
02973  */
02974 
02975 #ifdef USE_CONSERVATIVE_STACK_END
02976 void
02977 rb_gc_set_stack_end(VALUE **stack_end_p)
02978 {
02979     VALUE stack_end;
02980     *stack_end_p = &stack_end;
02981 }
02982 #endif
02983 
02984 void
02985 rb_gc_save_machine_context(rb_thread_t *th)
02986 {
02987     FLUSH_REGISTER_WINDOWS;
02988 #ifdef __ia64
02989     th->machine_register_stack_end = rb_ia64_bsp();
02990 #endif
02991     setjmp(th->machine_regs);
02992 }
02993 
02994 /*
02995  *
02996  */
02997 
02998 void
02999 rb_threadptr_check_signal(rb_thread_t *mth)
03000 {
03001     /* mth must be main_thread */
03002     if (rb_signal_buff_size() > 0) {
03003         /* wakeup main thread */
03004         rb_threadptr_interrupt(mth);
03005     }
03006 }
03007 
03008 static void
03009 timer_thread_function(void *arg)
03010 {
03011     rb_vm_t *vm = GET_VM(); /* TODO: fix me for Multi-VM */
03012 
03013     /* for time slice */
03014     RUBY_VM_SET_TIMER_INTERRUPT(vm->running_thread);
03015 
03016     /* check signal */
03017     rb_threadptr_check_signal(vm->main_thread);
03018 
03019 #if 0
03020     /* prove profiler */
03021     if (vm->prove_profile.enable) {
03022         rb_thread_t *th = vm->running_thread;
03023 
03024         if (vm->during_gc) {
03025             /* GC prove profiling */
03026         }
03027     }
03028 #endif
03029 }
03030 
03031 void
03032 rb_thread_stop_timer_thread(int close_anyway)
03033 {
03034     if (timer_thread_id && native_stop_timer_thread(close_anyway)) {
03035         native_reset_timer_thread();
03036     }
03037 }
03038 
03039 void
03040 rb_thread_reset_timer_thread(void)
03041 {
03042     native_reset_timer_thread();
03043 }
03044 
03045 void
03046 rb_thread_start_timer_thread(void)
03047 {
03048     system_working = 1;
03049     rb_thread_create_timer_thread();
03050 }
03051 
03052 static int
03053 clear_coverage_i(st_data_t key, st_data_t val, st_data_t dummy)
03054 {
03055     int i;
03056     VALUE lines = (VALUE)val;
03057 
03058     for (i = 0; i < RARRAY_LEN(lines); i++) {
03059         if (RARRAY_PTR(lines)[i] != Qnil) {
03060             RARRAY_PTR(lines)[i] = INT2FIX(0);
03061         }
03062     }
03063     return ST_CONTINUE;
03064 }
03065 
03066 static void
03067 clear_coverage(void)
03068 {
03069     VALUE coverages = rb_get_coverages();
03070     if (RTEST(coverages)) {
03071         st_foreach(RHASH_TBL(coverages), clear_coverage_i, 0);
03072     }
03073 }
03074 
03075 static void
03076 rb_thread_atfork_internal(int (*atfork)(st_data_t, st_data_t, st_data_t))
03077 {
03078     rb_thread_t *th = GET_THREAD();
03079     rb_vm_t *vm = th->vm;
03080     VALUE thval = th->self;
03081     vm->main_thread = th;
03082 
03083     gvl_atfork(th->vm);
03084     st_foreach(vm->living_threads, atfork, (st_data_t)th);
03085     st_clear(vm->living_threads);
03086     st_insert(vm->living_threads, thval, (st_data_t)th->thread_id);
03087     vm->sleeper = 0;
03088     clear_coverage();
03089 }
03090 
03091 static int
03092 terminate_atfork_i(st_data_t key, st_data_t val, st_data_t current_th)
03093 {
03094     VALUE thval = key;
03095     rb_thread_t *th;
03096     GetThreadPtr(thval, th);
03097 
03098     if (th != (rb_thread_t *)current_th) {
03099         if (th->keeping_mutexes) {
03100             rb_mutex_abandon_all(th->keeping_mutexes);
03101         }
03102         th->keeping_mutexes = NULL;
03103         thread_cleanup_func(th, TRUE);
03104     }
03105     return ST_CONTINUE;
03106 }
03107 
03108 void
03109 rb_thread_atfork(void)
03110 {
03111     rb_thread_atfork_internal(terminate_atfork_i);
03112     GET_THREAD()->join_list_head = 0;
03113 
03114     /* We don't want reproduce CVE-2003-0900. */
03115     rb_reset_random_seed();
03116 }
03117 
03118 static int
03119 terminate_atfork_before_exec_i(st_data_t key, st_data_t val, st_data_t current_th)
03120 {
03121     VALUE thval = key;
03122     rb_thread_t *th;
03123     GetThreadPtr(thval, th);
03124 
03125     if (th != (rb_thread_t *)current_th) {
03126         thread_cleanup_func_before_exec(th);
03127     }
03128     return ST_CONTINUE;
03129 }
03130 
03131 void
03132 rb_thread_atfork_before_exec(void)
03133 {
03134     rb_thread_atfork_internal(terminate_atfork_before_exec_i);
03135 }
03136 
03137 struct thgroup {
03138     int enclosed;
03139     VALUE group;
03140 };
03141 
03142 static size_t
03143 thgroup_memsize(const void *ptr)
03144 {
03145     return ptr ? sizeof(struct thgroup) : 0;
03146 }
03147 
03148 static const rb_data_type_t thgroup_data_type = {
03149     "thgroup",
03150     {NULL, RUBY_TYPED_DEFAULT_FREE, thgroup_memsize,},
03151 };
03152 
03153 /*
03154  * Document-class: ThreadGroup
03155  *
03156  *  <code>ThreadGroup</code> provides a means of keeping track of a number of
03157  *  threads as a group. A <code>Thread</code> can belong to only one
03158  *  <code>ThreadGroup</code> at a time; adding a thread to a new group will
03159  *  remove it from any previous group.
03160  *
03161  *  Newly created threads belong to the same group as the thread from which they
03162  *  were created.
03163  */
03164 
03165 static VALUE
03166 thgroup_s_alloc(VALUE klass)
03167 {
03168     VALUE group;
03169     struct thgroup *data;
03170 
03171     group = TypedData_Make_Struct(klass, struct thgroup, &thgroup_data_type, data);
03172     data->enclosed = 0;
03173     data->group = group;
03174 
03175     return group;
03176 }
03177 
03178 struct thgroup_list_params {
03179     VALUE ary;
03180     VALUE group;
03181 };
03182 
03183 static int
03184 thgroup_list_i(st_data_t key, st_data_t val, st_data_t data)
03185 {
03186     VALUE thread = (VALUE)key;
03187     VALUE ary = ((struct thgroup_list_params *)data)->ary;
03188     VALUE group = ((struct thgroup_list_params *)data)->group;
03189     rb_thread_t *th;
03190     GetThreadPtr(thread, th);
03191 
03192     if (th->thgroup == group) {
03193         rb_ary_push(ary, thread);
03194     }
03195     return ST_CONTINUE;
03196 }
03197 
03198 /*
03199  *  call-seq:
03200  *     thgrp.list   -> array
03201  *
03202  *  Returns an array of all existing <code>Thread</code> objects that belong to
03203  *  this group.
03204  *
03205  *     ThreadGroup::Default.list   #=> [#<Thread:0x401bdf4c run>]
03206  */
03207 
03208 static VALUE
03209 thgroup_list(VALUE group)
03210 {
03211     VALUE ary = rb_ary_new();
03212     struct thgroup_list_params param;
03213 
03214     param.ary = ary;
03215     param.group = group;
03216     st_foreach(GET_THREAD()->vm->living_threads, thgroup_list_i, (st_data_t) & param);
03217     return ary;
03218 }
03219 
03220 
03221 /*
03222  *  call-seq:
03223  *     thgrp.enclose   -> thgrp
03224  *
03225  *  Prevents threads from being added to or removed from the receiving
03226  *  <code>ThreadGroup</code>. New threads can still be started in an enclosed
03227  *  <code>ThreadGroup</code>.
03228  *
03229  *     ThreadGroup::Default.enclose        #=> #<ThreadGroup:0x4029d914>
03230  *     thr = Thread::new { Thread.stop }   #=> #<Thread:0x402a7210 sleep>
03231  *     tg = ThreadGroup::new               #=> #<ThreadGroup:0x402752d4>
03232  *     tg.add thr
03233  *
03234  *  <em>produces:</em>
03235  *
03236  *     ThreadError: can't move from the enclosed thread group
03237  */
03238 
03239 static VALUE
03240 thgroup_enclose(VALUE group)
03241 {
03242     struct thgroup *data;
03243 
03244     TypedData_Get_Struct(group, struct thgroup, &thgroup_data_type, data);
03245     data->enclosed = 1;
03246 
03247     return group;
03248 }
03249 
03250 
03251 /*
03252  *  call-seq:
03253  *     thgrp.enclosed?   -> true or false
03254  *
03255  *  Returns <code>true</code> if <em>thgrp</em> is enclosed. See also
03256  *  ThreadGroup#enclose.
03257  */
03258 
03259 static VALUE
03260 thgroup_enclosed_p(VALUE group)
03261 {
03262     struct thgroup *data;
03263 
03264     TypedData_Get_Struct(group, struct thgroup, &thgroup_data_type, data);
03265     if (data->enclosed)
03266         return Qtrue;
03267     return Qfalse;
03268 }
03269 
03270 
03271 /*
03272  *  call-seq:
03273  *     thgrp.add(thread)   -> thgrp
03274  *
03275  *  Adds the given <em>thread</em> to this group, removing it from any other
03276  *  group to which it may have previously belonged.
03277  *
03278  *     puts "Initial group is #{ThreadGroup::Default.list}"
03279  *     tg = ThreadGroup.new
03280  *     t1 = Thread.new { sleep }
03281  *     t2 = Thread.new { sleep }
03282  *     puts "t1 is #{t1}"
03283  *     puts "t2 is #{t2}"
03284  *     tg.add(t1)
03285  *     puts "Initial group now #{ThreadGroup::Default.list}"
03286  *     puts "tg group now #{tg.list}"
03287  *
03288  *  <em>produces:</em>
03289  *
03290  *     Initial group is #<Thread:0x401bdf4c>
03291  *     t1 is #<Thread:0x401b3c90>
03292  *     t2 is #<Thread:0x401b3c18>
03293  *     Initial group now #<Thread:0x401b3c18>#<Thread:0x401bdf4c>
03294  *     tg group now #<Thread:0x401b3c90>
03295  */
03296 
03297 static VALUE
03298 thgroup_add(VALUE group, VALUE thread)
03299 {
03300     rb_thread_t *th;
03301     struct thgroup *data;
03302 
03303     rb_secure(4);
03304     GetThreadPtr(thread, th);
03305 
03306     if (OBJ_FROZEN(group)) {
03307         rb_raise(rb_eThreadError, "can't move to the frozen thread group");
03308     }
03309     TypedData_Get_Struct(group, struct thgroup, &thgroup_data_type, data);
03310     if (data->enclosed) {
03311         rb_raise(rb_eThreadError, "can't move to the enclosed thread group");
03312     }
03313 
03314     if (!th->thgroup) {
03315         return Qnil;
03316     }
03317 
03318     if (OBJ_FROZEN(th->thgroup)) {
03319         rb_raise(rb_eThreadError, "can't move from the frozen thread group");
03320     }
03321     TypedData_Get_Struct(th->thgroup, struct thgroup, &thgroup_data_type, data);
03322     if (data->enclosed) {
03323         rb_raise(rb_eThreadError,
03324                  "can't move from the enclosed thread group");
03325     }
03326 
03327     th->thgroup = group;
03328     return group;
03329 }
03330 
03331 
03332 /*
03333  *  Document-class: Mutex
03334  *
03335  *  Mutex implements a simple semaphore that can be used to coordinate access to
03336  *  shared data from multiple concurrent threads.
03337  *
03338  *  Example:
03339  *
03340  *    require 'thread'
03341  *    semaphore = Mutex.new
03342  *
03343  *    a = Thread.new {
03344  *      semaphore.synchronize {
03345  *        # access shared resource
03346  *      }
03347  *    }
03348  *
03349  *    b = Thread.new {
03350  *      semaphore.synchronize {
03351  *        # access shared resource
03352  *      }
03353  *    }
03354  *
03355  */
03356 
03357 #define GetMutexPtr(obj, tobj) \
03358     TypedData_Get_Struct((obj), rb_mutex_t, &mutex_data_type, (tobj))
03359 
03360 static const char *rb_mutex_unlock_th(rb_mutex_t *mutex, rb_thread_t volatile *th);
03361 
03362 #define mutex_mark NULL
03363 
03364 static void
03365 mutex_free(void *ptr)
03366 {
03367     if (ptr) {
03368         rb_mutex_t *mutex = ptr;
03369         if (mutex->th) {
03370             /* rb_warn("free locked mutex"); */
03371             const char *err = rb_mutex_unlock_th(mutex, mutex->th);
03372             if (err) rb_bug("%s", err);
03373         }
03374         native_mutex_destroy(&mutex->lock);
03375         native_cond_destroy(&mutex->cond);
03376     }
03377     ruby_xfree(ptr);
03378 }
03379 
03380 static size_t
03381 mutex_memsize(const void *ptr)
03382 {
03383     return ptr ? sizeof(rb_mutex_t) : 0;
03384 }
03385 
03386 static const rb_data_type_t mutex_data_type = {
03387     "mutex",
03388     {mutex_mark, mutex_free, mutex_memsize,},
03389 };
03390 
03391 VALUE
03392 rb_obj_is_mutex(VALUE obj)
03393 {
03394     if (rb_typeddata_is_kind_of(obj, &mutex_data_type)) {
03395         return Qtrue;
03396     }
03397     else {
03398         return Qfalse;
03399     }
03400 }
03401 
03402 static VALUE
03403 mutex_alloc(VALUE klass)
03404 {
03405     VALUE volatile obj;
03406     rb_mutex_t *mutex;
03407 
03408     obj = TypedData_Make_Struct(klass, rb_mutex_t, &mutex_data_type, mutex);
03409     native_mutex_initialize(&mutex->lock);
03410     native_cond_initialize(&mutex->cond, RB_CONDATTR_CLOCK_MONOTONIC);
03411     return obj;
03412 }
03413 
03414 /*
03415  *  call-seq:
03416  *     Mutex.new   -> mutex
03417  *
03418  *  Creates a new Mutex
03419  */
03420 static VALUE
03421 mutex_initialize(VALUE self)
03422 {
03423     return self;
03424 }
03425 
03426 VALUE
03427 rb_mutex_new(void)
03428 {
03429     return mutex_alloc(rb_cMutex);
03430 }
03431 
03432 /*
03433  * call-seq:
03434  *    mutex.locked?  -> true or false
03435  *
03436  * Returns +true+ if this lock is currently held by some thread.
03437  */
03438 VALUE
03439 rb_mutex_locked_p(VALUE self)
03440 {
03441     rb_mutex_t *mutex;
03442     GetMutexPtr(self, mutex);
03443     return mutex->th ? Qtrue : Qfalse;
03444 }
03445 
03446 static void
03447 mutex_locked(rb_thread_t *th, VALUE self)
03448 {
03449     rb_mutex_t *mutex;
03450     GetMutexPtr(self, mutex);
03451 
03452     if (th->keeping_mutexes) {
03453         mutex->next_mutex = th->keeping_mutexes;
03454     }
03455     th->keeping_mutexes = mutex;
03456 }
03457 
03458 /*
03459  * call-seq:
03460  *    mutex.try_lock  -> true or false
03461  *
03462  * Attempts to obtain the lock and returns immediately. Returns +true+ if the
03463  * lock was granted.
03464  */
03465 VALUE
03466 rb_mutex_trylock(VALUE self)
03467 {
03468     rb_mutex_t *mutex;
03469     VALUE locked = Qfalse;
03470     GetMutexPtr(self, mutex);
03471 
03472     native_mutex_lock(&mutex->lock);
03473     if (mutex->th == 0) {
03474         mutex->th = GET_THREAD();
03475         locked = Qtrue;
03476 
03477         mutex_locked(GET_THREAD(), self);
03478     }
03479     native_mutex_unlock(&mutex->lock);
03480 
03481     return locked;
03482 }
03483 
03484 static int
03485 lock_func(rb_thread_t *th, rb_mutex_t *mutex, int timeout_ms)
03486 {
03487     int interrupted = 0;
03488     int err = 0;
03489 
03490     mutex->cond_waiting++;
03491     for (;;) {
03492         if (!mutex->th) {
03493             mutex->th = th;
03494             break;
03495         }
03496         if (RUBY_VM_INTERRUPTED(th)) {
03497             interrupted = 1;
03498             break;
03499         }
03500         if (err == ETIMEDOUT) {
03501             interrupted = 2;
03502             break;
03503         }
03504 
03505         if (timeout_ms) {
03506             struct timespec timeout_rel;
03507             struct timespec timeout;
03508 
03509             timeout_rel.tv_sec = 0;
03510             timeout_rel.tv_nsec = timeout_ms * 1000 * 1000;
03511             timeout = native_cond_timeout(&mutex->cond, timeout_rel);
03512             err = native_cond_timedwait(&mutex->cond, &mutex->lock, &timeout);
03513         }
03514         else {
03515             native_cond_wait(&mutex->cond, &mutex->lock);
03516             err = 0;
03517         }
03518     }
03519     mutex->cond_waiting--;
03520 
03521     return interrupted;
03522 }
03523 
03524 static void
03525 lock_interrupt(void *ptr)
03526 {
03527     rb_mutex_t *mutex = (rb_mutex_t *)ptr;
03528     native_mutex_lock(&mutex->lock);
03529     if (mutex->cond_waiting > 0)
03530         native_cond_broadcast(&mutex->cond);
03531     native_mutex_unlock(&mutex->lock);
03532 }
03533 
03534 /*
03535  * At maximum, only one thread can use cond_timedwait and watch deadlock
03536  * periodically. Multiple polling thread (i.e. concurrent deadlock check)
03537  * introduces new race conditions. [Bug #6278] [ruby-core:44275]
03538  */
03539 rb_thread_t *patrol_thread = NULL;
03540 
03541 /*
03542  * call-seq:
03543  *    mutex.lock  -> self
03544  *
03545  * Attempts to grab the lock and waits if it isn't available.
03546  * Raises +ThreadError+ if +mutex+ was locked by the current thread.
03547  */
03548 VALUE
03549 rb_mutex_lock(VALUE self)
03550 {
03551 
03552     if (rb_mutex_trylock(self) == Qfalse) {
03553         rb_mutex_t *mutex;
03554         rb_thread_t *th = GET_THREAD();
03555         GetMutexPtr(self, mutex);
03556 
03557         if (mutex->th == GET_THREAD()) {
03558             rb_raise(rb_eThreadError, "deadlock; recursive locking");
03559         }
03560 
03561         while (mutex->th != th) {
03562             int interrupted;
03563             enum rb_thread_status prev_status = th->status;
03564             int timeout_ms = 0;
03565             struct rb_unblock_callback oldubf;
03566 
03567             set_unblock_function(th, lock_interrupt, mutex, &oldubf);
03568             th->status = THREAD_STOPPED_FOREVER;
03569             th->locking_mutex = self;
03570 
03571             native_mutex_lock(&mutex->lock);
03572             th->vm->sleeper++;
03573             /*
03574              * Carefully! while some contended threads are in lock_func(),
03575              * vm->sleepr is unstable value. we have to avoid both deadlock
03576              * and busy loop.
03577              */
03578             if ((vm_living_thread_num(th->vm) == th->vm->sleeper) &&
03579                 !patrol_thread) {
03580                 timeout_ms = 100;
03581                 patrol_thread = th;
03582             }
03583 
03584             GVL_UNLOCK_BEGIN();
03585             interrupted = lock_func(th, mutex, timeout_ms);
03586             native_mutex_unlock(&mutex->lock);
03587             GVL_UNLOCK_END();
03588 
03589             if (patrol_thread == th)
03590                 patrol_thread = NULL;
03591 
03592             reset_unblock_function(th, &oldubf);
03593 
03594             th->locking_mutex = Qfalse;
03595             if (mutex->th && interrupted == 2) {
03596                 rb_check_deadlock(th->vm);
03597             }
03598             if (th->status == THREAD_STOPPED_FOREVER) {
03599                 th->status = prev_status;
03600             }
03601             th->vm->sleeper--;
03602 
03603             if (mutex->th == th) mutex_locked(th, self);
03604 
03605             if (interrupted) {
03606                 RUBY_VM_CHECK_INTS();
03607             }
03608         }
03609     }
03610     return self;
03611 }
03612 
03613 static const char *
03614 rb_mutex_unlock_th(rb_mutex_t *mutex, rb_thread_t volatile *th)
03615 {
03616     const char *err = NULL;
03617     rb_mutex_t *th_mutex;
03618 
03619     native_mutex_lock(&mutex->lock);
03620 
03621     if (mutex->th == 0) {
03622         err = "Attempt to unlock a mutex which is not locked";
03623     }
03624     else if (mutex->th != th) {
03625         err = "Attempt to unlock a mutex which is locked by another thread";
03626     }
03627     else {
03628         mutex->th = 0;
03629         if (mutex->cond_waiting > 0)
03630             native_cond_signal(&mutex->cond);
03631     }
03632 
03633     native_mutex_unlock(&mutex->lock);
03634 
03635     if (!err) {
03636         th_mutex = th->keeping_mutexes;
03637         if (th_mutex == mutex) {
03638             th->keeping_mutexes = mutex->next_mutex;
03639         }
03640         else {
03641             while (1) {
03642                 rb_mutex_t *tmp_mutex;
03643                 tmp_mutex = th_mutex->next_mutex;
03644                 if (tmp_mutex == mutex) {
03645                     th_mutex->next_mutex = tmp_mutex->next_mutex;
03646                     break;
03647                 }
03648                 th_mutex = tmp_mutex;
03649             }
03650         }
03651         mutex->next_mutex = NULL;
03652     }
03653 
03654     return err;
03655 }
03656 
03657 /*
03658  * call-seq:
03659  *    mutex.unlock    -> self
03660  *
03661  * Releases the lock.
03662  * Raises +ThreadError+ if +mutex+ wasn't locked by the current thread.
03663  */
03664 VALUE
03665 rb_mutex_unlock(VALUE self)
03666 {
03667     const char *err;
03668     rb_mutex_t *mutex;
03669     GetMutexPtr(self, mutex);
03670 
03671     err = rb_mutex_unlock_th(mutex, GET_THREAD());
03672     if (err) rb_raise(rb_eThreadError, "%s", err);
03673 
03674     return self;
03675 }
03676 
03677 static void
03678 rb_mutex_abandon_all(rb_mutex_t *mutexes)
03679 {
03680     rb_mutex_t *mutex;
03681 
03682     while (mutexes) {
03683         mutex = mutexes;
03684         mutexes = mutex->next_mutex;
03685         mutex->th = 0;
03686         mutex->next_mutex = 0;
03687     }
03688 }
03689 
03690 static VALUE
03691 rb_mutex_sleep_forever(VALUE time)
03692 {
03693     rb_thread_sleep_deadly();
03694     return Qnil;
03695 }
03696 
03697 static VALUE
03698 rb_mutex_wait_for(VALUE time)
03699 {
03700     const struct timeval *t = (struct timeval *)time;
03701     rb_thread_wait_for(*t);
03702     return Qnil;
03703 }
03704 
03705 VALUE
03706 rb_mutex_sleep(VALUE self, VALUE timeout)
03707 {
03708     time_t beg, end;
03709     struct timeval t;
03710 
03711     if (!NIL_P(timeout)) {
03712         t = rb_time_interval(timeout);
03713     }
03714     rb_mutex_unlock(self);
03715     beg = time(0);
03716     if (NIL_P(timeout)) {
03717         rb_ensure(rb_mutex_sleep_forever, Qnil, rb_mutex_lock, self);
03718     }
03719     else {
03720         rb_ensure(rb_mutex_wait_for, (VALUE)&t, rb_mutex_lock, self);
03721     }
03722     end = time(0) - beg;
03723     return INT2FIX(end);
03724 }
03725 
03726 /*
03727  * call-seq:
03728  *    mutex.sleep(timeout = nil)    -> number
03729  *
03730  * Releases the lock and sleeps +timeout+ seconds if it is given and
03731  * non-nil or forever.  Raises +ThreadError+ if +mutex+ wasn't locked by
03732  * the current thread.
03733  */
03734 static VALUE
03735 mutex_sleep(int argc, VALUE *argv, VALUE self)
03736 {
03737     VALUE timeout;
03738 
03739     rb_scan_args(argc, argv, "01", &timeout);
03740     return rb_mutex_sleep(self, timeout);
03741 }
03742 
03743 /*
03744  * call-seq:
03745  *    mutex.synchronize { ... }    -> result of the block
03746  *
03747  * Obtains a lock, runs the block, and releases the lock when the block
03748  * completes.  See the example under +Mutex+.
03749  */
03750 
03751 VALUE
03752 rb_mutex_synchronize(VALUE mutex, VALUE (*func)(VALUE arg), VALUE arg)
03753 {
03754     rb_mutex_lock(mutex);
03755     return rb_ensure(func, arg, rb_mutex_unlock, mutex);
03756 }
03757 
03758 /*
03759  * Document-class: Barrier
03760  */
03761 static void
03762 barrier_mark(void *ptr)
03763 {
03764     rb_gc_mark((VALUE)ptr);
03765 }
03766 
03767 static const rb_data_type_t barrier_data_type = {
03768     "barrier",
03769     {barrier_mark, 0, 0,},
03770 };
03771 
03772 static VALUE
03773 barrier_alloc(VALUE klass)
03774 {
03775     return TypedData_Wrap_Struct(klass, &barrier_data_type, (void *)mutex_alloc(0));
03776 }
03777 
03778 #define GetBarrierPtr(obj) ((VALUE)rb_check_typeddata((obj), &barrier_data_type))
03779 
03780 VALUE
03781 rb_barrier_new(void)
03782 {
03783     VALUE barrier = barrier_alloc(rb_cBarrier);
03784     rb_mutex_lock((VALUE)DATA_PTR(barrier));
03785     return barrier;
03786 }
03787 
03788 VALUE
03789 rb_barrier_wait(VALUE self)
03790 {
03791     VALUE mutex = GetBarrierPtr(self);
03792     rb_mutex_t *m;
03793 
03794     if (!mutex) return Qfalse;
03795     GetMutexPtr(mutex, m);
03796     if (m->th == GET_THREAD()) return Qfalse;
03797     rb_mutex_lock(mutex);
03798     if (DATA_PTR(self)) return Qtrue;
03799     rb_mutex_unlock(mutex);
03800     return Qfalse;
03801 }
03802 
03803 VALUE
03804 rb_barrier_release(VALUE self)
03805 {
03806     return rb_mutex_unlock(GetBarrierPtr(self));
03807 }
03808 
03809 VALUE
03810 rb_barrier_destroy(VALUE self)
03811 {
03812     VALUE mutex = GetBarrierPtr(self);
03813     DATA_PTR(self) = 0;
03814     return rb_mutex_unlock(mutex);
03815 }
03816 
03817 /* variables for recursive traversals */
03818 static ID recursive_key;
03819 
03820 /*
03821  * Returns the current "recursive list" used to detect recursion.
03822  * This list is a hash table, unique for the current thread and for
03823  * the current __callee__.
03824  */
03825 
03826 static VALUE
03827 recursive_list_access(void)
03828 {
03829     volatile VALUE hash = rb_thread_local_aref(rb_thread_current(), recursive_key);
03830     VALUE sym = ID2SYM(rb_frame_this_func());
03831     VALUE list;
03832     if (NIL_P(hash) || TYPE(hash) != T_HASH) {
03833         hash = rb_hash_new();
03834         OBJ_UNTRUST(hash);
03835         rb_thread_local_aset(rb_thread_current(), recursive_key, hash);
03836         list = Qnil;
03837     }
03838     else {
03839         list = rb_hash_aref(hash, sym);
03840     }
03841     if (NIL_P(list) || TYPE(list) != T_HASH) {
03842         list = rb_hash_new();
03843         OBJ_UNTRUST(list);
03844         rb_hash_aset(hash, sym, list);
03845     }
03846     return list;
03847 }
03848 
03849 /*
03850  * Returns Qtrue iff obj_id (or the pair <obj, paired_obj>) is already
03851  * in the recursion list.
03852  * Assumes the recursion list is valid.
03853  */
03854 
03855 static VALUE
03856 recursive_check(VALUE list, VALUE obj_id, VALUE paired_obj_id)
03857 {
03858 #if SIZEOF_LONG == SIZEOF_VOIDP
03859   #define OBJ_ID_EQL(obj_id, other) ((obj_id) == (other))
03860 #elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
03861   #define OBJ_ID_EQL(obj_id, other) (RB_TYPE_P((obj_id), T_BIGNUM) ? \
03862     rb_big_eql((obj_id), (other)) : ((obj_id) == (other)))
03863 #endif
03864 
03865     VALUE pair_list = rb_hash_lookup2(list, obj_id, Qundef);
03866     if (pair_list == Qundef)
03867         return Qfalse;
03868     if (paired_obj_id) {
03869         if (TYPE(pair_list) != T_HASH) {
03870             if (!OBJ_ID_EQL(paired_obj_id, pair_list))
03871                 return Qfalse;
03872         }
03873         else {
03874             if (NIL_P(rb_hash_lookup(pair_list, paired_obj_id)))
03875                 return Qfalse;
03876         }
03877     }
03878     return Qtrue;
03879 }
03880 
03881 /*
03882  * Pushes obj_id (or the pair <obj_id, paired_obj_id>) in the recursion list.
03883  * For a single obj_id, it sets list[obj_id] to Qtrue.
03884  * For a pair, it sets list[obj_id] to paired_obj_id if possible,
03885  * otherwise list[obj_id] becomes a hash like:
03886  *   {paired_obj_id_1 => true, paired_obj_id_2 => true, ... }
03887  * Assumes the recursion list is valid.
03888  */
03889 
03890 static void
03891 recursive_push(VALUE list, VALUE obj, VALUE paired_obj)
03892 {
03893     VALUE pair_list;
03894 
03895     if (!paired_obj) {
03896         rb_hash_aset(list, obj, Qtrue);
03897     }
03898     else if ((pair_list = rb_hash_lookup2(list, obj, Qundef)) == Qundef) {
03899         rb_hash_aset(list, obj, paired_obj);
03900     }
03901     else {
03902         if (TYPE(pair_list) != T_HASH){
03903             VALUE other_paired_obj = pair_list;
03904             pair_list = rb_hash_new();
03905             OBJ_UNTRUST(pair_list);
03906             rb_hash_aset(pair_list, other_paired_obj, Qtrue);
03907             rb_hash_aset(list, obj, pair_list);
03908         }
03909         rb_hash_aset(pair_list, paired_obj, Qtrue);
03910     }
03911 }
03912 
03913 /*
03914  * Pops obj_id (or the pair <obj_id, paired_obj_id>) from the recursion list.
03915  * For a pair, if list[obj_id] is a hash, then paired_obj_id is
03916  * removed from the hash and no attempt is made to simplify
03917  * list[obj_id] from {only_one_paired_id => true} to only_one_paired_id
03918  * Assumes the recursion list is valid.
03919  */
03920 
03921 static void
03922 recursive_pop(VALUE list, VALUE obj, VALUE paired_obj)
03923 {
03924     if (paired_obj) {
03925         VALUE pair_list = rb_hash_lookup2(list, obj, Qundef);
03926         if (pair_list == Qundef) {
03927             VALUE symname = rb_inspect(ID2SYM(rb_frame_this_func()));
03928             VALUE thrname = rb_inspect(rb_thread_current());
03929             rb_raise(rb_eTypeError, "invalid inspect_tbl pair_list for %s in %s",
03930                      StringValuePtr(symname), StringValuePtr(thrname));
03931         }
03932         if (TYPE(pair_list) == T_HASH) {
03933             rb_hash_delete(pair_list, paired_obj);
03934             if (!RHASH_EMPTY_P(pair_list)) {
03935                 return; /* keep hash until is empty */
03936             }
03937         }
03938     }
03939     rb_hash_delete(list, obj);
03940 }
03941 
03942 struct exec_recursive_params {
03943     VALUE (*func) (VALUE, VALUE, int);
03944     VALUE list;
03945     VALUE obj;
03946     VALUE objid;
03947     VALUE pairid;
03948     VALUE arg;
03949 };
03950 
03951 static VALUE
03952 exec_recursive_i(VALUE tag, struct exec_recursive_params *p)
03953 {
03954     VALUE result = Qundef;
03955     int state;
03956 
03957     recursive_push(p->list, p->objid, p->pairid);
03958     PUSH_TAG();
03959     if ((state = EXEC_TAG()) == 0) {
03960         result = (*p->func)(p->obj, p->arg, FALSE);
03961     }
03962     POP_TAG();
03963     recursive_pop(p->list, p->objid, p->pairid);
03964     if (state)
03965         JUMP_TAG(state);
03966     return result;
03967 }
03968 
03969 /*
03970  * Calls func(obj, arg, recursive), where recursive is non-zero if the
03971  * current method is called recursively on obj, or on the pair <obj, pairid>
03972  * If outer is 0, then the innermost func will be called with recursive set
03973  * to Qtrue, otherwise the outermost func will be called. In the latter case,
03974  * all inner func are short-circuited by throw.
03975  * Implementation details: the value thrown is the recursive list which is
03976  * proper to the current method and unlikely to be catched anywhere else.
03977  * list[recursive_key] is used as a flag for the outermost call.
03978  */
03979 
03980 static VALUE
03981 exec_recursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE pairid, VALUE arg, int outer)
03982 {
03983     VALUE result = Qundef;
03984     struct exec_recursive_params p;
03985     int outermost;
03986     p.list = recursive_list_access();
03987     p.objid = rb_obj_id(obj);
03988     p.obj = obj;
03989     p.pairid = pairid;
03990     p.arg = arg;
03991     outermost = outer && !recursive_check(p.list, ID2SYM(recursive_key), 0);
03992 
03993     if (recursive_check(p.list, p.objid, pairid)) {
03994         if (outer && !outermost) {
03995             rb_throw_obj(p.list, p.list);
03996         }
03997         return (*func)(obj, arg, TRUE);
03998     }
03999     else {
04000         p.func = func;
04001 
04002         if (outermost) {
04003             recursive_push(p.list, ID2SYM(recursive_key), 0);
04004             result = rb_catch_obj(p.list, exec_recursive_i, (VALUE)&p);
04005             recursive_pop(p.list, ID2SYM(recursive_key), 0);
04006             if (result == p.list) {
04007                 result = (*func)(obj, arg, TRUE);
04008             }
04009         }
04010         else {
04011             result = exec_recursive_i(0, &p);
04012         }
04013     }
04014     *(volatile struct exec_recursive_params *)&p;
04015     return result;
04016 }
04017 
04018 /*
04019  * Calls func(obj, arg, recursive), where recursive is non-zero if the
04020  * current method is called recursively on obj
04021  */
04022 
04023 VALUE
04024 rb_exec_recursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE arg)
04025 {
04026     return exec_recursive(func, obj, 0, arg, 0);
04027 }
04028 
04029 /*
04030  * Calls func(obj, arg, recursive), where recursive is non-zero if the
04031  * current method is called recursively on the ordered pair <obj, paired_obj>
04032  */
04033 
04034 VALUE
04035 rb_exec_recursive_paired(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE paired_obj, VALUE arg)
04036 {
04037     return exec_recursive(func, obj, rb_obj_id(paired_obj), arg, 0);
04038 }
04039 
04040 /*
04041  * If recursion is detected on the current method and obj, the outermost
04042  * func will be called with (obj, arg, Qtrue). All inner func will be
04043  * short-circuited using throw.
04044  */
04045 
04046 VALUE
04047 rb_exec_recursive_outer(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE arg)
04048 {
04049     return exec_recursive(func, obj, 0, arg, 1);
04050 }
04051 
04052 /* tracer */
04053 #define RUBY_EVENT_REMOVED 0x1000000
04054 
04055 enum {
04056     EVENT_RUNNING_NOTHING,
04057     EVENT_RUNNING_TRACE = 1,
04058     EVENT_RUNNING_THREAD = 2,
04059     EVENT_RUNNING_VM = 4,
04060     EVENT_RUNNING_EVENT_MASK = EVENT_RUNNING_VM|EVENT_RUNNING_THREAD
04061 };
04062 
04063 static VALUE thread_suppress_tracing(rb_thread_t *th, int ev, VALUE (*func)(VALUE, int), VALUE arg, int always, int pop_p);
04064 
04065 struct event_call_args {
04066     rb_thread_t *th;
04067     VALUE klass;
04068     VALUE self;
04069     VALUE proc;
04070     ID id;
04071     rb_event_flag_t event;
04072 };
04073 
04074 static rb_event_hook_t *
04075 alloc_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data)
04076 {
04077     rb_event_hook_t *hook = ALLOC(rb_event_hook_t);
04078     hook->func = func;
04079     hook->flag = events;
04080     hook->data = data;
04081     return hook;
04082 }
04083 
04084 static void
04085 thread_reset_event_flags(rb_thread_t *th)
04086 {
04087     rb_event_hook_t *hook = th->event_hooks;
04088     rb_event_flag_t flag = th->event_flags & RUBY_EVENT_VM;
04089 
04090     while (hook) {
04091         if (!(flag & RUBY_EVENT_REMOVED))
04092             flag |= hook->flag;
04093         hook = hook->next;
04094     }
04095     th->event_flags = flag;
04096 }
04097 
04098 static void
04099 rb_threadptr_add_event_hook(rb_thread_t *th,
04100                          rb_event_hook_func_t func, rb_event_flag_t events, VALUE data)
04101 {
04102     rb_event_hook_t *hook = alloc_event_hook(func, events, data);
04103     hook->next = th->event_hooks;
04104     th->event_hooks = hook;
04105     thread_reset_event_flags(th);
04106 }
04107 
04108 static rb_thread_t *
04109 thval2thread_t(VALUE thval)
04110 {
04111     rb_thread_t *th;
04112     GetThreadPtr(thval, th);
04113     return th;
04114 }
04115 
04116 void
04117 rb_thread_add_event_hook(VALUE thval,
04118                          rb_event_hook_func_t func, rb_event_flag_t events, VALUE data)
04119 {
04120     rb_threadptr_add_event_hook(thval2thread_t(thval), func, events, data);
04121 }
04122 
04123 static int
04124 set_threads_event_flags_i(st_data_t key, st_data_t val, st_data_t flag)
04125 {
04126     VALUE thval = key;
04127     rb_thread_t *th;
04128     GetThreadPtr(thval, th);
04129 
04130     if (flag) {
04131         th->event_flags |= RUBY_EVENT_VM;
04132     }
04133     else {
04134         th->event_flags &= (~RUBY_EVENT_VM);
04135     }
04136     return ST_CONTINUE;
04137 }
04138 
04139 static void
04140 set_threads_event_flags(int flag)
04141 {
04142     st_foreach(GET_VM()->living_threads, set_threads_event_flags_i, (st_data_t) flag);
04143 }
04144 
04145 static inline int
04146 exec_event_hooks(const rb_event_hook_t *hook, rb_event_flag_t flag, VALUE self, ID id, VALUE klass)
04147 {
04148     int removed = 0;
04149     for (; hook; hook = hook->next) {
04150         if (hook->flag & RUBY_EVENT_REMOVED) {
04151             removed++;
04152             continue;
04153         }
04154         if (flag & hook->flag) {
04155             (*hook->func)(flag, hook->data, self, id, klass);
04156         }
04157     }
04158     return removed;
04159 }
04160 
04161 static int remove_defered_event_hook(rb_event_hook_t **root);
04162 
04163 static VALUE
04164 thread_exec_event_hooks(VALUE args, int running)
04165 {
04166     struct event_call_args *argp = (struct event_call_args *)args;
04167     rb_thread_t *th = argp->th;
04168     rb_event_flag_t flag = argp->event;
04169     VALUE self = argp->self;
04170     ID id = argp->id;
04171     VALUE klass = argp->klass;
04172     const rb_event_flag_t wait_event = th->event_flags;
04173     int removed;
04174 
04175     if (self == rb_mRubyVMFrozenCore) return 0;
04176 
04177     if ((wait_event & flag) && !(running & EVENT_RUNNING_THREAD)) {
04178         th->tracing |= EVENT_RUNNING_THREAD;
04179         removed = exec_event_hooks(th->event_hooks, flag, self, id, klass);
04180         th->tracing &= ~EVENT_RUNNING_THREAD;
04181         if (removed) {
04182             remove_defered_event_hook(&th->event_hooks);
04183         }
04184     }
04185     if (wait_event & RUBY_EVENT_VM) {
04186         if (th->vm->event_hooks == NULL) {
04187             th->event_flags &= (~RUBY_EVENT_VM);
04188         }
04189         else if (!(running & EVENT_RUNNING_VM)) {
04190             th->tracing |= EVENT_RUNNING_VM;
04191             removed = exec_event_hooks(th->vm->event_hooks, flag, self, id, klass);
04192             th->tracing &= ~EVENT_RUNNING_VM;
04193             if (removed) {
04194                 remove_defered_event_hook(&th->vm->event_hooks);
04195             }
04196         }
04197     }
04198     return 0;
04199 }
04200 
04201 void
04202 rb_threadptr_exec_event_hooks(rb_thread_t *th, rb_event_flag_t flag, VALUE self, ID id, VALUE klass, int pop_p)
04203 {
04204     const VALUE errinfo = th->errinfo;
04205     struct event_call_args args;
04206     args.th = th;
04207     args.event = flag;
04208     args.self = self;
04209     args.id = id;
04210     args.klass = klass;
04211     args.proc = 0;
04212     thread_suppress_tracing(th, EVENT_RUNNING_EVENT_MASK, thread_exec_event_hooks, (VALUE)&args, FALSE, pop_p);
04213     th->errinfo = errinfo;
04214 }
04215 
04216 void
04217 rb_add_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data)
04218 {
04219     rb_event_hook_t *hook = alloc_event_hook(func, events, data);
04220     rb_vm_t *vm = GET_VM();
04221 
04222     hook->next = vm->event_hooks;
04223     vm->event_hooks = hook;
04224 
04225     set_threads_event_flags(1);
04226 }
04227 
04228 static int
04229 defer_remove_event_hook(rb_event_hook_t *hook, rb_event_hook_func_t func)
04230 {
04231     while (hook) {
04232         if (func == 0 || hook->func == func) {
04233             hook->flag |= RUBY_EVENT_REMOVED;
04234         }
04235         hook = hook->next;
04236     }
04237     return -1;
04238 }
04239 
04240 static int
04241 remove_event_hook(rb_event_hook_t **root, rb_event_hook_func_t func)
04242 {
04243     rb_event_hook_t *hook = *root, *next;
04244 
04245     while (hook) {
04246         next = hook->next;
04247         if (func == 0 || hook->func == func || (hook->flag & RUBY_EVENT_REMOVED)) {
04248             *root = next;
04249             xfree(hook);
04250         }
04251         else {
04252             root = &hook->next;
04253         }
04254         hook = next;
04255     }
04256     return -1;
04257 }
04258 
04259 static int
04260 remove_defered_event_hook(rb_event_hook_t **root)
04261 {
04262     rb_event_hook_t *hook = *root, *next;
04263 
04264     while (hook) {
04265         next = hook->next;
04266         if (hook->flag & RUBY_EVENT_REMOVED) {
04267             *root = next;
04268             xfree(hook);
04269         }
04270         else {
04271             root = &hook->next;
04272         }
04273         hook = next;
04274     }
04275     return -1;
04276 }
04277 
04278 static int
04279 rb_threadptr_remove_event_hook(rb_thread_t *th, rb_event_hook_func_t func)
04280 {
04281     int ret;
04282     if (th->tracing & EVENT_RUNNING_THREAD) {
04283         ret = defer_remove_event_hook(th->event_hooks, func);
04284     }
04285     else {
04286         ret = remove_event_hook(&th->event_hooks, func);
04287     }
04288     thread_reset_event_flags(th);
04289     return ret;
04290 }
04291 
04292 int
04293 rb_thread_remove_event_hook(VALUE thval, rb_event_hook_func_t func)
04294 {
04295     return rb_threadptr_remove_event_hook(thval2thread_t(thval), func);
04296 }
04297 
04298 static rb_event_hook_t *
04299 search_live_hook(rb_event_hook_t *hook)
04300 {
04301     while (hook) {
04302         if (!(hook->flag & RUBY_EVENT_REMOVED))
04303             return hook;
04304         hook = hook->next;
04305     }
04306     return NULL;
04307 }
04308 
04309 static int
04310 running_vm_event_hooks(st_data_t key, st_data_t val, st_data_t data)
04311 {
04312     rb_thread_t *th = thval2thread_t((VALUE)key);
04313     if (!(th->tracing & EVENT_RUNNING_VM)) return ST_CONTINUE;
04314     *(rb_thread_t **)data = th;
04315     return ST_STOP;
04316 }
04317 
04318 static rb_thread_t *
04319 vm_event_hooks_running_thread(rb_vm_t *vm)
04320 {
04321     rb_thread_t *found = NULL;
04322     st_foreach(vm->living_threads, running_vm_event_hooks, (st_data_t)&found);
04323     return found;
04324 }
04325 
04326 int
04327 rb_remove_event_hook(rb_event_hook_func_t func)
04328 {
04329     rb_vm_t *vm = GET_VM();
04330     rb_event_hook_t *hook = search_live_hook(vm->event_hooks);
04331     int ret;
04332 
04333     if (vm_event_hooks_running_thread(vm)) {
04334         ret = defer_remove_event_hook(vm->event_hooks, func);
04335     }
04336     else {
04337         ret = remove_event_hook(&vm->event_hooks, func);
04338     }
04339 
04340     if (hook && !search_live_hook(vm->event_hooks)) {
04341         set_threads_event_flags(0);
04342     }
04343 
04344     return ret;
04345 }
04346 
04347 static int
04348 clear_trace_func_i(st_data_t key, st_data_t val, st_data_t flag)
04349 {
04350     rb_thread_t *th;
04351     GetThreadPtr((VALUE)key, th);
04352     rb_threadptr_remove_event_hook(th, 0);
04353     return ST_CONTINUE;
04354 }
04355 
04356 void
04357 rb_clear_trace_func(void)
04358 {
04359     st_foreach(GET_VM()->living_threads, clear_trace_func_i, (st_data_t) 0);
04360     rb_remove_event_hook(0);
04361 }
04362 
04363 static void call_trace_func(rb_event_flag_t, VALUE data, VALUE self, ID id, VALUE klass);
04364 
04365 /*
04366  *  call-seq:
04367  *     set_trace_func(proc)    -> proc
04368  *     set_trace_func(nil)     -> nil
04369  *
04370  *  Establishes _proc_ as the handler for tracing, or disables
04371  *  tracing if the parameter is +nil+. _proc_ takes up
04372  *  to six parameters: an event name, a filename, a line number, an
04373  *  object id, a binding, and the name of a class. _proc_ is
04374  *  invoked whenever an event occurs. Events are: <code>c-call</code>
04375  *  (call a C-language routine), <code>c-return</code> (return from a
04376  *  C-language routine), <code>call</code> (call a Ruby method),
04377  *  <code>class</code> (start a class or module definition),
04378  *  <code>end</code> (finish a class or module definition),
04379  *  <code>line</code> (execute code on a new line), <code>raise</code>
04380  *  (raise an exception), and <code>return</code> (return from a Ruby
04381  *  method). Tracing is disabled within the context of _proc_.
04382  *
04383  *      class Test
04384  *      def test
04385  *        a = 1
04386  *        b = 2
04387  *      end
04388  *      end
04389  *
04390  *      set_trace_func proc { |event, file, line, id, binding, classname|
04391  *         printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname
04392  *      }
04393  *      t = Test.new
04394  *      t.test
04395  *
04396  *        line prog.rb:11               false
04397  *      c-call prog.rb:11        new    Class
04398  *      c-call prog.rb:11 initialize   Object
04399  *    c-return prog.rb:11 initialize   Object
04400  *    c-return prog.rb:11        new    Class
04401  *        line prog.rb:12               false
04402  *        call prog.rb:2        test     Test
04403  *        line prog.rb:3        test     Test
04404  *        line prog.rb:4        test     Test
04405  *      return prog.rb:4        test     Test
04406  */
04407 
04408 static VALUE
04409 set_trace_func(VALUE obj, VALUE trace)
04410 {
04411     rb_remove_event_hook(call_trace_func);
04412 
04413     if (NIL_P(trace)) {
04414         GET_THREAD()->tracing = EVENT_RUNNING_NOTHING;
04415         return Qnil;
04416     }
04417 
04418     if (!rb_obj_is_proc(trace)) {
04419         rb_raise(rb_eTypeError, "trace_func needs to be Proc");
04420     }
04421 
04422     rb_add_event_hook(call_trace_func, RUBY_EVENT_ALL, trace);
04423     return trace;
04424 }
04425 
04426 static void
04427 thread_add_trace_func(rb_thread_t *th, VALUE trace)
04428 {
04429     if (!rb_obj_is_proc(trace)) {
04430         rb_raise(rb_eTypeError, "trace_func needs to be Proc");
04431     }
04432 
04433     rb_threadptr_add_event_hook(th, call_trace_func, RUBY_EVENT_ALL, trace);
04434 }
04435 
04436 /*
04437  *  call-seq:
04438  *     thr.add_trace_func(proc)    -> proc
04439  *
04440  *  Adds _proc_ as a handler for tracing.
04441  *  See <code>Thread#set_trace_func</code> and +set_trace_func+.
04442  */
04443 
04444 static VALUE
04445 thread_add_trace_func_m(VALUE obj, VALUE trace)
04446 {
04447     rb_thread_t *th;
04448     GetThreadPtr(obj, th);
04449     thread_add_trace_func(th, trace);
04450     return trace;
04451 }
04452 
04453 /*
04454  *  call-seq:
04455  *     thr.set_trace_func(proc)    -> proc
04456  *     thr.set_trace_func(nil)     -> nil
04457  *
04458  *  Establishes _proc_ on _thr_ as the handler for tracing, or
04459  *  disables tracing if the parameter is +nil+.
04460  *  See +set_trace_func+.
04461  */
04462 
04463 static VALUE
04464 thread_set_trace_func_m(VALUE obj, VALUE trace)
04465 {
04466     rb_thread_t *th;
04467     GetThreadPtr(obj, th);
04468     rb_threadptr_remove_event_hook(th, call_trace_func);
04469 
04470     if (NIL_P(trace)) {
04471         th->tracing = EVENT_RUNNING_NOTHING;
04472         return Qnil;
04473     }
04474     thread_add_trace_func(th, trace);
04475     return trace;
04476 }
04477 
04478 static const char *
04479 get_event_name(rb_event_flag_t event)
04480 {
04481     switch (event) {
04482       case RUBY_EVENT_LINE:
04483         return "line";
04484       case RUBY_EVENT_CLASS:
04485         return "class";
04486       case RUBY_EVENT_END:
04487         return "end";
04488       case RUBY_EVENT_CALL:
04489         return "call";
04490       case RUBY_EVENT_RETURN:
04491         return "return";
04492       case RUBY_EVENT_C_CALL:
04493         return "c-call";
04494       case RUBY_EVENT_C_RETURN:
04495         return "c-return";
04496       case RUBY_EVENT_RAISE:
04497         return "raise";
04498       default:
04499         return "unknown";
04500     }
04501 }
04502 
04503 static VALUE
04504 call_trace_proc(VALUE args, int tracing)
04505 {
04506     struct event_call_args *p = (struct event_call_args *)args;
04507     const char *srcfile = rb_sourcefile();
04508     VALUE eventname = rb_str_new2(get_event_name(p->event));
04509     VALUE filename = srcfile ? rb_str_new2(srcfile) : Qnil;
04510     VALUE argv[6];
04511     int line = rb_sourceline();
04512     ID id = 0;
04513     VALUE klass = 0;
04514 
04515     if (p->klass != 0) {
04516         id = p->id;
04517         klass = p->klass;
04518     }
04519     else {
04520         rb_thread_method_id_and_class(p->th, &id, &klass);
04521     }
04522     if (id == ID_ALLOCATOR)
04523       return Qnil;
04524     if (klass) {
04525         if (TYPE(klass) == T_ICLASS) {
04526             klass = RBASIC(klass)->klass;
04527         }
04528         else if (FL_TEST(klass, FL_SINGLETON)) {
04529             klass = rb_iv_get(klass, "__attached__");
04530         }
04531     }
04532 
04533     argv[0] = eventname;
04534     argv[1] = filename;
04535     argv[2] = INT2FIX(line);
04536     argv[3] = id ? ID2SYM(id) : Qnil;
04537     argv[4] = (p->self && srcfile) ? rb_binding_new() : Qnil;
04538     argv[5] = klass ? klass : Qnil;
04539 
04540     return rb_proc_call_with_block(p->proc, 6, argv, Qnil);
04541 }
04542 
04543 static void
04544 call_trace_func(rb_event_flag_t event, VALUE proc, VALUE self, ID id, VALUE klass)
04545 {
04546     struct event_call_args args;
04547 
04548     args.th = GET_THREAD();
04549     args.event = event;
04550     args.proc = proc;
04551     args.self = self;
04552     args.id = id;
04553     args.klass = klass;
04554     ruby_suppress_tracing(call_trace_proc, (VALUE)&args, FALSE);
04555 }
04556 
04557 VALUE
04558 ruby_suppress_tracing(VALUE (*func)(VALUE, int), VALUE arg, int always)
04559 {
04560     rb_thread_t *th = GET_THREAD();
04561     return thread_suppress_tracing(th, EVENT_RUNNING_TRACE, func, arg, always, 0);
04562 }
04563 
04564 static VALUE
04565 thread_suppress_tracing(rb_thread_t *th, int ev, VALUE (*func)(VALUE, int), VALUE arg, int always, int pop_p)
04566 {
04567     int state, tracing = th->tracing, running = tracing & ev;
04568     volatile int raised;
04569     volatile int outer_state;
04570     VALUE result = Qnil;
04571 
04572     if (running == ev && !always) {
04573         return Qnil;
04574     }
04575     else {
04576         th->tracing |= ev;
04577     }
04578 
04579     raised = rb_threadptr_reset_raised(th);
04580     outer_state = th->state;
04581     th->state = 0;
04582 
04583     PUSH_TAG();
04584     if ((state = EXEC_TAG()) == 0) {
04585         result = (*func)(arg, running);
04586     }
04587 
04588     if (raised) {
04589         rb_threadptr_set_raised(th);
04590     }
04591     POP_TAG();
04592 
04593     th->tracing = tracing;
04594     if (state) {
04595         if (pop_p) {
04596             th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
04597         }
04598         JUMP_TAG(state);
04599     }
04600     th->state = outer_state;
04601 
04602     return result;
04603 }
04604 
04605 /*
04606  *  call-seq:
04607  *     thr.backtrace    -> array
04608  *
04609  *  Returns the current back trace of the _thr_.
04610  */
04611 
04612 static VALUE
04613 rb_thread_backtrace_m(VALUE thval)
04614 {
04615     return rb_thread_backtrace(thval);
04616 }
04617 
04618 /*
04619  *  Document-class: ThreadError
04620  *
04621  *  Raised when an invalid operation is attempted on a thread.
04622  *
04623  *  For example, when no other thread has been started:
04624  *
04625  *     Thread.stop
04626  *
04627  *  <em>raises the exception:</em>
04628  *
04629  *     ThreadError: stopping only thread
04630  */
04631 
04632 /*
04633  *  +Thread+ encapsulates the behavior of a thread of
04634  *  execution, including the main thread of the Ruby script.
04635  *
04636  *  In the descriptions of the methods in this class, the parameter _sym_
04637  *  refers to a symbol, which is either a quoted string or a
04638  *  +Symbol+ (such as <code>:name</code>).
04639  */
04640 
04641 void
04642 Init_Thread(void)
04643 {
04644 #undef rb_intern
04645 #define rb_intern(str) rb_intern_const(str)
04646 
04647     VALUE cThGroup;
04648     rb_thread_t *th = GET_THREAD();
04649 
04650     rb_define_singleton_method(rb_cThread, "new", thread_s_new, -1);
04651     rb_define_singleton_method(rb_cThread, "start", thread_start, -2);
04652     rb_define_singleton_method(rb_cThread, "fork", thread_start, -2);
04653     rb_define_singleton_method(rb_cThread, "main", rb_thread_s_main, 0);
04654     rb_define_singleton_method(rb_cThread, "current", thread_s_current, 0);
04655     rb_define_singleton_method(rb_cThread, "stop", rb_thread_stop, 0);
04656     rb_define_singleton_method(rb_cThread, "kill", rb_thread_s_kill, 1);
04657     rb_define_singleton_method(rb_cThread, "exit", rb_thread_exit, 0);
04658     rb_define_singleton_method(rb_cThread, "pass", thread_s_pass, 0);
04659     rb_define_singleton_method(rb_cThread, "list", rb_thread_list, 0);
04660     rb_define_singleton_method(rb_cThread, "abort_on_exception", rb_thread_s_abort_exc, 0);
04661     rb_define_singleton_method(rb_cThread, "abort_on_exception=", rb_thread_s_abort_exc_set, 1);
04662 #if THREAD_DEBUG < 0
04663     rb_define_singleton_method(rb_cThread, "DEBUG", rb_thread_s_debug, 0);
04664     rb_define_singleton_method(rb_cThread, "DEBUG=", rb_thread_s_debug_set, 1);
04665 #endif
04666 
04667     rb_define_method(rb_cThread, "initialize", thread_initialize, -2);
04668     rb_define_method(rb_cThread, "raise", thread_raise_m, -1);
04669     rb_define_method(rb_cThread, "join", thread_join_m, -1);
04670     rb_define_method(rb_cThread, "value", thread_value, 0);
04671     rb_define_method(rb_cThread, "kill", rb_thread_kill, 0);
04672     rb_define_method(rb_cThread, "terminate", rb_thread_kill, 0);
04673     rb_define_method(rb_cThread, "exit", rb_thread_kill, 0);
04674     rb_define_method(rb_cThread, "run", rb_thread_run, 0);
04675     rb_define_method(rb_cThread, "wakeup", rb_thread_wakeup, 0);
04676     rb_define_method(rb_cThread, "[]", rb_thread_aref, 1);
04677     rb_define_method(rb_cThread, "[]=", rb_thread_aset, 2);
04678     rb_define_method(rb_cThread, "key?", rb_thread_key_p, 1);
04679     rb_define_method(rb_cThread, "keys", rb_thread_keys, 0);
04680     rb_define_method(rb_cThread, "priority", rb_thread_priority, 0);
04681     rb_define_method(rb_cThread, "priority=", rb_thread_priority_set, 1);
04682     rb_define_method(rb_cThread, "status", rb_thread_status, 0);
04683     rb_define_method(rb_cThread, "alive?", rb_thread_alive_p, 0);
04684     rb_define_method(rb_cThread, "stop?", rb_thread_stop_p, 0);
04685     rb_define_method(rb_cThread, "abort_on_exception", rb_thread_abort_exc, 0);
04686     rb_define_method(rb_cThread, "abort_on_exception=", rb_thread_abort_exc_set, 1);
04687     rb_define_method(rb_cThread, "safe_level", rb_thread_safe_level, 0);
04688     rb_define_method(rb_cThread, "group", rb_thread_group, 0);
04689     rb_define_method(rb_cThread, "backtrace", rb_thread_backtrace_m, 0);
04690 
04691     rb_define_method(rb_cThread, "inspect", rb_thread_inspect, 0);
04692 
04693     closed_stream_error = rb_exc_new2(rb_eIOError, "stream closed");
04694     OBJ_TAINT(closed_stream_error);
04695     OBJ_FREEZE(closed_stream_error);
04696 
04697     cThGroup = rb_define_class("ThreadGroup", rb_cObject);
04698     rb_define_alloc_func(cThGroup, thgroup_s_alloc);
04699     rb_define_method(cThGroup, "list", thgroup_list, 0);
04700     rb_define_method(cThGroup, "enclose", thgroup_enclose, 0);
04701     rb_define_method(cThGroup, "enclosed?", thgroup_enclosed_p, 0);
04702     rb_define_method(cThGroup, "add", thgroup_add, 1);
04703 
04704     {
04705         th->thgroup = th->vm->thgroup_default = rb_obj_alloc(cThGroup);
04706         rb_define_const(cThGroup, "Default", th->thgroup);
04707     }
04708 
04709     rb_cMutex = rb_define_class("Mutex", rb_cObject);
04710     rb_define_alloc_func(rb_cMutex, mutex_alloc);
04711     rb_define_method(rb_cMutex, "initialize", mutex_initialize, 0);
04712     rb_define_method(rb_cMutex, "locked?", rb_mutex_locked_p, 0);
04713     rb_define_method(rb_cMutex, "try_lock", rb_mutex_trylock, 0);
04714     rb_define_method(rb_cMutex, "lock", rb_mutex_lock, 0);
04715     rb_define_method(rb_cMutex, "unlock", rb_mutex_unlock, 0);
04716     rb_define_method(rb_cMutex, "sleep", mutex_sleep, -1);
04717 
04718     recursive_key = rb_intern("__recursive_key__");
04719     rb_eThreadError = rb_define_class("ThreadError", rb_eStandardError);
04720 
04721     /* trace */
04722     rb_define_global_function("set_trace_func", set_trace_func, 1);
04723     rb_define_method(rb_cThread, "set_trace_func", thread_set_trace_func_m, 1);
04724     rb_define_method(rb_cThread, "add_trace_func", thread_add_trace_func_m, 1);
04725 
04726     /* init thread core */
04727     {
04728         /* main thread setting */
04729         {
04730             /* acquire global vm lock */
04731             gvl_init(th->vm);
04732             gvl_acquire(th->vm, th);
04733             native_mutex_initialize(&th->interrupt_lock);
04734         }
04735     }
04736 
04737     rb_thread_create_timer_thread();
04738 
04739     /* suppress warnings on cygwin, mingw and mswin.*/
04740     (void)native_mutex_trylock;
04741 }
04742 
04743 int
04744 ruby_native_thread_p(void)
04745 {
04746     rb_thread_t *th = ruby_thread_from_native();
04747 
04748     return th != 0;
04749 }
04750 
04751 static int
04752 check_deadlock_i(st_data_t key, st_data_t val, int *found)
04753 {
04754     VALUE thval = key;
04755     rb_thread_t *th;
04756     GetThreadPtr(thval, th);
04757 
04758     if (th->status != THREAD_STOPPED_FOREVER || RUBY_VM_INTERRUPTED(th)) {
04759         *found = 1;
04760     }
04761     else if (th->locking_mutex) {
04762         rb_mutex_t *mutex;
04763         GetMutexPtr(th->locking_mutex, mutex);
04764 
04765         native_mutex_lock(&mutex->lock);
04766         if (mutex->th == th || (!mutex->th && mutex->cond_waiting)) {
04767             *found = 1;
04768         }
04769         native_mutex_unlock(&mutex->lock);
04770     }
04771 
04772     return (*found) ? ST_STOP : ST_CONTINUE;
04773 }
04774 
04775 #ifdef DEBUG_DEADLOCK_CHECK
04776 static int
04777 debug_i(st_data_t key, st_data_t val, int *found)
04778 {
04779     VALUE thval = key;
04780     rb_thread_t *th;
04781     GetThreadPtr(thval, th);
04782 
04783     printf("th:%p %d %d", th, th->status, th->interrupt_flag);
04784     if (th->locking_mutex) {
04785         rb_mutex_t *mutex;
04786         GetMutexPtr(th->locking_mutex, mutex);
04787 
04788         native_mutex_lock(&mutex->lock);
04789         printf(" %p %d\n", mutex->th, mutex->cond_waiting);
04790         native_mutex_unlock(&mutex->lock);
04791     }
04792     else
04793         puts("");
04794 
04795     return ST_CONTINUE;
04796 }
04797 #endif
04798 
04799 static void
04800 rb_check_deadlock(rb_vm_t *vm)
04801 {
04802     int found = 0;
04803 
04804     if (vm_living_thread_num(vm) > vm->sleeper) return;
04805     if (vm_living_thread_num(vm) < vm->sleeper) rb_bug("sleeper must not be more than vm_living_thread_num(vm)");
04806     if (patrol_thread && patrol_thread != GET_THREAD()) return;
04807 
04808     st_foreach(vm->living_threads, check_deadlock_i, (st_data_t)&found);
04809 
04810     if (!found) {
04811         VALUE argv[2];
04812         argv[0] = rb_eFatal;
04813         argv[1] = rb_str_new2("deadlock detected");
04814 #ifdef DEBUG_DEADLOCK_CHECK
04815         printf("%d %d %p %p\n", vm->living_threads->num_entries, vm->sleeper, GET_THREAD(), vm->main_thread);
04816         st_foreach(vm->living_threads, debug_i, (st_data_t)0);
04817 #endif
04818         vm->sleeper--;
04819         rb_threadptr_raise(vm->main_thread, 2, argv);
04820     }
04821 }
04822 
04823 static void
04824 update_coverage(rb_event_flag_t event, VALUE proc, VALUE self, ID id, VALUE klass)
04825 {
04826     VALUE coverage = GET_THREAD()->cfp->iseq->coverage;
04827     if (coverage && RBASIC(coverage)->klass == 0) {
04828         long line = rb_sourceline() - 1;
04829         long count;
04830         if (RARRAY_PTR(coverage)[line] == Qnil) {
04831             return;
04832         }
04833         count = FIX2LONG(RARRAY_PTR(coverage)[line]) + 1;
04834         if (POSFIXABLE(count)) {
04835             RARRAY_PTR(coverage)[line] = LONG2FIX(count);
04836         }
04837     }
04838 }
04839 
04840 VALUE
04841 rb_get_coverages(void)
04842 {
04843     return GET_VM()->coverages;
04844 }
04845 
04846 void
04847 rb_set_coverages(VALUE coverages)
04848 {
04849     GET_VM()->coverages = coverages;
04850     rb_add_event_hook(update_coverage, RUBY_EVENT_COVERAGE, Qnil);
04851 }
04852 
04853 void
04854 rb_reset_coverages(void)
04855 {
04856     GET_VM()->coverages = Qfalse;
04857     rb_remove_event_hook(update_coverage);
04858 }
04859 
04860