OSDN Git Service

ruby-1.9.1-rc1
[splhack/AndroidRuby.git] / lib / ruby-1.9.1-rc1 / thread.c
1 /**********************************************************************
2
3   thread.c -
4
5   $Author: yugui $
6
7   Copyright (C) 2004-2007 Koichi Sasada
8
9 **********************************************************************/
10
11 /*
12   YARV Thread Desgin
13
14   model 1: Userlevel Thread
15     Same as traditional ruby thread.
16
17   model 2: Native Thread with Giant VM lock
18     Using pthread (or Windows thread) and Ruby threads run concurrent.
19
20   model 3: Native Thread with fine grain lock
21     Using pthread and Ruby threads run concurrent or parallel.
22
23 ------------------------------------------------------------------------
24
25   model 2:
26     A thread has mutex (GVL: Global VM Lock) can run.  When thread
27     scheduling, running thread release GVL.  If running thread
28     try blocking operation, this thread must release GVL and another
29     thread can continue this flow.  After blocking operation, thread
30     must check interrupt (RUBY_VM_CHECK_INTS).
31
32     Every VM can run parallel.
33
34     Ruby threads are scheduled by OS thread scheduler.
35
36 ------------------------------------------------------------------------
37
38   model 3:
39     Every threads run concurrent or parallel and to access shared object
40     exclusive access control is needed.  For example, to access String
41     object or Array object, fine grain lock must be locked every time.
42  */
43
44
45 /* for model 2 */
46
47 #include "eval_intern.h"
48 #include "gc.h"
49
50 #ifndef USE_NATIVE_THREAD_PRIORITY
51 #define USE_NATIVE_THREAD_PRIORITY 0
52 #define RUBY_THREAD_PRIORITY_MAX 3
53 #define RUBY_THREAD_PRIORITY_MIN -3
54 #endif
55
56 #ifndef THREAD_DEBUG
57 #define THREAD_DEBUG 0
58 #endif
59
60 VALUE rb_cMutex;
61 VALUE rb_cBarrier;
62
63 static void sleep_timeval(rb_thread_t *th, struct timeval time);
64 static void sleep_wait_for_interrupt(rb_thread_t *th, double sleepsec);
65 static void sleep_forever(rb_thread_t *th, int nodeadlock);
66 static double timeofday(void);
67 struct timeval rb_time_interval(VALUE);
68 static int rb_thread_dead(rb_thread_t *th);
69
70 static void rb_check_deadlock(rb_vm_t *vm);
71
72 void rb_signal_exec(rb_thread_t *th, int sig);
73 void rb_disable_interrupt(void);
74 void rb_thread_stop_timer_thread(void);
75
76 static const VALUE eKillSignal = INT2FIX(0);
77 static const VALUE eTerminateSignal = INT2FIX(1);
78 static volatile int system_working = 1;
79
80 inline static void
81 st_delete_wrap(st_table *table, st_data_t key)
82 {
83     st_delete(table, &key, 0);
84 }
85
86 /********************************************************************************/
87
88 #define THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION
89
90 struct rb_blocking_region_buffer {
91     enum rb_thread_status prev_status;
92     struct rb_unblock_callback oldubf;
93 };
94
95 static void set_unblock_function(rb_thread_t *th, rb_unblock_function_t *func, void *arg,
96                                  struct rb_unblock_callback *old);
97 static void reset_unblock_function(rb_thread_t *th, const struct rb_unblock_callback *old);
98
99 static void inline blocking_region_begin(rb_thread_t *th, struct rb_blocking_region_buffer *region,
100                                          rb_unblock_function_t *func, void *arg);
101 static void inline blocking_region_end(rb_thread_t *th, struct rb_blocking_region_buffer *region);
102
103 #define GVL_UNLOCK_BEGIN() do { \
104   rb_thread_t *_th_stored = GET_THREAD(); \
105   rb_gc_save_machine_context(_th_stored); \
106   native_mutex_unlock(&_th_stored->vm->global_vm_lock)
107
108 #define GVL_UNLOCK_END() \
109   native_mutex_lock(&_th_stored->vm->global_vm_lock); \
110   rb_thread_set_current(_th_stored); \
111 } while(0)
112
113 #define BLOCKING_REGION_CORE(exec) do { \
114     GVL_UNLOCK_BEGIN(); {\
115             exec; \
116     } \
117     GVL_UNLOCK_END(); \
118 } while(0);
119
120 #define BLOCKING_REGION(exec, ubf, ubfarg) do { \
121     rb_thread_t *__th = GET_THREAD(); \
122     struct rb_blocking_region_buffer __region; \
123     blocking_region_begin(__th, &__region, ubf, ubfarg); \
124     exec; \
125     blocking_region_end(__th, &__region); \
126     RUBY_VM_CHECK_INTS(); \
127 } while(0)
128
129 #if THREAD_DEBUG
130 #ifdef HAVE_VA_ARGS_MACRO
131 void rb_thread_debug(const char *file, int line, const char *fmt, ...);
132 #define thread_debug(fmt, ...) rb_thread_debug(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
133 #define POSITION_FORMAT "%s:%d:"
134 #define POSITION_ARGS ,file, line
135 #else
136 void rb_thread_debug(const char *fmt, ...);
137 #define thread_debug rb_thread_debug
138 #define POSITION_FORMAT
139 #define POSITION_ARGS
140 #endif
141
142 # if THREAD_DEBUG < 0
143 static int rb_thread_debug_enabled;
144
145 static VALUE
146 rb_thread_s_debug(void)
147 {
148     return INT2NUM(rb_thread_debug_enabled);
149 }
150
151 static VALUE
152 rb_thread_s_debug_set(VALUE self, VALUE val)
153 {
154     rb_thread_debug_enabled = RTEST(val);
155     return val;
156 }
157 # else
158 # define rb_thread_debug_enabled THREAD_DEBUG
159 # endif
160 #else
161 #define thread_debug if(0)printf
162 #endif
163
164 #ifndef __ia64
165 #define thread_start_func_2(th, st, rst) thread_start_func_2(th, st)
166 #endif
167 NOINLINE(static int thread_start_func_2(rb_thread_t *th, VALUE *stack_start,
168                                         VALUE *register_stack_start));
169 static void timer_thread_function(void *);
170
171 #if   defined(_WIN32)
172 #include "thread_win32.c"
173
174 #define DEBUG_OUT() \
175   WaitForSingleObject(&debug_mutex, INFINITE); \
176   printf(POSITION_FORMAT"%p - %s" POSITION_ARGS, GetCurrentThreadId(), buf); \
177   fflush(stdout); \
178   ReleaseMutex(&debug_mutex);
179
180 #elif defined(HAVE_PTHREAD_H)
181 #include "thread_pthread.c"
182
183 #define DEBUG_OUT() \
184   pthread_mutex_lock(&debug_mutex); \
185   printf(POSITION_FORMAT"%#"PRIxVALUE" - %s" POSITION_ARGS, (VALUE)pthread_self(), buf); \
186   fflush(stdout); \
187   pthread_mutex_unlock(&debug_mutex);
188
189 #else
190 #error "unsupported thread type"
191 #endif
192
193 #if THREAD_DEBUG
194 static int debug_mutex_initialized = 1;
195 static rb_thread_lock_t debug_mutex;
196
197 void
198 rb_thread_debug(
199 #ifdef HAVE_VA_ARGS_MACRO
200     const char *file, int line,
201 #endif
202     const char *fmt, ...)
203 {
204     va_list args;
205     char buf[BUFSIZ];
206
207     if (!rb_thread_debug_enabled) return;
208
209     if (debug_mutex_initialized == 1) {
210         debug_mutex_initialized = 0;
211         native_mutex_initialize(&debug_mutex);
212     }
213
214     va_start(args, fmt);
215     vsnprintf(buf, BUFSIZ, fmt, args);
216     va_end(args);
217
218     DEBUG_OUT();
219 }
220 #endif
221
222
223 static void
224 set_unblock_function(rb_thread_t *th, rb_unblock_function_t *func, void *arg,
225                      struct rb_unblock_callback *old)
226 {
227   check_ints:
228     RUBY_VM_CHECK_INTS(); /* check signal or so */
229     native_mutex_lock(&th->interrupt_lock);
230     if (th->interrupt_flag) {
231         native_mutex_unlock(&th->interrupt_lock);
232         goto check_ints;
233     }
234     else {
235         if (old) *old = th->unblock;
236         th->unblock.func = func;
237         th->unblock.arg = arg;
238     }
239     native_mutex_unlock(&th->interrupt_lock);
240 }
241
242 static void
243 reset_unblock_function(rb_thread_t *th, const struct rb_unblock_callback *old)
244 {
245     native_mutex_lock(&th->interrupt_lock);
246     th->unblock = *old;
247     native_mutex_unlock(&th->interrupt_lock);
248 }
249
250 static void
251 rb_thread_interrupt(rb_thread_t *th)
252 {
253     native_mutex_lock(&th->interrupt_lock);
254     RUBY_VM_SET_INTERRUPT(th);
255     if (th->unblock.func) {
256         (th->unblock.func)(th->unblock.arg);
257     }
258     else {
259         /* none */
260     }
261     native_mutex_unlock(&th->interrupt_lock);
262 }
263
264
265 static int
266 terminate_i(st_data_t key, st_data_t val, rb_thread_t *main_thread)
267 {
268     VALUE thval = key;
269     rb_thread_t *th;
270     GetThreadPtr(thval, th);
271
272     if (th != main_thread) {
273         thread_debug("terminate_i: %p\n", (void *)th);
274         rb_thread_interrupt(th);
275         th->thrown_errinfo = eTerminateSignal;
276         th->status = THREAD_TO_KILL;
277     }
278     else {
279         thread_debug("terminate_i: main thread (%p)\n", (void *)th);
280     }
281     return ST_CONTINUE;
282 }
283
284 typedef struct rb_mutex_struct
285 {
286     rb_thread_lock_t lock;
287     rb_thread_cond_t cond;
288     struct rb_thread_struct volatile *th;
289     volatile int cond_waiting, cond_notified;
290     struct rb_mutex_struct *next_mutex;
291 } mutex_t;
292
293 static void rb_mutex_unlock_all(mutex_t *mutex);
294
295 void
296 rb_thread_terminate_all(void)
297 {
298     rb_thread_t *th = GET_THREAD(); /* main thread */
299     rb_vm_t *vm = th->vm;
300     if (vm->main_thread != th) {
301         rb_bug("rb_thread_terminate_all: called by child thread (%p, %p)",
302                (void *)vm->main_thread, (void *)th);
303     }
304
305     /* unlock all locking mutexes */
306     if (th->keeping_mutexes) {
307         rb_mutex_unlock_all(th->keeping_mutexes);
308     }
309
310     thread_debug("rb_thread_terminate_all (main thread: %p)\n", (void *)th);
311     st_foreach(vm->living_threads, terminate_i, (st_data_t)th);
312
313     while (!rb_thread_alone()) {
314         PUSH_TAG();
315         if (EXEC_TAG() == 0) {
316             rb_thread_schedule();
317         }
318         else {
319             /* ignore exception */
320         }
321         POP_TAG();
322     }
323     rb_thread_stop_timer_thread();
324 }
325
326 static void
327 thread_cleanup_func_before_exec(void *th_ptr)
328 {
329     rb_thread_t *th = th_ptr;
330     th->status = THREAD_KILLED;
331     th->machine_stack_start = th->machine_stack_end = 0;
332 #ifdef __ia64
333     th->machine_register_stack_start = th->machine_register_stack_end = 0;
334 #endif
335 }
336
337 static void
338 thread_cleanup_func(void *th_ptr)
339 {
340     rb_thread_t *th = th_ptr;
341     thread_cleanup_func_before_exec(th_ptr);
342     native_thread_destroy(th);
343 }
344
345 extern void ruby_error_print(void);
346 static VALUE rb_thread_raise(int, VALUE *, rb_thread_t *);
347 void rb_thread_recycle_stack_release(VALUE *);
348
349 void
350 ruby_thread_init_stack(rb_thread_t *th)
351 {
352     native_thread_init_stack(th);
353 }
354
355 static int
356 thread_start_func_2(rb_thread_t *th, VALUE *stack_start, VALUE *register_stack_start)
357 {
358     int state;
359     VALUE args = th->first_args;
360     rb_proc_t *proc;
361     rb_thread_t *join_th;
362     rb_thread_t *main_th;
363     VALUE errinfo = Qnil;
364
365     ruby_thread_set_native(th);
366
367     th->machine_stack_start = stack_start;
368 #ifdef __ia64
369     th->machine_register_stack_start = register_stack_start;
370 #endif
371     thread_debug("thread start: %p\n", (void *)th);
372
373     native_mutex_lock(&th->vm->global_vm_lock);
374     {
375         thread_debug("thread start (get lock): %p\n", (void *)th);
376         rb_thread_set_current(th);
377
378         TH_PUSH_TAG(th);
379         if ((state = EXEC_TAG()) == 0) {
380             SAVE_ROOT_JMPBUF(th, {
381                 if (th->first_proc) {
382                     GetProcPtr(th->first_proc, proc);
383                     th->errinfo = Qnil;
384                     th->local_lfp = proc->block.lfp;
385                     th->local_svar = Qnil;
386                     th->value = vm_invoke_proc(th, proc, proc->block.self,
387                                                RARRAY_LEN(args), RARRAY_PTR(args), 0);
388                 }
389                 else {
390                     th->value = (*th->first_func)((void *)th->first_args);
391                 }
392             });
393         }
394         else {
395             errinfo = th->errinfo;
396             if (NIL_P(errinfo)) errinfo = rb_errinfo();
397             if (state == TAG_FATAL) {
398                 /* fatal error within this thread, need to stop whole script */
399             }
400             else if (rb_obj_is_kind_of(errinfo, rb_eSystemExit)) {
401                 if (th->safe_level >= 4) {
402                     th->errinfo = rb_exc_new3(rb_eSecurityError,
403                                               rb_sprintf("Insecure exit at level %d", th->safe_level));
404                     errinfo = Qnil;
405                 }
406             }
407             else if (th->safe_level < 4 &&
408                      (th->vm->thread_abort_on_exception ||
409                       th->abort_on_exception || RTEST(ruby_debug))) {
410                 /* exit on main_thread */
411             }
412             else {
413                 errinfo = Qnil;
414             }
415             th->value = Qnil;
416         }
417
418         th->status = THREAD_KILLED;
419         thread_debug("thread end: %p\n", (void *)th);
420
421         main_th = th->vm->main_thread;
422         if (th != main_th) {
423             if (TYPE(errinfo) == T_OBJECT) {
424                 /* treat with normal error object */
425                 rb_thread_raise(1, &errinfo, main_th);
426             }
427         }
428         TH_POP_TAG();
429
430         /* locking_mutex must be Qfalse */
431         if (th->locking_mutex != Qfalse) {
432             rb_bug("thread_start_func_2: locking_mutex must not be set (%p:%"PRIxVALUE")",
433                    (void *)th, th->locking_mutex);
434         }
435
436         /* unlock all locking mutexes */
437         if (th->keeping_mutexes) {
438             rb_mutex_unlock_all(th->keeping_mutexes);
439             th->keeping_mutexes = NULL;
440         }
441
442         /* delete self from living_threads */
443         st_delete_wrap(th->vm->living_threads, th->self);
444
445         /* wake up joinning threads */
446         join_th = th->join_list_head;
447         while (join_th) {
448             if (join_th == main_th) errinfo = Qnil;
449             rb_thread_interrupt(join_th);
450             switch (join_th->status) {
451               case THREAD_STOPPED: case THREAD_STOPPED_FOREVER:
452                 join_th->status = THREAD_RUNNABLE;
453               default: break;
454             }
455             join_th = join_th->join_list_next;
456         }
457         if (th != main_th) rb_check_deadlock(th->vm);
458
459         if (!th->root_fiber) {
460             rb_thread_recycle_stack_release(th->stack);
461             th->stack = 0;
462         }
463     }
464     thread_cleanup_func(th);
465     if (th->vm->main_thread == th) {
466         rb_thread_stop_timer_thread();
467     }
468     native_mutex_unlock(&th->vm->global_vm_lock);
469
470     return 0;
471 }
472
473 static VALUE
474 thread_create_core(VALUE thval, VALUE args, VALUE (*fn)(ANYARGS))
475 {
476     rb_thread_t *th;
477
478     if (OBJ_FROZEN(GET_THREAD()->thgroup)) {
479         rb_raise(rb_eThreadError,
480                  "can't start a new thread (frozen ThreadGroup)");
481     }
482     GetThreadPtr(thval, th);
483
484     /* setup thread environment */
485     th->first_func = fn;
486     th->first_proc = fn ? Qfalse : rb_block_proc();
487     th->first_args = args; /* GC: shouldn't put before above line */
488
489     th->priority = GET_THREAD()->priority;
490     th->thgroup = GET_THREAD()->thgroup;
491
492     native_mutex_initialize(&th->interrupt_lock);
493     /* kick thread */
494     st_insert(th->vm->living_threads, thval, (st_data_t) th->thread_id);
495     native_thread_create(th);
496     return thval;
497 }
498
499 static VALUE
500 thread_s_new(int argc, VALUE *argv, VALUE klass)
501 {
502     rb_thread_t *th;
503     VALUE thread = rb_thread_alloc(klass);
504     rb_obj_call_init(thread, argc, argv);
505     GetThreadPtr(thread, th);
506     if (!th->first_args) {
507         rb_raise(rb_eThreadError, "uninitialized thread - check `%s#initialize'",
508                  rb_class2name(klass));
509     }
510     return thread;
511 }
512
513 /*
514  *  call-seq:
515  *     Thread.start([args]*) {|args| block }   => thread
516  *     Thread.fork([args]*) {|args| block }    => thread
517  *
518  *  Basically the same as <code>Thread::new</code>. However, if class
519  *  <code>Thread</code> is subclassed, then calling <code>start</code> in that
520  *  subclass will not invoke the subclass's <code>initialize</code> method.
521  */
522
523 static VALUE
524 thread_start(VALUE klass, VALUE args)
525 {
526     return thread_create_core(rb_thread_alloc(klass), args, 0);
527 }
528
529 static VALUE
530 thread_initialize(VALUE thread, VALUE args)
531 {
532     rb_thread_t *th;
533     if (!rb_block_given_p()) {
534         rb_raise(rb_eThreadError, "must be called with a block");
535     }
536     GetThreadPtr(thread, th);
537     if (th->first_args) {
538         VALUE rb_proc_location(VALUE self);
539         VALUE proc = th->first_proc, line, loc;
540         const char *file;
541         if (!proc || !RTEST(loc = rb_proc_location(proc))) {
542             rb_raise(rb_eThreadError, "already initialized thread");
543         }
544         file = RSTRING_PTR(RARRAY_PTR(loc)[0]);
545         if (NIL_P(line = RARRAY_PTR(loc)[1])) {
546             rb_raise(rb_eThreadError, "already initialized thread - %s",
547                      file);
548         }
549         rb_raise(rb_eThreadError, "already initialized thread - %s:%d",
550                  file, NUM2INT(line));
551     }
552     return thread_create_core(thread, args, 0);
553 }
554
555 VALUE
556 rb_thread_create(VALUE (*fn)(ANYARGS), void *arg)
557 {
558     return thread_create_core(rb_thread_alloc(rb_cThread), (VALUE)arg, fn);
559 }
560
561
562 /* +infty, for this purpose */
563 #define DELAY_INFTY 1E30
564
565 struct join_arg {
566     rb_thread_t *target, *waiting;
567     double limit;
568     int forever;
569 };
570
571 static VALUE
572 remove_from_join_list(VALUE arg)
573 {
574     struct join_arg *p = (struct join_arg *)arg;
575     rb_thread_t *target_th = p->target, *th = p->waiting;
576
577     if (target_th->status != THREAD_KILLED) {
578         rb_thread_t **pth = &target_th->join_list_head;
579
580         while (*pth) {
581             if (*pth == th) {
582                 *pth = th->join_list_next;
583                 break;
584             }
585             pth = &(*pth)->join_list_next;
586         }
587     }
588
589     return Qnil;
590 }
591
592 static VALUE
593 thread_join_sleep(VALUE arg)
594 {
595     struct join_arg *p = (struct join_arg *)arg;
596     rb_thread_t *target_th = p->target, *th = p->waiting;
597     double now, limit = p->limit;
598
599     while (target_th->status != THREAD_KILLED) {
600         if (p->forever) {
601             sleep_forever(th, 1);
602         }
603         else {
604             now = timeofday();
605             if (now > limit) {
606                 thread_debug("thread_join: timeout (thid: %p)\n",
607                              (void *)target_th->thread_id);
608                 return Qfalse;
609             }
610             sleep_wait_for_interrupt(th, limit - now);
611         }
612         thread_debug("thread_join: interrupted (thid: %p)\n",
613                      (void *)target_th->thread_id);
614     }
615     return Qtrue;
616 }
617
618 static VALUE
619 thread_join(rb_thread_t *target_th, double delay)
620 {
621     rb_thread_t *th = GET_THREAD();
622     struct join_arg arg;
623
624     arg.target = target_th;
625     arg.waiting = th;
626     arg.limit = timeofday() + delay;
627     arg.forever = delay == DELAY_INFTY;
628
629     thread_debug("thread_join (thid: %p)\n", (void *)target_th->thread_id);
630
631     if (target_th->status != THREAD_KILLED) {
632         th->join_list_next = target_th->join_list_head;
633         target_th->join_list_head = th;
634         if (!rb_ensure(thread_join_sleep, (VALUE)&arg,
635                        remove_from_join_list, (VALUE)&arg)) {
636             return Qnil;
637         }
638     }
639
640     thread_debug("thread_join: success (thid: %p)\n",
641                  (void *)target_th->thread_id);
642
643     if (target_th->errinfo != Qnil) {
644         VALUE err = target_th->errinfo;
645
646         if (FIXNUM_P(err)) {
647             /* */
648         }
649         else if (TYPE(target_th->errinfo) == T_NODE) {
650             rb_exc_raise(vm_make_jump_tag_but_local_jump(
651                 GET_THROWOBJ_STATE(err), GET_THROWOBJ_VAL(err)));
652         }
653         else {
654             /* normal exception */
655             rb_exc_raise(err);
656         }
657     }
658     return target_th->self;
659 }
660
661 /*
662  *  call-seq:
663  *     thr.join          => thr
664  *     thr.join(limit)   => thr
665  *
666  *  The calling thread will suspend execution and run <i>thr</i>. Does not
667  *  return until <i>thr</i> exits or until <i>limit</i> seconds have passed. If
668  *  the time limit expires, <code>nil</code> will be returned, otherwise
669  *  <i>thr</i> is returned.
670  *
671  *  Any threads not joined will be killed when the main program exits.  If
672  *  <i>thr</i> had previously raised an exception and the
673  *  <code>abort_on_exception</code> and <code>$DEBUG</code> flags are not set
674  *  (so the exception has not yet been processed) it will be processed at this
675  *  time.
676  *
677  *     a = Thread.new { print "a"; sleep(10); print "b"; print "c" }
678  *     x = Thread.new { print "x"; Thread.pass; print "y"; print "z" }
679  *     x.join # Let x thread finish, a will be killed on exit.
680  *
681  *  <em>produces:</em>
682  *
683  *     axyz
684  *
685  *  The following example illustrates the <i>limit</i> parameter.
686  *
687  *     y = Thread.new { 4.times { sleep 0.1; puts 'tick... ' }}
688  *     puts "Waiting" until y.join(0.15)
689  *
690  *  <em>produces:</em>
691  *
692  *     tick...
693  *     Waiting
694  *     tick...
695  *     Waitingtick...
696  *
697  *
698  *     tick...
699  */
700
701 static VALUE
702 thread_join_m(int argc, VALUE *argv, VALUE self)
703 {
704     rb_thread_t *target_th;
705     double delay = DELAY_INFTY;
706     VALUE limit;
707
708     GetThreadPtr(self, target_th);
709
710     rb_scan_args(argc, argv, "01", &limit);
711     if (!NIL_P(limit)) {
712         delay = rb_num2dbl(limit);
713     }
714
715     return thread_join(target_th, delay);
716 }
717
718 /*
719  *  call-seq:
720  *     thr.value   => obj
721  *
722  *  Waits for <i>thr</i> to complete (via <code>Thread#join</code>) and returns
723  *  its value.
724  *
725  *     a = Thread.new { 2 + 2 }
726  *     a.value   #=> 4
727  */
728
729 static VALUE
730 thread_value(VALUE self)
731 {
732     rb_thread_t *th;
733     GetThreadPtr(self, th);
734     thread_join(th, DELAY_INFTY);
735     return th->value;
736 }
737
738 /*
739  * Thread Scheduling
740  */
741
742 static struct timeval
743 double2timeval(double d)
744 {
745     struct timeval time;
746
747     time.tv_sec = (int)d;
748     time.tv_usec = (int)((d - (int)d) * 1e6);
749     if (time.tv_usec < 0) {
750         time.tv_usec += (long)1e6;
751         time.tv_sec -= 1;
752     }
753     return time;
754 }
755
756 static void
757 sleep_forever(rb_thread_t *th, int deadlockable)
758 {
759     enum rb_thread_status prev_status = th->status;
760
761     th->status = deadlockable ? THREAD_STOPPED_FOREVER : THREAD_STOPPED;
762     do {
763         if (deadlockable) {
764             th->vm->sleeper++;
765             rb_check_deadlock(th->vm);
766         }
767         native_sleep(th, 0);
768         if (deadlockable) {
769             th->vm->sleeper--;
770         }
771         RUBY_VM_CHECK_INTS();
772     } while (th->status == THREAD_STOPPED_FOREVER);
773     th->status = prev_status;
774 }
775
776 static void
777 getclockofday(struct timeval *tp)
778 {
779 #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
780     struct timespec ts;
781
782     if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
783         tp->tv_sec = ts.tv_sec;
784         tp->tv_usec = ts.tv_nsec / 1000;
785     } else
786 #endif
787     {
788         gettimeofday(tp, NULL);
789     }
790 }
791
792 static void
793 sleep_timeval(rb_thread_t *th, struct timeval tv)
794 {
795     struct timeval to, tvn;
796     enum rb_thread_status prev_status = th->status;
797
798     getclockofday(&to);
799     to.tv_sec += tv.tv_sec;
800     if ((to.tv_usec += tv.tv_usec) >= 1000000) {
801         to.tv_sec++;
802         to.tv_usec -= 1000000;
803     }
804
805     th->status = THREAD_STOPPED;
806     do {
807         native_sleep(th, &tv);
808         RUBY_VM_CHECK_INTS();
809         getclockofday(&tvn);
810         if (to.tv_sec < tvn.tv_sec) break;
811         if (to.tv_sec == tvn.tv_sec && to.tv_usec <= tvn.tv_usec) break;
812         thread_debug("sleep_timeval: %ld.%.6ld > %ld.%.6ld\n",
813                      (long)to.tv_sec, (long)to.tv_usec,
814                      (long)tvn.tv_sec, (long)tvn.tv_usec);
815         tv.tv_sec = to.tv_sec - tvn.tv_sec;
816         if ((tv.tv_usec = to.tv_usec - tvn.tv_usec) < 0) {
817             --tv.tv_sec;
818             tv.tv_usec += 1000000;
819         }
820     } while (th->status == THREAD_STOPPED);
821     th->status = prev_status;
822 }
823
824 void
825 rb_thread_sleep_forever()
826 {
827     thread_debug("rb_thread_sleep_forever\n");
828     sleep_forever(GET_THREAD(), 0);
829 }
830
831 static void
832 rb_thread_sleep_deadly()
833 {
834     thread_debug("rb_thread_sleep_deadly\n");
835     sleep_forever(GET_THREAD(), 1);
836 }
837
838 static double
839 timeofday(void)
840 {
841 #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
842     struct timespec tp;
843
844     if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) {
845         return (double)tp.tv_sec + (double)tp.tv_nsec * 1e-9;
846     } else
847 #endif
848     {
849         struct timeval tv;
850         gettimeofday(&tv, NULL);
851         return (double)tv.tv_sec + (double)tv.tv_usec * 1e-6;
852     }
853 }
854
855 static void
856 sleep_wait_for_interrupt(rb_thread_t *th, double sleepsec)
857 {
858     sleep_timeval(th, double2timeval(sleepsec));
859 }
860
861 static void
862 sleep_for_polling(rb_thread_t *th)
863 {
864     struct timeval time;
865     time.tv_sec = 0;
866     time.tv_usec = 100 * 1000;  /* 0.1 sec */
867     sleep_timeval(th, time);
868 }
869
870 void
871 rb_thread_wait_for(struct timeval time)
872 {
873     rb_thread_t *th = GET_THREAD();
874     sleep_timeval(th, time);
875 }
876
877 void
878 rb_thread_polling(void)
879 {
880     RUBY_VM_CHECK_INTS();
881     if (!rb_thread_alone()) {
882         rb_thread_t *th = GET_THREAD();
883         sleep_for_polling(th);
884     }
885 }
886
887 /*
888  * CAUTION: This function causes thread switching.
889  *          rb_thread_check_ints() check ruby's interrupts.
890  *          some interrupt needs thread switching/invoke handlers,
891  *          and so on.
892  */
893
894 void
895 rb_thread_check_ints(void)
896 {
897     RUBY_VM_CHECK_INTS();
898 }
899
900 /*
901  * Hidden API for tcl/tk wrapper.
902  * There is no guarantee to perpetuate it.
903  */
904 int
905 rb_thread_check_trap_pending(void)
906 {
907     return GET_THREAD()->exec_signal != 0;
908 }
909
910 /* This function can be called in blocking region. */
911 int
912 rb_thread_interrupted(VALUE thval)
913 {
914     rb_thread_t *th;
915     GetThreadPtr(thval, th);
916     return RUBY_VM_INTERRUPTED(th);
917 }
918
919 struct timeval rb_time_timeval();
920
921 void
922 rb_thread_sleep(int sec)
923 {
924     rb_thread_wait_for(rb_time_timeval(INT2FIX(sec)));
925 }
926
927 void
928 rb_thread_schedule(void)
929 {
930     thread_debug("rb_thread_schedule\n");
931     if (!rb_thread_alone()) {
932         rb_thread_t *th = GET_THREAD();
933
934         thread_debug("rb_thread_schedule/switch start\n");
935
936         rb_gc_save_machine_context(th);
937         native_mutex_unlock(&th->vm->global_vm_lock);
938         {
939             native_thread_yield();
940         }
941         native_mutex_lock(&th->vm->global_vm_lock);
942
943         rb_thread_set_current(th);
944         thread_debug("rb_thread_schedule/switch done\n");
945
946         RUBY_VM_CHECK_INTS();
947     }
948 }
949
950 /* blocking region */
951 static inline void
952 blocking_region_begin(rb_thread_t *th, struct rb_blocking_region_buffer *region,
953                       rb_unblock_function_t *func, void *arg)
954 {
955     region->prev_status = th->status;
956     set_unblock_function(th, func, arg, &region->oldubf);
957     th->status = THREAD_STOPPED;
958     thread_debug("enter blocking region (%p)\n", (void *)th);
959     rb_gc_save_machine_context(th);
960     native_mutex_unlock(&th->vm->global_vm_lock);
961 }
962
963 static inline void
964 blocking_region_end(rb_thread_t *th, struct rb_blocking_region_buffer *region)
965 {
966     native_mutex_lock(&th->vm->global_vm_lock);
967     rb_thread_set_current(th);
968     thread_debug("leave blocking region (%p)\n", (void *)th);
969     remove_signal_thread_list(th);
970     reset_unblock_function(th, &region->oldubf);
971     if (th->status == THREAD_STOPPED) {
972         th->status = region->prev_status;
973     }
974 }
975
976 struct rb_blocking_region_buffer *
977 rb_thread_blocking_region_begin(void)
978 {
979     rb_thread_t *th = GET_THREAD();
980     struct rb_blocking_region_buffer *region = ALLOC(struct rb_blocking_region_buffer);
981     blocking_region_begin(th, region, ubf_select, th);
982     return region;
983 }
984
985 void
986 rb_thread_blocking_region_end(struct rb_blocking_region_buffer *region)
987 {
988     rb_thread_t *th = GET_THREAD();
989     blocking_region_end(th, region);
990     xfree(region);
991     RUBY_VM_CHECK_INTS();
992 }
993
994 /*
995  * rb_thread_blocking_region - permit concurrent/parallel execution.
996  *
997  * This function does:
998  *   (1) release GVL.
999  *       Other Ruby threads may run in parallel.
1000  *   (2) call func with data1.
1001  *   (3) aquire GVL.
1002  *       Other Ruby threads can not run in parallel any more.
1003  *
1004  *   If another thread interrupts this thread (Thread#kill, signal deliverly,
1005  *   VM-shutdown request, and so on), `ubf()' is called (`ubf()' means
1006  *   "un-blocking function").  `ubf()' should interrupt `func()' execution.
1007  *
1008  *   There are built-in ubfs and you can specify these ubfs.
1009  *   However, we can not guarantee our built-in ubfs interrupt
1010  *   your `func()' correctly.  Be careful to use rb_thread_blocking_region().
1011  *
1012  *     * RUBY_UBF_IO: ubf for IO operation
1013  *     * RUBY_UBF_PROCESS: ubf for process operation
1014  *
1015  *   NOTE: You can not execute most of Ruby C API and touch Ruby objects
1016  *         in `func()' and `ubf()' because current thread doesn't acquire
1017  *         GVL (cause synchronization problem).  Especially, ALLOC*() are
1018  *         forbidden because they are related to GC.  If you need to do it,
1019  *         read source code of C APIs and confirm by yourself.
1020  *
1021  *   NOTE: In short, this API is difficult to use safely.  I recommend you
1022  *         use other ways if you have.  We lack experiences to use this API.
1023  *         Please report your problem related on it.
1024  *
1025  *   Safe C API:
1026  *     * rb_thread_interrupted() - check interrupt flag
1027  */
1028 VALUE
1029 rb_thread_blocking_region(
1030     rb_blocking_function_t *func, void *data1,
1031     rb_unblock_function_t *ubf, void *data2)
1032 {
1033     VALUE val;
1034     rb_thread_t *th = GET_THREAD();
1035
1036     if (ubf == RUBY_UBF_IO || ubf == RUBY_UBF_PROCESS) {
1037         ubf = ubf_select;
1038         data2 = th;
1039     }
1040
1041     BLOCKING_REGION({
1042         val = func(data1);
1043     }, ubf, data2);
1044
1045     return val;
1046 }
1047
1048 /* alias of rb_thread_blocking_region() */
1049
1050 VALUE
1051 rb_thread_call_without_gvl(
1052     rb_blocking_function_t *func, void *data1,
1053     rb_unblock_function_t *ubf, void *data2)
1054 {
1055     return rb_thread_blocking_region(func, data1, ubf, data2);
1056 }
1057
1058 /*
1059  * rb_thread_call_with_gvl - re-enter into Ruby world while releasing GVL.
1060  *
1061  * While releasing GVL using rb_thread_blocking_region() or
1062  * rb_thread_call_without_gvl(), you can not access Ruby values or invoke methods.
1063  * If you need to access it, you must use this function rb_thread_call_with_gvl().
1064  *
1065  * This function rb_thread_call_with_gvl() does:
1066  * (1) acquire GVL.
1067  * (2) call passed function `func'.
1068  * (3) release GVL.
1069  * (4) return a value which is returned at (2).
1070  *
1071  * NOTE: You should not return Ruby object at (2) because such Object
1072  *       will not marked.
1073  *
1074  * NOTE: If an exception is raised in `func', this function "DOES NOT"
1075  *       protect (catch) the exception.  If you have any resources
1076  *       which should free before throwing exception, you need use
1077  *       rb_protect() in `func' and return a value which represents
1078  *       exception is raised.
1079  *
1080  * NOTE: This functions should not be called by a thread which
1081  *       is not created as Ruby thread (created by Thread.new or so).
1082  *       In other words, this function *DOES NOT* associate
1083  *       NON-Ruby thread to Ruby thread.
1084  */
1085 void *
1086 rb_thread_call_with_gvl(void *(*func)(void *), void *data1)
1087 {
1088     rb_thread_t *th = ruby_thread_from_native();
1089     struct rb_blocking_region_buffer *brb;
1090     struct rb_unblock_callback prev_unblock;
1091     void *r;
1092
1093     if (th == 0) {
1094         /* Error is occurred, but we can't use rb_bug()
1095          * because this thread is not Ruby's thread.
1096          * What should we do?
1097          */
1098
1099         fprintf(stderr, "[BUG] rb_thread_call_with_gvl() is called by non-ruby thread\n");
1100         exit(1);
1101     }
1102
1103     brb = (struct rb_blocking_region_buffer *)th->blocking_region_buffer;
1104     prev_unblock = th->unblock;
1105
1106     blocking_region_end(th, brb);
1107     /* enter to Ruby world: You can access Ruby values, methods and so on. */
1108     r = (*func)(data1);
1109     /* levae from Ruby world: You can not access Ruby values, etc. */
1110     blocking_region_begin(th, brb, prev_unblock.func, prev_unblock.arg);
1111     return r;
1112 }
1113
1114 /*
1115  *  call-seq:
1116  *     Thread.pass   => nil
1117  *
1118  *  Invokes the thread scheduler to pass execution to another thread.
1119  *
1120  *     a = Thread.new { print "a"; Thread.pass;
1121  *                      print "b"; Thread.pass;
1122  *                      print "c" }
1123  *     b = Thread.new { print "x"; Thread.pass;
1124  *                      print "y"; Thread.pass;
1125  *                      print "z" }
1126  *     a.join
1127  *     b.join
1128  *
1129  *  <em>produces:</em>
1130  *
1131  *     axbycz
1132  */
1133
1134 static VALUE
1135 thread_s_pass(VALUE klass)
1136 {
1137     rb_thread_schedule();
1138     return Qnil;
1139 }
1140
1141 /*
1142  *
1143  */
1144
1145 void
1146 rb_thread_execute_interrupts(rb_thread_t *th)
1147 {
1148     if (th->raised_flag) return;
1149
1150     while (th->interrupt_flag) {
1151         enum rb_thread_status status = th->status;
1152         int timer_interrupt = th->interrupt_flag & 0x01;
1153         int finalizer_interrupt = th->interrupt_flag & 0x04;
1154
1155         th->status = THREAD_RUNNABLE;
1156         th->interrupt_flag = 0;
1157
1158         /* signal handling */
1159         if (th->exec_signal) {
1160             int sig = th->exec_signal;
1161             th->exec_signal = 0;
1162             rb_signal_exec(th, sig);
1163         }
1164
1165         /* exception from another thread */
1166         if (th->thrown_errinfo) {
1167             VALUE err = th->thrown_errinfo;
1168             th->thrown_errinfo = 0;
1169             thread_debug("rb_thread_execute_interrupts: %ld\n", err);
1170
1171             if (err == eKillSignal || err == eTerminateSignal) {
1172                 th->errinfo = INT2FIX(TAG_FATAL);
1173                 TH_JUMP_TAG(th, TAG_FATAL);
1174             }
1175             else {
1176                 rb_exc_raise(err);
1177             }
1178         }
1179         th->status = status;
1180
1181         if (finalizer_interrupt) {
1182             rb_gc_finalize_deferred();
1183         }
1184
1185         if (timer_interrupt) {
1186             EXEC_EVENT_HOOK(th, RUBY_EVENT_SWITCH, th->cfp->self, 0, 0);
1187
1188             if (th->slice > 0) {
1189                 th->slice--;
1190             }
1191             else {
1192               reschedule:
1193                 rb_thread_schedule();
1194                 if (th->slice < 0) {
1195                     th->slice++;
1196                     goto reschedule;
1197                 }
1198                 else {
1199                     th->slice = th->priority;
1200                 }
1201             }
1202         }
1203     }
1204 }
1205
1206
1207 void
1208 rb_gc_mark_threads(void)
1209 {
1210     /* TODO: remove */
1211 }
1212
1213 /*****************************************************/
1214
1215 static void
1216 rb_thread_ready(rb_thread_t *th)
1217 {
1218     rb_thread_interrupt(th);
1219 }
1220
1221 static VALUE
1222 rb_thread_raise(int argc, VALUE *argv, rb_thread_t *th)
1223 {
1224     VALUE exc;
1225
1226   again:
1227     if (rb_thread_dead(th)) {
1228         return Qnil;
1229     }
1230
1231     if (th->thrown_errinfo != 0 || th->raised_flag) {
1232         rb_thread_schedule();
1233         goto again;
1234     }
1235
1236     exc = rb_make_exception(argc, argv);
1237     th->thrown_errinfo = exc;
1238     rb_thread_ready(th);
1239     return Qnil;
1240 }
1241
1242 void
1243 rb_thread_signal_raise(void *thptr, int sig)
1244 {
1245     VALUE argv[2];
1246     rb_thread_t *th = thptr;
1247
1248     argv[0] = rb_eSignal;
1249     argv[1] = INT2FIX(sig);
1250     rb_thread_raise(2, argv, th->vm->main_thread);
1251 }
1252
1253 void
1254 rb_thread_signal_exit(void *thptr)
1255 {
1256     VALUE argv[2];
1257     rb_thread_t *th = thptr;
1258
1259     argv[0] = rb_eSystemExit;
1260     argv[1] = rb_str_new2("exit");
1261     rb_thread_raise(2, argv, th->vm->main_thread);
1262 }
1263
1264 void
1265 ruby_thread_stack_overflow(rb_thread_t *th)
1266 {
1267     th->errinfo = sysstack_error;
1268     th->raised_flag = 0;
1269     TH_JUMP_TAG(th, TAG_RAISE);
1270 }
1271
1272 int
1273 rb_thread_set_raised(rb_thread_t *th)
1274 {
1275     if (th->raised_flag & RAISED_EXCEPTION) {
1276         return 1;
1277     }
1278     th->raised_flag |= RAISED_EXCEPTION;
1279     return 0;
1280 }
1281
1282 int
1283 rb_thread_reset_raised(rb_thread_t *th)
1284 {
1285     if (!(th->raised_flag & RAISED_EXCEPTION)) {
1286         return 0;
1287     }
1288     th->raised_flag &= ~RAISED_EXCEPTION;
1289     return 1;
1290 }
1291
1292 void
1293 rb_thread_fd_close(int fd)
1294 {
1295     /* TODO: fix me */
1296 }
1297
1298 /*
1299  *  call-seq:
1300  *     thr.raise(exception)
1301  *
1302  *  Raises an exception (see <code>Kernel::raise</code>) from <i>thr</i>. The
1303  *  caller does not have to be <i>thr</i>.
1304  *
1305  *     Thread.abort_on_exception = true
1306  *     a = Thread.new { sleep(200) }
1307  *     a.raise("Gotcha")
1308  *
1309  *  <em>produces:</em>
1310  *
1311  *     prog.rb:3: Gotcha (RuntimeError)
1312  *      from prog.rb:2:in `initialize'
1313  *      from prog.rb:2:in `new'
1314  *      from prog.rb:2
1315  */
1316
1317 static VALUE
1318 thread_raise_m(int argc, VALUE *argv, VALUE self)
1319 {
1320     rb_thread_t *th;
1321     GetThreadPtr(self, th);
1322     rb_thread_raise(argc, argv, th);
1323     return Qnil;
1324 }
1325
1326
1327 /*
1328  *  call-seq:
1329  *     thr.exit        => thr or nil
1330  *     thr.kill        => thr or nil
1331  *     thr.terminate   => thr or nil
1332  *
1333  *  Terminates <i>thr</i> and schedules another thread to be run. If this thread
1334  *  is already marked to be killed, <code>exit</code> returns the
1335  *  <code>Thread</code>. If this is the main thread, or the last thread, exits
1336  *  the process.
1337  */
1338
1339 VALUE
1340 rb_thread_kill(VALUE thread)
1341 {
1342     rb_thread_t *th;
1343
1344     GetThreadPtr(thread, th);
1345
1346     if (th != GET_THREAD() && th->safe_level < 4) {
1347         rb_secure(4);
1348     }
1349     if (th->status == THREAD_TO_KILL || th->status == THREAD_KILLED) {
1350         return thread;
1351     }
1352     if (th == th->vm->main_thread) {
1353         rb_exit(EXIT_SUCCESS);
1354     }
1355
1356     thread_debug("rb_thread_kill: %p (%p)\n", (void *)th, (void *)th->thread_id);
1357
1358     rb_thread_interrupt(th);
1359     th->thrown_errinfo = eKillSignal;
1360     th->status = THREAD_TO_KILL;
1361
1362     return thread;
1363 }
1364
1365
1366 /*
1367  *  call-seq:
1368  *     Thread.kill(thread)   => thread
1369  *
1370  *  Causes the given <em>thread</em> to exit (see <code>Thread::exit</code>).
1371  *
1372  *     count = 0
1373  *     a = Thread.new { loop { count += 1 } }
1374  *     sleep(0.1)       #=> 0
1375  *     Thread.kill(a)   #=> #<Thread:0x401b3d30 dead>
1376  *     count            #=> 93947
1377  *     a.alive?         #=> false
1378  */
1379
1380 static VALUE
1381 rb_thread_s_kill(VALUE obj, VALUE th)
1382 {
1383     return rb_thread_kill(th);
1384 }
1385
1386
1387 /*
1388  *  call-seq:
1389  *     Thread.exit   => thread
1390  *
1391  *  Terminates the currently running thread and schedules another thread to be
1392  *  run. If this thread is already marked to be killed, <code>exit</code>
1393  *  returns the <code>Thread</code>. If this is the main thread, or the last
1394  *  thread, exit the process.
1395  */
1396
1397 static VALUE
1398 rb_thread_exit(void)
1399 {
1400     return rb_thread_kill(GET_THREAD()->self);
1401 }
1402
1403
1404 /*
1405  *  call-seq:
1406  *     thr.wakeup   => thr
1407  *
1408  *  Marks <i>thr</i> as eligible for scheduling (it may still remain blocked on
1409  *  I/O, however). Does not invoke the scheduler (see <code>Thread#run</code>).
1410  *
1411  *     c = Thread.new { Thread.stop; puts "hey!" }
1412  *     c.wakeup
1413  *
1414  *  <em>produces:</em>
1415  *
1416  *     hey!
1417  */
1418
1419 VALUE
1420 rb_thread_wakeup(VALUE thread)
1421 {
1422     rb_thread_t *th;
1423     GetThreadPtr(thread, th);
1424
1425     if (th->status == THREAD_KILLED) {
1426         rb_raise(rb_eThreadError, "killed thread");
1427     }
1428     rb_thread_ready(th);
1429     if (th->status != THREAD_TO_KILL) {
1430         th->status = THREAD_RUNNABLE;
1431     }
1432     return thread;
1433 }
1434
1435
1436 /*
1437  *  call-seq:
1438  *     thr.run   => thr
1439  *
1440  *  Wakes up <i>thr</i>, making it eligible for scheduling.
1441  *
1442  *     a = Thread.new { puts "a"; Thread.stop; puts "c" }
1443  *     Thread.pass
1444  *     puts "Got here"
1445  *     a.run
1446  *     a.join
1447  *
1448  *  <em>produces:</em>
1449  *
1450  *     a
1451  *     Got here
1452  *     c
1453  */
1454
1455 VALUE
1456 rb_thread_run(VALUE thread)
1457 {
1458     rb_thread_wakeup(thread);
1459     rb_thread_schedule();
1460     return thread;
1461 }
1462
1463
1464 /*
1465  *  call-seq:
1466  *     Thread.stop   => nil
1467  *
1468  *  Stops execution of the current thread, putting it into a ``sleep'' state,
1469  *  and schedules execution of another thread.
1470  *
1471  *     a = Thread.new { print "a"; Thread.stop; print "c" }
1472  *     Thread.pass
1473  *     print "b"
1474  *     a.run
1475  *     a.join
1476  *
1477  *  <em>produces:</em>
1478  *
1479  *     abc
1480  */
1481
1482 VALUE
1483 rb_thread_stop(void)
1484 {
1485     if (rb_thread_alone()) {
1486         rb_raise(rb_eThreadError,
1487                  "stopping only thread\n\tnote: use sleep to stop forever");
1488     }
1489     rb_thread_sleep_deadly();
1490     return Qnil;
1491 }
1492
1493 static int
1494 thread_list_i(st_data_t key, st_data_t val, void *data)
1495 {
1496     VALUE ary = (VALUE)data;
1497     rb_thread_t *th;
1498     GetThreadPtr((VALUE)key, th);
1499
1500     switch (th->status) {
1501       case THREAD_RUNNABLE:
1502       case THREAD_STOPPED:
1503       case THREAD_STOPPED_FOREVER:
1504       case THREAD_TO_KILL:
1505         rb_ary_push(ary, th->self);
1506       default:
1507         break;
1508     }
1509     return ST_CONTINUE;
1510 }
1511
1512 /********************************************************************/
1513
1514 /*
1515  *  call-seq:
1516  *     Thread.list   => array
1517  *
1518  *  Returns an array of <code>Thread</code> objects for all threads that are
1519  *  either runnable or stopped.
1520  *
1521  *     Thread.new { sleep(200) }
1522  *     Thread.new { 1000000.times {|i| i*i } }
1523  *     Thread.new { Thread.stop }
1524  *     Thread.list.each {|t| p t}
1525  *
1526  *  <em>produces:</em>
1527  *
1528  *     #<Thread:0x401b3e84 sleep>
1529  *     #<Thread:0x401b3f38 run>
1530  *     #<Thread:0x401b3fb0 sleep>
1531  *     #<Thread:0x401bdf4c run>
1532  */
1533
1534 VALUE
1535 rb_thread_list(void)
1536 {
1537     VALUE ary = rb_ary_new();
1538     st_foreach(GET_THREAD()->vm->living_threads, thread_list_i, ary);
1539     return ary;
1540 }
1541
1542 VALUE
1543 rb_thread_current(void)
1544 {
1545     return GET_THREAD()->self;
1546 }
1547
1548 /*
1549  *  call-seq:
1550  *     Thread.current   => thread
1551  *
1552  *  Returns the currently executing thread.
1553  *
1554  *     Thread.current   #=> #<Thread:0x401bdf4c run>
1555  */
1556
1557 static VALUE
1558 thread_s_current(VALUE klass)
1559 {
1560     return rb_thread_current();
1561 }
1562
1563 VALUE
1564 rb_thread_main(void)
1565 {
1566     return GET_THREAD()->vm->main_thread->self;
1567 }
1568
1569 static VALUE
1570 rb_thread_s_main(VALUE klass)
1571 {
1572     return rb_thread_main();
1573 }
1574
1575
1576 /*
1577  *  call-seq:
1578  *     Thread.abort_on_exception   => true or false
1579  *
1580  *  Returns the status of the global ``abort on exception'' condition.  The
1581  *  default is <code>false</code>. When set to <code>true</code>, or if the
1582  *  global <code>$DEBUG</code> flag is <code>true</code> (perhaps because the
1583  *  command line option <code>-d</code> was specified) all threads will abort
1584  *  (the process will <code>exit(0)</code>) if an exception is raised in any
1585  *  thread. See also <code>Thread::abort_on_exception=</code>.
1586  */
1587
1588 static VALUE
1589 rb_thread_s_abort_exc(void)
1590 {
1591     return GET_THREAD()->vm->thread_abort_on_exception ? Qtrue : Qfalse;
1592 }
1593
1594
1595 /*
1596  *  call-seq:
1597  *     Thread.abort_on_exception= boolean   => true or false
1598  *
1599  *  When set to <code>true</code>, all threads will abort if an exception is
1600  *  raised. Returns the new state.
1601  *
1602  *     Thread.abort_on_exception = true
1603  *     t1 = Thread.new do
1604  *       puts  "In new thread"
1605  *       raise "Exception from thread"
1606  *     end
1607  *     sleep(1)
1608  *     puts "not reached"
1609  *
1610  *  <em>produces:</em>
1611  *
1612  *     In new thread
1613  *     prog.rb:4: Exception from thread (RuntimeError)
1614  *      from prog.rb:2:in `initialize'
1615  *      from prog.rb:2:in `new'
1616  *      from prog.rb:2
1617  */
1618
1619 static VALUE
1620 rb_thread_s_abort_exc_set(VALUE self, VALUE val)
1621 {
1622     rb_secure(4);
1623     GET_THREAD()->vm->thread_abort_on_exception = RTEST(val);
1624     return val;
1625 }
1626
1627
1628 /*
1629  *  call-seq:
1630  *     thr.abort_on_exception   => true or false
1631  *
1632  *  Returns the status of the thread-local ``abort on exception'' condition for
1633  *  <i>thr</i>. The default is <code>false</code>. See also
1634  *  <code>Thread::abort_on_exception=</code>.
1635  */
1636
1637 static VALUE
1638 rb_thread_abort_exc(VALUE thread)
1639 {
1640     rb_thread_t *th;
1641     GetThreadPtr(thread, th);
1642     return th->abort_on_exception ? Qtrue : Qfalse;
1643 }
1644
1645
1646 /*
1647  *  call-seq:
1648  *     thr.abort_on_exception= boolean   => true or false
1649  *
1650  *  When set to <code>true</code>, causes all threads (including the main
1651  *  program) to abort if an exception is raised in <i>thr</i>. The process will
1652  *  effectively <code>exit(0)</code>.
1653  */
1654
1655 static VALUE
1656 rb_thread_abort_exc_set(VALUE thread, VALUE val)
1657 {
1658     rb_thread_t *th;
1659     rb_secure(4);
1660
1661     GetThreadPtr(thread, th);
1662     th->abort_on_exception = RTEST(val);
1663     return val;
1664 }
1665
1666
1667 /*
1668  *  call-seq:
1669  *     thr.group   => thgrp or nil
1670  *
1671  *  Returns the <code>ThreadGroup</code> which contains <i>thr</i>, or nil if
1672  *  the thread is not a member of any group.
1673  *
1674  *     Thread.main.group   #=> #<ThreadGroup:0x4029d914>
1675  */
1676
1677 VALUE
1678 rb_thread_group(VALUE thread)
1679 {
1680     rb_thread_t *th;
1681     VALUE group;
1682     GetThreadPtr(thread, th);
1683     group = th->thgroup;
1684
1685     if (!group) {
1686         group = Qnil;
1687     }
1688     return group;
1689 }
1690
1691 static const char *
1692 thread_status_name(enum rb_thread_status status)
1693 {
1694     switch (status) {
1695       case THREAD_RUNNABLE:
1696         return "run";
1697       case THREAD_STOPPED:
1698       case THREAD_STOPPED_FOREVER:
1699         return "sleep";
1700       case THREAD_TO_KILL:
1701         return "aborting";
1702       case THREAD_KILLED:
1703         return "dead";
1704       default:
1705         return "unknown";
1706     }
1707 }
1708
1709 static int
1710 rb_thread_dead(rb_thread_t *th)
1711 {
1712     return th->status == THREAD_KILLED;
1713 }
1714
1715
1716 /*
1717  *  call-seq:
1718  *     thr.status   => string, false or nil
1719  *
1720  *  Returns the status of <i>thr</i>: ``<code>sleep</code>'' if <i>thr</i> is
1721  *  sleeping or waiting on I/O, ``<code>run</code>'' if <i>thr</i> is executing,
1722  *  ``<code>aborting</code>'' if <i>thr</i> is aborting, <code>false</code> if
1723  *  <i>thr</i> terminated normally, and <code>nil</code> if <i>thr</i>
1724  *  terminated with an exception.
1725  *
1726  *     a = Thread.new { raise("die now") }
1727  *     b = Thread.new { Thread.stop }
1728  *     c = Thread.new { Thread.exit }
1729  *     d = Thread.new { sleep }
1730  *     d.kill                  #=> #<Thread:0x401b3678 aborting>
1731  *     a.status                #=> nil
1732  *     b.status                #=> "sleep"
1733  *     c.status                #=> false
1734  *     d.status                #=> "aborting"
1735  *     Thread.current.status   #=> "run"
1736  */
1737
1738 static VALUE
1739 rb_thread_status(VALUE thread)
1740 {
1741     rb_thread_t *th;
1742     GetThreadPtr(thread, th);
1743
1744     if (rb_thread_dead(th)) {
1745         if (!NIL_P(th->errinfo) && !FIXNUM_P(th->errinfo)
1746             /* TODO */ ) {
1747             return Qnil;
1748         }
1749         return Qfalse;
1750     }
1751     return rb_str_new2(thread_status_name(th->status));
1752 }
1753
1754
1755 /*
1756  *  call-seq:
1757  *     thr.alive?   => true or false
1758  *
1759  *  Returns <code>true</code> if <i>thr</i> is running or sleeping.
1760  *
1761  *     thr = Thread.new { }
1762  *     thr.join                #=> #<Thread:0x401b3fb0 dead>
1763  *     Thread.current.alive?   #=> true
1764  *     thr.alive?              #=> false
1765  */
1766
1767 static VALUE
1768 rb_thread_alive_p(VALUE thread)
1769 {
1770     rb_thread_t *th;
1771     GetThreadPtr(thread, th);
1772
1773     if (rb_thread_dead(th))
1774         return Qfalse;
1775     return Qtrue;
1776 }
1777
1778 /*
1779  *  call-seq:
1780  *     thr.stop?   => true or false
1781  *
1782  *  Returns <code>true</code> if <i>thr</i> is dead or sleeping.
1783  *
1784  *     a = Thread.new { Thread.stop }
1785  *     b = Thread.current
1786  *     a.stop?   #=> true
1787  *     b.stop?   #=> false
1788  */
1789
1790 static VALUE
1791 rb_thread_stop_p(VALUE thread)
1792 {
1793     rb_thread_t *th;
1794     GetThreadPtr(thread, th);
1795
1796     if (rb_thread_dead(th))
1797         return Qtrue;
1798     if (th->status == THREAD_STOPPED || th->status == THREAD_STOPPED_FOREVER)
1799         return Qtrue;
1800     return Qfalse;
1801 }
1802
1803 /*
1804  *  call-seq:
1805  *     thr.safe_level   => integer
1806  *
1807  *  Returns the safe level in effect for <i>thr</i>. Setting thread-local safe
1808  *  levels can help when implementing sandboxes which run insecure code.
1809  *
1810  *     thr = Thread.new { $SAFE = 3; sleep }
1811  *     Thread.current.safe_level   #=> 0
1812  *     thr.safe_level              #=> 3
1813  */
1814
1815 static VALUE
1816 rb_thread_safe_level(VALUE thread)
1817 {
1818     rb_thread_t *th;
1819     GetThreadPtr(thread, th);
1820
1821     return INT2NUM(th->safe_level);
1822 }
1823
1824 /*
1825  * call-seq:
1826  *   thr.inspect   => string
1827  *
1828  * Dump the name, id, and status of _thr_ to a string.
1829  */
1830
1831 static VALUE
1832 rb_thread_inspect(VALUE thread)
1833 {
1834     const char *cname = rb_obj_classname(thread);
1835     rb_thread_t *th;
1836     const char *status;
1837     VALUE str;
1838
1839     GetThreadPtr(thread, th);
1840     status = thread_status_name(th->status);
1841     str = rb_sprintf("#<%s:%p %s>", cname, (void *)thread, status);
1842     OBJ_INFECT(str, thread);
1843
1844     return str;
1845 }
1846
1847 VALUE
1848 rb_thread_local_aref(VALUE thread, ID id)
1849 {
1850     rb_thread_t *th;
1851     VALUE val;
1852
1853     GetThreadPtr(thread, th);
1854     if (rb_safe_level() >= 4 && th != GET_THREAD()) {
1855         rb_raise(rb_eSecurityError, "Insecure: thread locals");
1856     }
1857     if (!th->local_storage) {
1858         return Qnil;
1859     }
1860     if (st_lookup(th->local_storage, id, &val)) {
1861         return val;
1862     }
1863     return Qnil;
1864 }
1865
1866 /*
1867  *  call-seq:
1868  *      thr[sym]   => obj or nil
1869  *
1870  *  Attribute Reference---Returns the value of a thread-local variable, using
1871  *  either a symbol or a string name. If the specified variable does not exist,
1872  *  returns <code>nil</code>.
1873  *
1874  *     a = Thread.new { Thread.current["name"] = "A"; Thread.stop }
1875  *     b = Thread.new { Thread.current[:name]  = "B"; Thread.stop }
1876  *     c = Thread.new { Thread.current["name"] = "C"; Thread.stop }
1877  *     Thread.list.each {|x| puts "#{x.inspect}: #{x[:name]}" }
1878  *
1879  *  <em>produces:</em>
1880  *
1881  *     #<Thread:0x401b3b3c sleep>: C
1882  *     #<Thread:0x401b3bc8 sleep>: B
1883  *     #<Thread:0x401b3c68 sleep>: A
1884  *     #<Thread:0x401bdf4c run>:
1885  */
1886
1887 static VALUE
1888 rb_thread_aref(VALUE thread, VALUE id)
1889 {
1890     return rb_thread_local_aref(thread, rb_to_id(id));
1891 }
1892
1893 VALUE
1894 rb_thread_local_aset(VALUE thread, ID id, VALUE val)
1895 {
1896     rb_thread_t *th;
1897     GetThreadPtr(thread, th);
1898
1899     if (rb_safe_level() >= 4 && th != GET_THREAD()) {
1900         rb_raise(rb_eSecurityError, "Insecure: can't modify thread locals");
1901     }
1902     if (OBJ_FROZEN(thread)) {
1903         rb_error_frozen("thread locals");
1904     }
1905     if (!th->local_storage) {
1906         th->local_storage = st_init_numtable();
1907     }
1908     if (NIL_P(val)) {
1909         st_delete_wrap(th->local_storage, id);
1910         return Qnil;
1911     }
1912     st_insert(th->local_storage, id, val);
1913     return val;
1914 }
1915
1916 /*
1917  *  call-seq:
1918  *      thr[sym] = obj   => obj
1919  *
1920  *  Attribute Assignment---Sets or creates the value of a thread-local variable,
1921  *  using either a symbol or a string. See also <code>Thread#[]</code>.
1922  */
1923
1924 static VALUE
1925 rb_thread_aset(VALUE self, ID id, VALUE val)
1926 {
1927     return rb_thread_local_aset(self, rb_to_id(id), val);
1928 }
1929
1930 /*
1931  *  call-seq:
1932  *     thr.key?(sym)   => true or false
1933  *
1934  *  Returns <code>true</code> if the given string (or symbol) exists as a
1935  *  thread-local variable.
1936  *
1937  *     me = Thread.current
1938  *     me[:oliver] = "a"
1939  *     me.key?(:oliver)    #=> true
1940  *     me.key?(:stanley)   #=> false
1941  */
1942
1943 static VALUE
1944 rb_thread_key_p(VALUE self, VALUE key)
1945 {
1946     rb_thread_t *th;
1947     ID id = rb_to_id(key);
1948
1949     GetThreadPtr(self, th);
1950
1951     if (!th->local_storage) {
1952         return Qfalse;
1953     }
1954     if (st_lookup(th->local_storage, id, 0)) {
1955         return Qtrue;
1956     }
1957     return Qfalse;
1958 }
1959
1960 static int
1961 thread_keys_i(ID key, VALUE value, VALUE ary)
1962 {
1963     rb_ary_push(ary, ID2SYM(key));
1964     return ST_CONTINUE;
1965 }
1966
1967 static int
1968 vm_living_thread_num(rb_vm_t *vm)
1969 {
1970     return vm->living_threads->num_entries;
1971 }
1972
1973 int
1974 rb_thread_alone()
1975 {
1976     int num = 1;
1977     if (GET_THREAD()->vm->living_threads) {
1978         num = vm_living_thread_num(GET_THREAD()->vm);
1979         thread_debug("rb_thread_alone: %d\n", num);
1980     }
1981     return num == 1;
1982 }
1983
1984 /*
1985  *  call-seq:
1986  *     thr.keys   => array
1987  *
1988  *  Returns an an array of the names of the thread-local variables (as Symbols).
1989  *
1990  *     thr = Thread.new do
1991  *       Thread.current[:cat] = 'meow'
1992  *       Thread.current["dog"] = 'woof'
1993  *     end
1994  *     thr.join   #=> #<Thread:0x401b3f10 dead>
1995  *     thr.keys   #=> [:dog, :cat]
1996  */
1997
1998 static VALUE
1999 rb_thread_keys(VALUE self)
2000 {
2001     rb_thread_t *th;
2002     VALUE ary = rb_ary_new();
2003     GetThreadPtr(self, th);
2004
2005     if (th->local_storage) {
2006         st_foreach(th->local_storage, thread_keys_i, ary);
2007     }
2008     return ary;
2009 }
2010
2011 /*
2012  *  call-seq:
2013  *     thr.priority   => integer
2014  *
2015  *  Returns the priority of <i>thr</i>. Default is inherited from the
2016  *  current thread which creating the new thread, or zero for the
2017  *  initial main thread; higher-priority threads will run before
2018  *  lower-priority threads.
2019  *
2020  *     Thread.current.priority   #=> 0
2021  */
2022
2023 static VALUE
2024 rb_thread_priority(VALUE thread)
2025 {
2026     rb_thread_t *th;
2027     GetThreadPtr(thread, th);
2028     return INT2NUM(th->priority);
2029 }
2030
2031
2032 /*
2033  *  call-seq:
2034  *     thr.priority= integer   => thr
2035  *
2036  *  Sets the priority of <i>thr</i> to <i>integer</i>. Higher-priority threads
2037  *  will run before lower-priority threads.
2038  *
2039  *     count1 = count2 = 0
2040  *     a = Thread.new do
2041  *           loop { count1 += 1 }
2042  *         end
2043  *     a.priority = -1
2044  *
2045  *     b = Thread.new do
2046  *           loop { count2 += 1 }
2047  *         end
2048  *     b.priority = -2
2049  *     sleep 1   #=> 1
2050  *     count1    #=> 622504
2051  *     count2    #=> 5832
2052  */
2053
2054 static VALUE
2055 rb_thread_priority_set(VALUE thread, VALUE prio)
2056 {
2057     rb_thread_t *th;
2058     int priority;
2059     GetThreadPtr(thread, th);
2060
2061     rb_secure(4);
2062
2063 #if USE_NATIVE_THREAD_PRIORITY
2064     th->priority = NUM2INT(prio);
2065     native_thread_apply_priority(th);
2066 #else
2067     priority = NUM2INT(prio);
2068     if (priority > RUBY_THREAD_PRIORITY_MAX) {
2069         priority = RUBY_THREAD_PRIORITY_MAX;
2070     }
2071     else if (priority < RUBY_THREAD_PRIORITY_MIN) {
2072         priority = RUBY_THREAD_PRIORITY_MIN;
2073     }
2074     th->priority = priority;
2075     th->slice = priority;
2076 #endif
2077     return INT2NUM(th->priority);
2078 }
2079
2080 /* for IO */
2081
2082 #if defined(NFDBITS) && defined(HAVE_RB_FD_INIT)
2083
2084 /*
2085  * several Unix platforms supports file descriptors bigger than FD_SETSIZE
2086  * in select(2) system call.
2087  *
2088  * - Linux 2.2.12 (?)
2089  * - NetBSD 1.2 (src/sys/kern/sys_generic.c:1.25)
2090  *   select(2) documents how to allocate fd_set dynamically.
2091  *   http://netbsd.gw.com/cgi-bin/man-cgi?select++NetBSD-4.0
2092  * - FreeBSD 2.2 (src/sys/kern/sys_generic.c:1.19)
2093  * - OpenBSD 2.0 (src/sys/kern/sys_generic.c:1.4)
2094  *   select(2) documents how to allocate fd_set dynamically.
2095  *   http://www.openbsd.org/cgi-bin/man.cgi?query=select&manpath=OpenBSD+4.4
2096  * - HP-UX documents how to allocate fd_set dynamically. 
2097  *   http://docs.hp.com/en/B2355-60105/select.2.html
2098  * - Solaris 8 has select_large_fdset
2099  *
2100  * When fd_set is not big enough to hold big file descriptors,
2101  * it should be allocated dynamically.
2102  * Note that this assumes fd_set is structured as bitmap.
2103  *
2104  * rb_fd_init allocates the memory.
2105  * rb_fd_term free the memory.
2106  * rb_fd_set may re-allocates bitmap.
2107  *
2108  * So rb_fd_set doesn't reject file descriptors bigger than FD_SETSIZE.
2109  */
2110
2111 void
2112 rb_fd_init(volatile rb_fdset_t *fds)
2113 {
2114     fds->maxfd = 0;
2115     fds->fdset = ALLOC(fd_set);
2116     FD_ZERO(fds->fdset);
2117 }
2118
2119 void
2120 rb_fd_term(rb_fdset_t *fds)
2121 {
2122     if (fds->fdset) xfree(fds->fdset);
2123     fds->maxfd = 0;
2124     fds->fdset = 0;
2125 }
2126
2127 void
2128 rb_fd_zero(rb_fdset_t *fds)
2129 {
2130     if (fds->fdset) {
2131         MEMZERO(fds->fdset, fd_mask, howmany(fds->maxfd, NFDBITS));
2132         FD_ZERO(fds->fdset);
2133     }
2134 }
2135
2136 static void
2137 rb_fd_resize(int n, rb_fdset_t *fds)
2138 {
2139     int m = howmany(n + 1, NFDBITS) * sizeof(fd_mask);
2140     int o = howmany(fds->maxfd, NFDBITS) * sizeof(fd_mask);
2141
2142     if (m < sizeof(fd_set)) m = sizeof(fd_set);
2143     if (o < sizeof(fd_set)) o = sizeof(fd_set);
2144
2145     if (m > o) {
2146         fds->fdset = realloc(fds->fdset, m);
2147         memset((char *)fds->fdset + o, 0, m - o);
2148     }
2149     if (n >= fds->maxfd) fds->maxfd = n + 1;
2150 }
2151
2152 void
2153 rb_fd_set(int n, rb_fdset_t *fds)
2154 {
2155     rb_fd_resize(n, fds);
2156     FD_SET(n, fds->fdset);
2157 }
2158
2159 void
2160 rb_fd_clr(int n, rb_fdset_t *fds)
2161 {
2162     if (n >= fds->maxfd) return;
2163     FD_CLR(n, fds->fdset);
2164 }
2165
2166 int
2167 rb_fd_isset(int n, const rb_fdset_t *fds)
2168 {
2169     if (n >= fds->maxfd) return 0;
2170     return FD_ISSET(n, fds->fdset) != 0; /* "!= 0" avoids FreeBSD PR 91421 */
2171 }
2172
2173 void
2174 rb_fd_copy(rb_fdset_t *dst, const fd_set *src, int max)
2175 {
2176     int size = howmany(max, NFDBITS) * sizeof(fd_mask);
2177
2178     if (size < sizeof(fd_set)) size = sizeof(fd_set);
2179     dst->maxfd = max;
2180     dst->fdset = realloc(dst->fdset, size);
2181     memcpy(dst->fdset, src, size);
2182 }
2183
2184 int
2185 rb_fd_select(int n, rb_fdset_t *readfds, rb_fdset_t *writefds, rb_fdset_t *exceptfds, struct timeval *timeout)
2186 {
2187     fd_set *r = NULL, *w = NULL, *e = NULL;
2188     if (readfds) {
2189         rb_fd_resize(n - 1, readfds);
2190         r = rb_fd_ptr(readfds);
2191     }
2192     if (writefds) {
2193         rb_fd_resize(n - 1, writefds);
2194         w = rb_fd_ptr(writefds);
2195     }
2196     if (exceptfds) {
2197         rb_fd_resize(n - 1, exceptfds);
2198         e = rb_fd_ptr(exceptfds);
2199     }
2200     return select(n, r, w, e, timeout);
2201 }
2202
2203 #undef FD_ZERO
2204 #undef FD_SET
2205 #undef FD_CLR
2206 #undef FD_ISSET
2207
2208 #define FD_ZERO(f)      rb_fd_zero(f)
2209 #define FD_SET(i, f)    rb_fd_set(i, f)
2210 #define FD_CLR(i, f)    rb_fd_clr(i, f)
2211 #define FD_ISSET(i, f)  rb_fd_isset(i, f)
2212
2213 #endif
2214
2215 #if defined(__CYGWIN__) || defined(_WIN32)
2216 static long
2217 cmp_tv(const struct timeval *a, const struct timeval *b)
2218 {
2219     long d = (a->tv_sec - b->tv_sec);
2220     return (d != 0) ? d : (a->tv_usec - b->tv_usec);
2221 }
2222
2223 static int
2224 subtract_tv(struct timeval *rest, const struct timeval *wait)
2225 {
2226     while (rest->tv_usec < wait->tv_usec) {
2227         if (rest->tv_sec <= wait->tv_sec) {
2228             return 0;
2229         }
2230         rest->tv_sec -= 1;
2231         rest->tv_usec += 1000 * 1000;
2232     }
2233     rest->tv_sec -= wait->tv_sec;
2234     rest->tv_usec -= wait->tv_usec;
2235     return 1;
2236 }
2237 #endif
2238
2239 static int
2240 do_select(int n, fd_set *read, fd_set *write, fd_set *except,
2241           struct timeval *timeout)
2242 {
2243     int result, lerrno;
2244     fd_set orig_read, orig_write, orig_except;
2245
2246 #ifndef linux
2247     double limit = 0;
2248     struct timeval wait_rest;
2249 # if defined(__CYGWIN__) || defined(_WIN32)
2250     struct timeval start_time;
2251 # endif
2252
2253     if (timeout) {
2254 # if defined(__CYGWIN__) || defined(_WIN32)
2255         gettimeofday(&start_time, NULL);
2256         limit = (double)start_time.tv_sec + (double)start_time.tv_usec*1e-6;
2257 # else
2258         limit = timeofday();
2259 # endif
2260         limit += (double)timeout->tv_sec+(double)timeout->tv_usec*1e-6;
2261         wait_rest = *timeout;
2262         timeout = &wait_rest;
2263     }
2264 #endif
2265
2266     if (read) orig_read = *read;
2267     if (write) orig_write = *write;
2268     if (except) orig_except = *except;
2269
2270   retry:
2271     lerrno = 0;
2272
2273 #if defined(__CYGWIN__) || defined(_WIN32)
2274     {
2275         int finish = 0;
2276         /* polling duration: 100ms */
2277         struct timeval wait_100ms, *wait;
2278         wait_100ms.tv_sec = 0;
2279         wait_100ms.tv_usec = 100 * 1000; /* 100 ms */
2280
2281         do {
2282             wait = (timeout == 0 || cmp_tv(&wait_100ms, timeout) > 0) ? &wait_100ms : timeout;
2283             BLOCKING_REGION({
2284                 do {
2285                     result = select(n, read, write, except, wait);
2286                     if (result < 0) lerrno = errno;
2287                     if (result != 0) break;
2288
2289                     if (read) *read = orig_read;
2290                     if (write) *write = orig_write;
2291                     if (except) *except = orig_except;
2292                     wait = &wait_100ms;
2293                     if (timeout) {
2294                         struct timeval elapsed;
2295                         gettimeofday(&elapsed, NULL);
2296                         subtract_tv(&elapsed, &start_time);
2297                         if (!subtract_tv(timeout, &elapsed)) {
2298                             finish = 1;
2299                             break;
2300                         }
2301                         if (cmp_tv(&wait_100ms, timeout) < 0) wait = timeout;
2302                     }
2303                 } while (__th->interrupt_flag == 0);
2304             }, 0, 0);
2305         } while (result == 0 && !finish);
2306     }
2307 #else
2308     BLOCKING_REGION({
2309         result = select(n, read, write, except, timeout);
2310         if (result < 0) lerrno = errno;
2311     }, ubf_select, GET_THREAD());
2312 #endif
2313
2314     errno = lerrno;
2315
2316     if (result < 0) {
2317         switch (errno) {
2318           case EINTR:
2319 #ifdef ERESTART
2320           case ERESTART:
2321 #endif
2322             if (read) *read = orig_read;
2323             if (write) *write = orig_write;
2324             if (except) *except = orig_except;
2325 #ifndef linux
2326             if (timeout) {
2327                 double d = limit - timeofday();
2328
2329                 wait_rest.tv_sec = (unsigned int)d;
2330                 wait_rest.tv_usec = (long)((d-(double)wait_rest.tv_sec)*1e6);
2331                 if (wait_rest.tv_sec < 0)  wait_rest.tv_sec = 0;
2332                 if (wait_rest.tv_usec < 0) wait_rest.tv_usec = 0;
2333             }
2334 #endif
2335             goto retry;
2336           default:
2337             break;
2338         }
2339     }
2340     return result;
2341 }
2342
2343 static void
2344 rb_thread_wait_fd_rw(int fd, int read)
2345 {
2346     int result = 0;
2347     thread_debug("rb_thread_wait_fd_rw(%d, %s)\n", fd, read ? "read" : "write");
2348
2349     if (fd < 0) {
2350         rb_raise(rb_eIOError, "closed stream");
2351     }
2352     if (rb_thread_alone()) return;
2353     while (result <= 0) {
2354         rb_fdset_t set;
2355         rb_fd_init(&set);
2356         FD_SET(fd, &set);
2357
2358         if (read) {
2359             result = do_select(fd + 1, rb_fd_ptr(&set), 0, 0, 0);
2360         }
2361         else {
2362             result = do_select(fd + 1, 0, rb_fd_ptr(&set), 0, 0);
2363         }
2364
2365         rb_fd_term(&set);
2366
2367         if (result < 0) {
2368             rb_sys_fail(0);
2369         }
2370     }
2371
2372     thread_debug("rb_thread_wait_fd_rw(%d, %s): done\n", fd, read ? "read" : "write");
2373 }
2374
2375 void
2376 rb_thread_wait_fd(int fd)
2377 {
2378     rb_thread_wait_fd_rw(fd, 1);
2379 }
2380
2381 int
2382 rb_thread_fd_writable(int fd)
2383 {
2384     rb_thread_wait_fd_rw(fd, 0);
2385     return Qtrue;
2386 }
2387
2388 int
2389 rb_thread_select(int max, fd_set * read, fd_set * write, fd_set * except,
2390                  struct timeval *timeout)
2391 {
2392     if (!read && !write && !except) {
2393         if (!timeout) {
2394             rb_thread_sleep_forever();
2395             return 0;
2396         }
2397         rb_thread_wait_for(*timeout);
2398         return 0;
2399     }
2400     else {
2401         return do_select(max, read, write, except, timeout);
2402     }
2403 }
2404
2405
2406 /*
2407  * for GC
2408  */
2409
2410 #ifdef USE_CONSERVATIVE_STACK_END
2411 void
2412 rb_gc_set_stack_end(VALUE **stack_end_p)
2413 {
2414     VALUE stack_end;
2415     *stack_end_p = &stack_end;
2416 }
2417 #endif
2418
2419 void
2420 rb_gc_save_machine_context(rb_thread_t *th)
2421 {
2422     SET_MACHINE_STACK_END(&th->machine_stack_end);
2423     FLUSH_REGISTER_WINDOWS;
2424 #ifdef __ia64
2425     th->machine_register_stack_end = rb_ia64_bsp();
2426 #endif
2427     setjmp(th->machine_regs);
2428 }
2429
2430 /*
2431  *
2432  */
2433
2434 int rb_get_next_signal(void);
2435
2436 static void
2437 timer_thread_function(void *arg)
2438 {
2439     rb_vm_t *vm = GET_VM(); /* TODO: fix me for Multi-VM */
2440     int sig;
2441
2442     /* for time slice */
2443     RUBY_VM_SET_TIMER_INTERRUPT(vm->running_thread);
2444
2445     /* check signal */
2446     if ((sig = rb_get_next_signal()) > 0) {
2447         rb_thread_t *mth = vm->main_thread;
2448         enum rb_thread_status prev_status = mth->status;
2449         thread_debug("main_thread: %s, sig: %d\n",
2450                      thread_status_name(prev_status), sig);
2451         mth->exec_signal = sig;
2452         if (mth->status != THREAD_KILLED) mth->status = THREAD_RUNNABLE;
2453         rb_thread_interrupt(mth);
2454         mth->status = prev_status;
2455     }
2456
2457 #if 0
2458     /* prove profiler */
2459     if (vm->prove_profile.enable) {
2460         rb_thread_t *th = vm->running_thread;
2461
2462         if (vm->during_gc) {
2463             /* GC prove profiling */
2464         }
2465     }
2466 #endif
2467 }
2468
2469 void
2470 rb_thread_stop_timer_thread(void)
2471 {
2472     if (timer_thread_id && native_stop_timer_thread()) {
2473         native_thread_join(timer_thread_id);
2474         timer_thread_id = 0;
2475     }
2476 }
2477
2478 void
2479 rb_thread_reset_timer_thread(void)
2480 {
2481     timer_thread_id = 0;
2482 }
2483
2484 void
2485 rb_thread_start_timer_thread(void)
2486 {
2487     system_working = 1;
2488     rb_thread_create_timer_thread();
2489 }
2490
2491 static int
2492 clear_coverage_i(st_data_t key, st_data_t val, st_data_t dummy)
2493 {
2494     int i;
2495     VALUE lines = (VALUE)val;
2496
2497     for (i = 0; i < RARRAY_LEN(lines); i++) {
2498         if (RARRAY_PTR(lines)[i] != Qnil) {
2499             RARRAY_PTR(lines)[i] = INT2FIX(0);
2500         }
2501     }
2502     return ST_CONTINUE;
2503 }
2504
2505 static void
2506 clear_coverage(void)
2507 {
2508     extern VALUE rb_get_coverages(void);
2509     VALUE coverages = rb_get_coverages();
2510     if (RTEST(coverages)) {
2511         st_foreach(RHASH_TBL(coverages), clear_coverage_i, 0);
2512     }
2513 }
2514
2515 static void
2516 rb_thread_atfork_internal(int (*atfork)(st_data_t, st_data_t, st_data_t))
2517 {
2518     rb_thread_t *th = GET_THREAD();
2519     rb_vm_t *vm = th->vm;
2520     VALUE thval = th->self;
2521     vm->main_thread = th;
2522
2523     st_foreach(vm->living_threads, atfork, (st_data_t)th);
2524     st_clear(vm->living_threads);
2525     st_insert(vm->living_threads, thval, (st_data_t)th->thread_id);
2526     vm->sleeper = 0;
2527     clear_coverage();
2528 }
2529
2530 static int
2531 terminate_atfork_i(st_data_t key, st_data_t val, st_data_t current_th)
2532 {
2533     VALUE thval = key;
2534     rb_thread_t *th;
2535     GetThreadPtr(thval, th);
2536
2537     if (th != (rb_thread_t *)current_th) {
2538         thread_cleanup_func(th);
2539     }
2540     return ST_CONTINUE;
2541 }
2542
2543 void
2544 rb_thread_atfork(void)
2545 {
2546     rb_thread_atfork_internal(terminate_atfork_i);
2547     rb_reset_random_seed();
2548 }
2549
2550 static int
2551 terminate_atfork_before_exec_i(st_data_t key, st_data_t val, st_data_t current_th)
2552 {
2553     VALUE thval = key;
2554     rb_thread_t *th;
2555     GetThreadPtr(thval, th);
2556
2557     if (th != (rb_thread_t *)current_th) {
2558         thread_cleanup_func_before_exec(th);
2559     }
2560     return ST_CONTINUE;
2561 }
2562
2563 void
2564 rb_thread_atfork_before_exec(void)
2565 {
2566     rb_thread_atfork_internal(terminate_atfork_before_exec_i);
2567 }
2568
2569 struct thgroup {
2570     int enclosed;
2571     VALUE group;
2572 };
2573
2574 /*
2575  * Document-class: ThreadGroup
2576  *
2577  *  <code>ThreadGroup</code> provides a means of keeping track of a number of
2578  *  threads as a group. A <code>Thread</code> can belong to only one
2579  *  <code>ThreadGroup</code> at a time; adding a thread to a new group will
2580  *  remove it from any previous group.
2581  *
2582  *  Newly created threads belong to the same group as the thread from which they
2583  *  were created.
2584  */
2585
2586 static VALUE thgroup_s_alloc(VALUE);
2587 static VALUE
2588 thgroup_s_alloc(VALUE klass)
2589 {
2590     VALUE group;
2591     struct thgroup *data;
2592
2593     group = Data_Make_Struct(klass, struct thgroup, 0, -1, data);
2594     data->enclosed = 0;
2595     data->group = group;
2596
2597     return group;
2598 }
2599
2600 struct thgroup_list_params {
2601     VALUE ary;
2602     VALUE group;
2603 };
2604
2605 static int
2606 thgroup_list_i(st_data_t key, st_data_t val, st_data_t data)
2607 {
2608     VALUE thread = (VALUE)key;
2609     VALUE ary = ((struct thgroup_list_params *)data)->ary;
2610     VALUE group = ((struct thgroup_list_params *)data)->group;
2611     rb_thread_t *th;
2612     GetThreadPtr(thread, th);
2613
2614     if (th->thgroup == group) {
2615         rb_ary_push(ary, thread);
2616     }
2617     return ST_CONTINUE;
2618 }
2619
2620 /*
2621  *  call-seq:
2622  *     thgrp.list   => array
2623  *
2624  *  Returns an array of all existing <code>Thread</code> objects that belong to
2625  *  this group.
2626  *
2627  *     ThreadGroup::Default.list   #=> [#<Thread:0x401bdf4c run>]
2628  */
2629
2630 static VALUE
2631 thgroup_list(VALUE group)
2632 {
2633     VALUE ary = rb_ary_new();
2634     struct thgroup_list_params param;
2635     
2636     param.ary = ary;
2637     param.group = group;
2638     st_foreach(GET_THREAD()->vm->living_threads, thgroup_list_i, (st_data_t) & param);
2639     return ary;
2640 }
2641
2642
2643 /*
2644  *  call-seq:
2645  *     thgrp.enclose   => thgrp
2646  *
2647  *  Prevents threads from being added to or removed from the receiving
2648  *  <code>ThreadGroup</code>. New threads can still be started in an enclosed
2649  *  <code>ThreadGroup</code>.
2650  *
2651  *     ThreadGroup::Default.enclose        #=> #<ThreadGroup:0x4029d914>
2652  *     thr = Thread::new { Thread.stop }   #=> #<Thread:0x402a7210 sleep>
2653  *     tg = ThreadGroup::new               #=> #<ThreadGroup:0x402752d4>
2654  *     tg.add thr
2655  *
2656  *  <em>produces:</em>
2657  *
2658  *     ThreadError: can't move from the enclosed thread group
2659  */
2660
2661 static VALUE
2662 thgroup_enclose(VALUE group)
2663 {
2664     struct thgroup *data;
2665
2666     Data_Get_Struct(group, struct thgroup, data);
2667     data->enclosed = 1;
2668
2669     return group;
2670 }
2671
2672
2673 /*
2674  *  call-seq:
2675  *     thgrp.enclosed?   => true or false
2676  *
2677  *  Returns <code>true</code> if <em>thgrp</em> is enclosed. See also
2678  *  ThreadGroup#enclose.
2679  */
2680
2681 static VALUE
2682 thgroup_enclosed_p(VALUE group)
2683 {
2684     struct thgroup *data;
2685
2686     Data_Get_Struct(group, struct thgroup, data);
2687     if (data->enclosed)
2688         return Qtrue;
2689     return Qfalse;
2690 }
2691
2692
2693 /*
2694  *  call-seq:
2695  *     thgrp.add(thread)   => thgrp
2696  *
2697  *  Adds the given <em>thread</em> to this group, removing it from any other
2698  *  group to which it may have previously belonged.
2699  *
2700  *     puts "Initial group is #{ThreadGroup::Default.list}"
2701  *     tg = ThreadGroup.new
2702  *     t1 = Thread.new { sleep }
2703  *     t2 = Thread.new { sleep }
2704  *     puts "t1 is #{t1}"
2705  *     puts "t2 is #{t2}"
2706  *     tg.add(t1)
2707  *     puts "Initial group now #{ThreadGroup::Default.list}"
2708  *     puts "tg group now #{tg.list}"
2709  *
2710  *  <em>produces:</em>
2711  *
2712  *     Initial group is #<Thread:0x401bdf4c>
2713  *     t1 is #<Thread:0x401b3c90>
2714  *     t2 is #<Thread:0x401b3c18>
2715  *     Initial group now #<Thread:0x401b3c18>#<Thread:0x401bdf4c>
2716  *     tg group now #<Thread:0x401b3c90>
2717  */
2718
2719 static VALUE
2720 thgroup_add(VALUE group, VALUE thread)
2721 {
2722     rb_thread_t *th;
2723     struct thgroup *data;
2724
2725     rb_secure(4);
2726     GetThreadPtr(thread, th);
2727
2728     if (OBJ_FROZEN(group)) {
2729         rb_raise(rb_eThreadError, "can't move to the frozen thread group");
2730     }
2731     Data_Get_Struct(group, struct thgroup, data);
2732     if (data->enclosed) {
2733         rb_raise(rb_eThreadError, "can't move to the enclosed thread group");
2734     }
2735
2736     if (!th->thgroup) {
2737         return Qnil;
2738     }
2739
2740     if (OBJ_FROZEN(th->thgroup)) {
2741         rb_raise(rb_eThreadError, "can't move from the frozen thread group");
2742     }
2743     Data_Get_Struct(th->thgroup, struct thgroup, data);
2744     if (data->enclosed) {
2745         rb_raise(rb_eThreadError,
2746                  "can't move from the enclosed thread group");
2747     }
2748
2749     th->thgroup = group;
2750     return group;
2751 }
2752
2753
2754 /*
2755  *  Document-class: Mutex
2756  *
2757  *  Mutex implements a simple semaphore that can be used to coordinate access to
2758  *  shared data from multiple concurrent threads.
2759  *
2760  *  Example:
2761  *
2762  *    require 'thread'
2763  *    semaphore = Mutex.new
2764  *
2765  *    a = Thread.new {
2766  *      semaphore.synchronize {
2767  *        # access shared resource
2768  *      }
2769  *    }
2770  *
2771  *    b = Thread.new {
2772  *      semaphore.synchronize {
2773  *        # access shared resource
2774  *      }
2775  *    }
2776  *
2777  */
2778
2779 #define GetMutexPtr(obj, tobj) \
2780   Data_Get_Struct(obj, mutex_t, tobj)
2781
2782 static const char *mutex_unlock(mutex_t *mutex, rb_thread_t volatile *th);
2783
2784 static void
2785 mutex_free(void *ptr)
2786 {
2787     if (ptr) {
2788         mutex_t *mutex = ptr;
2789         if (mutex->th) {
2790             /* rb_warn("free locked mutex"); */
2791             const char *err = mutex_unlock(mutex, mutex->th);
2792             if (err) rb_bug("%s", err);
2793         }
2794         native_mutex_destroy(&mutex->lock);
2795         native_cond_destroy(&mutex->cond);
2796     }
2797     ruby_xfree(ptr);
2798 }
2799
2800 static VALUE
2801 mutex_alloc(VALUE klass)
2802 {
2803     VALUE volatile obj;
2804     mutex_t *mutex;
2805
2806     obj = Data_Make_Struct(klass, mutex_t, NULL, mutex_free, mutex);
2807     native_mutex_initialize(&mutex->lock);
2808     native_cond_initialize(&mutex->cond);
2809     return obj;
2810 }
2811
2812 /*
2813  *  call-seq:
2814  *     Mutex.new   => mutex
2815  *
2816  *  Creates a new Mutex
2817  */
2818 static VALUE
2819 mutex_initialize(VALUE self)
2820 {
2821     return self;
2822 }
2823
2824 VALUE
2825 rb_mutex_new(void)
2826 {
2827     return mutex_alloc(rb_cMutex);
2828 }
2829
2830 /*
2831  * call-seq:
2832  *    mutex.locked?  => true or false
2833  *
2834  * Returns +true+ if this lock is currently held by some thread.
2835  */
2836 VALUE
2837 rb_mutex_locked_p(VALUE self)
2838 {
2839     mutex_t *mutex;
2840     GetMutexPtr(self, mutex);
2841     return mutex->th ? Qtrue : Qfalse;
2842 }
2843
2844 static void
2845 mutex_locked(rb_thread_t *th, VALUE self)
2846 {
2847     mutex_t *mutex;
2848     GetMutexPtr(self, mutex);
2849
2850     if (th->keeping_mutexes) {
2851         mutex->next_mutex = th->keeping_mutexes;
2852     }
2853     th->keeping_mutexes = mutex;
2854 }
2855
2856 /*
2857  * call-seq:
2858  *    mutex.try_lock  => true or false
2859  *
2860  * Attempts to obtain the lock and returns immediately. Returns +true+ if the
2861  * lock was granted.
2862  */
2863 VALUE
2864 rb_mutex_trylock(VALUE self)
2865 {
2866     mutex_t *mutex;
2867     VALUE locked = Qfalse;
2868     GetMutexPtr(self, mutex);
2869
2870     native_mutex_lock(&mutex->lock);
2871     if (mutex->th == 0) {
2872         mutex->th = GET_THREAD();
2873         locked = Qtrue;
2874
2875         mutex_locked(GET_THREAD(), self);
2876     }
2877     native_mutex_unlock(&mutex->lock);
2878
2879     return locked;
2880 }
2881
2882 static int
2883 lock_func(rb_thread_t *th, mutex_t *mutex, int last_thread)
2884 {
2885     int interrupted = 0;
2886 #if 0 /* for debug */
2887     native_thread_yield();
2888 #endif
2889
2890     native_mutex_lock(&mutex->lock);
2891     th->transition_for_lock = 0;
2892     while (mutex->th || (mutex->th = th, 0)) {
2893         if (last_thread) {
2894             interrupted = 2;
2895             break;
2896         }
2897
2898         mutex->cond_waiting++;
2899         native_cond_wait(&mutex->cond, &mutex->lock);
2900         mutex->cond_notified--;
2901
2902         if (RUBY_VM_INTERRUPTED(th)) {
2903             interrupted = 1;
2904             break;
2905         }
2906     }
2907     th->transition_for_lock = 1;
2908     native_mutex_unlock(&mutex->lock);
2909
2910     if (interrupted == 2) native_thread_yield();
2911 #if 0 /* for debug */
2912     native_thread_yield();
2913 #endif
2914
2915     return interrupted;
2916 }
2917
2918 static void
2919 lock_interrupt(void *ptr)
2920 {
2921     mutex_t *mutex = (mutex_t *)ptr;
2922     native_mutex_lock(&mutex->lock);
2923     if (mutex->cond_waiting > 0) {
2924         native_cond_broadcast(&mutex->cond);
2925         mutex->cond_notified = mutex->cond_waiting;
2926         mutex->cond_waiting = 0;
2927     }
2928     native_mutex_unlock(&mutex->lock);
2929 }
2930
2931 /*
2932  * call-seq:
2933  *    mutex.lock  => true or false
2934  *
2935  * Attempts to grab the lock and waits if it isn't available.
2936  * Raises +ThreadError+ if +mutex+ was locked by the current thread.
2937  */
2938 VALUE
2939 rb_mutex_lock(VALUE self)
2940 {
2941
2942     if (rb_mutex_trylock(self) == Qfalse) {
2943         mutex_t *mutex;
2944         rb_thread_t *th = GET_THREAD();
2945         GetMutexPtr(self, mutex);
2946
2947         if (mutex->th == GET_THREAD()) {
2948             rb_raise(rb_eThreadError, "deadlock; recursive locking");
2949         }
2950
2951         while (mutex->th != th) {
2952             int interrupted;
2953             enum rb_thread_status prev_status = th->status;
2954             int last_thread = 0;
2955             struct rb_unblock_callback oldubf;
2956
2957             set_unblock_function(th, lock_interrupt, mutex, &oldubf);
2958             th->status = THREAD_STOPPED_FOREVER;
2959             th->vm->sleeper++;
2960             th->locking_mutex = self;
2961             if (vm_living_thread_num(th->vm) == th->vm->sleeper) {
2962                 last_thread = 1;
2963             }
2964
2965             th->transition_for_lock = 1;
2966             BLOCKING_REGION_CORE({
2967                 interrupted = lock_func(th, mutex, last_thread);
2968             });
2969             th->transition_for_lock = 0;
2970             remove_signal_thread_list(th);
2971             reset_unblock_function(th, &oldubf);
2972
2973             th->locking_mutex = Qfalse;
2974             if (mutex->th && interrupted == 2) {
2975                 rb_check_deadlock(th->vm);
2976             }
2977             if (th->status == THREAD_STOPPED_FOREVER) {
2978                 th->status = prev_status;
2979             }
2980             th->vm->sleeper--;
2981
2982             if (mutex->th == th) mutex_locked(th, self);
2983
2984             if (interrupted) {
2985                 RUBY_VM_CHECK_INTS();
2986             }
2987         }
2988     }
2989     return self;
2990 }
2991
2992 static const char *
2993 mutex_unlock(mutex_t *mutex, rb_thread_t volatile *th)
2994 {
2995     const char *err = NULL;
2996     mutex_t *th_mutex;
2997
2998     native_mutex_lock(&mutex->lock);
2999
3000     if (mutex->th == 0) {
3001         err = "Attempt to unlock a mutex which is not locked";
3002     }
3003     else if (mutex->th != th) {
3004         err = "Attempt to unlock a mutex which is locked by another thread";
3005     }
3006     else {
3007         mutex->th = 0;
3008         if (mutex->cond_waiting > 0) {
3009             /* waiting thread */
3010             native_cond_signal(&mutex->cond);
3011             mutex->cond_waiting--;
3012             mutex->cond_notified++;
3013         }
3014     }
3015
3016     native_mutex_unlock(&mutex->lock);
3017
3018     if (!err) {
3019         th_mutex = th->keeping_mutexes;
3020         if (th_mutex == mutex) {
3021             th->keeping_mutexes = mutex->next_mutex;
3022         }
3023         else {
3024             while (1) {
3025                 mutex_t *tmp_mutex;
3026                 tmp_mutex = th_mutex->next_mutex;
3027                 if (tmp_mutex == mutex) {
3028                     th_mutex->next_mutex = tmp_mutex->next_mutex;
3029                     break;
3030                 }
3031                 th_mutex = tmp_mutex;
3032             }
3033         }
3034         mutex->next_mutex = NULL;
3035     }
3036
3037     return err;
3038 }
3039
3040 /*
3041  * call-seq:
3042  *    mutex.unlock    => self
3043  *
3044  * Releases the lock.
3045  * Raises +ThreadError+ if +mutex+ wasn't locked by the current thread.
3046  */
3047 VALUE
3048 rb_mutex_unlock(VALUE self)
3049 {
3050     const char *err;
3051     mutex_t *mutex;
3052     GetMutexPtr(self, mutex);
3053
3054     err = mutex_unlock(mutex, GET_THREAD());
3055     if (err) rb_raise(rb_eThreadError, "%s", err);
3056
3057     return self;
3058 }
3059
3060 static void
3061 rb_mutex_unlock_all(mutex_t *mutexes)
3062 {
3063     const char *err;
3064     mutex_t *mutex;
3065
3066     while (mutexes) {
3067         mutex = mutexes;
3068         /* rb_warn("mutex #<%p> remains to be locked by terminated thread",
3069                 mutexes); */
3070         mutexes = mutex->next_mutex;
3071         err = mutex_unlock(mutex, GET_THREAD());
3072         if (err) rb_bug("invalid keeping_mutexes: %s", err);
3073     }
3074 }
3075
3076 static VALUE
3077 rb_mutex_sleep_forever(VALUE time)
3078 {
3079     rb_thread_sleep_deadly();
3080     return Qnil;
3081 }
3082
3083 static VALUE
3084 rb_mutex_wait_for(VALUE time)
3085 {
3086     const struct timeval *t = (struct timeval *)time;
3087     rb_thread_wait_for(*t);
3088     return Qnil;
3089 }
3090
3091 VALUE
3092 rb_mutex_sleep(VALUE self, VALUE timeout)
3093 {
3094     time_t beg, end;
3095     struct timeval t;
3096
3097     if (!NIL_P(timeout)) {
3098         t = rb_time_interval(timeout);
3099     }
3100     rb_mutex_unlock(self);
3101     beg = time(0);
3102     if (NIL_P(timeout)) {
3103         rb_ensure(rb_mutex_sleep_forever, Qnil, rb_mutex_lock, self);
3104     }
3105     else {
3106         rb_ensure(rb_mutex_wait_for, (VALUE)&t, rb_mutex_lock, self);
3107     }
3108     end = time(0) - beg;
3109     return INT2FIX(end);
3110 }
3111
3112 /*
3113  * call-seq:
3114  *    mutex.sleep(timeout = nil)    => number
3115  *
3116  * Releases the lock and sleeps +timeout+ seconds if it is given and
3117  * non-nil or forever.  Raises +ThreadError+ if +mutex+ wasn't locked by
3118  * the current thread.
3119  */
3120 static VALUE
3121 mutex_sleep(int argc, VALUE *argv, VALUE self)
3122 {
3123     VALUE timeout;
3124
3125     rb_scan_args(argc, argv, "01", &timeout);
3126     return rb_mutex_sleep(self, timeout);
3127 }
3128
3129 /*
3130  * call-seq:
3131  *    mutex.synchronize { ... }    => result of the block
3132  *
3133  * Obtains a lock, runs the block, and releases the lock when the block
3134  * completes.  See the example under +Mutex+.
3135  */
3136
3137 VALUE
3138 rb_mutex_synchronize(VALUE mutex, VALUE (*func)(VALUE arg), VALUE arg)
3139 {
3140     rb_mutex_lock(mutex);
3141     return rb_ensure(func, arg, rb_mutex_unlock, mutex);
3142 }
3143
3144 /*
3145  * Document-class: Barrier
3146  */
3147 static VALUE
3148 barrier_alloc(VALUE klass)
3149 {
3150     return Data_Wrap_Struct(klass, rb_gc_mark, 0, (void *)mutex_alloc(0));
3151 }
3152
3153 VALUE
3154 rb_barrier_new(void)
3155 {
3156     VALUE barrier = barrier_alloc(rb_cBarrier);
3157     rb_mutex_lock((VALUE)DATA_PTR(barrier));
3158     return barrier;
3159 }
3160
3161 VALUE
3162 rb_barrier_wait(VALUE self)
3163 {
3164     VALUE mutex = (VALUE)DATA_PTR(self);
3165     mutex_t *m;
3166
3167     if (!mutex) return Qfalse;
3168     GetMutexPtr(mutex, m);
3169     if (m->th == GET_THREAD()) return Qfalse;
3170     rb_mutex_lock(mutex);
3171     if (DATA_PTR(self)) return Qtrue;
3172     rb_mutex_unlock(mutex);
3173     return Qfalse;
3174 }
3175
3176 VALUE
3177 rb_barrier_release(VALUE self)
3178 {
3179     return rb_mutex_unlock((VALUE)DATA_PTR(self));
3180 }
3181
3182 VALUE
3183 rb_barrier_destroy(VALUE self)
3184 {
3185     VALUE mutex = (VALUE)DATA_PTR(self);
3186     DATA_PTR(self) = 0;
3187     return rb_mutex_unlock(mutex);
3188 }
3189
3190 /* variables for recursive traversals */
3191 static ID recursive_key;
3192
3193 static VALUE
3194 recursive_check(VALUE hash, VALUE obj)
3195 {
3196     if (NIL_P(hash) || TYPE(hash) != T_HASH) {
3197         return Qfalse;
3198     }
3199     else {
3200         VALUE list = rb_hash_aref(hash, ID2SYM(rb_frame_this_func()));
3201
3202         if (NIL_P(list) || TYPE(list) != T_HASH)
3203             return Qfalse;
3204         if (NIL_P(rb_hash_lookup(list, obj)))
3205             return Qfalse;
3206         return Qtrue;
3207     }
3208 }
3209
3210 static VALUE
3211 recursive_push(VALUE hash, VALUE obj)
3212 {
3213     VALUE list, sym;
3214
3215     sym = ID2SYM(rb_frame_this_func());
3216     if (NIL_P(hash) || TYPE(hash) != T_HASH) {
3217         hash = rb_hash_new();
3218         rb_thread_local_aset(rb_thread_current(), recursive_key, hash);
3219         list = Qnil;
3220     }
3221     else {
3222         list = rb_hash_aref(hash, sym);
3223     }
3224     if (NIL_P(list) || TYPE(list) != T_HASH) {
3225         list = rb_hash_new();
3226         rb_hash_aset(hash, sym, list);
3227     }
3228     rb_hash_aset(list, obj, Qtrue);
3229     return hash;
3230 }
3231
3232 static void
3233 recursive_pop(VALUE hash, VALUE obj)
3234 {
3235     VALUE list, sym;
3236
3237     sym = ID2SYM(rb_frame_this_func());
3238     if (NIL_P(hash) || TYPE(hash) != T_HASH) {
3239         VALUE symname;
3240         VALUE thrname;
3241         symname = rb_inspect(sym);
3242         thrname = rb_inspect(rb_thread_current());
3243
3244         rb_raise(rb_eTypeError, "invalid inspect_tbl hash for %s in %s",
3245                  StringValuePtr(symname), StringValuePtr(thrname));
3246     }
3247     list = rb_hash_aref(hash, sym);
3248     if (NIL_P(list) || TYPE(list) != T_HASH) {
3249         VALUE symname = rb_inspect(sym);
3250         VALUE thrname = rb_inspect(rb_thread_current());
3251         rb_raise(rb_eTypeError, "invalid inspect_tbl list for %s in %s",
3252                  StringValuePtr(symname), StringValuePtr(thrname));
3253     }
3254     rb_hash_delete(list, obj);
3255 }
3256
3257 VALUE
3258 rb_exec_recursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE arg)
3259 {
3260     VALUE hash = rb_thread_local_aref(rb_thread_current(), recursive_key);
3261     VALUE objid = rb_obj_id(obj);
3262
3263     if (recursive_check(hash, objid)) {
3264         return (*func) (obj, arg, Qtrue);
3265     }
3266     else {
3267         VALUE result = Qundef;
3268         int state;
3269
3270         hash = recursive_push(hash, objid);
3271         PUSH_TAG();
3272         if ((state = EXEC_TAG()) == 0) {
3273             result = (*func) (obj, arg, Qfalse);
3274         }
3275         POP_TAG();
3276         recursive_pop(hash, objid);
3277         if (state)
3278             JUMP_TAG(state);
3279         return result;
3280     }
3281 }
3282
3283 /* tracer */
3284
3285 static rb_event_hook_t *
3286 alloc_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data)
3287 {
3288     rb_event_hook_t *hook = ALLOC(rb_event_hook_t);
3289     hook->func = func;
3290     hook->flag = events;
3291     hook->data = data;
3292     return hook;
3293 }
3294
3295 static void
3296 thread_reset_event_flags(rb_thread_t *th)
3297 {
3298     rb_event_hook_t *hook = th->event_hooks;
3299     rb_event_flag_t flag = th->event_flags & RUBY_EVENT_VM;
3300
3301     while (hook) {
3302         flag |= hook->flag;
3303         hook = hook->next;
3304     }
3305 }
3306
3307 void
3308 rb_thread_add_event_hook(rb_thread_t *th,
3309                          rb_event_hook_func_t func, rb_event_flag_t events, VALUE data)
3310 {
3311     rb_event_hook_t *hook = alloc_event_hook(func, events, data);
3312     hook->next = th->event_hooks;
3313     th->event_hooks = hook;
3314     thread_reset_event_flags(th);
3315 }
3316
3317 static int
3318 set_threads_event_flags_i(st_data_t key, st_data_t val, st_data_t flag)
3319 {
3320     VALUE thval = key;
3321     rb_thread_t *th;
3322     GetThreadPtr(thval, th);
3323
3324     if (flag) {
3325         th->event_flags |= RUBY_EVENT_VM;
3326     }
3327     else {
3328         th->event_flags &= (~RUBY_EVENT_VM);
3329     }
3330     return ST_CONTINUE;
3331 }
3332
3333 static void
3334 set_threads_event_flags(int flag)
3335 {
3336     st_foreach(GET_VM()->living_threads, set_threads_event_flags_i, (st_data_t) flag);
3337 }
3338
3339 void
3340 rb_add_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data)
3341 {
3342     rb_event_hook_t *hook = alloc_event_hook(func, events, data);
3343     rb_vm_t *vm = GET_VM();
3344
3345     hook->next = vm->event_hooks;
3346     vm->event_hooks = hook;
3347
3348     set_threads_event_flags(1);
3349 }
3350
3351 static int
3352 remove_event_hook(rb_event_hook_t **root, rb_event_hook_func_t func)
3353 {
3354     rb_event_hook_t *prev = NULL, *hook = *root, *next;
3355
3356     while (hook) {
3357         next = hook->next;
3358         if (func == 0 || hook->func == func) {
3359             if (prev) {
3360                 prev->next = hook->next;
3361             }
3362             else {
3363                 *root = hook->next;
3364             }
3365             xfree(hook);
3366         }
3367         else {
3368             prev = hook;
3369         }
3370         hook = next;
3371     }
3372     return -1;
3373 }
3374
3375 int
3376 rb_thread_remove_event_hook(rb_thread_t *th, rb_event_hook_func_t func)
3377 {
3378     int ret = remove_event_hook(&th->event_hooks, func);
3379     thread_reset_event_flags(th);
3380     return ret;
3381 }
3382
3383 int
3384 rb_remove_event_hook(rb_event_hook_func_t func)
3385 {
3386     rb_vm_t *vm = GET_VM();
3387     rb_event_hook_t *hook = vm->event_hooks;
3388     int ret = remove_event_hook(&vm->event_hooks, func);
3389
3390     if (hook != NULL && vm->event_hooks == NULL) {
3391         set_threads_event_flags(0);
3392     }
3393
3394     return ret;
3395 }
3396
3397 static int
3398 clear_trace_func_i(st_data_t key, st_data_t val, st_data_t flag)
3399 {
3400     rb_thread_t *th;
3401     GetThreadPtr((VALUE)key, th);
3402     rb_thread_remove_event_hook(th, 0);
3403     return ST_CONTINUE;
3404 }
3405
3406 void
3407 rb_clear_trace_func(void)
3408 {
3409     st_foreach(GET_VM()->living_threads, clear_trace_func_i, (st_data_t) 0);
3410     rb_remove_event_hook(0);
3411 }
3412
3413 static void call_trace_func(rb_event_flag_t, VALUE data, VALUE self, ID id, VALUE klass);
3414
3415 /*
3416  *  call-seq:
3417  *     set_trace_func(proc)    => proc
3418  *     set_trace_func(nil)     => nil
3419  *
3420  *  Establishes _proc_ as the handler for tracing, or disables
3421  *  tracing if the parameter is +nil+. _proc_ takes up
3422  *  to six parameters: an event name, a filename, a line number, an
3423  *  object id, a binding, and the name of a class. _proc_ is
3424  *  invoked whenever an event occurs. Events are: <code>c-call</code>
3425  *  (call a C-language routine), <code>c-return</code> (return from a
3426  *  C-language routine), <code>call</code> (call a Ruby method),
3427  *  <code>class</code> (start a class or module definition),
3428  *  <code>end</code> (finish a class or module definition),
3429  *  <code>line</code> (execute code on a new line), <code>raise</code>
3430  *  (raise an exception), and <code>return</code> (return from a Ruby
3431  *  method). Tracing is disabled within the context of _proc_.
3432  *
3433  *      class Test
3434  *      def test
3435  *        a = 1
3436  *        b = 2
3437  *      end
3438  *      end
3439  *
3440  *      set_trace_func proc { |event, file, line, id, binding, classname|
3441  *         printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname
3442  *      }
3443  *      t = Test.new
3444  *      t.test
3445  *
3446  *        line prog.rb:11               false
3447  *      c-call prog.rb:11        new    Class
3448  *      c-call prog.rb:11 initialize   Object
3449  *    c-return prog.rb:11 initialize   Object
3450  *    c-return prog.rb:11        new    Class
3451  *        line prog.rb:12               false
3452  *        call prog.rb:2        test     Test
3453  *        line prog.rb:3        test     Test
3454  *        line prog.rb:4        test     Test
3455  *      return prog.rb:4        test     Test
3456  */
3457
3458 static VALUE
3459 set_trace_func(VALUE obj, VALUE trace)
3460 {
3461     rb_remove_event_hook(call_trace_func);
3462
3463     if (NIL_P(trace)) {
3464         return Qnil;
3465     }
3466
3467     if (!rb_obj_is_proc(trace)) {
3468         rb_raise(rb_eTypeError, "trace_func needs to be Proc");
3469     }
3470
3471     rb_add_event_hook(call_trace_func, RUBY_EVENT_ALL, trace);
3472     return trace;
3473 }
3474
3475 static const char *
3476 get_event_name(rb_event_flag_t event)
3477 {
3478     switch (event) {
3479       case RUBY_EVENT_LINE:
3480         return "line";
3481       case RUBY_EVENT_CLASS:
3482         return "class";
3483       case RUBY_EVENT_END:
3484         return "end";
3485       case RUBY_EVENT_CALL:
3486         return "call";
3487       case RUBY_EVENT_RETURN:
3488         return "return";
3489       case RUBY_EVENT_C_CALL:
3490         return "c-call";
3491       case RUBY_EVENT_C_RETURN:
3492         return "c-return";
3493       case RUBY_EVENT_RAISE:
3494         return "raise";
3495       default:
3496         return "unknown";
3497     }
3498 }
3499
3500 VALUE ruby_suppress_tracing(VALUE (*func)(VALUE, int), VALUE arg, int always);
3501
3502 struct call_trace_func_args {
3503     rb_event_flag_t event;
3504     VALUE proc;
3505     VALUE self;
3506     ID id;
3507     VALUE klass;
3508 };
3509
3510 static VALUE
3511 call_trace_proc(VALUE args, int tracing)
3512 {
3513     struct call_trace_func_args *p = (struct call_trace_func_args *)args;
3514     VALUE eventname = rb_str_new2(get_event_name(p->event));
3515     VALUE filename = rb_str_new2(rb_sourcefile());
3516     VALUE argv[6];
3517     int line = rb_sourceline();
3518     ID id = 0;
3519     VALUE klass = 0;
3520
3521     if (p->event == RUBY_EVENT_C_CALL ||
3522         p->event == RUBY_EVENT_C_RETURN) {
3523         id = p->id;
3524         klass = p->klass;
3525     }
3526     else {
3527         rb_thread_method_id_and_class(GET_THREAD(), &id, &klass);
3528     }
3529     if (id == ID_ALLOCATOR)
3530       return Qnil;
3531     if (klass) {
3532         if (TYPE(klass) == T_ICLASS) {
3533             klass = RBASIC(klass)->klass;
3534         }
3535         else if (FL_TEST(klass, FL_SINGLETON)) {
3536             klass = rb_iv_get(klass, "__attached__");
3537         }
3538     }
3539
3540     argv[0] = eventname;
3541     argv[1] = filename;
3542     argv[2] = INT2FIX(line);
3543     argv[3] = id ? ID2SYM(id) : Qnil;
3544     argv[4] = p->self ? rb_binding_new() : Qnil;
3545     argv[5] = klass ? klass : Qnil;
3546
3547     return rb_proc_call_with_block(p->proc, 6, argv, Qnil);
3548 }
3549
3550 static void
3551 call_trace_func(rb_event_flag_t event, VALUE proc, VALUE self, ID id, VALUE klass)
3552 {
3553     struct call_trace_func_args args;
3554     
3555     args.event = event;
3556     args.proc = proc;
3557     args.self = self;
3558     args.id = id;
3559     args.klass = klass;
3560     ruby_suppress_tracing(call_trace_proc, (VALUE)&args, Qfalse);
3561 }
3562
3563 VALUE
3564 ruby_suppress_tracing(VALUE (*func)(VALUE, int), VALUE arg, int always)
3565 {
3566     rb_thread_t *th = GET_THREAD();
3567     int state, raised, tracing;
3568     VALUE result = Qnil;
3569
3570     if ((tracing = th->tracing) != 0 && !always) {
3571         return Qnil;
3572     }
3573     else {
3574         th->tracing = 1;
3575     }
3576
3577     raised = rb_thread_reset_raised(th);
3578
3579     PUSH_TAG();
3580     if ((state = EXEC_TAG()) == 0) {
3581         result = (*func)(arg, tracing);
3582     }
3583
3584     if (raised) {
3585         rb_thread_set_raised(th);
3586     }
3587     POP_TAG();
3588
3589     th->tracing = tracing;
3590     if (state) {
3591         JUMP_TAG(state);
3592     }
3593
3594     return result;
3595 }
3596
3597 /*
3598  *  +Thread+ encapsulates the behavior of a thread of
3599  *  execution, including the main thread of the Ruby script.
3600  *
3601  *  In the descriptions of the methods in this class, the parameter _sym_
3602  *  refers to a symbol, which is either a quoted string or a
3603  *  +Symbol+ (such as <code>:name</code>).
3604  */
3605
3606 void
3607 Init_Thread(void)
3608 {
3609 #undef rb_intern
3610 #define rb_intern(str) rb_intern_const(str)
3611
3612     VALUE cThGroup;
3613
3614     rb_define_singleton_method(rb_cThread, "new", thread_s_new, -1);
3615     rb_define_singleton_method(rb_cThread, "start", thread_start, -2);
3616     rb_define_singleton_method(rb_cThread, "fork", thread_start, -2);
3617     rb_define_singleton_method(rb_cThread, "main", rb_thread_s_main, 0);
3618     rb_define_singleton_method(rb_cThread, "current", thread_s_current, 0);
3619     rb_define_singleton_method(rb_cThread, "stop", rb_thread_stop, 0);
3620     rb_define_singleton_method(rb_cThread, "kill", rb_thread_s_kill, 1);
3621     rb_define_singleton_method(rb_cThread, "exit", rb_thread_exit, 0);
3622     rb_define_singleton_method(rb_cThread, "pass", thread_s_pass, 0);
3623     rb_define_singleton_method(rb_cThread, "list", rb_thread_list, 0);
3624     rb_define_singleton_method(rb_cThread, "abort_on_exception", rb_thread_s_abort_exc, 0);
3625     rb_define_singleton_method(rb_cThread, "abort_on_exception=", rb_thread_s_abort_exc_set, 1);
3626 #if THREAD_DEBUG < 0
3627     rb_define_singleton_method(rb_cThread, "DEBUG", rb_thread_s_debug, 0);
3628     rb_define_singleton_method(rb_cThread, "DEBUG=", rb_thread_s_debug_set, 1);
3629 #endif
3630
3631     rb_define_method(rb_cThread, "initialize", thread_initialize, -2);
3632     rb_define_method(rb_cThread, "raise", thread_raise_m, -1);
3633     rb_define_method(rb_cThread, "join", thread_join_m, -1);
3634     rb_define_method(rb_cThread, "value", thread_value, 0);
3635     rb_define_method(rb_cThread, "kill", rb_thread_kill, 0);
3636     rb_define_method(rb_cThread, "terminate", rb_thread_kill, 0);
3637     rb_define_method(rb_cThread, "exit", rb_thread_kill, 0);
3638     rb_define_method(rb_cThread, "run", rb_thread_run, 0);
3639     rb_define_method(rb_cThread, "wakeup", rb_thread_wakeup, 0);
3640     rb_define_method(rb_cThread, "[]", rb_thread_aref, 1);
3641     rb_define_method(rb_cThread, "[]=", rb_thread_aset, 2);
3642     rb_define_method(rb_cThread, "key?", rb_thread_key_p, 1);
3643     rb_define_method(rb_cThread, "keys", rb_thread_keys, 0);
3644     rb_define_method(rb_cThread, "priority", rb_thread_priority, 0);
3645     rb_define_method(rb_cThread, "priority=", rb_thread_priority_set, 1);
3646     rb_define_method(rb_cThread, "status", rb_thread_status, 0);
3647     rb_define_method(rb_cThread, "alive?", rb_thread_alive_p, 0);
3648     rb_define_method(rb_cThread, "stop?", rb_thread_stop_p, 0);
3649     rb_define_method(rb_cThread, "abort_on_exception", rb_thread_abort_exc, 0);
3650     rb_define_method(rb_cThread, "abort_on_exception=", rb_thread_abort_exc_set, 1);
3651     rb_define_method(rb_cThread, "safe_level", rb_thread_safe_level, 0);
3652     rb_define_method(rb_cThread, "group", rb_thread_group, 0);
3653
3654     rb_define_method(rb_cThread, "inspect", rb_thread_inspect, 0);
3655
3656     cThGroup = rb_define_class("ThreadGroup", rb_cObject);
3657     rb_define_alloc_func(cThGroup, thgroup_s_alloc);
3658     rb_define_method(cThGroup, "list", thgroup_list, 0);
3659     rb_define_method(cThGroup, "enclose", thgroup_enclose, 0);
3660     rb_define_method(cThGroup, "enclosed?", thgroup_enclosed_p, 0);
3661     rb_define_method(cThGroup, "add", thgroup_add, 1);
3662
3663     {
3664         rb_thread_t *th = GET_THREAD();
3665         th->thgroup = th->vm->thgroup_default = rb_obj_alloc(cThGroup);
3666         rb_define_const(cThGroup, "Default", th->thgroup);
3667     }
3668
3669     rb_cMutex = rb_define_class("Mutex", rb_cObject);
3670     rb_define_alloc_func(rb_cMutex, mutex_alloc);
3671     rb_define_method(rb_cMutex, "initialize", mutex_initialize, 0);
3672     rb_define_method(rb_cMutex, "locked?", rb_mutex_locked_p, 0);
3673     rb_define_method(rb_cMutex, "try_lock", rb_mutex_trylock, 0);
3674     rb_define_method(rb_cMutex, "lock", rb_mutex_lock, 0);
3675     rb_define_method(rb_cMutex, "unlock", rb_mutex_unlock, 0);
3676     rb_define_method(rb_cMutex, "sleep", mutex_sleep, -1);
3677
3678     recursive_key = rb_intern("__recursive_key__");
3679     rb_eThreadError = rb_define_class("ThreadError", rb_eStandardError);
3680
3681     /* trace */
3682     rb_define_global_function("set_trace_func", set_trace_func, 1);
3683
3684     /* init thread core */
3685     Init_native_thread();
3686     {
3687         /* main thread setting */
3688         {
3689             /* acquire global interpreter lock */
3690             rb_thread_lock_t *lp = &GET_THREAD()->vm->global_vm_lock;
3691             native_mutex_initialize(lp);
3692             native_mutex_lock(lp);
3693             native_mutex_initialize(&GET_THREAD()->interrupt_lock);
3694         }
3695     }
3696
3697     rb_thread_create_timer_thread();
3698
3699     (void)native_mutex_trylock;
3700     (void)ruby_thread_set_native;
3701 }
3702
3703 int
3704 ruby_native_thread_p(void)
3705 {
3706     rb_thread_t *th = ruby_thread_from_native();
3707
3708     return th ? Qtrue : Qfalse;
3709 }
3710
3711 static int
3712 check_deadlock_i(st_data_t key, st_data_t val, int *found)
3713 {
3714     VALUE thval = key;
3715     rb_thread_t *th;
3716     GetThreadPtr(thval, th);
3717
3718     if (th->status != THREAD_STOPPED_FOREVER || RUBY_VM_INTERRUPTED(th) || th->transition_for_lock) {
3719         *found = 1;
3720     }
3721     else if (th->locking_mutex) {
3722         mutex_t *mutex;
3723         GetMutexPtr(th->locking_mutex, mutex);
3724
3725         native_mutex_lock(&mutex->lock);
3726         if (mutex->th == th || (!mutex->th && mutex->cond_notified)) {
3727             *found = 1;
3728         }
3729         native_mutex_unlock(&mutex->lock);
3730     }
3731
3732     return (*found) ? ST_STOP : ST_CONTINUE;
3733 }
3734
3735 #if 0 /* for debug */
3736 static int
3737 debug_i(st_data_t key, st_data_t val, int *found)
3738 {
3739     VALUE thval = key;
3740     rb_thread_t *th;
3741     GetThreadPtr(thval, th);
3742
3743     printf("th:%p %d %d %d", th, th->status, th->interrupt_flag, th->transition_for_lock);
3744     if (th->locking_mutex) {
3745         mutex_t *mutex;
3746         GetMutexPtr(th->locking_mutex, mutex);
3747
3748         native_mutex_lock(&mutex->lock);
3749         printf(" %p %d\n", mutex->th, mutex->cond_notified);
3750         native_mutex_unlock(&mutex->lock);
3751     }
3752     else puts("");
3753
3754     return ST_CONTINUE;
3755 }
3756 #endif
3757
3758 static void
3759 rb_check_deadlock(rb_vm_t *vm)
3760 {
3761     int found = 0;
3762
3763     if (vm_living_thread_num(vm) > vm->sleeper) return;
3764     if (vm_living_thread_num(vm) < vm->sleeper) rb_bug("sleeper must not be more than vm_living_thread_num(vm)");
3765
3766     st_foreach(vm->living_threads, check_deadlock_i, (st_data_t)&found);
3767
3768     if (!found) {
3769         VALUE argv[2];
3770         argv[0] = rb_eFatal;
3771         argv[1] = rb_str_new2("deadlock detected");
3772 #if 0 /* for debug */
3773         printf("%d %d %p %p\n", vm->living_threads->num_entries, vm->sleeper, GET_THREAD(), vm->main_thread);
3774         st_foreach(vm->living_threads, debug_i, (st_data_t)0);
3775 #endif
3776         rb_thread_raise(2, argv, vm->main_thread);
3777     }
3778 }
3779
3780 static void
3781 update_coverage(rb_event_flag_t event, VALUE proc, VALUE self, ID id, VALUE klass)
3782 {
3783     VALUE coverage = GET_THREAD()->cfp->iseq->coverage;
3784     if (coverage && RBASIC(coverage)->klass == 0) {
3785         long line = rb_sourceline() - 1;
3786         long count;
3787         if (RARRAY_PTR(coverage)[line] == Qnil) {
3788             rb_bug("bug");
3789         }
3790         count = FIX2LONG(RARRAY_PTR(coverage)[line]) + 1;
3791         if (POSFIXABLE(count)) {
3792             RARRAY_PTR(coverage)[line] = LONG2FIX(count);
3793         }
3794     }
3795 }
3796
3797 VALUE
3798 rb_get_coverages(void)
3799 {
3800     return GET_VM()->coverages;
3801 }
3802
3803 void
3804 rb_set_coverages(VALUE coverages)
3805 {
3806     GET_VM()->coverages = coverages;
3807     rb_add_event_hook(update_coverage, RUBY_EVENT_COVERAGE, Qnil);
3808 }
3809
3810 void
3811 rb_reset_coverages(void)
3812 {
3813     GET_VM()->coverages = Qfalse;
3814     rb_remove_event_hook(update_coverage);
3815 }