thread.c

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

Generated on 19 Jul 2016 for Ruby by  doxygen 1.4.7