Ruby 2.0.0p247(2013-06-27revision41674)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

thread.c
Go to the documentation of this file.
1 /**********************************************************************
2
3 thread.c -
4
5 $Author: nagachika $
6
7 Copyright (C) 2004-2007 Koichi Sasada
8
9 **********************************************************************/
10
11 /*
12 YARV Thread Design
13
14 model 1: Userlevel Thread
15 Same as traditional ruby thread.
16
17 model 2: Native Thread with Global 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 or Giant VM Lock) can run.
27 When thread 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 /*
46 * FD_SET, FD_CLR and FD_ISSET have a small sanity check when using glibc
47 * 2.15 or later and set _FORTIFY_SOURCE > 0.
48 * However, the implementation is wrong. Even though Linux's select(2)
49 * support large fd size (>FD_SETSIZE), it wrongly assume fd is always
50 * less than FD_SETSIZE (i.e. 1024). And then when enabling HAVE_RB_FD_INIT,
51 * it doesn't work correctly and makes program abort. Therefore we need to
52 * disable FORTY_SOURCE until glibc fixes it.
53 */
54 #undef _FORTIFY_SOURCE
55 #undef __USE_FORTIFY_LEVEL
56 #define __USE_FORTIFY_LEVEL 0
57
58 /* for model 2 */
59
60 #include "eval_intern.h"
61 #include "gc.h"
62 #include "internal.h"
63 #include "ruby/io.h"
64 #include "ruby/thread.h"
65
66 #ifndef USE_NATIVE_THREAD_PRIORITY
67 #define USE_NATIVE_THREAD_PRIORITY 0
68 #define RUBY_THREAD_PRIORITY_MAX 3
69 #define RUBY_THREAD_PRIORITY_MIN -3
70 #endif
71
72 #ifndef THREAD_DEBUG
73 #define THREAD_DEBUG 0
74 #endif
75
76 #define TIMET_MAX (~(time_t)0 <= 0 ? (time_t)((~(unsigned_time_t)0) >> 1) : (time_t)(~(unsigned_time_t)0))
77 #define TIMET_MIN (~(time_t)0 <= 0 ? (time_t)(((unsigned_time_t)1) << (sizeof(time_t) * CHAR_BIT - 1)) : (time_t)0)
78
79 VALUE rb_cMutex;
80 VALUE rb_cThreadShield;
81
82 static VALUE sym_immediate;
83 static VALUE sym_on_blocking;
84 static VALUE sym_never;
85
86 static void sleep_timeval(rb_thread_t *th, struct timeval time, int spurious_check);
87 static void sleep_wait_for_interrupt(rb_thread_t *th, double sleepsec, int spurious_check);
88 static void sleep_forever(rb_thread_t *th, int nodeadlock, int spurious_check);
89 static double timeofday(void);
90 static int rb_threadptr_dead(rb_thread_t *th);
91 static void rb_check_deadlock(rb_vm_t *vm);
92 static int rb_threadptr_pending_interrupt_empty_p(rb_thread_t *th);
93
94 #define eKillSignal INT2FIX(0)
95 #define eTerminateSignal INT2FIX(1)
96 static volatile int system_working = 1;
97
98 #define closed_stream_error GET_VM()->special_exceptions[ruby_error_closed_stream]
99
100 inline static void
101 st_delete_wrap(st_table *table, st_data_t key)
102 {
103 st_delete(table, &key, 0);
104 }
105
106 /********************************************************************************/
107
108 #define THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION
109
110 struct rb_blocking_region_buffer {
111 enum rb_thread_status prev_status;
112 struct rb_unblock_callback oldubf;
113 };
114
115 static int set_unblock_function(rb_thread_t *th, rb_unblock_function_t *func, void *arg,
116 struct rb_unblock_callback *old, int fail_if_interrupted);
117 static void reset_unblock_function(rb_thread_t *th, const struct rb_unblock_callback *old);
118
119 static inline int blocking_region_begin(rb_thread_t *th, struct rb_blocking_region_buffer *region,
120 rb_unblock_function_t *ubf, void *arg, int fail_if_interrupted);
121 static inline void blocking_region_end(rb_thread_t *th, struct rb_blocking_region_buffer *region);
122
123 #ifdef __ia64
124 #define RB_GC_SAVE_MACHINE_REGISTER_STACK(th) \
125 do{(th)->machine_register_stack_end = rb_ia64_bsp();}while(0)
126 #else
127 #define RB_GC_SAVE_MACHINE_REGISTER_STACK(th)
128 #endif
129 #define RB_GC_SAVE_MACHINE_CONTEXT(th) \
130 do { \
131 FLUSH_REGISTER_WINDOWS; \
132 RB_GC_SAVE_MACHINE_REGISTER_STACK(th); \
133 setjmp((th)->machine_regs); \
134 SET_MACHINE_STACK_END(&(th)->machine_stack_end); \
135 } while (0)
136
137 #define GVL_UNLOCK_BEGIN() do { \
138 rb_thread_t *_th_stored = GET_THREAD(); \
139 RB_GC_SAVE_MACHINE_CONTEXT(_th_stored); \
140 gvl_release(_th_stored->vm);
141
142 #define GVL_UNLOCK_END() \
143 gvl_acquire(_th_stored->vm, _th_stored); \
144 rb_thread_set_current(_th_stored); \
145 } while(0)
146
147 #ifdef __GNUC__
148 #define only_if_constant(expr, notconst) (__builtin_constant_p(expr) ? (expr) : (notconst))
149 #else
150 #define only_if_constant(expr, notconst) notconst
151 #endif
152 #define BLOCKING_REGION(exec, ubf, ubfarg, fail_if_interrupted) do { \
153 rb_thread_t *__th = GET_THREAD(); \
154 struct rb_blocking_region_buffer __region; \
155 if (blocking_region_begin(__th, &__region, (ubf), (ubfarg), fail_if_interrupted) || \
156 /* always return true unless fail_if_interrupted */ \
157 !only_if_constant(fail_if_interrupted, TRUE)) { \
158 exec; \
159 blocking_region_end(__th, &__region); \
160 }; \
161 } while(0)
162
163 #if THREAD_DEBUG
164 #ifdef HAVE_VA_ARGS_MACRO
165 void rb_thread_debug(const char *file, int line, const char *fmt, ...);
166 #define thread_debug(fmt, ...) rb_thread_debug(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
167 #define POSITION_FORMAT "%s:%d:"
168 #define POSITION_ARGS ,file, line
169 #else
170 void rb_thread_debug(const char *fmt, ...);
171 #define thread_debug rb_thread_debug
172 #define POSITION_FORMAT
173 #define POSITION_ARGS
174 #endif
175
176 # if THREAD_DEBUG < 0
177 static int rb_thread_debug_enabled;
178
179 /*
180 * call-seq:
181 * Thread.DEBUG -> num
182 *
183 * Returns the thread debug level. Available only if compiled with
184 * THREAD_DEBUG=-1.
185 */
186
187 static VALUE
188 rb_thread_s_debug(void)
189 {
190 return INT2NUM(rb_thread_debug_enabled);
191 }
192
193 /*
194 * call-seq:
195 * Thread.DEBUG = num
196 *
197 * Sets the thread debug level. Available only if compiled with
198 * THREAD_DEBUG=-1.
199 */
200
201 static VALUE
202 rb_thread_s_debug_set(VALUE self, VALUE val)
203 {
204 rb_thread_debug_enabled = RTEST(val) ? NUM2INT(val) : 0;
205 return val;
206 }
207 # else
208 # define rb_thread_debug_enabled THREAD_DEBUG
209 # endif
210 #else
211 #define thread_debug if(0)printf
212 #endif
213
214 #ifndef __ia64
215 #define thread_start_func_2(th, st, rst) thread_start_func_2(th, st)
216 #endif
217 NOINLINE(static int thread_start_func_2(rb_thread_t *th, VALUE *stack_start,
218 VALUE *register_stack_start));
219 static void timer_thread_function(void *);
220
221 #if defined(_WIN32)
222 #include "thread_win32.c"
223
224 #define DEBUG_OUT() \
225 WaitForSingleObject(&debug_mutex, INFINITE); \
226 printf(POSITION_FORMAT"%p - %s" POSITION_ARGS, GetCurrentThreadId(), buf); \
227 fflush(stdout); \
228 ReleaseMutex(&debug_mutex);
229
230 #elif defined(HAVE_PTHREAD_H)
231 #include "thread_pthread.c"
232
233 #define DEBUG_OUT() \
234 pthread_mutex_lock(&debug_mutex); \
235 printf(POSITION_FORMAT"%#"PRIxVALUE" - %s" POSITION_ARGS, (VALUE)pthread_self(), buf); \
236 fflush(stdout); \
237 pthread_mutex_unlock(&debug_mutex);
238
239 #else
240 #error "unsupported thread type"
241 #endif
242
243 #if THREAD_DEBUG
244 static int debug_mutex_initialized = 1;
245 static rb_thread_lock_t debug_mutex;
246
247 void
248 rb_thread_debug(
249 #ifdef HAVE_VA_ARGS_MACRO
250 const char *file, int line,
251 #endif
252 const char *fmt, ...)
253 {
254 va_list args;
255 char buf[BUFSIZ];
256
257 if (!rb_thread_debug_enabled) return;
258
259 if (debug_mutex_initialized == 1) {
260 debug_mutex_initialized = 0;
261 native_mutex_initialize(&debug_mutex);
262 }
263
264 va_start(args, fmt);
265 vsnprintf(buf, BUFSIZ, fmt, args);
266 va_end(args);
267
268 DEBUG_OUT();
269 }
270 #endif
271
272 void
273 rb_vm_gvl_destroy(rb_vm_t *vm)
274 {
275 gvl_release(vm);
276 gvl_destroy(vm);
277 native_mutex_destroy(&vm->thread_destruct_lock);
278 }
279
280 void
281 rb_thread_lock_unlock(rb_thread_lock_t *lock)
282 {
283 native_mutex_unlock(lock);
284 }
285
286 void
287 rb_thread_lock_destroy(rb_thread_lock_t *lock)
288 {
289 native_mutex_destroy(lock);
290 }
291
292 static int
293 set_unblock_function(rb_thread_t *th, rb_unblock_function_t *func, void *arg,
294 struct rb_unblock_callback *old, int fail_if_interrupted)
295 {
296 check_ints:
297 if (fail_if_interrupted) {
298 if (RUBY_VM_INTERRUPTED_ANY(th)) {
299 return FALSE;
300 }
301 }
302 else {
303 RUBY_VM_CHECK_INTS(th);
304 }
305
306 native_mutex_lock(&th->interrupt_lock);
307 if (RUBY_VM_INTERRUPTED_ANY(th)) {
308 native_mutex_unlock(&th->interrupt_lock);
309 goto check_ints;
310 }
311 else {
312 if (old) *old = th->unblock;
313 th->unblock.func = func;
314 th->unblock.arg = arg;
315 }
316 native_mutex_unlock(&th->interrupt_lock);
317
318 return TRUE;
319 }
320
321 static void
322 reset_unblock_function(rb_thread_t *th, const struct rb_unblock_callback *old)
323 {
324 native_mutex_lock(&th->interrupt_lock);
325 th->unblock = *old;
326 native_mutex_unlock(&th->interrupt_lock);
327 }
328
329 static void
330 rb_threadptr_interrupt_common(rb_thread_t *th, int trap)
331 {
332 native_mutex_lock(&th->interrupt_lock);
333 if (trap)
334 RUBY_VM_SET_TRAP_INTERRUPT(th);
335 else
336 RUBY_VM_SET_INTERRUPT(th);
337 if (th->unblock.func) {
338 (th->unblock.func)(th->unblock.arg);
339 }
340 else {
341 /* none */
342 }
343 native_mutex_unlock(&th->interrupt_lock);
344 }
345
346 void
347 rb_threadptr_interrupt(rb_thread_t *th)
348 {
349 rb_threadptr_interrupt_common(th, 0);
350 }
351
352 void
353 rb_threadptr_trap_interrupt(rb_thread_t *th)
354 {
355 rb_threadptr_interrupt_common(th, 1);
356 }
357
358 static int
359 terminate_i(st_data_t key, st_data_t val, rb_thread_t *main_thread)
360 {
361 VALUE thval = key;
362 rb_thread_t *th;
363 GetThreadPtr(thval, th);
364
365 if (th != main_thread) {
366 thread_debug("terminate_i: %p\n", (void *)th);
367 rb_threadptr_pending_interrupt_enque(th, eTerminateSignal);
368 rb_threadptr_interrupt(th);
369 }
370 else {
371 thread_debug("terminate_i: main thread (%p)\n", (void *)th);
372 }
373 return ST_CONTINUE;
374 }
375
376 typedef struct rb_mutex_struct
377 {
378 rb_thread_lock_t lock;
379 rb_thread_cond_t cond;
380 struct rb_thread_struct volatile *th;
381 int cond_waiting;
382 struct rb_mutex_struct *next_mutex;
383 int allow_trap;
384 } rb_mutex_t;
385
386 static void rb_mutex_abandon_all(rb_mutex_t *mutexes);
387 static const char* rb_mutex_unlock_th(rb_mutex_t *mutex, rb_thread_t volatile *th);
388
389 void
390 rb_threadptr_unlock_all_locking_mutexes(rb_thread_t *th)
391 {
392 const char *err;
393 rb_mutex_t *mutex;
394 rb_mutex_t *mutexes = th->keeping_mutexes;
395
396 while (mutexes) {
397 mutex = mutexes;
398 /* rb_warn("mutex #<%p> remains to be locked by terminated thread",
399 mutexes); */
400 mutexes = mutex->next_mutex;
401 err = rb_mutex_unlock_th(mutex, th);
402 if (err) rb_bug("invalid keeping_mutexes: %s", err);
403 }
404 }
405
406 void
407 rb_thread_terminate_all(void)
408 {
409 rb_thread_t *th = GET_THREAD(); /* main thread */
410 rb_vm_t *vm = th->vm;
411
412 if (vm->main_thread != th) {
413 rb_bug("rb_thread_terminate_all: called by child thread (%p, %p)",
414 (void *)vm->main_thread, (void *)th);
415 }
416
417 /* unlock all locking mutexes */
418 rb_threadptr_unlock_all_locking_mutexes(th);
419
420 retry:
421 thread_debug("rb_thread_terminate_all (main thread: %p)\n", (void *)th);
422 st_foreach(vm->living_threads, terminate_i, (st_data_t)th);
423
424 while (!rb_thread_alone()) {
425 int state;
426
427 TH_PUSH_TAG(th);
428 if ((state = TH_EXEC_TAG()) == 0) {
429 native_sleep(th, 0);
430 RUBY_VM_CHECK_INTS_BLOCKING(th);
431 }
432 TH_POP_TAG();
433
434 if (state) {
435 goto retry;
436 }
437 }
438 }
439
440 static void
441 thread_cleanup_func_before_exec(void *th_ptr)
442 {
443 rb_thread_t *th = th_ptr;
444 th->status = THREAD_KILLED;
445 th->machine_stack_start = th->machine_stack_end = 0;
446 #ifdef __ia64
447 th->machine_register_stack_start = th->machine_register_stack_end = 0;
448 #endif
449 }
450
451 static void
452 thread_cleanup_func(void *th_ptr, int atfork)
453 {
454 rb_thread_t *th = th_ptr;
455
456 th->locking_mutex = Qfalse;
457 thread_cleanup_func_before_exec(th_ptr);
458
459 /*
460 * Unfortunately, we can't release native threading resource at fork
461 * because libc may have unstable locking state therefore touching
462 * a threading resource may cause a deadlock.
463 */
464 if (atfork)
465 return;
466
467 native_mutex_destroy(&th->interrupt_lock);
468 native_thread_destroy(th);
469 }
470
471 static VALUE rb_threadptr_raise(rb_thread_t *, int, VALUE *);
472
473 void
474 ruby_thread_init_stack(rb_thread_t *th)
475 {
476 native_thread_init_stack(th);
477 }
478
479 static int
480 thread_start_func_2(rb_thread_t *th, VALUE *stack_start, VALUE *register_stack_start)
481 {
482 int state;
483 VALUE args = th->first_args;
484 rb_proc_t *proc;
485 rb_thread_list_t *join_list;
486 rb_thread_t *main_th;
487 VALUE errinfo = Qnil;
488 # ifdef USE_SIGALTSTACK
489 void rb_register_sigaltstack(rb_thread_t *th);
490
491 rb_register_sigaltstack(th);
492 # endif
493
494 if (th == th->vm->main_thread)
495 rb_bug("thread_start_func_2 must not used for main thread");
496
497 ruby_thread_set_native(th);
498
499 th->machine_stack_start = stack_start;
500 #ifdef __ia64
501 th->machine_register_stack_start = register_stack_start;
502 #endif
503 thread_debug("thread start: %p\n", (void *)th);
504
505 gvl_acquire(th->vm, th);
506 {
507 thread_debug("thread start (get lock): %p\n", (void *)th);
508 rb_thread_set_current(th);
509
510 TH_PUSH_TAG(th);
511 if ((state = EXEC_TAG()) == 0) {
512 SAVE_ROOT_JMPBUF(th, {
513 if (!th->first_func) {
514 GetProcPtr(th->first_proc, proc);
515 th->errinfo = Qnil;
516 th->root_lep = rb_vm_ep_local_ep(proc->block.ep);
517 th->root_svar = Qnil;
518 EXEC_EVENT_HOOK(th, RUBY_EVENT_THREAD_BEGIN, th->self, 0, 0, Qundef);
519 th->value = rb_vm_invoke_proc(th, proc, (int)RARRAY_LEN(args), RARRAY_PTR(args), 0);
520 EXEC_EVENT_HOOK(th, RUBY_EVENT_THREAD_END, th->self, 0, 0, Qundef);
521 }
522 else {
523 th->value = (*th->first_func)((void *)args);
524 }
525 });
526 }
527 else {
528 errinfo = th->errinfo;
529 if (state == TAG_FATAL) {
530 /* fatal error within this thread, need to stop whole script */
531 }
532 else if (th->safe_level >= 4) {
533 /* Ignore it. Main thread shouldn't be harmed from untrusted thread. */
534 errinfo = Qnil;
535 }
536 else if (rb_obj_is_kind_of(errinfo, rb_eSystemExit)) {
537 /* exit on main_thread. */
538 }
539 else if (th->vm->thread_abort_on_exception ||
540 th->abort_on_exception || RTEST(ruby_debug)) {
541 /* exit on main_thread */
542 }
543 else {
544 errinfo = Qnil;
545 }
546 th->value = Qnil;
547 }
548
549 th->status = THREAD_KILLED;
550 thread_debug("thread end: %p\n", (void *)th);
551
552 main_th = th->vm->main_thread;
553 if (RB_TYPE_P(errinfo, T_OBJECT)) {
554 /* treat with normal error object */
555 rb_threadptr_raise(main_th, 1, &errinfo);
556 }
557 TH_POP_TAG();
558
559 /* locking_mutex must be Qfalse */
560 if (th->locking_mutex != Qfalse) {
561 rb_bug("thread_start_func_2: locking_mutex must not be set (%p:%"PRIxVALUE")",
562 (void *)th, th->locking_mutex);
563 }
564
565 /* delete self other than main thread from living_threads */
566 st_delete_wrap(th->vm->living_threads, th->self);
567 if (rb_thread_alone()) {
568 /* I'm last thread. wake up main thread from rb_thread_terminate_all */
569 rb_threadptr_interrupt(main_th);
570 }
571
572 /* wake up joining threads */
573 join_list = th->join_list;
574 while (join_list) {
575 rb_threadptr_interrupt(join_list->th);
576 switch (join_list->th->status) {
577 case THREAD_STOPPED: case THREAD_STOPPED_FOREVER:
578 join_list->th->status = THREAD_RUNNABLE;
579 default: break;
580 }
581 join_list = join_list->next;
582 }
583
584 rb_threadptr_unlock_all_locking_mutexes(th);
585 rb_check_deadlock(th->vm);
586
587 if (!th->root_fiber) {
588 rb_thread_recycle_stack_release(th->stack);
589 th->stack = 0;
590 }
591 }
592 native_mutex_lock(&th->vm->thread_destruct_lock);
593 /* make sure vm->running_thread never point me after this point.*/
594 th->vm->running_thread = NULL;
595 native_mutex_unlock(&th->vm->thread_destruct_lock);
596 thread_cleanup_func(th, FALSE);
597 gvl_release(th->vm);
598
599 return 0;
600 }
601
602 static VALUE
603 thread_create_core(VALUE thval, VALUE args, VALUE (*fn)(ANYARGS))
604 {
605 rb_thread_t *th, *current_th = GET_THREAD();
606 int err;
607
608 if (OBJ_FROZEN(GET_THREAD()->thgroup)) {
609 rb_raise(rb_eThreadError,
610 "can't start a new thread (frozen ThreadGroup)");
611 }
612 GetThreadPtr(thval, th);
613
614 /* setup thread environment */
615 th->first_func = fn;
616 th->first_proc = fn ? Qfalse : rb_block_proc();
617 th->first_args = args; /* GC: shouldn't put before above line */
618
619 th->priority = current_th->priority;
620 th->thgroup = current_th->thgroup;
621
622 th->pending_interrupt_queue = rb_ary_tmp_new(0);
623 th->pending_interrupt_queue_checked = 0;
624 th->pending_interrupt_mask_stack = rb_ary_dup(current_th->pending_interrupt_mask_stack);
625 RBASIC(th->pending_interrupt_mask_stack)->klass = 0;
626
627 th->interrupt_mask = 0;
628
629 native_mutex_initialize(&th->interrupt_lock);
630
631 /* kick thread */
632 err = native_thread_create(th);
633 if (err) {
634 th->status = THREAD_KILLED;
635 rb_raise(rb_eThreadError, "can't create Thread (%d)", err);
636 }
637 st_insert(th->vm->living_threads, thval, (st_data_t) th->thread_id);
638 return thval;
639 }
640
641 /*
642 * call-seq:
643 * Thread.new { ... } -> thread
644 * Thread.new(*args, &proc) -> thread
645 * Thread.new(*args) { |args| ... } -> thread
646 *
647 * Creates a new thread executing the given block.
648 *
649 * Any +args+ given to ::new will be passed to the block:
650 *
651 * arr = []
652 * a, b, c = 1, 2, 3
653 * Thread.new(a,b,c) { |d,e,f| arr << d << e << f }.join
654 * arr #=> [1, 2, 3]
655 *
656 * A ThreadError exception is raised if ::new is called without a block.
657 *
658 * If you're going to subclass Thread, be sure to call super in your
659 * +initialize+ method, otherwise a ThreadError will be raised.
660 */
661 static VALUE
662 thread_s_new(int argc, VALUE *argv, VALUE klass)
663 {
664 rb_thread_t *th;
665 VALUE thread = rb_thread_alloc(klass);
666
667 if (GET_VM()->main_thread->status == THREAD_KILLED)
668 rb_raise(rb_eThreadError, "can't alloc thread");
669
670 rb_obj_call_init(thread, argc, argv);
671 GetThreadPtr(thread, th);
672 if (!th->first_args) {
673 rb_raise(rb_eThreadError, "uninitialized thread - check `%s#initialize'",
674 rb_class2name(klass));
675 }
676 return thread;
677 }
678
679 /*
680 * call-seq:
681 * Thread.start([args]*) {|args| block } -> thread
682 * Thread.fork([args]*) {|args| block } -> thread
683 *
684 * Basically the same as ::new. However, if class Thread is subclassed, then
685 * calling +start+ in that subclass will not invoke the subclass's
686 * +initialize+ method.
687 */
688
689 static VALUE
690 thread_start(VALUE klass, VALUE args)
691 {
692 return thread_create_core(rb_thread_alloc(klass), args, 0);
693 }
694
695 /* :nodoc: */
696 static VALUE
697 thread_initialize(VALUE thread, VALUE args)
698 {
699 rb_thread_t *th;
700 if (!rb_block_given_p()) {
701 rb_raise(rb_eThreadError, "must be called with a block");
702 }
703 GetThreadPtr(thread, th);
704 if (th->first_args) {
705 VALUE proc = th->first_proc, line, loc;
706 const char *file;
707 if (!proc || !RTEST(loc = rb_proc_location(proc))) {
708 rb_raise(rb_eThreadError, "already initialized thread");
709 }
710 file = RSTRING_PTR(RARRAY_PTR(loc)[0]);
711 if (NIL_P(line = RARRAY_PTR(loc)[1])) {
712 rb_raise(rb_eThreadError, "already initialized thread - %s",
713 file);
714 }
715 rb_raise(rb_eThreadError, "already initialized thread - %s:%d",
716 file, NUM2INT(line));
717 }
718 return thread_create_core(thread, args, 0);
719 }
720
721 VALUE
722 rb_thread_create(VALUE (*fn)(ANYARGS), void *arg)
723 {
724 return thread_create_core(rb_thread_alloc(rb_cThread), (VALUE)arg, fn);
725 }
726
727
728 /* +infty, for this purpose */
729 #define DELAY_INFTY 1E30
730
731 struct join_arg {
732 rb_thread_t *target, *waiting;
733 double limit;
734 int forever;
735 };
736
737 static VALUE
738 remove_from_join_list(VALUE arg)
739 {
740 struct join_arg *p = (struct join_arg *)arg;
741 rb_thread_t *target_th = p->target, *th = p->waiting;
742
743 if (target_th->status != THREAD_KILLED) {
744 rb_thread_list_t **p = &target_th->join_list;
745
746 while (*p) {
747 if ((*p)->th == th) {
748 *p = (*p)->next;
749 break;
750 }
751 p = &(*p)->next;
752 }
753 }
754
755 return Qnil;
756 }
757
758 static VALUE
759 thread_join_sleep(VALUE arg)
760 {
761 struct join_arg *p = (struct join_arg *)arg;
762 rb_thread_t *target_th = p->target, *th = p->waiting;
763 double now, limit = p->limit;
764
765 while (target_th->status != THREAD_KILLED) {
766 if (p->forever) {
767 sleep_forever(th, 1, 0);
768 }
769 else {
770 now = timeofday();
771 if (now > limit) {
772 thread_debug("thread_join: timeout (thid: %p)\n",
773 (void *)target_th->thread_id);
774 return Qfalse;
775 }
776 sleep_wait_for_interrupt(th, limit - now, 0);
777 }
778 thread_debug("thread_join: interrupted (thid: %p)\n",
779 (void *)target_th->thread_id);
780 }
781 return Qtrue;
782 }
783
784 static VALUE
785 thread_join(rb_thread_t *target_th, double delay)
786 {
787 rb_thread_t *th = GET_THREAD();
788 struct join_arg arg;
789
790 if (th == target_th) {
791 rb_raise(rb_eThreadError, "Target thread must not be current thread");
792 }
793 if (GET_VM()->main_thread == target_th) {
794 rb_raise(rb_eThreadError, "Target thread must not be main thread");
795 }
796
797 arg.target = target_th;
798 arg.waiting = th;
799 arg.limit = timeofday() + delay;
800 arg.forever = delay == DELAY_INFTY;
801
802 thread_debug("thread_join (thid: %p)\n", (void *)target_th->thread_id);
803
804 if (target_th->status != THREAD_KILLED) {
805 rb_thread_list_t list;
806 list.next = target_th->join_list;
807 list.th = th;
808 target_th->join_list = &list;
809 if (!rb_ensure(thread_join_sleep, (VALUE)&arg,
810 remove_from_join_list, (VALUE)&arg)) {
811 return Qnil;
812 }
813 }
814
815 thread_debug("thread_join: success (thid: %p)\n",
816 (void *)target_th->thread_id);
817
818 if (target_th->errinfo != Qnil) {
819 VALUE err = target_th->errinfo;
820
821 if (FIXNUM_P(err)) {
822 /* */
823 }
824 else if (RB_TYPE_P(target_th->errinfo, T_NODE)) {
825 rb_exc_raise(rb_vm_make_jump_tag_but_local_jump(
826 GET_THROWOBJ_STATE(err), GET_THROWOBJ_VAL(err)));
827 }
828 else {
829 /* normal exception */
830 rb_exc_raise(err);
831 }
832 }
833 return target_th->self;
834 }
835
836 /*
837 * call-seq:
838 * thr.join -> thr
839 * thr.join(limit) -> thr
840 *
841 * The calling thread will suspend execution and run <i>thr</i>. Does not
842 * return until <i>thr</i> exits or until <i>limit</i> seconds have passed. If
843 * the time limit expires, <code>nil</code> will be returned, otherwise
844 * <i>thr</i> is returned.
845 *
846 * Any threads not joined will be killed when the main program exits. If
847 * <i>thr</i> had previously raised an exception and the
848 * <code>abort_on_exception</code> and <code>$DEBUG</code> flags are not set
849 * (so the exception has not yet been processed) it will be processed at this
850 * time.
851 *
852 * a = Thread.new { print "a"; sleep(10); print "b"; print "c" }
853 * x = Thread.new { print "x"; Thread.pass; print "y"; print "z" }
854 * x.join # Let x thread finish, a will be killed on exit.
855 *
856 * <em>produces:</em>
857 *
858 * axyz
859 *
860 * The following example illustrates the <i>limit</i> parameter.
861 *
862 * y = Thread.new { 4.times { sleep 0.1; puts 'tick... ' }}
863 * puts "Waiting" until y.join(0.15)
864 *
865 * <em>produces:</em>
866 *
867 * tick...
868 * Waiting
869 * tick...
870 * Waitingtick...
871 *
872 *
873 * tick...
874 */
875
876 static VALUE
877 thread_join_m(int argc, VALUE *argv, VALUE self)
878 {
879 rb_thread_t *target_th;
880 double delay = DELAY_INFTY;
881 VALUE limit;
882
883 GetThreadPtr(self, target_th);
884
885 rb_scan_args(argc, argv, "01", &limit);
886 if (!NIL_P(limit)) {
887 delay = rb_num2dbl(limit);
888 }
889
890 return thread_join(target_th, delay);
891 }
892
893 /*
894 * call-seq:
895 * thr.value -> obj
896 *
897 * Waits for <i>thr</i> to complete (via <code>Thread#join</code>) and returns
898 * its value.
899 *
900 * a = Thread.new { 2 + 2 }
901 * a.value #=> 4
902 */
903
904 static VALUE
905 thread_value(VALUE self)
906 {
907 rb_thread_t *th;
908 GetThreadPtr(self, th);
909 thread_join(th, DELAY_INFTY);
910 return th->value;
911 }
912
913 /*
914 * Thread Scheduling
915 */
916
917 static struct timeval
918 double2timeval(double d)
919 {
920 struct timeval time;
921
922 if (isinf(d)) {
923 time.tv_sec = TIMET_MAX;
924 time.tv_usec = 0;
925 return time;
926 }
927
928 time.tv_sec = (int)d;
929 time.tv_usec = (int)((d - (int)d) * 1e6);
930 if (time.tv_usec < 0) {
931 time.tv_usec += (int)1e6;
932 time.tv_sec -= 1;
933 }
934 return time;
935 }
936
937 static void
938 sleep_forever(rb_thread_t *th, int deadlockable, int spurious_check)
939 {
940 enum rb_thread_status prev_status = th->status;
941 enum rb_thread_status status = deadlockable ? THREAD_STOPPED_FOREVER : THREAD_STOPPED;
942
943 th->status = status;
944 RUBY_VM_CHECK_INTS_BLOCKING(th);
945 while (th->status == status) {
946 if (deadlockable) {
947 th->vm->sleeper++;
948 rb_check_deadlock(th->vm);
949 }
950 native_sleep(th, 0);
951 if (deadlockable) {
952 th->vm->sleeper--;
953 }
954 RUBY_VM_CHECK_INTS_BLOCKING(th);
955 if (!spurious_check)
956 break;
957 }
958 th->status = prev_status;
959 }
960
961 static void
962 getclockofday(struct timeval *tp)
963 {
964 #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
965 struct timespec ts;
966
967 if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
968 tp->tv_sec = ts.tv_sec;
969 tp->tv_usec = ts.tv_nsec / 1000;
970 } else
971 #endif
972 {
973 gettimeofday(tp, NULL);
974 }
975 }
976
977 static void
978 sleep_timeval(rb_thread_t *th, struct timeval tv, int spurious_check)
979 {
980 struct timeval to, tvn;
981 enum rb_thread_status prev_status = th->status;
982
983 getclockofday(&to);
984 if (TIMET_MAX - tv.tv_sec < to.tv_sec)
985 to.tv_sec = TIMET_MAX;
986 else
987 to.tv_sec += tv.tv_sec;
988 if ((to.tv_usec += tv.tv_usec) >= 1000000) {
989 if (to.tv_sec == TIMET_MAX)
990 to.tv_usec = 999999;
991 else {
992 to.tv_sec++;
993 to.tv_usec -= 1000000;
994 }
995 }
996
997 th->status = THREAD_STOPPED;
998 RUBY_VM_CHECK_INTS_BLOCKING(th);
999 while (th->status == THREAD_STOPPED) {
1000 native_sleep(th, &tv);
1001 RUBY_VM_CHECK_INTS_BLOCKING(th);
1002 getclockofday(&tvn);
1003 if (to.tv_sec < tvn.tv_sec) break;
1004 if (to.tv_sec == tvn.tv_sec && to.tv_usec <= tvn.tv_usec) break;
1005 thread_debug("sleep_timeval: %ld.%.6ld > %ld.%.6ld\n",
1006 (long)to.tv_sec, (long)to.tv_usec,
1007 (long)tvn.tv_sec, (long)tvn.tv_usec);
1008 tv.tv_sec = to.tv_sec - tvn.tv_sec;
1009 if ((tv.tv_usec = to.tv_usec - tvn.tv_usec) < 0) {
1010 --tv.tv_sec;
1011 tv.tv_usec += 1000000;
1012 }
1013 if (!spurious_check)
1014 break;
1015 }
1016 th->status = prev_status;
1017 }
1018
1019 void
1020 rb_thread_sleep_forever(void)
1021 {
1022 thread_debug("rb_thread_sleep_forever\n");
1023 sleep_forever(GET_THREAD(), 0, 1);
1024 }
1025
1026 static void
1027 rb_thread_sleep_deadly(void)
1028 {
1029 thread_debug("rb_thread_sleep_deadly\n");
1030 sleep_forever(GET_THREAD(), 1, 1);
1031 }
1032
1033 static double
1034 timeofday(void)
1035 {
1036 #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
1037 struct timespec tp;
1038
1039 if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) {
1040 return (double)tp.tv_sec + (double)tp.tv_nsec * 1e-9;
1041 } else
1042 #endif
1043 {
1044 struct timeval tv;
1045 gettimeofday(&tv, NULL);
1046 return (double)tv.tv_sec + (double)tv.tv_usec * 1e-6;
1047 }
1048 }
1049
1050 static void
1051 sleep_wait_for_interrupt(rb_thread_t *th, double sleepsec, int spurious_check)
1052 {
1053 sleep_timeval(th, double2timeval(sleepsec), spurious_check);
1054 }
1055
1056 static void
1057 sleep_for_polling(rb_thread_t *th)
1058 {
1059 struct timeval time;
1060 time.tv_sec = 0;
1061 time.tv_usec = 100 * 1000; /* 0.1 sec */
1062 sleep_timeval(th, time, 1);
1063 }
1064
1065 void
1066 rb_thread_wait_for(struct timeval time)
1067 {
1068 rb_thread_t *th = GET_THREAD();
1069 sleep_timeval(th, time, 1);
1070 }
1071
1072 void
1073 rb_thread_polling(void)
1074 {
1075 if (!rb_thread_alone()) {
1076 rb_thread_t *th = GET_THREAD();
1077 RUBY_VM_CHECK_INTS_BLOCKING(th);
1078 sleep_for_polling(th);
1079 }
1080 }
1081
1082 /*
1083 * CAUTION: This function causes thread switching.
1084 * rb_thread_check_ints() check ruby's interrupts.
1085 * some interrupt needs thread switching/invoke handlers,
1086 * and so on.
1087 */
1088
1089 void
1090 rb_thread_check_ints(void)
1091 {
1092 RUBY_VM_CHECK_INTS_BLOCKING(GET_THREAD());
1093 }
1094
1095 /*
1096 * Hidden API for tcl/tk wrapper.
1097 * There is no guarantee to perpetuate it.
1098 */
1099 int
1100 rb_thread_check_trap_pending(void)
1101 {
1102 return rb_signal_buff_size() != 0;
1103 }
1104
1105 /* This function can be called in blocking region. */
1106 int
1107 rb_thread_interrupted(VALUE thval)
1108 {
1109 rb_thread_t *th;
1110 GetThreadPtr(thval, th);
1111 return (int)RUBY_VM_INTERRUPTED(th);
1112 }
1113
1114 void
1115 rb_thread_sleep(int sec)
1116 {
1117 rb_thread_wait_for(rb_time_timeval(INT2FIX(sec)));
1118 }
1119
1120 static void
1121 rb_thread_schedule_limits(unsigned long limits_us)
1122 {
1123 thread_debug("rb_thread_schedule\n");
1124 if (!rb_thread_alone()) {
1125 rb_thread_t *th = GET_THREAD();
1126
1127 if (th->running_time_us >= limits_us) {
1128 thread_debug("rb_thread_schedule/switch start\n");
1129 RB_GC_SAVE_MACHINE_CONTEXT(th);
1130 gvl_yield(th->vm, th);
1131 rb_thread_set_current(th);
1132 thread_debug("rb_thread_schedule/switch done\n");
1133 }
1134 }
1135 }
1136
1137 void
1138 rb_thread_schedule(void)
1139 {
1140 rb_thread_t *cur_th = GET_THREAD();
1141 rb_thread_schedule_limits(0);
1142
1143 if (UNLIKELY(RUBY_VM_INTERRUPTED_ANY(cur_th))) {
1144 rb_threadptr_execute_interrupts(cur_th, 0);
1145 }
1146 }
1147
1148 /* blocking region */
1149
1150 static inline int
1151 blocking_region_begin(rb_thread_t *th, struct rb_blocking_region_buffer *region,
1152 rb_unblock_function_t *ubf, void *arg, int fail_if_interrupted)
1153 {
1154 region->prev_status = th->status;
1155 if (set_unblock_function(th, ubf, arg, &region->oldubf, fail_if_interrupted)) {
1156 th->blocking_region_buffer = region;
1157 th->status = THREAD_STOPPED;
1158 thread_debug("enter blocking region (%p)\n", (void *)th);
1159 RB_GC_SAVE_MACHINE_CONTEXT(th);
1160 gvl_release(th->vm);
1161 return TRUE;
1162 }
1163 else {
1164 return FALSE;
1165 }
1166 }
1167
1168 static inline void
1169 blocking_region_end(rb_thread_t *th, struct rb_blocking_region_buffer *region)
1170 {
1171 gvl_acquire(th->vm, th);
1172 rb_thread_set_current(th);
1173 thread_debug("leave blocking region (%p)\n", (void *)th);
1174 remove_signal_thread_list(th);
1175 th->blocking_region_buffer = 0;
1176 reset_unblock_function(th, &region->oldubf);
1177 if (th->status == THREAD_STOPPED) {
1178 th->status = region->prev_status;
1179 }
1180 }
1181
1182 struct rb_blocking_region_buffer *
1183 rb_thread_blocking_region_begin(void)
1184 {
1185 rb_thread_t *th = GET_THREAD();
1186 struct rb_blocking_region_buffer *region = ALLOC(struct rb_blocking_region_buffer);
1187 blocking_region_begin(th, region, ubf_select, th, FALSE);
1188 return region;
1189 }
1190
1191 void
1192 rb_thread_blocking_region_end(struct rb_blocking_region_buffer *region)
1193 {
1194 int saved_errno = errno;
1195 rb_thread_t *th = ruby_thread_from_native();
1196 blocking_region_end(th, region);
1197 xfree(region);
1198 RUBY_VM_CHECK_INTS_BLOCKING(th);
1199 errno = saved_errno;
1200 }
1201
1202 static void *
1203 call_without_gvl(void *(*func)(void *), void *data1,
1204 rb_unblock_function_t *ubf, void *data2, int fail_if_interrupted)
1205 {
1206 void *val = 0;
1207
1208 rb_thread_t *th = GET_THREAD();
1209 int saved_errno = 0;
1210
1211 th->waiting_fd = -1;
1212 if (ubf == RUBY_UBF_IO || ubf == RUBY_UBF_PROCESS) {
1213 ubf = ubf_select;
1214 data2 = th;
1215 }
1216
1217 BLOCKING_REGION({
1218 val = func(data1);
1219 saved_errno = errno;
1220 }, ubf, data2, fail_if_interrupted);
1221
1222 if (!fail_if_interrupted) {
1223 RUBY_VM_CHECK_INTS_BLOCKING(th);
1224 }
1225
1226 errno = saved_errno;
1227
1228 return val;
1229 }
1230
1231 /*
1232 * rb_thread_call_without_gvl - permit concurrent/parallel execution.
1233 * rb_thread_call_without_gvl2 - permit concurrent/parallel execution
1234 * without interrupt proceess.
1235 *
1236 * rb_thread_call_without_gvl() does:
1237 * (1) Check interrupts.
1238 * (2) release GVL.
1239 * Other Ruby threads may run in parallel.
1240 * (3) call func with data1
1241 * (4) acquire GVL.
1242 * Other Ruby threads can not run in parallel any more.
1243 * (5) Check interrupts.
1244 *
1245 * rb_thread_call_without_gvl2() does:
1246 * (1) Check interrupt and return if interrupted.
1247 * (2) release GVL.
1248 * (3) call func with data1 and a pointer to the flags.
1249 * (4) acquire GVL.
1250 *
1251 * If another thread interrupts this thread (Thread#kill, signal delivery,
1252 * VM-shutdown request, and so on), `ubf()' is called (`ubf()' means
1253 * "un-blocking function"). `ubf()' should interrupt `func()' execution by
1254 * toggling a cancellation flag, canceling the invocation of a call inside
1255 * `func()' or similar. Note that `ubf()' may not be called with the GVL.
1256 *
1257 * There are built-in ubfs and you can specify these ubfs:
1258 *
1259 * * RUBY_UBF_IO: ubf for IO operation
1260 * * RUBY_UBF_PROCESS: ubf for process operation
1261 *
1262 * However, we can not guarantee our built-in ubfs interrupt your `func()'
1263 * correctly. Be careful to use rb_thread_call_without_gvl(). If you don't
1264 * provide proper ubf(), your program will not stop for Control+C or other
1265 * shutdown events.
1266 *
1267 * "Check interrupts" on above list means that check asynchronous
1268 * interrupt events (such as Thread#kill, signal delivery, VM-shutdown
1269 * request, and so on) and call corresponding procedures
1270 * (such as `trap' for signals, raise an exception for Thread#raise).
1271 * If `func()' finished and receive interrupts, you may skip interrupt
1272 * checking. For example, assume the following func() it read data from file.
1273 *
1274 * read_func(...) {
1275 * // (a) before read
1276 * read(buffer); // (b) reading
1277 * // (c) after read
1278 * }
1279 *
1280 * If an interrupt occurs at (a) or (b), then `ubf()' cancels this
1281 * `read_func()' and interrupts are checked. However, if an interrupt occurs
1282 * at (c), after *read* operation is completed, check intterrupts is harmful
1283 * because it causes irrevocable side-effect, the read data will vanish. To
1284 * avoid such problem, the `read_func()' should be used with
1285 * `rb_thread_call_without_gvl2()'.
1286 *
1287 * If `rb_thread_call_without_gvl2()' detects interrupt, return its execution
1288 * immediately. This function does not show when the execution was interrupted.
1289 * For example, there are 4 possible timing (a), (b), (c) and before calling
1290 * read_func(). You need to record progress of a read_func() and check
1291 * the progress after `rb_thread_call_without_gvl2()'. You may need to call
1292 * `rb_thread_check_ints()' correctly or your program can not process proper
1293 * process such as `trap' and so on.
1294 *
1295 * NOTE: You can not execute most of Ruby C API and touch Ruby
1296 * objects in `func()' and `ubf()', including raising an
1297 * exception, because current thread doesn't acquire GVL
1298 * (it causes synchronization problems). If you need to
1299 * call ruby functions either use rb_thread_call_with_gvl()
1300 * or read source code of C APIs and confirm safety by
1301 * yourself.
1302 *
1303 * NOTE: In short, this API is difficult to use safely. I recommend you
1304 * use other ways if you have. We lack experiences to use this API.
1305 * Please report your problem related on it.
1306 *
1307 * NOTE: Releasing GVL and re-acquiring GVL may be expensive operations
1308 * for a short running `func()'. Be sure to benchmark and use this
1309 * mechanism when `func()' consumes enough time.
1310 *
1311 * Safe C API:
1312 * * rb_thread_interrupted() - check interrupt flag
1313 * * ruby_xmalloc(), ruby_xrealloc(), ruby_xfree() -
1314 * they will work without GVL, and may acquire GVL when GC is needed.
1315 */
1316 void *
1317 rb_thread_call_without_gvl2(void *(*func)(void *), void *data1,
1318 rb_unblock_function_t *ubf, void *data2)
1319 {
1320 return call_without_gvl(func, data1, ubf, data2, TRUE);
1321 }
1322
1323 void *
1324 rb_thread_call_without_gvl(void *(*func)(void *data), void *data1,
1325 rb_unblock_function_t *ubf, void *data2)
1326 {
1327 return call_without_gvl(func, data1, ubf, data2, FALSE);
1328 }
1329
1330 VALUE
1331 rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd)
1332 {
1333 VALUE val = Qundef; /* shouldn't be used */
1334 rb_thread_t *th = GET_THREAD();
1335 int saved_errno = 0;
1336 int state;
1337
1338 th->waiting_fd = fd;
1339
1340 TH_PUSH_TAG(th);
1341 if ((state = EXEC_TAG()) == 0) {
1342 BLOCKING_REGION({
1343 val = func(data1);
1344 saved_errno = errno;
1345 }, ubf_select, th, FALSE);
1346 }
1347 TH_POP_TAG();
1348
1349 /* clear waitinf_fd anytime */
1350 th->waiting_fd = -1;
1351
1352 if (state) {
1353 JUMP_TAG(state);
1354 }
1355 /* TODO: check func() */
1356 RUBY_VM_CHECK_INTS_BLOCKING(th);
1357
1358 errno = saved_errno;
1359
1360 return val;
1361 }
1362
1363 VALUE
1364 rb_thread_blocking_region(
1365 rb_blocking_function_t *func, void *data1,
1366 rb_unblock_function_t *ubf, void *data2)
1367 {
1368 void *(*f)(void*) = (void *(*)(void*))func;
1369 return (VALUE)rb_thread_call_without_gvl(f, data1, ubf, data2);
1370 }
1371
1372 /*
1373 * rb_thread_call_with_gvl - re-enter the Ruby world after GVL release.
1374 *
1375 * After releasing GVL using rb_thread_blocking_region() or
1376 * rb_thread_call_without_gvl() you can not access Ruby values or invoke
1377 * methods. If you need to access Ruby you must use this function
1378 * rb_thread_call_with_gvl().
1379 *
1380 * This function rb_thread_call_with_gvl() does:
1381 * (1) acquire GVL.
1382 * (2) call passed function `func'.
1383 * (3) release GVL.
1384 * (4) return a value which is returned at (2).
1385 *
1386 * NOTE: You should not return Ruby object at (2) because such Object
1387 * will not marked.
1388 *
1389 * NOTE: If an exception is raised in `func', this function DOES NOT
1390 * protect (catch) the exception. If you have any resources
1391 * which should free before throwing exception, you need use
1392 * rb_protect() in `func' and return a value which represents
1393 * exception is raised.
1394 *
1395 * NOTE: This function should not be called by a thread which was not
1396 * created as Ruby thread (created by Thread.new or so). In other
1397 * words, this function *DOES NOT* associate or convert a NON-Ruby
1398 * thread to a Ruby thread.
1399 */
1400 void *
1401 rb_thread_call_with_gvl(void *(*func)(void *), void *data1)
1402 {
1403 rb_thread_t *th = ruby_thread_from_native();
1404 struct rb_blocking_region_buffer *brb;
1405 struct rb_unblock_callback prev_unblock;
1406 void *r;
1407
1408 if (th == 0) {
1409 /* Error is occurred, but we can't use rb_bug()
1410 * because this thread is not Ruby's thread.
1411 * What should we do?
1412 */
1413
1414 fprintf(stderr, "[BUG] rb_thread_call_with_gvl() is called by non-ruby thread\n");
1415 exit(EXIT_FAILURE);
1416 }
1417
1418 brb = (struct rb_blocking_region_buffer *)th->blocking_region_buffer;
1419 prev_unblock = th->unblock;
1420
1421 if (brb == 0) {
1422 rb_bug("rb_thread_call_with_gvl: called by a thread which has GVL.");
1423 }
1424
1425 blocking_region_end(th, brb);
1426 /* enter to Ruby world: You can access Ruby values, methods and so on. */
1427 r = (*func)(data1);
1428 /* leave from Ruby world: You can not access Ruby values, etc. */
1429 blocking_region_begin(th, brb, prev_unblock.func, prev_unblock.arg, FALSE);
1430 return r;
1431 }
1432
1433 /*
1434 * ruby_thread_has_gvl_p - check if current native thread has GVL.
1435 *
1436 ***
1437 *** This API is EXPERIMENTAL!
1438 *** We do not guarantee that this API remains in ruby 1.9.2 or later.
1439 ***
1440 */
1441
1442 int
1443 ruby_thread_has_gvl_p(void)
1444 {
1445 rb_thread_t *th = ruby_thread_from_native();
1446
1447 if (th && th->blocking_region_buffer == 0) {
1448 return 1;
1449 }
1450 else {
1451 return 0;
1452 }
1453 }
1454
1455 /*
1456 * call-seq:
1457 * Thread.pass -> nil
1458 *
1459 * Give the thread scheduler a hint to pass execution to another thread.
1460 * A running thread may or may not switch, it depends on OS and processor.
1461 */
1462
1463 static VALUE
1464 thread_s_pass(VALUE klass)
1465 {
1466 rb_thread_schedule();
1467 return Qnil;
1468 }
1469
1470 /*****************************************************/
1471
1472 /*
1473 * rb_threadptr_pending_interrupt_* - manage asynchronous error queue
1474 *
1475 * Async events such as an exception throwed by Thread#raise,
1476 * Thread#kill and thread termination (after main thread termination)
1477 * will be queued to th->pending_interrupt_queue.
1478 * - clear: clear the queue.
1479 * - enque: enque err object into queue.
1480 * - deque: deque err object from queue.
1481 * - active_p: return 1 if the queue should be checked.
1482 *
1483 * All rb_threadptr_pending_interrupt_* functions are called by
1484 * a GVL acquired thread, of course.
1485 * Note that all "rb_" prefix APIs need GVL to call.
1486 */
1487
1488 void
1489 rb_threadptr_pending_interrupt_clear(rb_thread_t *th)
1490 {
1491 rb_ary_clear(th->pending_interrupt_queue);
1492 }
1493
1494 void
1495 rb_threadptr_pending_interrupt_enque(rb_thread_t *th, VALUE v)
1496 {
1497 rb_ary_push(th->pending_interrupt_queue, v);
1498 th->pending_interrupt_queue_checked = 0;
1499 }
1500
1501 enum handle_interrupt_timing {
1502 INTERRUPT_NONE,
1503 INTERRUPT_IMMEDIATE,
1504 INTERRUPT_ON_BLOCKING,
1505 INTERRUPT_NEVER
1506 };
1507
1508 static enum handle_interrupt_timing
1509 rb_threadptr_pending_interrupt_check_mask(rb_thread_t *th, VALUE err)
1510 {
1511 VALUE mask;
1512 long mask_stack_len = RARRAY_LEN(th->pending_interrupt_mask_stack);
1513 VALUE *mask_stack = RARRAY_PTR(th->pending_interrupt_mask_stack);
1514 VALUE ancestors = rb_mod_ancestors(err); /* TODO: GC guard */
1515 long ancestors_len = RARRAY_LEN(ancestors);
1516 VALUE *ancestors_ptr = RARRAY_PTR(ancestors);
1517 int i, j;
1518
1519 for (i=0; i<mask_stack_len; i++) {
1520 mask = mask_stack[mask_stack_len-(i+1)];
1521
1522 for (j=0; j<ancestors_len; j++) {
1523 VALUE klass = ancestors_ptr[j];
1524 VALUE sym;
1525
1526 /* TODO: remove rb_intern() */
1527 if ((sym = rb_hash_aref(mask, klass)) != Qnil) {
1528 if (sym == sym_immediate) {
1529 return INTERRUPT_IMMEDIATE;
1530 }
1531 else if (sym == sym_on_blocking) {
1532 return INTERRUPT_ON_BLOCKING;
1533 }
1534 else if (sym == sym_never) {
1535 return INTERRUPT_NEVER;
1536 }
1537 else {
1538 rb_raise(rb_eThreadError, "unknown mask signature");
1539 }
1540 }
1541 }
1542 /* try to next mask */
1543 }
1544 return INTERRUPT_NONE;
1545 }
1546
1547 static int
1548 rb_threadptr_pending_interrupt_empty_p(rb_thread_t *th)
1549 {
1550 return RARRAY_LEN(th->pending_interrupt_queue) == 0;
1551 }
1552
1553 static int
1554 rb_threadptr_pending_interrupt_include_p(rb_thread_t *th, VALUE err)
1555 {
1556 int i;
1557 for (i=0; i<RARRAY_LEN(th->pending_interrupt_queue); i++) {
1558 VALUE e = RARRAY_PTR(th->pending_interrupt_queue)[i];
1559 if (rb_class_inherited_p(e, err)) {
1560 return TRUE;
1561 }
1562 }
1563 return FALSE;
1564 }
1565
1566 static VALUE
1567 rb_threadptr_pending_interrupt_deque(rb_thread_t *th, enum handle_interrupt_timing timing)
1568 {
1569 #if 1 /* 1 to enable Thread#handle_interrupt, 0 to ignore it */
1570 int i;
1571
1572 for (i=0; i<RARRAY_LEN(th->pending_interrupt_queue); i++) {
1573 VALUE err = RARRAY_PTR(th->pending_interrupt_queue)[i];
1574
1575 enum handle_interrupt_timing mask_timing = rb_threadptr_pending_interrupt_check_mask(th, CLASS_OF(err));
1576
1577 switch (mask_timing) {
1578 case INTERRUPT_ON_BLOCKING:
1579 if (timing != INTERRUPT_ON_BLOCKING) {
1580 break;
1581 }
1582 /* fall through */
1583 case INTERRUPT_NONE: /* default: IMMEDIATE */
1584 case INTERRUPT_IMMEDIATE:
1585 rb_ary_delete_at(th->pending_interrupt_queue, i);
1586 return err;
1587 case INTERRUPT_NEVER:
1588 break;
1589 }
1590 }
1591
1592 th->pending_interrupt_queue_checked = 1;
1593 return Qundef;
1594 #else
1595 VALUE err = rb_ary_shift(th->pending_interrupt_queue);
1596 if (rb_threadptr_pending_interrupt_empty_p(th)) {
1597 th->pending_interrupt_queue_checked = 1;
1598 }
1599 return err;
1600 #endif
1601 }
1602
1603 int
1604 rb_threadptr_pending_interrupt_active_p(rb_thread_t *th)
1605 {
1606 /*
1607 * For optimization, we don't check async errinfo queue
1608 * if it nor a thread interrupt mask were not changed
1609 * since last check.
1610 */
1611 if (th->pending_interrupt_queue_checked) {
1612 return 0;
1613 }
1614
1615 if (rb_threadptr_pending_interrupt_empty_p(th)) {
1616 return 0;
1617 }
1618
1619 return 1;
1620 }
1621
1622 static int
1623 handle_interrupt_arg_check_i(VALUE key, VALUE val)
1624 {
1625 if (val != sym_immediate && val != sym_on_blocking && val != sym_never) {
1626 rb_raise(rb_eArgError, "unknown mask signature");
1627 }
1628
1629 return ST_CONTINUE;
1630 }
1631
1632 /*
1633 * call-seq:
1634 * Thread.handle_interrupt(hash) { ... } -> result of the block
1635 *
1636 * Changes asynchronous interrupt timing.
1637 *
1638 * _interrupt_ means asynchronous event and corresponding procedure
1639 * by Thread#raise, Thread#kill, signal trap (not supported yet)
1640 * and main thread termination (if main thread terminates, then all
1641 * other thread will be killed).
1642 *
1643 * The given +hash+ has pairs like <code>ExceptionClass =>
1644 * :TimingSymbol</code>. Where the ExceptionClass is the interrupt handled by
1645 * the given block. The TimingSymbol can be one of the following symbols:
1646 *
1647 * [+:immediate+] Invoke interrupts immediately.
1648 * [+:on_blocking+] Invoke interrupts while _BlockingOperation_.
1649 * [+:never+] Never invoke all interrupts.
1650 *
1651 * _BlockingOperation_ means that the operation will block the calling thread,
1652 * such as read and write. On CRuby implementation, _BlockingOperation_ is any
1653 * operation executed without GVL.
1654 *
1655 * Masked asynchronous interrupts are delayed until they are enabled.
1656 * This method is similar to sigprocmask(3).
1657 *
1658 * === NOTE
1659 *
1660 * Asynchronous interrupts are difficult to use.
1661 *
1662 * If you need to communicate between threads, please consider to use another way such as Queue.
1663 *
1664 * Or use them with deep understanding about this method.
1665 *
1666 * === Usage
1667 *
1668 * In this example, we can guard from Thread#raise exceptions.
1669 *
1670 * Using the +:never+ TimingSymbol the RuntimeError exception will always be
1671 * ignored in the first block of the main thread. In the second
1672 * ::handle_interrupt block we can purposefully handle RuntimeError exceptions.
1673 *
1674 * th = Thread.new do
1675 * Thead.handle_interrupt(RuntimeError => :never) {
1676 * begin
1677 * # You can write resource allocation code safely.
1678 * Thread.handle_interrupt(RuntimeError => :immediate) {
1679 * # ...
1680 * }
1681 * ensure
1682 * # You can write resource deallocation code safely.
1683 * end
1684 * }
1685 * end
1686 * Thread.pass
1687 * # ...
1688 * th.raise "stop"
1689 *
1690 * While we are ignoring the RuntimeError exception, it's safe to write our
1691 * resource allocation code. Then, the ensure block is where we can safely
1692 * deallocate your resources.
1693 *
1694 * ==== Guarding from TimeoutError
1695 *
1696 * In the next example, we will guard from the TimeoutError exception. This
1697 * will help prevent from leaking resources when TimeoutError exceptions occur
1698 * during normal ensure clause. For this example we use the help of the
1699 * standard library Timeout, from lib/timeout.rb
1700 *
1701 * require 'timeout'
1702 * Thread.handle_interrupt(TimeoutError => :never) {
1703 * timeout(10){
1704 * # TimeoutError doesn't occur here
1705 * Thread.handle_interrupt(TimeoutError => :on_blocking) {
1706 * # possible to be killed by TimeoutError
1707 * # while blocking operation
1708 * }
1709 * # TimeoutError doesn't occur here
1710 * }
1711 * }
1712 *
1713 * In the first part of the +timeout+ block, we can rely on TimeoutError being
1714 * ignored. Then in the <code>TimeoutError => :on_blocking</code> block, any
1715 * operation that will block the calling thread is susceptible to a
1716 * TimeoutError exception being raised.
1717 *
1718 * ==== Stack control settings
1719 *
1720 * It's possible to stack multiple levels of ::handle_interrupt blocks in order
1721 * to control more than one ExceptionClass and TimingSymbol at a time.
1722 *
1723 * Thread.handle_interrupt(FooError => :never) {
1724 * Thread.handle_interrupt(BarError => :never) {
1725 * # FooError and BarError are prohibited.
1726 * }
1727 * }
1728 *
1729 * ==== Inheritance with ExceptionClass
1730 *
1731 * All exceptions inherited from the ExceptionClass parameter will be considered.
1732 *
1733 * Thread.handle_interrupt(Exception => :never) {
1734 * # all exceptions inherited from Exception are prohibited.
1735 * }
1736 *
1737 */
1738 static VALUE
1739 rb_thread_s_handle_interrupt(VALUE self, VALUE mask_arg)
1740 {
1741 VALUE mask;
1742 rb_thread_t *th = GET_THREAD();
1743 VALUE r = Qnil;
1744 int state;
1745
1746 if (!rb_block_given_p()) {
1747 rb_raise(rb_eArgError, "block is needed.");
1748 }
1749
1750 mask = rb_convert_type(mask_arg, T_HASH, "Hash", "to_hash");
1751 rb_hash_foreach(mask, handle_interrupt_arg_check_i, 0);
1752 rb_ary_push(th->pending_interrupt_mask_stack, mask);
1753 if (!rb_threadptr_pending_interrupt_empty_p(th)) {
1754 th->pending_interrupt_queue_checked = 0;
1755 RUBY_VM_SET_INTERRUPT(th);
1756 }
1757
1758 TH_PUSH_TAG(th);
1759 if ((state = EXEC_TAG()) == 0) {
1760 r = rb_yield(Qnil);
1761 }
1762 TH_POP_TAG();
1763
1764 rb_ary_pop(th->pending_interrupt_mask_stack);
1765 if (!rb_threadptr_pending_interrupt_empty_p(th)) {
1766 th->pending_interrupt_queue_checked = 0;
1767 RUBY_VM_SET_INTERRUPT(th);
1768 }
1769
1770 RUBY_VM_CHECK_INTS(th);
1771
1772 if (state) {
1773 JUMP_TAG(state);
1774 }
1775
1776 return r;
1777 }
1778
1779 /*
1780 * call-seq:
1781 * target_thread.pending_interrupt?(error = nil) -> true/false
1782 *
1783 * Returns whether or not the asychronous queue is empty for the target thread.
1784 *
1785 * If +error+ is given, then check only for +error+ type deferred events.
1786 *
1787 * See ::pending_interrupt? for more information.
1788 */
1789 static VALUE
1790 rb_thread_pending_interrupt_p(int argc, VALUE *argv, VALUE target_thread)
1791 {
1792 rb_thread_t *target_th;
1793
1794 GetThreadPtr(target_thread, target_th);
1795
1796 if (rb_threadptr_pending_interrupt_empty_p(target_th)) {
1797 return Qfalse;
1798 }
1799 else {
1800 if (argc == 1) {
1801 VALUE err;
1802 rb_scan_args(argc, argv, "01", &err);
1803 if (!rb_obj_is_kind_of(err, rb_cModule)) {
1804 rb_raise(rb_eTypeError, "class or module required for rescue clause");
1805 }
1806 if (rb_threadptr_pending_interrupt_include_p(target_th, err)) {
1807 return Qtrue;
1808 }
1809 else {
1810 return Qfalse;
1811 }
1812 }
1813 return Qtrue;
1814 }
1815 }
1816
1817 /*
1818 * call-seq:
1819 * Thread.pending_interrupt?(error = nil) -> true/false
1820 *
1821 * Returns whether or not the asynchronous queue is empty.
1822 *
1823 * Since Thread::handle_interrupt can be used to defer asynchronous events.
1824 * This method can be used to determine if there are any deferred events.
1825 *
1826 * If you find this method returns true, then you may finish +:never+ blocks.
1827 *
1828 * For example, the following method processes deferred asynchronous events
1829 * immediately.
1830 *
1831 * def Thread.kick_interrupt_immediately
1832 * Thread.handle_interrupt(Object => :immediate) {
1833 * Thread.pass
1834 * }
1835 * end
1836 *
1837 * If +error+ is given, then check only for +error+ type deferred events.
1838 *
1839 * === Usage
1840 *
1841 * th = Thread.new{
1842 * Thread.handle_interrupt(RuntimeError => :on_blocking){
1843 * while true
1844 * ...
1845 * # reach safe point to invoke interrupt
1846 * if Thread.pending_interrupt?
1847 * Thread.handle_interrupt(Object => :immediate){}
1848 * end
1849 * ...
1850 * end
1851 * }
1852 * }
1853 * ...
1854 * th.raise # stop thread
1855 *
1856 * This example can also be written as the following, which you should use to
1857 * avoid asynchronous interrupts.
1858 *
1859 * flag = true
1860 * th = Thread.new{
1861 * Thread.handle_interrupt(RuntimeError => :on_blocking){
1862 * while true
1863 * ...
1864 * # reach safe point to invoke interrupt
1865 * break if flag == false
1866 * ...
1867 * end
1868 * }
1869 * }
1870 * ...
1871 * flag = false # stop thread
1872 */
1873
1874 static VALUE
1875 rb_thread_s_pending_interrupt_p(int argc, VALUE *argv, VALUE self)
1876 {
1877 return rb_thread_pending_interrupt_p(argc, argv, GET_THREAD()->self);
1878 }
1879
1880 static void
1881 rb_threadptr_to_kill(rb_thread_t *th)
1882 {
1883 rb_threadptr_pending_interrupt_clear(th);
1884 th->status = THREAD_RUNNABLE;
1885 th->to_kill = 1;
1886 th->errinfo = INT2FIX(TAG_FATAL);
1887 TH_JUMP_TAG(th, TAG_FATAL);
1888 }
1889
1890 void
1891 rb_threadptr_execute_interrupts(rb_thread_t *th, int blocking_timing)
1892 {
1893 if (th->raised_flag) return;
1894
1895 while (1) {
1896 rb_atomic_t interrupt;
1897 rb_atomic_t old;
1898 int sig;
1899 int timer_interrupt;
1900 int pending_interrupt;
1901 int finalizer_interrupt;
1902 int trap_interrupt;
1903
1904 do {
1905 interrupt = th->interrupt_flag;
1906 old = ATOMIC_CAS(th->interrupt_flag, interrupt, interrupt & th->interrupt_mask);
1907 } while (old != interrupt);
1908
1909 interrupt &= (rb_atomic_t)~th->interrupt_mask;
1910 if (!interrupt)
1911 return;
1912
1913 timer_interrupt = interrupt & TIMER_INTERRUPT_MASK;
1914 pending_interrupt = interrupt & PENDING_INTERRUPT_MASK;
1915 finalizer_interrupt = interrupt & FINALIZER_INTERRUPT_MASK;
1916 trap_interrupt = interrupt & TRAP_INTERRUPT_MASK;
1917
1918 /* signal handling */
1919 if (trap_interrupt && (th == th->vm->main_thread)) {
1920 enum rb_thread_status prev_status = th->status;
1921 th->status = THREAD_RUNNABLE;
1922 while ((sig = rb_get_next_signal()) != 0) {
1923 rb_signal_exec(th, sig);
1924 }
1925 th->status = prev_status;
1926 }
1927
1928 /* exception from another thread */
1929 if (pending_interrupt && rb_threadptr_pending_interrupt_active_p(th)) {
1930 VALUE err = rb_threadptr_pending_interrupt_deque(th, blocking_timing ? INTERRUPT_ON_BLOCKING : INTERRUPT_NONE);
1931 thread_debug("rb_thread_execute_interrupts: %"PRIdVALUE"\n", err);
1932
1933 if (err == Qundef) {
1934 /* no error */
1935 }
1936 else if (err == eKillSignal /* Thread#kill receieved */ ||
1937 err == eTerminateSignal /* Terminate thread */ ||
1938 err == INT2FIX(TAG_FATAL) /* Thread.exit etc. */ ) {
1939 rb_threadptr_to_kill(th);
1940 }
1941 else {
1942 /* set runnable if th was slept. */
1943 if (th->status == THREAD_STOPPED ||
1944 th->status == THREAD_STOPPED_FOREVER)
1945 th->status = THREAD_RUNNABLE;
1946 rb_exc_raise(err);
1947 }
1948 }
1949
1950 if (finalizer_interrupt) {
1951 rb_gc_finalize_deferred();
1952 }
1953
1954 if (timer_interrupt) {
1955 unsigned long limits_us = TIME_QUANTUM_USEC;
1956
1957 if (th->priority > 0)
1958 limits_us <<= th->priority;
1959 else
1960 limits_us >>= -th->priority;
1961
1962 if (th->status == THREAD_RUNNABLE)
1963 th->running_time_us += TIME_QUANTUM_USEC;
1964
1965 EXEC_EVENT_HOOK(th, RUBY_EVENT_SWITCH, th->cfp->self, 0, 0, Qundef);
1966
1967 rb_thread_schedule_limits(limits_us);
1968 }
1969 }
1970 }
1971
1972 void
1973 rb_thread_execute_interrupts(VALUE thval)
1974 {
1975 rb_thread_t *th;
1976 GetThreadPtr(thval, th);
1977 rb_threadptr_execute_interrupts(th, 1);
1978 }
1979
1980 static void
1981 rb_threadptr_ready(rb_thread_t *th)
1982 {
1983 rb_threadptr_interrupt(th);
1984 }
1985
1986 static VALUE
1987 rb_threadptr_raise(rb_thread_t *th, int argc, VALUE *argv)
1988 {
1989 VALUE exc;
1990
1991 if (rb_threadptr_dead(th)) {
1992 return Qnil;
1993 }
1994
1995 if (argc == 0) {
1996 exc = rb_exc_new(rb_eRuntimeError, 0, 0);
1997 }
1998 else {
1999 exc = rb_make_exception(argc, argv);
2000 }
2001 rb_threadptr_pending_interrupt_enque(th, exc);
2002 rb_threadptr_interrupt(th);
2003 return Qnil;
2004 }
2005
2006 void
2007 rb_threadptr_signal_raise(rb_thread_t *th, int sig)
2008 {
2009 VALUE argv[2];
2010
2011 argv[0] = rb_eSignal;
2012 argv[1] = INT2FIX(sig);
2013 rb_threadptr_raise(th->vm->main_thread, 2, argv);
2014 }
2015
2016 void
2017 rb_threadptr_signal_exit(rb_thread_t *th)
2018 {
2019 VALUE argv[2];
2020
2021 argv[0] = rb_eSystemExit;
2022 argv[1] = rb_str_new2("exit");
2023 rb_threadptr_raise(th->vm->main_thread, 2, argv);
2024 }
2025
2026 #if defined(POSIX_SIGNAL) && defined(SIGSEGV) && defined(HAVE_SIGALTSTACK)
2027 #define USE_SIGALTSTACK
2028 #endif
2029
2030 void
2031 ruby_thread_stack_overflow(rb_thread_t *th)
2032 {
2033 th->raised_flag = 0;
2034 #ifdef USE_SIGALTSTACK
2035 rb_exc_raise(sysstack_error);
2036 #else
2037 th->errinfo = sysstack_error;
2038 TH_JUMP_TAG(th, TAG_RAISE);
2039 #endif
2040 }
2041
2042 int
2043 rb_threadptr_set_raised(rb_thread_t *th)
2044 {
2045 if (th->raised_flag & RAISED_EXCEPTION) {
2046 return 1;
2047 }
2048 th->raised_flag |= RAISED_EXCEPTION;
2049 return 0;
2050 }
2051
2052 int
2053 rb_threadptr_reset_raised(rb_thread_t *th)
2054 {
2055 if (!(th->raised_flag & RAISED_EXCEPTION)) {
2056 return 0;
2057 }
2058 th->raised_flag &= ~RAISED_EXCEPTION;
2059 return 1;
2060 }
2061
2062 static int
2063 thread_fd_close_i(st_data_t key, st_data_t val, st_data_t data)
2064 {
2065 int fd = (int)data;
2066 rb_thread_t *th;
2067 GetThreadPtr((VALUE)key, th);
2068
2069 if (th->waiting_fd == fd) {
2070 VALUE err = th->vm->special_exceptions[ruby_error_closed_stream];
2071 rb_threadptr_pending_interrupt_enque(th, err);
2072 rb_threadptr_interrupt(th);
2073 }
2074 return ST_CONTINUE;
2075 }
2076
2077 void
2078 rb_thread_fd_close(int fd)
2079 {
2080 st_foreach(GET_THREAD()->vm->living_threads, thread_fd_close_i, (st_index_t)fd);
2081 }
2082
2083 /*
2084 * call-seq:
2085 * thr.raise
2086 * thr.raise(string)
2087 * thr.raise(exception [, string [, array]])
2088 *
2089 * Raises an exception (see <code>Kernel::raise</code>) from <i>thr</i>. The
2090 * caller does not have to be <i>thr</i>.
2091 *
2092 * Thread.abort_on_exception = true
2093 * a = Thread.new { sleep(200) }
2094 * a.raise("Gotcha")
2095 *
2096 * <em>produces:</em>
2097 *
2098 * prog.rb:3: Gotcha (RuntimeError)
2099 * from prog.rb:2:in `initialize'
2100 * from prog.rb:2:in `new'
2101 * from prog.rb:2
2102 */
2103
2104 static VALUE
2105 thread_raise_m(int argc, VALUE *argv, VALUE self)
2106 {
2107 rb_thread_t *target_th;
2108 rb_thread_t *th = GET_THREAD();
2109 GetThreadPtr(self, target_th);
2110 rb_threadptr_raise(target_th, argc, argv);
2111
2112 /* To perform Thread.current.raise as Kernel.raise */
2113 if (th == target_th) {
2114 RUBY_VM_CHECK_INTS(th);
2115 }
2116 return Qnil;
2117 }
2118
2119
2120 /*
2121 * call-seq:
2122 * thr.exit -> thr or nil
2123 * thr.kill -> thr or nil
2124 * thr.terminate -> thr or nil
2125 *
2126 * Terminates <i>thr</i> and schedules another thread to be run. If this thread
2127 * is already marked to be killed, <code>exit</code> returns the
2128 * <code>Thread</code>. If this is the main thread, or the last thread, exits
2129 * the process.
2130 */
2131
2132 VALUE
2133 rb_thread_kill(VALUE thread)
2134 {
2135 rb_thread_t *th;
2136
2137 GetThreadPtr(thread, th);
2138
2139 if (th != GET_THREAD() && th->safe_level < 4) {
2140 rb_secure(4);
2141 }
2142 if (th->to_kill || th->status == THREAD_KILLED) {
2143 return thread;
2144 }
2145 if (th == th->vm->main_thread) {
2146 rb_exit(EXIT_SUCCESS);
2147 }
2148
2149 thread_debug("rb_thread_kill: %p (%p)\n", (void *)th, (void *)th->thread_id);
2150
2151 if (th == GET_THREAD()) {
2152 /* kill myself immediately */
2153 rb_threadptr_to_kill(th);
2154 }
2155 else {
2156 rb_threadptr_pending_interrupt_enque(th, eKillSignal);
2157 rb_threadptr_interrupt(th);
2158 }
2159 return thread;
2160 }
2161
2162
2163 /*
2164 * call-seq:
2165 * Thread.kill(thread) -> thread
2166 *
2167 * Causes the given <em>thread</em> to exit (see <code>Thread::exit</code>).
2168 *
2169 * count = 0
2170 * a = Thread.new { loop { count += 1 } }
2171 * sleep(0.1) #=> 0
2172 * Thread.kill(a) #=> #<Thread:0x401b3d30 dead>
2173 * count #=> 93947
2174 * a.alive? #=> false
2175 */
2176
2177 static VALUE
2178 rb_thread_s_kill(VALUE obj, VALUE th)
2179 {
2180 return rb_thread_kill(th);
2181 }
2182
2183
2184 /*
2185 * call-seq:
2186 * Thread.exit -> thread
2187 *
2188 * Terminates the currently running thread and schedules another thread to be
2189 * run. If this thread is already marked to be killed, <code>exit</code>
2190 * returns the <code>Thread</code>. If this is the main thread, or the last
2191 * thread, exit the process.
2192 */
2193
2194 static VALUE
2195 rb_thread_exit(void)
2196 {
2197 rb_thread_t *th = GET_THREAD();
2198 return rb_thread_kill(th->self);
2199 }
2200
2201
2202 /*
2203 * call-seq:
2204 * thr.wakeup -> thr
2205 *
2206 * Marks <i>thr</i> as eligible for scheduling (it may still remain blocked on
2207 * I/O, however). Does not invoke the scheduler (see <code>Thread#run</code>).
2208 *
2209 * c = Thread.new { Thread.stop; puts "hey!" }
2210 * sleep 0.1 while c.status!='sleep'
2211 * c.wakeup
2212 * c.join
2213 *
2214 * <em>produces:</em>
2215 *
2216 * hey!
2217 */
2218
2219 VALUE
2220 rb_thread_wakeup(VALUE thread)
2221 {
2222 if (!RTEST(rb_thread_wakeup_alive(thread))) {
2223 rb_raise(rb_eThreadError, "killed thread");
2224 }
2225 return thread;
2226 }
2227
2228 VALUE
2229 rb_thread_wakeup_alive(VALUE thread)
2230 {
2231 rb_thread_t *th;
2232 GetThreadPtr(thread, th);
2233
2234 if (th->status == THREAD_KILLED) {
2235 return Qnil;
2236 }
2237 rb_threadptr_ready(th);
2238 if (th->status == THREAD_STOPPED || th->status == THREAD_STOPPED_FOREVER)
2239 th->status = THREAD_RUNNABLE;
2240 return thread;
2241 }
2242
2243
2244 /*
2245 * call-seq:
2246 * thr.run -> thr
2247 *
2248 * Wakes up <i>thr</i>, making it eligible for scheduling.
2249 *
2250 * a = Thread.new { puts "a"; Thread.stop; puts "c" }
2251 * sleep 0.1 while a.status!='sleep'
2252 * puts "Got here"
2253 * a.run
2254 * a.join
2255 *
2256 * <em>produces:</em>
2257 *
2258 * a
2259 * Got here
2260 * c
2261 */
2262
2263 VALUE
2264 rb_thread_run(VALUE thread)
2265 {
2266 rb_thread_wakeup(thread);
2267 rb_thread_schedule();
2268 return thread;
2269 }
2270
2271
2272 /*
2273 * call-seq:
2274 * Thread.stop -> nil
2275 *
2276 * Stops execution of the current thread, putting it into a ``sleep'' state,
2277 * and schedules execution of another thread.
2278 *
2279 * a = Thread.new { print "a"; Thread.stop; print "c" }
2280 * sleep 0.1 while a.status!='sleep'
2281 * print "b"
2282 * a.run
2283 * a.join
2284 *
2285 * <em>produces:</em>
2286 *
2287 * abc
2288 */
2289
2290 VALUE
2291 rb_thread_stop(void)
2292 {
2293 if (rb_thread_alone()) {
2294 rb_raise(rb_eThreadError,
2295 "stopping only thread\n\tnote: use sleep to stop forever");
2296 }
2297 rb_thread_sleep_deadly();
2298 return Qnil;
2299 }
2300
2301 static int
2302 thread_list_i(st_data_t key, st_data_t val, void *data)
2303 {
2304 VALUE ary = (VALUE)data;
2305 rb_thread_t *th;
2306 GetThreadPtr((VALUE)key, th);
2307
2308 switch (th->status) {
2309 case THREAD_RUNNABLE:
2310 case THREAD_STOPPED:
2311 case THREAD_STOPPED_FOREVER:
2312 rb_ary_push(ary, th->self);
2313 default:
2314 break;
2315 }
2316 return ST_CONTINUE;
2317 }
2318
2319 /********************************************************************/
2320
2321 /*
2322 * call-seq:
2323 * Thread.list -> array
2324 *
2325 * Returns an array of <code>Thread</code> objects for all threads that are
2326 * either runnable or stopped.
2327 *
2328 * Thread.new { sleep(200) }
2329 * Thread.new { 1000000.times {|i| i*i } }
2330 * Thread.new { Thread.stop }
2331 * Thread.list.each {|t| p t}
2332 *
2333 * <em>produces:</em>
2334 *
2335 * #<Thread:0x401b3e84 sleep>
2336 * #<Thread:0x401b3f38 run>
2337 * #<Thread:0x401b3fb0 sleep>
2338 * #<Thread:0x401bdf4c run>
2339 */
2340
2341 VALUE
2342 rb_thread_list(void)
2343 {
2344 VALUE ary = rb_ary_new();
2345 st_foreach(GET_THREAD()->vm->living_threads, thread_list_i, ary);
2346 return ary;
2347 }
2348
2349 VALUE
2350 rb_thread_current(void)
2351 {
2352 return GET_THREAD()->self;
2353 }
2354
2355 /*
2356 * call-seq:
2357 * Thread.current -> thread
2358 *
2359 * Returns the currently executing thread.
2360 *
2361 * Thread.current #=> #<Thread:0x401bdf4c run>
2362 */
2363
2364 static VALUE
2365 thread_s_current(VALUE klass)
2366 {
2367 return rb_thread_current();
2368 }
2369
2370 VALUE
2371 rb_thread_main(void)
2372 {
2373 return GET_THREAD()->vm->main_thread->self;
2374 }
2375
2376 /*
2377 * call-seq:
2378 * Thread.main -> thread
2379 *
2380 * Returns the main thread.
2381 */
2382
2383 static VALUE
2384 rb_thread_s_main(VALUE klass)
2385 {
2386 return rb_thread_main();
2387 }
2388
2389
2390 /*
2391 * call-seq:
2392 * Thread.abort_on_exception -> true or false
2393 *
2394 * Returns the status of the global ``abort on exception'' condition. The
2395 * default is <code>false</code>. When set to <code>true</code>, or if the
2396 * global <code>$DEBUG</code> flag is <code>true</code> (perhaps because the
2397 * command line option <code>-d</code> was specified) all threads will abort
2398 * (the process will <code>exit(0)</code>) if an exception is raised in any
2399 * thread. See also <code>Thread::abort_on_exception=</code>.
2400 */
2401
2402 static VALUE
2403 rb_thread_s_abort_exc(void)
2404 {
2405 return GET_THREAD()->vm->thread_abort_on_exception ? Qtrue : Qfalse;
2406 }
2407
2408
2409 /*
2410 * call-seq:
2411 * Thread.abort_on_exception= boolean -> true or false
2412 *
2413 * When set to <code>true</code>, all threads will abort if an exception is
2414 * raised. Returns the new state.
2415 *
2416 * Thread.abort_on_exception = true
2417 * t1 = Thread.new do
2418 * puts "In new thread"
2419 * raise "Exception from thread"
2420 * end
2421 * sleep(1)
2422 * puts "not reached"
2423 *
2424 * <em>produces:</em>
2425 *
2426 * In new thread
2427 * prog.rb:4: Exception from thread (RuntimeError)
2428 * from prog.rb:2:in `initialize'
2429 * from prog.rb:2:in `new'
2430 * from prog.rb:2
2431 */
2432
2433 static VALUE
2434 rb_thread_s_abort_exc_set(VALUE self, VALUE val)
2435 {
2436 rb_secure(4);
2437 GET_THREAD()->vm->thread_abort_on_exception = RTEST(val);
2438 return val;
2439 }
2440
2441
2442 /*
2443 * call-seq:
2444 * thr.abort_on_exception -> true or false
2445 *
2446 * Returns the status of the thread-local ``abort on exception'' condition for
2447 * <i>thr</i>. The default is <code>false</code>. See also
2448 * <code>Thread::abort_on_exception=</code>.
2449 */
2450
2451 static VALUE
2452 rb_thread_abort_exc(VALUE thread)
2453 {
2454 rb_thread_t *th;
2455 GetThreadPtr(thread, th);
2456 return th->abort_on_exception ? Qtrue : Qfalse;
2457 }
2458
2459
2460 /*
2461 * call-seq:
2462 * thr.abort_on_exception= boolean -> true or false
2463 *
2464 * When set to <code>true</code>, causes all threads (including the main
2465 * program) to abort if an exception is raised in <i>thr</i>. The process will
2466 * effectively <code>exit(0)</code>.
2467 */
2468
2469 static VALUE
2470 rb_thread_abort_exc_set(VALUE thread, VALUE val)
2471 {
2472 rb_thread_t *th;
2473 rb_secure(4);
2474
2475 GetThreadPtr(thread, th);
2476 th->abort_on_exception = RTEST(val);
2477 return val;
2478 }
2479
2480
2481 /*
2482 * call-seq:
2483 * thr.group -> thgrp or nil
2484 *
2485 * Returns the <code>ThreadGroup</code> which contains <i>thr</i>, or nil if
2486 * the thread is not a member of any group.
2487 *
2488 * Thread.main.group #=> #<ThreadGroup:0x4029d914>
2489 */
2490
2491 VALUE
2492 rb_thread_group(VALUE thread)
2493 {
2494 rb_thread_t *th;
2495 VALUE group;
2496 GetThreadPtr(thread, th);
2497 group = th->thgroup;
2498
2499 if (!group) {
2500 group = Qnil;
2501 }
2502 return group;
2503 }
2504
2505 static const char *
2506 thread_status_name(rb_thread_t *th)
2507 {
2508 switch (th->status) {
2509 case THREAD_RUNNABLE:
2510 if (th->to_kill)
2511 return "aborting";
2512 else
2513 return "run";
2514 case THREAD_STOPPED:
2515 case THREAD_STOPPED_FOREVER:
2516 return "sleep";
2517 case THREAD_KILLED:
2518 return "dead";
2519 default:
2520 return "unknown";
2521 }
2522 }
2523
2524 static int
2525 rb_threadptr_dead(rb_thread_t *th)
2526 {
2527 return th->status == THREAD_KILLED;
2528 }
2529
2530
2531 /*
2532 * call-seq:
2533 * thr.status -> string, false or nil
2534 *
2535 * Returns the status of <i>thr</i>: ``<code>sleep</code>'' if <i>thr</i> is
2536 * sleeping or waiting on I/O, ``<code>run</code>'' if <i>thr</i> is executing,
2537 * ``<code>aborting</code>'' if <i>thr</i> is aborting, <code>false</code> if
2538 * <i>thr</i> terminated normally, and <code>nil</code> if <i>thr</i>
2539 * terminated with an exception.
2540 *
2541 * a = Thread.new { raise("die now") }
2542 * b = Thread.new { Thread.stop }
2543 * c = Thread.new { Thread.exit }
2544 * d = Thread.new { sleep }
2545 * d.kill #=> #<Thread:0x401b3678 aborting>
2546 * a.status #=> nil
2547 * b.status #=> "sleep"
2548 * c.status #=> false
2549 * d.status #=> "aborting"
2550 * Thread.current.status #=> "run"
2551 */
2552
2553 static VALUE
2554 rb_thread_status(VALUE thread)
2555 {
2556 rb_thread_t *th;
2557 GetThreadPtr(thread, th);
2558
2559 if (rb_threadptr_dead(th)) {
2560 if (!NIL_P(th->errinfo) && !FIXNUM_P(th->errinfo)
2561 /* TODO */ ) {
2562 return Qnil;
2563 }
2564 return Qfalse;
2565 }
2566 return rb_str_new2(thread_status_name(th));
2567 }
2568
2569
2570 /*
2571 * call-seq:
2572 * thr.alive? -> true or false
2573 *
2574 * Returns <code>true</code> if <i>thr</i> is running or sleeping.
2575 *
2576 * thr = Thread.new { }
2577 * thr.join #=> #<Thread:0x401b3fb0 dead>
2578 * Thread.current.alive? #=> true
2579 * thr.alive? #=> false
2580 */
2581
2582 static VALUE
2583 rb_thread_alive_p(VALUE thread)
2584 {
2585 rb_thread_t *th;
2586 GetThreadPtr(thread, th);
2587
2588 if (rb_threadptr_dead(th))
2589 return Qfalse;
2590 return Qtrue;
2591 }
2592
2593 /*
2594 * call-seq:
2595 * thr.stop? -> true or false
2596 *
2597 * Returns <code>true</code> if <i>thr</i> is dead or sleeping.
2598 *
2599 * a = Thread.new { Thread.stop }
2600 * b = Thread.current
2601 * a.stop? #=> true
2602 * b.stop? #=> false
2603 */
2604
2605 static VALUE
2606 rb_thread_stop_p(VALUE thread)
2607 {
2608 rb_thread_t *th;
2609 GetThreadPtr(thread, th);
2610
2611 if (rb_threadptr_dead(th))
2612 return Qtrue;
2613 if (th->status == THREAD_STOPPED || th->status == THREAD_STOPPED_FOREVER)
2614 return Qtrue;
2615 return Qfalse;
2616 }
2617
2618 /*
2619 * call-seq:
2620 * thr.safe_level -> integer
2621 *
2622 * Returns the safe level in effect for <i>thr</i>. Setting thread-local safe
2623 * levels can help when implementing sandboxes which run insecure code.
2624 *
2625 * thr = Thread.new { $SAFE = 3; sleep }
2626 * Thread.current.safe_level #=> 0
2627 * thr.safe_level #=> 3
2628 */
2629
2630 static VALUE
2631 rb_thread_safe_level(VALUE thread)
2632 {
2633 rb_thread_t *th;
2634 GetThreadPtr(thread, th);
2635
2636 return INT2NUM(th->safe_level);
2637 }
2638
2639 /*
2640 * call-seq:
2641 * thr.inspect -> string
2642 *
2643 * Dump the name, id, and status of _thr_ to a string.
2644 */
2645
2646 static VALUE
2647 rb_thread_inspect(VALUE thread)
2648 {
2649 const char *cname = rb_obj_classname(thread);
2650 rb_thread_t *th;
2651 const char *status;
2652 VALUE str;
2653
2654 GetThreadPtr(thread, th);
2655 status = thread_status_name(th);
2656 str = rb_sprintf("#<%s:%p %s>", cname, (void *)thread, status);
2657 OBJ_INFECT(str, thread);
2658
2659 return str;
2660 }
2661
2662 VALUE
2663 rb_thread_local_aref(VALUE thread, ID id)
2664 {
2665 rb_thread_t *th;
2666 st_data_t val;
2667
2668 GetThreadPtr(thread, th);
2669 if (rb_safe_level() >= 4 && th != GET_THREAD()) {
2670 rb_raise(rb_eSecurityError, "Insecure: thread locals");
2671 }
2672 if (!th->local_storage) {
2673 return Qnil;
2674 }
2675 if (st_lookup(th->local_storage, id, &val)) {
2676 return (VALUE)val;
2677 }
2678 return Qnil;
2679 }
2680
2681 /*
2682 * call-seq:
2683 * thr[sym] -> obj or nil
2684 *
2685 * Attribute Reference---Returns the value of a fiber-local variable (current thread's root fiber
2686 * if not explicitely inside a Fiber), using either a symbol or a string name.
2687 * If the specified variable does not exist, returns <code>nil</code>.
2688 *
2689 * [
2690 * Thread.new { Thread.current["name"] = "A" },
2691 * Thread.new { Thread.current[:name] = "B" },
2692 * Thread.new { Thread.current["name"] = "C" }
2693 * ].each do |th|
2694 * th.join
2695 * puts "#{th.inspect}: #{th[:name]}"
2696 * end
2697 *
2698 * <em>produces:</em>
2699 *
2700 * #<Thread:0x00000002a54220 dead>: A
2701 * #<Thread:0x00000002a541a8 dead>: B
2702 * #<Thread:0x00000002a54130 dead>: C
2703 *
2704 * Thread#[] and Thread#[]= are not thread-local but fiber-local.
2705 * This confusion did not exist in Ruby 1.8 because
2706 * fibers were only available since Ruby 1.9.
2707 * Ruby 1.9 chooses that the methods behaves fiber-local to save
2708 * following idiom for dynamic scope.
2709 *
2710 * def meth(newvalue)
2711 * begin
2712 * oldvalue = Thread.current[:name]
2713 * Thread.current[:name] = newvalue
2714 * yield
2715 * ensure
2716 * Thread.current[:name] = oldvalue
2717 * end
2718 * end
2719 *
2720 * The idiom may not work as dynamic scope if the methods are thread-local
2721 * and a given block switches fiber.
2722 *
2723 * f = Fiber.new {
2724 * meth(1) {
2725 * Fiber.yield
2726 * }
2727 * }
2728 * meth(2) {
2729 * f.resume
2730 * }
2731 * f.resume
2732 * p Thread.current[:name]
2733 * #=> nil if fiber-local
2734 * #=> 2 if thread-local (The value 2 is leaked to outside of meth method.)
2735 *
2736 * For thread-local variables, please see <code>Thread#thread_local_get</code>
2737 * and <code>Thread#thread_local_set</code>.
2738 *
2739 */
2740
2741 static VALUE
2742 rb_thread_aref(VALUE thread, VALUE id)
2743 {
2744 return rb_thread_local_aref(thread, rb_to_id(id));
2745 }
2746
2747 VALUE
2748 rb_thread_local_aset(VALUE thread, ID id, VALUE val)
2749 {
2750 rb_thread_t *th;
2751 GetThreadPtr(thread, th);
2752
2753 if (rb_safe_level() >= 4 && th != GET_THREAD()) {
2754 rb_raise(rb_eSecurityError, "Insecure: can't modify thread locals");
2755 }
2756 if (OBJ_FROZEN(thread)) {
2757 rb_error_frozen("thread locals");
2758 }
2759 if (!th->local_storage) {
2760 th->local_storage = st_init_numtable();
2761 }
2762 if (NIL_P(val)) {
2763 st_delete_wrap(th->local_storage, id);
2764 return Qnil;
2765 }
2766 st_insert(th->local_storage, id, val);
2767 return val;
2768 }
2769
2770 /*
2771 * call-seq:
2772 * thr[sym] = obj -> obj
2773 *
2774 * Attribute Assignment---Sets or creates the value of a fiber-local variable,
2775 * using either a symbol or a string. See also <code>Thread#[]</code>. For
2776 * thread-local variables, please see <code>Thread#thread_variable_set</code>
2777 * and <code>Thread#thread_variable_get</code>.
2778 */
2779
2780 static VALUE
2781 rb_thread_aset(VALUE self, VALUE id, VALUE val)
2782 {
2783 return rb_thread_local_aset(self, rb_to_id(id), val);
2784 }
2785
2786 /*
2787 * call-seq:
2788 * thr.thread_variable_get(key) -> obj or nil
2789 *
2790 * Returns the value of a thread local variable that has been set. Note that
2791 * these are different than fiber local values. For fiber local values,
2792 * please see Thread#[] and Thread#[]=.
2793 *
2794 * Thread local values are carried along with threads, and do not respect
2795 * fibers. For example:
2796 *
2797 * Thread.new {
2798 * Thread.current.thread_variable_set("foo", "bar") # set a thread local
2799 * Thread.current["foo"] = "bar" # set a fiber local
2800 *
2801 * Fiber.new {
2802 * Fiber.yield [
2803 * Thread.current.thread_variable_get("foo"), # get the thread local
2804 * Thread.current["foo"], # get the fiber local
2805 * ]
2806 * }.resume
2807 * }.join.value # => ['bar', nil]
2808 *
2809 * The value "bar" is returned for the thread local, where nil is returned
2810 * for the fiber local. The fiber is executed in the same thread, so the
2811 * thread local values are available.
2812 *
2813 * See also Thread#[]
2814 */
2815
2816 static VALUE
2817 rb_thread_variable_get(VALUE thread, VALUE id)
2818 {
2819 VALUE locals;
2820 rb_thread_t *th;
2821
2822 GetThreadPtr(thread, th);
2823
2824 if (rb_safe_level() >= 4 && th != GET_THREAD()) {
2825 rb_raise(rb_eSecurityError, "Insecure: can't modify thread locals");
2826 }
2827
2828 locals = rb_iv_get(thread, "locals");
2829 return rb_hash_aref(locals, ID2SYM(rb_to_id(id)));
2830 }
2831
2832 /*
2833 * call-seq:
2834 * thr.thread_variable_set(key, value)
2835 *
2836 * Sets a thread local with +key+ to +value+. Note that these are local to
2837 * threads, and not to fibers. Please see Thread#thread_variable_get and
2838 * Thread#[] for more information.
2839 */
2840
2841 static VALUE
2842 rb_thread_variable_set(VALUE thread, VALUE id, VALUE val)
2843 {
2844 VALUE locals;
2845 rb_thread_t *th;
2846
2847 GetThreadPtr(thread, th);
2848
2849 if (rb_safe_level() >= 4 && th != GET_THREAD()) {
2850 rb_raise(rb_eSecurityError, "Insecure: can't modify thread locals");
2851 }
2852 if (OBJ_FROZEN(thread)) {
2853 rb_error_frozen("thread locals");
2854 }
2855
2856 locals = rb_iv_get(thread, "locals");
2857 return rb_hash_aset(locals, ID2SYM(rb_to_id(id)), val);
2858 }
2859
2860 /*
2861 * call-seq:
2862 * thr.key?(sym) -> true or false
2863 *
2864 * Returns <code>true</code> if the given string (or symbol) exists as a
2865 * fiber-local variable.
2866 *
2867 * me = Thread.current
2868 * me[:oliver] = "a"
2869 * me.key?(:oliver) #=> true
2870 * me.key?(:stanley) #=> false
2871 */
2872
2873 static VALUE
2874 rb_thread_key_p(VALUE self, VALUE key)
2875 {
2876 rb_thread_t *th;
2877 ID id = rb_to_id(key);
2878
2879 GetThreadPtr(self, th);
2880
2881 if (!th->local_storage) {
2882 return Qfalse;
2883 }
2884 if (st_lookup(th->local_storage, id, 0)) {
2885 return Qtrue;
2886 }
2887 return Qfalse;
2888 }
2889
2890 static int
2891 thread_keys_i(ID key, VALUE value, VALUE ary)
2892 {
2893 rb_ary_push(ary, ID2SYM(key));
2894 return ST_CONTINUE;
2895 }
2896
2897 static int
2898 vm_living_thread_num(rb_vm_t *vm)
2899 {
2900 return (int)vm->living_threads->num_entries;
2901 }
2902
2903 int
2904 rb_thread_alone(void)
2905 {
2906 int num = 1;
2907 if (GET_THREAD()->vm->living_threads) {
2908 num = vm_living_thread_num(GET_THREAD()->vm);
2909 thread_debug("rb_thread_alone: %d\n", num);
2910 }
2911 return num == 1;
2912 }
2913
2914 /*
2915 * call-seq:
2916 * thr.keys -> array
2917 *
2918 * Returns an an array of the names of the fiber-local variables (as Symbols).
2919 *
2920 * thr = Thread.new do
2921 * Thread.current[:cat] = 'meow'
2922 * Thread.current["dog"] = 'woof'
2923 * end
2924 * thr.join #=> #<Thread:0x401b3f10 dead>
2925 * thr.keys #=> [:dog, :cat]
2926 */
2927
2928 static VALUE
2929 rb_thread_keys(VALUE self)
2930 {
2931 rb_thread_t *th;
2932 VALUE ary = rb_ary_new();
2933 GetThreadPtr(self, th);
2934
2935 if (th->local_storage) {
2936 st_foreach(th->local_storage, thread_keys_i, ary);
2937 }
2938 return ary;
2939 }
2940
2941 static int
2942 keys_i(VALUE key, VALUE value, VALUE ary)
2943 {
2944 rb_ary_push(ary, key);
2945 return ST_CONTINUE;
2946 }
2947
2948 /*
2949 * call-seq:
2950 * thr.thread_variables -> array
2951 *
2952 * Returns an an array of the names of the thread-local variables (as Symbols).
2953 *
2954 * thr = Thread.new do
2955 * Thread.current.thread_variable_set(:cat, 'meow')
2956 * Thread.current.thread_variable_set("dog", 'woof')
2957 * end
2958 * thr.join #=> #<Thread:0x401b3f10 dead>
2959 * thr.thread_variables #=> [:dog, :cat]
2960 *
2961 * Note that these are not fiber local variables. Please see Thread#[] and
2962 * Thread#thread_variable_get for more details.
2963 */
2964
2965 static VALUE
2966 rb_thread_variables(VALUE thread)
2967 {
2968 VALUE locals;
2969 VALUE ary;
2970
2971 locals = rb_iv_get(thread, "locals");
2972 ary = rb_ary_new();
2973 rb_hash_foreach(locals, keys_i, ary);
2974
2975 return ary;
2976 }
2977
2978 /*
2979 * call-seq:
2980 * thr.thread_variable?(key) -> true or false
2981 *
2982 * Returns <code>true</code> if the given string (or symbol) exists as a
2983 * thread-local variable.
2984 *
2985 * me = Thread.current
2986 * me.thread_variable_set(:oliver, "a")
2987 * me.thread_variable?(:oliver) #=> true
2988 * me.thread_variable?(:stanley) #=> false
2989 *
2990 * Note that these are not fiber local variables. Please see Thread#[] and
2991 * Thread#thread_variable_get for more details.
2992 */
2993
2994 static VALUE
2995 rb_thread_variable_p(VALUE thread, VALUE key)
2996 {
2997 VALUE locals;
2998
2999 locals = rb_iv_get(thread, "locals");
3000
3001 if (!RHASH(locals)->ntbl)
3002 return Qfalse;
3003
3004 if (st_lookup(RHASH(locals)->ntbl, ID2SYM(rb_to_id(key)), 0)) {
3005 return Qtrue;
3006 }
3007
3008 return Qfalse;
3009 }
3010
3011 /*
3012 * call-seq:
3013 * thr.priority -> integer
3014 *
3015 * Returns the priority of <i>thr</i>. Default is inherited from the
3016 * current thread which creating the new thread, or zero for the
3017 * initial main thread; higher-priority thread will run more frequently
3018 * than lower-priority threads (but lower-priority threads can also run).
3019 *
3020 * This is just hint for Ruby thread scheduler. It may be ignored on some
3021 * platform.
3022 *
3023 * Thread.current.priority #=> 0
3024 */
3025
3026 static VALUE
3027 rb_thread_priority(VALUE thread)
3028 {
3029 rb_thread_t *th;
3030 GetThreadPtr(thread, th);
3031 return INT2NUM(th->priority);
3032 }
3033
3034
3035 /*
3036 * call-seq:
3037 * thr.priority= integer -> thr
3038 *
3039 * Sets the priority of <i>thr</i> to <i>integer</i>. Higher-priority threads
3040 * will run more frequently than lower-priority threads (but lower-priority
3041 * threads can also run).
3042 *
3043 * This is just hint for Ruby thread scheduler. It may be ignored on some
3044 * platform.
3045 *
3046 * count1 = count2 = 0
3047 * a = Thread.new do
3048 * loop { count1 += 1 }
3049 * end
3050 * a.priority = -1
3051 *
3052 * b = Thread.new do
3053 * loop { count2 += 1 }
3054 * end
3055 * b.priority = -2
3056 * sleep 1 #=> 1
3057 * count1 #=> 622504
3058 * count2 #=> 5832
3059 */
3060
3061 static VALUE
3062 rb_thread_priority_set(VALUE thread, VALUE prio)
3063 {
3064 rb_thread_t *th;
3065 int priority;
3066 GetThreadPtr(thread, th);
3067
3068 rb_secure(4);
3069
3070 #if USE_NATIVE_THREAD_PRIORITY
3071 th->priority = NUM2INT(prio);
3072 native_thread_apply_priority(th);
3073 #else
3074 priority = NUM2INT(prio);
3075 if (priority > RUBY_THREAD_PRIORITY_MAX) {
3076 priority = RUBY_THREAD_PRIORITY_MAX;
3077 }
3078 else if (priority < RUBY_THREAD_PRIORITY_MIN) {
3079 priority = RUBY_THREAD_PRIORITY_MIN;
3080 }
3081 th->priority = priority;
3082 #endif
3083 return INT2NUM(th->priority);
3084 }
3085
3086 /* for IO */
3087
3088 #if defined(NFDBITS) && defined(HAVE_RB_FD_INIT)
3089
3090 /*
3091 * several Unix platforms support file descriptors bigger than FD_SETSIZE
3092 * in select(2) system call.
3093 *
3094 * - Linux 2.2.12 (?)
3095 * - NetBSD 1.2 (src/sys/kern/sys_generic.c:1.25)
3096 * select(2) documents how to allocate fd_set dynamically.
3097 * http://netbsd.gw.com/cgi-bin/man-cgi?select++NetBSD-4.0
3098 * - FreeBSD 2.2 (src/sys/kern/sys_generic.c:1.19)
3099 * - OpenBSD 2.0 (src/sys/kern/sys_generic.c:1.4)
3100 * select(2) documents how to allocate fd_set dynamically.
3101 * http://www.openbsd.org/cgi-bin/man.cgi?query=select&manpath=OpenBSD+4.4
3102 * - HP-UX documents how to allocate fd_set dynamically.
3103 * http://docs.hp.com/en/B2355-60105/select.2.html
3104 * - Solaris 8 has select_large_fdset
3105 * - Mac OS X 10.7 (Lion)
3106 * select(2) returns EINVAL if nfds is greater than FD_SET_SIZE and
3107 * _DARWIN_UNLIMITED_SELECT (or _DARWIN_C_SOURCE) isn't defined.
3108 * http://developer.apple.com/library/mac/#releasenotes/Darwin/SymbolVariantsRelNotes/_index.html
3109 *
3110 * When fd_set is not big enough to hold big file descriptors,
3111 * it should be allocated dynamically.
3112 * Note that this assumes fd_set is structured as bitmap.
3113 *
3114 * rb_fd_init allocates the memory.
3115 * rb_fd_term free the memory.
3116 * rb_fd_set may re-allocates bitmap.
3117 *
3118 * So rb_fd_set doesn't reject file descriptors bigger than FD_SETSIZE.
3119 */
3120
3121 void
3122 rb_fd_init(rb_fdset_t *fds)
3123 {
3124 fds->maxfd = 0;
3125 fds->fdset = ALLOC(fd_set);
3126 FD_ZERO(fds->fdset);
3127 }
3128
3129 void
3130 rb_fd_init_copy(rb_fdset_t *dst, rb_fdset_t *src)
3131 {
3132 size_t size = howmany(rb_fd_max(src), NFDBITS) * sizeof(fd_mask);
3133
3134 if (size < sizeof(fd_set))
3135 size = sizeof(fd_set);
3136 dst->maxfd = src->maxfd;
3137 dst->fdset = xmalloc(size);
3138 memcpy(dst->fdset, src->fdset, size);
3139 }
3140
3141 void
3142 rb_fd_term(rb_fdset_t *fds)
3143 {
3144 if (fds->fdset) xfree(fds->fdset);
3145 fds->maxfd = 0;
3146 fds->fdset = 0;
3147 }
3148
3149 void
3150 rb_fd_zero(rb_fdset_t *fds)
3151 {
3152 if (fds->fdset)
3153 MEMZERO(fds->fdset, fd_mask, howmany(fds->maxfd, NFDBITS));
3154 }
3155
3156 static void
3157 rb_fd_resize(int n, rb_fdset_t *fds)
3158 {
3159 size_t m = howmany(n + 1, NFDBITS) * sizeof(fd_mask);
3160 size_t o = howmany(fds->maxfd, NFDBITS) * sizeof(fd_mask);
3161
3162 if (m < sizeof(fd_set)) m = sizeof(fd_set);
3163 if (o < sizeof(fd_set)) o = sizeof(fd_set);
3164
3165 if (m > o) {
3166 fds->fdset = xrealloc(fds->fdset, m);
3167 memset((char *)fds->fdset + o, 0, m - o);
3168 }
3169 if (n >= fds->maxfd) fds->maxfd = n + 1;
3170 }
3171
3172 void
3173 rb_fd_set(int n, rb_fdset_t *fds)
3174 {
3175 rb_fd_resize(n, fds);
3176 FD_SET(n, fds->fdset);
3177 }
3178
3179 void
3180 rb_fd_clr(int n, rb_fdset_t *fds)
3181 {
3182 if (n >= fds->maxfd) return;
3183 FD_CLR(n, fds->fdset);
3184 }
3185
3186 int
3187 rb_fd_isset(int n, const rb_fdset_t *fds)
3188 {
3189 if (n >= fds->maxfd) return 0;
3190 return FD_ISSET(n, fds->fdset) != 0; /* "!= 0" avoids FreeBSD PR 91421 */
3191 }
3192
3193 void
3194 rb_fd_copy(rb_fdset_t *dst, const fd_set *src, int max)
3195 {
3196 size_t size = howmany(max, NFDBITS) * sizeof(fd_mask);
3197
3198 if (size < sizeof(fd_set)) size = sizeof(fd_set);
3199 dst->maxfd = max;
3200 dst->fdset = xrealloc(dst->fdset, size);
3201 memcpy(dst->fdset, src, size);
3202 }
3203
3204 static void
3205 rb_fd_rcopy(fd_set *dst, rb_fdset_t *src)
3206 {
3207 size_t size = howmany(rb_fd_max(src), NFDBITS) * sizeof(fd_mask);
3208
3209 if (size > sizeof(fd_set)) {
3210 rb_raise(rb_eArgError, "too large fdsets");
3211 }
3212 memcpy(dst, rb_fd_ptr(src), sizeof(fd_set));
3213 }
3214
3215 void
3216 rb_fd_dup(rb_fdset_t *dst, const rb_fdset_t *src)
3217 {
3218 size_t size = howmany(rb_fd_max(src), NFDBITS) * sizeof(fd_mask);
3219
3220 if (size < sizeof(fd_set))
3221 size = sizeof(fd_set);
3222 dst->maxfd = src->maxfd;
3223 dst->fdset = xrealloc(dst->fdset, size);
3224 memcpy(dst->fdset, src->fdset, size);
3225 }
3226
3227 #ifdef __native_client__
3228 int select(int nfds, fd_set *readfds, fd_set *writefds,
3229 fd_set *exceptfds, struct timeval *timeout);
3230 #endif
3231
3232 int
3233 rb_fd_select(int n, rb_fdset_t *readfds, rb_fdset_t *writefds, rb_fdset_t *exceptfds, struct timeval *timeout)
3234 {
3235 fd_set *r = NULL, *w = NULL, *e = NULL;
3236 if (readfds) {
3237 rb_fd_resize(n - 1, readfds);
3238 r = rb_fd_ptr(readfds);
3239 }
3240 if (writefds) {
3241 rb_fd_resize(n - 1, writefds);
3242 w = rb_fd_ptr(writefds);
3243 }
3244 if (exceptfds) {
3245 rb_fd_resize(n - 1, exceptfds);
3246 e = rb_fd_ptr(exceptfds);
3247 }
3248 return select(n, r, w, e, timeout);
3249 }
3250
3251 #undef FD_ZERO
3252 #undef FD_SET
3253 #undef FD_CLR
3254 #undef FD_ISSET
3255
3256 #define FD_ZERO(f) rb_fd_zero(f)
3257 #define FD_SET(i, f) rb_fd_set((i), (f))
3258 #define FD_CLR(i, f) rb_fd_clr((i), (f))
3259 #define FD_ISSET(i, f) rb_fd_isset((i), (f))
3260
3261 #elif defined(_WIN32)
3262
3263 void
3264 rb_fd_init(rb_fdset_t *set)
3265 {
3266 set->capa = FD_SETSIZE;
3267 set->fdset = ALLOC(fd_set);
3268 FD_ZERO(set->fdset);
3269 }
3270
3271 void
3272 rb_fd_init_copy(rb_fdset_t *dst, rb_fdset_t *src)
3273 {
3274 rb_fd_init(dst);
3275 rb_fd_dup(dst, src);
3276 }
3277
3278 static void
3279 rb_fd_rcopy(fd_set *dst, rb_fdset_t *src)
3280 {
3281 int max = rb_fd_max(src);
3282
3283 /* we assume src is the result of select() with dst, so dst should be
3284 * larger or equal than src. */
3285 if (max > FD_SETSIZE || (UINT)max > dst->fd_count) {
3286 rb_raise(rb_eArgError, "too large fdsets");
3287 }
3288
3289 memcpy(dst->fd_array, src->fdset->fd_array, max);
3290 dst->fd_count = max;
3291 }
3292
3293 void
3294 rb_fd_term(rb_fdset_t *set)
3295 {
3296 xfree(set->fdset);
3297 set->fdset = NULL;
3298 set->capa = 0;
3299 }
3300
3301 void
3302 rb_fd_set(int fd, rb_fdset_t *set)
3303 {
3304 unsigned int i;
3305 SOCKET s = rb_w32_get_osfhandle(fd);
3306
3307 for (i = 0; i < set->fdset->fd_count; i++) {
3308 if (set->fdset->fd_array[i] == s) {
3309 return;
3310 }
3311 }
3312 if (set->fdset->fd_count >= (unsigned)set->capa) {
3313 set->capa = (set->fdset->fd_count / FD_SETSIZE + 1) * FD_SETSIZE;
3314 set->fdset = xrealloc(set->fdset, sizeof(unsigned int) + sizeof(SOCKET) * set->capa);
3315 }
3316 set->fdset->fd_array[set->fdset->fd_count++] = s;
3317 }
3318
3319 #undef FD_ZERO
3320 #undef FD_SET
3321 #undef FD_CLR
3322 #undef FD_ISSET
3323
3324 #define FD_ZERO(f) rb_fd_zero(f)
3325 #define FD_SET(i, f) rb_fd_set((i), (f))
3326 #define FD_CLR(i, f) rb_fd_clr((i), (f))
3327 #define FD_ISSET(i, f) rb_fd_isset((i), (f))
3328
3329 #else
3330 #define rb_fd_rcopy(d, s) (*(d) = *(s))
3331 #endif
3332
3333 static int
3334 do_select(int n, rb_fdset_t *read, rb_fdset_t *write, rb_fdset_t *except,
3335 struct timeval *timeout)
3336 {
3337 int UNINITIALIZED_VAR(result);
3338 int lerrno;
3339 rb_fdset_t UNINITIALIZED_VAR(orig_read);
3340 rb_fdset_t UNINITIALIZED_VAR(orig_write);
3341 rb_fdset_t UNINITIALIZED_VAR(orig_except);
3342 double limit = 0;
3343 struct timeval wait_rest;
3344 rb_thread_t *th = GET_THREAD();
3345
3346 if (timeout) {
3347 limit = timeofday();
3348 limit += (double)timeout->tv_sec+(double)timeout->tv_usec*1e-6;
3349 wait_rest = *timeout;
3350 timeout = &wait_rest;
3351 }
3352
3353 if (read)
3354 rb_fd_init_copy(&orig_read, read);
3355 if (write)
3356 rb_fd_init_copy(&orig_write, write);
3357 if (except)
3358 rb_fd_init_copy(&orig_except, except);
3359
3360 retry:
3361 lerrno = 0;
3362
3363 BLOCKING_REGION({
3364 result = native_fd_select(n, read, write, except, timeout, th);
3365 if (result < 0) lerrno = errno;
3366 }, ubf_select, th, FALSE);
3367
3368 RUBY_VM_CHECK_INTS_BLOCKING(th);
3369
3370 errno = lerrno;
3371
3372 if (result < 0) {
3373 switch (errno) {
3374 case EINTR:
3375 #ifdef ERESTART
3376 case ERESTART:
3377 #endif
3378 if (read)
3379 rb_fd_dup(read, &orig_read);
3380 if (write)
3381 rb_fd_dup(write, &orig_write);
3382 if (except)
3383 rb_fd_dup(except, &orig_except);
3384
3385 if (timeout) {
3386 double d = limit - timeofday();
3387
3388 wait_rest.tv_sec = (time_t)d;
3389 wait_rest.tv_usec = (int)((d-(double)wait_rest.tv_sec)*1e6);
3390 if (wait_rest.tv_sec < 0) wait_rest.tv_sec = 0;
3391 if (wait_rest.tv_usec < 0) wait_rest.tv_usec = 0;
3392 }
3393
3394 goto retry;
3395 default:
3396 break;
3397 }
3398 }
3399
3400 if (read)
3401 rb_fd_term(&orig_read);
3402 if (write)
3403 rb_fd_term(&orig_write);
3404 if (except)
3405 rb_fd_term(&orig_except);
3406
3407 return result;
3408 }
3409
3410 static void
3411 rb_thread_wait_fd_rw(int fd, int read)
3412 {
3413 int result = 0;
3414 int events = read ? RB_WAITFD_IN : RB_WAITFD_OUT;
3415
3416 thread_debug("rb_thread_wait_fd_rw(%d, %s)\n", fd, read ? "read" : "write");
3417
3418 if (fd < 0) {
3419 rb_raise(rb_eIOError, "closed stream");
3420 }
3421
3422 result = rb_wait_for_single_fd(fd, events, NULL);
3423 if (result < 0) {
3424 rb_sys_fail(0);
3425 }
3426
3427 thread_debug("rb_thread_wait_fd_rw(%d, %s): done\n", fd, read ? "read" : "write");
3428 }
3429
3430 void
3431 rb_thread_wait_fd(int fd)
3432 {
3433 rb_thread_wait_fd_rw(fd, 1);
3434 }
3435
3436 int
3437 rb_thread_fd_writable(int fd)
3438 {
3439 rb_thread_wait_fd_rw(fd, 0);
3440 return TRUE;
3441 }
3442
3443 int
3444 rb_thread_select(int max, fd_set * read, fd_set * write, fd_set * except,
3445 struct timeval *timeout)
3446 {
3447 rb_fdset_t fdsets[3];
3448 rb_fdset_t *rfds = NULL;
3449 rb_fdset_t *wfds = NULL;
3450 rb_fdset_t *efds = NULL;
3451 int retval;
3452
3453 if (read) {
3454 rfds = &fdsets[0];
3455 rb_fd_init(rfds);
3456 rb_fd_copy(rfds, read, max);
3457 }
3458 if (write) {
3459 wfds = &fdsets[1];
3460 rb_fd_init(wfds);
3461 rb_fd_copy(wfds, write, max);
3462 }
3463 if (except) {
3464 efds = &fdsets[2];
3465 rb_fd_init(efds);
3466 rb_fd_copy(efds, except, max);
3467 }
3468
3469 retval = rb_thread_fd_select(max, rfds, wfds, efds, timeout);
3470
3471 if (rfds) {
3472 rb_fd_rcopy(read, rfds);
3473 rb_fd_term(rfds);
3474 }
3475 if (wfds) {
3476 rb_fd_rcopy(write, wfds);
3477 rb_fd_term(wfds);
3478 }
3479 if (efds) {
3480 rb_fd_rcopy(except, efds);
3481 rb_fd_term(efds);
3482 }
3483
3484 return retval;
3485 }
3486
3487 int
3488 rb_thread_fd_select(int max, rb_fdset_t * read, rb_fdset_t * write, rb_fdset_t * except,
3489 struct timeval *timeout)
3490 {
3491 if (!read && !write && !except) {
3492 if (!timeout) {
3493 rb_thread_sleep_forever();
3494 return 0;
3495 }
3496 rb_thread_wait_for(*timeout);
3497 return 0;
3498 }
3499
3500 if (read) {
3501 rb_fd_resize(max - 1, read);
3502 }
3503 if (write) {
3504 rb_fd_resize(max - 1, write);
3505 }
3506 if (except) {
3507 rb_fd_resize(max - 1, except);
3508 }
3509 return do_select(max, read, write, except, timeout);
3510 }
3511
3512 /*
3513 * poll() is supported by many OSes, but so far Linux is the only
3514 * one we know of that supports using poll() in all places select()
3515 * would work.
3516 */
3517 #if defined(HAVE_POLL) && defined(__linux__)
3518 # define USE_POLL
3519 #endif
3520
3521 #ifdef USE_POLL
3522
3523 /* The same with linux kernel. TODO: make platform independent definition. */
3524 #define POLLIN_SET (POLLRDNORM | POLLRDBAND | POLLIN | POLLHUP | POLLERR)
3525 #define POLLOUT_SET (POLLWRBAND | POLLWRNORM | POLLOUT | POLLERR)
3526 #define POLLEX_SET (POLLPRI)
3527
3528 #ifndef HAVE_PPOLL
3529 /* TODO: don't ignore sigmask */
3530 int
3531 ppoll(struct pollfd *fds, nfds_t nfds,
3532 const struct timespec *ts, const sigset_t *sigmask)
3533 {
3534 int timeout_ms;
3535
3536 if (ts) {
3537 int tmp, tmp2;
3538
3539 if (ts->tv_sec > TIMET_MAX/1000)
3540 timeout_ms = -1;
3541 else {
3542 tmp = ts->tv_sec * 1000;
3543 tmp2 = ts->tv_nsec / (1000 * 1000);
3544 if (TIMET_MAX - tmp < tmp2)
3545 timeout_ms = -1;
3546 else
3547 timeout_ms = tmp + tmp2;
3548 }
3549 }
3550 else
3551 timeout_ms = -1;
3552
3553 return poll(fds, nfds, timeout_ms);
3554 }
3555 #endif
3556
3557 /*
3558 * returns a mask of events
3559 */
3560 int
3561 rb_wait_for_single_fd(int fd, int events, struct timeval *tv)
3562 {
3563 struct pollfd fds;
3564 int result = 0, lerrno;
3565 double limit = 0;
3566 struct timespec ts;
3567 struct timespec *timeout = NULL;
3568 rb_thread_t *th = GET_THREAD();
3569
3570 if (tv) {
3571 ts.tv_sec = tv->tv_sec;
3572 ts.tv_nsec = tv->tv_usec * 1000;
3573 limit = timeofday();
3574 limit += (double)tv->tv_sec + (double)tv->tv_usec * 1e-6;
3575 timeout = &ts;
3576 }
3577
3578 fds.fd = fd;
3579 fds.events = (short)events;
3580
3581 retry:
3582 lerrno = 0;
3583 BLOCKING_REGION({
3584 result = ppoll(&fds, 1, timeout, NULL);
3585 if (result < 0) lerrno = errno;
3586 }, ubf_select, th, FALSE);
3587
3588 RUBY_VM_CHECK_INTS_BLOCKING(th);
3589
3590 if (result < 0) {
3591 errno = lerrno;
3592 switch (errno) {
3593 case EINTR:
3594 #ifdef ERESTART
3595 case ERESTART:
3596 #endif
3597 if (timeout) {
3598 double d = limit - timeofday();
3599
3600 ts.tv_sec = (long)d;
3601 ts.tv_nsec = (long)((d - (double)ts.tv_sec) * 1e9);
3602 if (ts.tv_sec < 0)
3603 ts.tv_sec = 0;
3604 if (ts.tv_nsec < 0)
3605 ts.tv_nsec = 0;
3606 }
3607 goto retry;
3608 }
3609 return -1;
3610 }
3611
3612 if (fds.revents & POLLNVAL) {
3613 errno = EBADF;
3614 return -1;
3615 }
3616
3617 /*
3618 * POLLIN, POLLOUT have a different meanings from select(2)'s read/write bit.
3619 * Therefore we need fix it up.
3620 */
3621 result = 0;
3622 if (fds.revents & POLLIN_SET)
3623 result |= RB_WAITFD_IN;
3624 if (fds.revents & POLLOUT_SET)
3625 result |= RB_WAITFD_OUT;
3626 if (fds.revents & POLLEX_SET)
3627 result |= RB_WAITFD_PRI;
3628
3629 return result;
3630 }
3631 #else /* ! USE_POLL - implement rb_io_poll_fd() using select() */
3632 static rb_fdset_t *
3633 init_set_fd(int fd, rb_fdset_t *fds)
3634 {
3635 rb_fd_init(fds);
3636 rb_fd_set(fd, fds);
3637
3638 return fds;
3639 }
3640
3641 struct select_args {
3642 union {
3643 int fd;
3644 int error;
3645 } as;
3646 rb_fdset_t *read;
3647 rb_fdset_t *write;
3648 rb_fdset_t *except;
3649 struct timeval *tv;
3650 };
3651
3652 static VALUE
3653 select_single(VALUE ptr)
3654 {
3655 struct select_args *args = (struct select_args *)ptr;
3656 int r;
3657
3658 r = rb_thread_fd_select(args->as.fd + 1,
3659 args->read, args->write, args->except, args->tv);
3660 if (r == -1)
3661 args->as.error = errno;
3662 if (r > 0) {
3663 r = 0;
3664 if (args->read && rb_fd_isset(args->as.fd, args->read))
3665 r |= RB_WAITFD_IN;
3666 if (args->write && rb_fd_isset(args->as.fd, args->write))
3667 r |= RB_WAITFD_OUT;
3668 if (args->except && rb_fd_isset(args->as.fd, args->except))
3669 r |= RB_WAITFD_PRI;
3670 }
3671 return (VALUE)r;
3672 }
3673
3674 static VALUE
3675 select_single_cleanup(VALUE ptr)
3676 {
3677 struct select_args *args = (struct select_args *)ptr;
3678
3679 if (args->read) rb_fd_term(args->read);
3680 if (args->write) rb_fd_term(args->write);
3681 if (args->except) rb_fd_term(args->except);
3682
3683 return (VALUE)-1;
3684 }
3685
3686 int
3687 rb_wait_for_single_fd(int fd, int events, struct timeval *tv)
3688 {
3689 rb_fdset_t rfds, wfds, efds;
3690 struct select_args args;
3691 int r;
3692 VALUE ptr = (VALUE)&args;
3693
3694 args.as.fd = fd;
3695 args.read = (events & RB_WAITFD_IN) ? init_set_fd(fd, &rfds) : NULL;
3696 args.write = (events & RB_WAITFD_OUT) ? init_set_fd(fd, &wfds) : NULL;
3697 args.except = (events & RB_WAITFD_PRI) ? init_set_fd(fd, &efds) : NULL;
3698 args.tv = tv;
3699
3700 r = (int)rb_ensure(select_single, ptr, select_single_cleanup, ptr);
3701 if (r == -1)
3702 errno = args.as.error;
3703
3704 return r;
3705 }
3706 #endif /* ! USE_POLL */
3707
3708 /*
3709 * for GC
3710 */
3711
3712 #ifdef USE_CONSERVATIVE_STACK_END
3713 void
3714 rb_gc_set_stack_end(VALUE **stack_end_p)
3715 {
3716 VALUE stack_end;
3717 *stack_end_p = &stack_end;
3718 }
3719 #endif
3720
3721
3722 /*
3723 *
3724 */
3725
3726 void
3727 rb_threadptr_check_signal(rb_thread_t *mth)
3728 {
3729 /* mth must be main_thread */
3730 if (rb_signal_buff_size() > 0) {
3731 /* wakeup main thread */
3732 rb_threadptr_trap_interrupt(mth);
3733 }
3734 }
3735
3736 static void
3737 timer_thread_function(void *arg)
3738 {
3739 rb_vm_t *vm = GET_VM(); /* TODO: fix me for Multi-VM */
3740
3741 /*
3742 * Tricky: thread_destruct_lock doesn't close a race against
3743 * vm->running_thread switch. however it guarantee th->running_thread
3744 * point to valid pointer or NULL.
3745 */
3746 native_mutex_lock(&vm->thread_destruct_lock);
3747 /* for time slice */
3748 if (vm->running_thread)
3749 RUBY_VM_SET_TIMER_INTERRUPT(vm->running_thread);
3750 native_mutex_unlock(&vm->thread_destruct_lock);
3751
3752 /* check signal */
3753 rb_threadptr_check_signal(vm->main_thread);
3754
3755 #if 0
3756 /* prove profiler */
3757 if (vm->prove_profile.enable) {
3758 rb_thread_t *th = vm->running_thread;
3759
3760 if (vm->during_gc) {
3761 /* GC prove profiling */
3762 }
3763 }
3764 #endif
3765 }
3766
3767 void
3768 rb_thread_stop_timer_thread(int close_anyway)
3769 {
3770 if (timer_thread_id && native_stop_timer_thread(close_anyway)) {
3771 native_reset_timer_thread();
3772 }
3773 }
3774
3775 void
3776 rb_thread_reset_timer_thread(void)
3777 {
3778 native_reset_timer_thread();
3779 }
3780
3781 void
3782 rb_thread_start_timer_thread(void)
3783 {
3784 system_working = 1;
3785 rb_thread_create_timer_thread();
3786 }
3787
3788 static int
3789 clear_coverage_i(st_data_t key, st_data_t val, st_data_t dummy)
3790 {
3791 int i;
3792 VALUE lines = (VALUE)val;
3793
3794 for (i = 0; i < RARRAY_LEN(lines); i++) {
3795 if (RARRAY_PTR(lines)[i] != Qnil) {
3796 RARRAY_PTR(lines)[i] = INT2FIX(0);
3797 }
3798 }
3799 return ST_CONTINUE;
3800 }
3801
3802 static void
3803 clear_coverage(void)
3804 {
3805 VALUE coverages = rb_get_coverages();
3806 if (RTEST(coverages)) {
3807 st_foreach(RHASH_TBL(coverages), clear_coverage_i, 0);
3808 }
3809 }
3810
3811 static void
3812 rb_thread_atfork_internal(int (*atfork)(st_data_t, st_data_t, st_data_t))
3813 {
3814 rb_thread_t *th = GET_THREAD();
3815 rb_vm_t *vm = th->vm;
3816 VALUE thval = th->self;
3817 vm->main_thread = th;
3818
3819 gvl_atfork(th->vm);
3820 st_foreach(vm->living_threads, atfork, (st_data_t)th);
3821 st_clear(vm->living_threads);
3822 st_insert(vm->living_threads, thval, (st_data_t)th->thread_id);
3823 vm->sleeper = 0;
3824 clear_coverage();
3825 }
3826
3827 static int
3828 terminate_atfork_i(st_data_t key, st_data_t val, st_data_t current_th)
3829 {
3830 VALUE thval = key;
3831 rb_thread_t *th;
3832 GetThreadPtr(thval, th);
3833
3834 if (th != (rb_thread_t *)current_th) {
3835 if (th->keeping_mutexes) {
3836 rb_mutex_abandon_all(th->keeping_mutexes);
3837 }
3838 th->keeping_mutexes = NULL;
3839 thread_cleanup_func(th, TRUE);
3840 }
3841 return ST_CONTINUE;
3842 }
3843
3844 void
3845 rb_thread_atfork(void)
3846 {
3847 rb_thread_atfork_internal(terminate_atfork_i);
3848 GET_THREAD()->join_list = NULL;
3849
3850 /* We don't want reproduce CVE-2003-0900. */
3851 rb_reset_random_seed();
3852 }
3853
3854 static int
3855 terminate_atfork_before_exec_i(st_data_t key, st_data_t val, st_data_t current_th)
3856 {
3857 VALUE thval = key;
3858 rb_thread_t *th;
3859 GetThreadPtr(thval, th);
3860
3861 if (th != (rb_thread_t *)current_th) {
3862 thread_cleanup_func_before_exec(th);
3863 }
3864 return ST_CONTINUE;
3865 }
3866
3867 void
3868 rb_thread_atfork_before_exec(void)
3869 {
3870 rb_thread_atfork_internal(terminate_atfork_before_exec_i);
3871 }
3872
3873 struct thgroup {
3874 int enclosed;
3875 VALUE group;
3876 };
3877
3878 static size_t
3879 thgroup_memsize(const void *ptr)
3880 {
3881 return ptr ? sizeof(struct thgroup) : 0;
3882 }
3883
3884 static const rb_data_type_t thgroup_data_type = {
3885 "thgroup",
3886 {NULL, RUBY_TYPED_DEFAULT_FREE, thgroup_memsize,},
3887 };
3888
3889 /*
3890 * Document-class: ThreadGroup
3891 *
3892 * <code>ThreadGroup</code> provides a means of keeping track of a number of
3893 * threads as a group. A <code>Thread</code> can belong to only one
3894 * <code>ThreadGroup</code> at a time; adding a thread to a new group will
3895 * remove it from any previous group.
3896 *
3897 * Newly created threads belong to the same group as the thread from which they
3898 * were created.
3899 */
3900
3901 /*
3902 * Document-const: Default
3903 *
3904 * The default ThreadGroup created when Ruby starts; all Threads belong to it
3905 * by default.
3906 */
3907 static VALUE
3908 thgroup_s_alloc(VALUE klass)
3909 {
3910 VALUE group;
3911 struct thgroup *data;
3912
3913 group = TypedData_Make_Struct(klass, struct thgroup, &thgroup_data_type, data);
3914 data->enclosed = 0;
3915 data->group = group;
3916
3917 return group;
3918 }
3919
3920 struct thgroup_list_params {
3921 VALUE ary;
3922 VALUE group;
3923 };
3924
3925 static int
3926 thgroup_list_i(st_data_t key, st_data_t val, st_data_t data)
3927 {
3928 VALUE thread = (VALUE)key;
3929 VALUE ary = ((struct thgroup_list_params *)data)->ary;
3930 VALUE group = ((struct thgroup_list_params *)data)->group;
3931 rb_thread_t *th;
3932 GetThreadPtr(thread, th);
3933
3934 if (th->thgroup == group) {
3935 rb_ary_push(ary, thread);
3936 }
3937 return ST_CONTINUE;
3938 }
3939
3940 /*
3941 * call-seq:
3942 * thgrp.list -> array
3943 *
3944 * Returns an array of all existing <code>Thread</code> objects that belong to
3945 * this group.
3946 *
3947 * ThreadGroup::Default.list #=> [#<Thread:0x401bdf4c run>]
3948 */
3949
3950 static VALUE
3951 thgroup_list(VALUE group)
3952 {
3953 VALUE ary = rb_ary_new();
3954 struct thgroup_list_params param;
3955
3956 param.ary = ary;
3957 param.group = group;
3958 st_foreach(GET_THREAD()->vm->living_threads, thgroup_list_i, (st_data_t) & param);
3959 return ary;
3960 }
3961
3962
3963 /*
3964 * call-seq:
3965 * thgrp.enclose -> thgrp
3966 *
3967 * Prevents threads from being added to or removed from the receiving
3968 * <code>ThreadGroup</code>. New threads can still be started in an enclosed
3969 * <code>ThreadGroup</code>.
3970 *
3971 * ThreadGroup::Default.enclose #=> #<ThreadGroup:0x4029d914>
3972 * thr = Thread::new { Thread.stop } #=> #<Thread:0x402a7210 sleep>
3973 * tg = ThreadGroup::new #=> #<ThreadGroup:0x402752d4>
3974 * tg.add thr
3975 *
3976 * <em>produces:</em>
3977 *
3978 * ThreadError: can't move from the enclosed thread group
3979 */
3980
3981 static VALUE
3982 thgroup_enclose(VALUE group)
3983 {
3984 struct thgroup *data;
3985
3986 TypedData_Get_Struct(group, struct thgroup, &thgroup_data_type, data);
3987 data->enclosed = 1;
3988
3989 return group;
3990 }
3991
3992
3993 /*
3994 * call-seq:
3995 * thgrp.enclosed? -> true or false
3996 *
3997 * Returns <code>true</code> if <em>thgrp</em> is enclosed. See also
3998 * ThreadGroup#enclose.
3999 */
4000
4001 static VALUE
4002 thgroup_enclosed_p(VALUE group)
4003 {
4004 struct thgroup *data;
4005
4006 TypedData_Get_Struct(group, struct thgroup, &thgroup_data_type, data);
4007 if (data->enclosed)
4008 return Qtrue;
4009 return Qfalse;
4010 }
4011
4012
4013 /*
4014 * call-seq:
4015 * thgrp.add(thread) -> thgrp
4016 *
4017 * Adds the given <em>thread</em> to this group, removing it from any other
4018 * group to which it may have previously belonged.
4019 *
4020 * puts "Initial group is #{ThreadGroup::Default.list}"
4021 * tg = ThreadGroup.new
4022 * t1 = Thread.new { sleep }
4023 * t2 = Thread.new { sleep }
4024 * puts "t1 is #{t1}"
4025 * puts "t2 is #{t2}"
4026 * tg.add(t1)
4027 * puts "Initial group now #{ThreadGroup::Default.list}"
4028 * puts "tg group now #{tg.list}"
4029 *
4030 * <em>produces:</em>
4031 *
4032 * Initial group is #<Thread:0x401bdf4c>
4033 * t1 is #<Thread:0x401b3c90>
4034 * t2 is #<Thread:0x401b3c18>
4035 * Initial group now #<Thread:0x401b3c18>#<Thread:0x401bdf4c>
4036 * tg group now #<Thread:0x401b3c90>
4037 */
4038
4039 static VALUE
4040 thgroup_add(VALUE group, VALUE thread)
4041 {
4042 rb_thread_t *th;
4043 struct thgroup *data;
4044
4045 rb_secure(4);
4046 GetThreadPtr(thread, th);
4047
4048 if (OBJ_FROZEN(group)) {
4049 rb_raise(rb_eThreadError, "can't move to the frozen thread group");
4050 }
4051 TypedData_Get_Struct(group, struct thgroup, &thgroup_data_type, data);
4052 if (data->enclosed) {
4053 rb_raise(rb_eThreadError, "can't move to the enclosed thread group");
4054 }
4055
4056 if (!th->thgroup) {
4057 return Qnil;
4058 }
4059
4060 if (OBJ_FROZEN(th->thgroup)) {
4061 rb_raise(rb_eThreadError, "can't move from the frozen thread group");
4062 }
4063 TypedData_Get_Struct(th->thgroup, struct thgroup, &thgroup_data_type, data);
4064 if (data->enclosed) {
4065 rb_raise(rb_eThreadError,
4066 "can't move from the enclosed thread group");
4067 }
4068
4069 th->thgroup = group;
4070 return group;
4071 }
4072
4073
4074 /*
4075 * Document-class: Mutex
4076 *
4077 * Mutex implements a simple semaphore that can be used to coordinate access to
4078 * shared data from multiple concurrent threads.
4079 *
4080 * Example:
4081 *
4082 * require 'thread'
4083 * semaphore = Mutex.new
4084 *
4085 * a = Thread.new {
4086 * semaphore.synchronize {
4087 * # access shared resource
4088 * }
4089 * }
4090 *
4091 * b = Thread.new {
4092 * semaphore.synchronize {
4093 * # access shared resource
4094 * }
4095 * }
4096 *
4097 */
4098
4099 #define GetMutexPtr(obj, tobj) \
4100 TypedData_Get_Struct((obj), rb_mutex_t, &mutex_data_type, (tobj))
4101
4102 static const char *rb_mutex_unlock_th(rb_mutex_t *mutex, rb_thread_t volatile *th);
4103
4104 #define mutex_mark NULL
4105
4106 static void
4107 mutex_free(void *ptr)
4108 {
4109 if (ptr) {
4110 rb_mutex_t *mutex = ptr;
4111 if (mutex->th) {
4112 /* rb_warn("free locked mutex"); */
4113 const char *err = rb_mutex_unlock_th(mutex, mutex->th);
4114 if (err) rb_bug("%s", err);
4115 }
4116 native_mutex_destroy(&mutex->lock);
4117 native_cond_destroy(&mutex->cond);
4118 }
4119 ruby_xfree(ptr);
4120 }
4121
4122 static size_t
4123 mutex_memsize(const void *ptr)
4124 {
4125 return ptr ? sizeof(rb_mutex_t) : 0;
4126 }
4127
4128 static const rb_data_type_t mutex_data_type = {
4129 "mutex",
4130 {mutex_mark, mutex_free, mutex_memsize,},
4131 };
4132
4133 VALUE
4134 rb_obj_is_mutex(VALUE obj)
4135 {
4136 if (rb_typeddata_is_kind_of(obj, &mutex_data_type)) {
4137 return Qtrue;
4138 }
4139 else {
4140 return Qfalse;
4141 }
4142 }
4143
4144 static VALUE
4145 mutex_alloc(VALUE klass)
4146 {
4147 VALUE volatile obj;
4148 rb_mutex_t *mutex;
4149
4150 obj = TypedData_Make_Struct(klass, rb_mutex_t, &mutex_data_type, mutex);
4151 native_mutex_initialize(&mutex->lock);
4152 native_cond_initialize(&mutex->cond, RB_CONDATTR_CLOCK_MONOTONIC);
4153 return obj;
4154 }
4155
4156 /*
4157 * call-seq:
4158 * Mutex.new -> mutex
4159 *
4160 * Creates a new Mutex
4161 */
4162 static VALUE
4163 mutex_initialize(VALUE self)
4164 {
4165 return self;
4166 }
4167
4168 VALUE
4169 rb_mutex_new(void)
4170 {
4171 return mutex_alloc(rb_cMutex);
4172 }
4173
4174 /*
4175 * call-seq:
4176 * mutex.locked? -> true or false
4177 *
4178 * Returns +true+ if this lock is currently held by some thread.
4179 */
4180 VALUE
4181 rb_mutex_locked_p(VALUE self)
4182 {
4183 rb_mutex_t *mutex;
4184 GetMutexPtr(self, mutex);
4185 return mutex->th ? Qtrue : Qfalse;
4186 }
4187
4188 static void
4189 mutex_locked(rb_thread_t *th, VALUE self)
4190 {
4191 rb_mutex_t *mutex;
4192 GetMutexPtr(self, mutex);
4193
4194 if (th->keeping_mutexes) {
4195 mutex->next_mutex = th->keeping_mutexes;
4196 }
4197 th->keeping_mutexes = mutex;
4198 }
4199
4200 /*
4201 * call-seq:
4202 * mutex.try_lock -> true or false
4203 *
4204 * Attempts to obtain the lock and returns immediately. Returns +true+ if the
4205 * lock was granted.
4206 */
4207 VALUE
4208 rb_mutex_trylock(VALUE self)
4209 {
4210 rb_mutex_t *mutex;
4211 VALUE locked = Qfalse;
4212 GetMutexPtr(self, mutex);
4213
4214 native_mutex_lock(&mutex->lock);
4215 if (mutex->th == 0) {
4216 mutex->th = GET_THREAD();
4217 locked = Qtrue;
4218
4219 mutex_locked(GET_THREAD(), self);
4220 }
4221 native_mutex_unlock(&mutex->lock);
4222
4223 return locked;
4224 }
4225
4226 static int
4227 lock_func(rb_thread_t *th, rb_mutex_t *mutex, int timeout_ms)
4228 {
4229 int interrupted = 0;
4230 int err = 0;
4231
4232 mutex->cond_waiting++;
4233 for (;;) {
4234 if (!mutex->th) {
4235 mutex->th = th;
4236 break;
4237 }
4238 if (RUBY_VM_INTERRUPTED(th)) {
4239 interrupted = 1;
4240 break;
4241 }
4242 if (err == ETIMEDOUT) {
4243 interrupted = 2;
4244 break;
4245 }
4246
4247 if (timeout_ms) {
4248 struct timespec timeout_rel;
4249 struct timespec timeout;
4250
4251 timeout_rel.tv_sec = 0;
4252 timeout_rel.tv_nsec = timeout_ms * 1000 * 1000;
4253 timeout = native_cond_timeout(&mutex->cond, timeout_rel);
4254 err = native_cond_timedwait(&mutex->cond, &mutex->lock, &timeout);
4255 }
4256 else {
4257 native_cond_wait(&mutex->cond, &mutex->lock);
4258 err = 0;
4259 }
4260 }
4261 mutex->cond_waiting--;
4262
4263 return interrupted;
4264 }
4265
4266 static void
4267 lock_interrupt(void *ptr)
4268 {
4269 rb_mutex_t *mutex = (rb_mutex_t *)ptr;
4270 native_mutex_lock(&mutex->lock);
4271 if (mutex->cond_waiting > 0)
4272 native_cond_broadcast(&mutex->cond);
4273 native_mutex_unlock(&mutex->lock);
4274 }
4275
4276 /*
4277 * At maximum, only one thread can use cond_timedwait and watch deadlock
4278 * periodically. Multiple polling thread (i.e. concurrent deadlock check)
4279 * introduces new race conditions. [Bug #6278] [ruby-core:44275]
4280 */
4281 static const rb_thread_t *patrol_thread = NULL;
4282
4283 /*
4284 * call-seq:
4285 * mutex.lock -> self
4286 *
4287 * Attempts to grab the lock and waits if it isn't available.
4288 * Raises +ThreadError+ if +mutex+ was locked by the current thread.
4289 */
4290 VALUE
4291 rb_mutex_lock(VALUE self)
4292 {
4293 rb_thread_t *th = GET_THREAD();
4294 rb_mutex_t *mutex;
4295 GetMutexPtr(self, mutex);
4296
4297 /* When running trap handler */
4298 if (!mutex->allow_trap && th->interrupt_mask & TRAP_INTERRUPT_MASK) {
4299 rb_raise(rb_eThreadError, "can't be called from trap context");
4300 }
4301
4302 if (rb_mutex_trylock(self) == Qfalse) {
4303 if (mutex->th == GET_THREAD()) {
4304 rb_raise(rb_eThreadError, "deadlock; recursive locking");
4305 }
4306
4307 while (mutex->th != th) {
4308 int interrupted;
4309 enum rb_thread_status prev_status = th->status;
4310 volatile int timeout_ms = 0;
4311 struct rb_unblock_callback oldubf;
4312
4313 set_unblock_function(th, lock_interrupt, mutex, &oldubf, FALSE);
4314 th->status = THREAD_STOPPED_FOREVER;
4315 th->locking_mutex = self;
4316
4317 native_mutex_lock(&mutex->lock);
4318 th->vm->sleeper++;
4319 /*
4320 * Carefully! while some contended threads are in lock_func(),
4321 * vm->sleepr is unstable value. we have to avoid both deadlock
4322 * and busy loop.
4323 */
4324 if ((vm_living_thread_num(th->vm) == th->vm->sleeper) &&
4325 !patrol_thread) {
4326 timeout_ms = 100;
4327 patrol_thread = th;
4328 }
4329
4330 GVL_UNLOCK_BEGIN();
4331 interrupted = lock_func(th, mutex, (int)timeout_ms);
4332 native_mutex_unlock(&mutex->lock);
4333 GVL_UNLOCK_END();
4334
4335 if (patrol_thread == th)
4336 patrol_thread = NULL;
4337
4338 reset_unblock_function(th, &oldubf);
4339
4340 th->locking_mutex = Qfalse;
4341 if (mutex->th && interrupted == 2) {
4342 rb_check_deadlock(th->vm);
4343 }
4344 if (th->status == THREAD_STOPPED_FOREVER) {
4345 th->status = prev_status;
4346 }
4347 th->vm->sleeper--;
4348
4349 if (mutex->th == th) mutex_locked(th, self);
4350
4351 if (interrupted) {
4352 RUBY_VM_CHECK_INTS_BLOCKING(th);
4353 }
4354 }
4355 }
4356 return self;
4357 }
4358
4359 /*
4360 * call-seq:
4361 * mutex.owned? -> true or false
4362 *
4363 * Returns +true+ if this lock is currently held by current thread.
4364 * <em>This API is experimental, and subject to change.</em>
4365 */
4366 VALUE
4367 rb_mutex_owned_p(VALUE self)
4368 {
4369 VALUE owned = Qfalse;
4370 rb_thread_t *th = GET_THREAD();
4371 rb_mutex_t *mutex;
4372
4373 GetMutexPtr(self, mutex);
4374
4375 if (mutex->th == th)
4376 owned = Qtrue;
4377
4378 return owned;
4379 }
4380
4381 static const char *
4382 rb_mutex_unlock_th(rb_mutex_t *mutex, rb_thread_t volatile *th)
4383 {
4384 const char *err = NULL;
4385
4386 native_mutex_lock(&mutex->lock);
4387
4388 if (mutex->th == 0) {
4389 err = "Attempt to unlock a mutex which is not locked";
4390 }
4391 else if (mutex->th != th) {
4392 err = "Attempt to unlock a mutex which is locked by another thread";
4393 }
4394 else {
4395 mutex->th = 0;
4396 if (mutex->cond_waiting > 0)
4397 native_cond_signal(&mutex->cond);
4398 }
4399
4400 native_mutex_unlock(&mutex->lock);
4401
4402 if (!err) {
4403 rb_mutex_t *volatile *th_mutex = &th->keeping_mutexes;
4404 while (*th_mutex != mutex) {
4405 th_mutex = &(*th_mutex)->next_mutex;
4406 }
4407 *th_mutex = mutex->next_mutex;
4408 mutex->next_mutex = NULL;
4409 }
4410
4411 return err;
4412 }
4413
4414 /*
4415 * call-seq:
4416 * mutex.unlock -> self
4417 *
4418 * Releases the lock.
4419 * Raises +ThreadError+ if +mutex+ wasn't locked by the current thread.
4420 */
4421 VALUE
4422 rb_mutex_unlock(VALUE self)
4423 {
4424 const char *err;
4425 rb_mutex_t *mutex;
4426 GetMutexPtr(self, mutex);
4427
4428 /* When running trap handler */
4429 if (!mutex->allow_trap && GET_THREAD()->interrupt_mask & TRAP_INTERRUPT_MASK) {
4430 rb_raise(rb_eThreadError, "can't be called from trap context");
4431 }
4432
4433 err = rb_mutex_unlock_th(mutex, GET_THREAD());
4434 if (err) rb_raise(rb_eThreadError, "%s", err);
4435
4436 return self;
4437 }
4438
4439 static void
4440 rb_mutex_abandon_all(rb_mutex_t *mutexes)
4441 {
4442 rb_mutex_t *mutex;
4443
4444 while (mutexes) {
4445 mutex = mutexes;
4446 mutexes = mutex->next_mutex;
4447 mutex->th = 0;
4448 mutex->next_mutex = 0;
4449 }
4450 }
4451
4452 static VALUE
4453 rb_mutex_sleep_forever(VALUE time)
4454 {
4455 sleep_forever(GET_THREAD(), 1, 0); /* permit spurious check */
4456 return Qnil;
4457 }
4458
4459 static VALUE
4460 rb_mutex_wait_for(VALUE time)
4461 {
4462 struct timeval *t = (struct timeval *)time;
4463 sleep_timeval(GET_THREAD(), *t, 0); /* permit spurious check */
4464 return Qnil;
4465 }
4466
4467 VALUE
4468 rb_mutex_sleep(VALUE self, VALUE timeout)
4469 {
4470 time_t beg, end;
4471 struct timeval t;
4472
4473 if (!NIL_P(timeout)) {
4474 t = rb_time_interval(timeout);
4475 }
4476 rb_mutex_unlock(self);
4477 beg = time(0);
4478 if (NIL_P(timeout)) {
4479 rb_ensure(rb_mutex_sleep_forever, Qnil, rb_mutex_lock, self);
4480 }
4481 else {
4482 rb_ensure(rb_mutex_wait_for, (VALUE)&t, rb_mutex_lock, self);
4483 }
4484 end = time(0) - beg;
4485 return INT2FIX(end);
4486 }
4487
4488 /*
4489 * call-seq:
4490 * mutex.sleep(timeout = nil) -> number
4491 *
4492 * Releases the lock and sleeps +timeout+ seconds if it is given and
4493 * non-nil or forever. Raises +ThreadError+ if +mutex+ wasn't locked by
4494 * the current thread.
4495 *
4496 * Note that this method can wakeup without explicit Thread#wakeup call.
4497 * For example, receiving signal and so on.
4498 */
4499 static VALUE
4500 mutex_sleep(int argc, VALUE *argv, VALUE self)
4501 {
4502 VALUE timeout;
4503
4504 rb_scan_args(argc, argv, "01", &timeout);
4505 return rb_mutex_sleep(self, timeout);
4506 }
4507
4508 /*
4509 * call-seq:
4510 * mutex.synchronize { ... } -> result of the block
4511 *
4512 * Obtains a lock, runs the block, and releases the lock when the block
4513 * completes. See the example under +Mutex+.
4514 */
4515
4516 VALUE
4517 rb_mutex_synchronize(VALUE mutex, VALUE (*func)(VALUE arg), VALUE arg)
4518 {
4519 rb_mutex_lock(mutex);
4520 return rb_ensure(func, arg, rb_mutex_unlock, mutex);
4521 }
4522
4523 /*
4524 * call-seq:
4525 * mutex.synchronize { ... } -> result of the block
4526 *
4527 * Obtains a lock, runs the block, and releases the lock when the block
4528 * completes. See the example under +Mutex+.
4529 */
4530 static VALUE
4531 rb_mutex_synchronize_m(VALUE self, VALUE args)
4532 {
4533 if (!rb_block_given_p()) {
4534 rb_raise(rb_eThreadError, "must be called with a block");
4535 }
4536
4537 return rb_mutex_synchronize(self, rb_yield, Qundef);
4538 }
4539
4540 void rb_mutex_allow_trap(VALUE self, int val)
4541 {
4542 rb_mutex_t *m;
4543 GetMutexPtr(self, m);
4544
4545 m->allow_trap = val;
4546 }
4547
4548 /*
4549 * Document-class: ThreadShield
4550 */
4551 static void
4552 thread_shield_mark(void *ptr)
4553 {
4554 rb_gc_mark((VALUE)ptr);
4555 }
4556
4557 static const rb_data_type_t thread_shield_data_type = {
4558 "thread_shield",
4559 {thread_shield_mark, 0, 0,},
4560 };
4561
4562 static VALUE
4563 thread_shield_alloc(VALUE klass)
4564 {
4565 return TypedData_Wrap_Struct(klass, &thread_shield_data_type, (void *)mutex_alloc(0));
4566 }
4567
4568 #define GetThreadShieldPtr(obj) ((VALUE)rb_check_typeddata((obj), &thread_shield_data_type))
4569 #define THREAD_SHIELD_WAITING_MASK (FL_USER0|FL_USER1|FL_USER2|FL_USER3|FL_USER4|FL_USER5|FL_USER6|FL_USER7|FL_USER8|FL_USER9|FL_USER10|FL_USER11|FL_USER12|FL_USER13|FL_USER14|FL_USER15|FL_USER16|FL_USER17|FL_USER18|FL_USER19)
4570 #define THREAD_SHIELD_WAITING_SHIFT (FL_USHIFT)
4571 #define rb_thread_shield_waiting(b) (int)((RBASIC(b)->flags&THREAD_SHIELD_WAITING_MASK)>>THREAD_SHIELD_WAITING_SHIFT)
4572
4573 static inline void
4574 rb_thread_shield_waiting_inc(VALUE b)
4575 {
4576 unsigned int w = rb_thread_shield_waiting(b);
4577 w++;
4578 if (w > (unsigned int)(THREAD_SHIELD_WAITING_MASK>>THREAD_SHIELD_WAITING_SHIFT))
4579 rb_raise(rb_eRuntimeError, "waiting count overflow");
4580 RBASIC(b)->flags &= ~THREAD_SHIELD_WAITING_MASK;
4581 RBASIC(b)->flags |= ((VALUE)w << THREAD_SHIELD_WAITING_SHIFT);
4582 }
4583
4584 static inline void
4585 rb_thread_shield_waiting_dec(VALUE b)
4586 {
4587 unsigned int w = rb_thread_shield_waiting(b);
4588 if (!w) rb_raise(rb_eRuntimeError, "waiting count underflow");
4589 w--;
4590 RBASIC(b)->flags &= ~THREAD_SHIELD_WAITING_MASK;
4591 RBASIC(b)->flags |= ((VALUE)w << THREAD_SHIELD_WAITING_SHIFT);
4592 }
4593
4594 VALUE
4595 rb_thread_shield_new(void)
4596 {
4597 VALUE thread_shield = thread_shield_alloc(rb_cThreadShield);
4598 rb_mutex_lock((VALUE)DATA_PTR(thread_shield));
4599 return thread_shield;
4600 }
4601
4602 /*
4603 * Wait a thread shield.
4604 *
4605 * Returns
4606 * true: acquired the thread shield
4607 * false: the thread shield was destroyed and no other threads waiting
4608 * nil: the thread shield was destroyed but still in use
4609 */
4610 VALUE
4611 rb_thread_shield_wait(VALUE self)
4612 {
4613 VALUE mutex = GetThreadShieldPtr(self);
4614 rb_mutex_t *m;
4615
4616 if (!mutex) return Qfalse;
4617 GetMutexPtr(mutex, m);
4618 if (m->th == GET_THREAD()) return Qnil;
4619 rb_thread_shield_waiting_inc(self);
4620 rb_mutex_lock(mutex);
4621 rb_thread_shield_waiting_dec(self);
4622 if (DATA_PTR(self)) return Qtrue;
4623 rb_mutex_unlock(mutex);
4624 return rb_thread_shield_waiting(self) > 0 ? Qnil : Qfalse;
4625 }
4626
4627 /*
4628 * Release a thread shield, and return true if it has waiting threads.
4629 */
4630 VALUE
4631 rb_thread_shield_release(VALUE self)
4632 {
4633 VALUE mutex = GetThreadShieldPtr(self);
4634 rb_mutex_unlock(mutex);
4635 return rb_thread_shield_waiting(self) > 0 ? Qtrue : Qfalse;
4636 }
4637
4638 /*
4639 * Release and destroy a thread shield, and return true if it has waiting threads.
4640 */
4641 VALUE
4642 rb_thread_shield_destroy(VALUE self)
4643 {
4644 VALUE mutex = GetThreadShieldPtr(self);
4645 DATA_PTR(self) = 0;
4646 rb_mutex_unlock(mutex);
4647 return rb_thread_shield_waiting(self) > 0 ? Qtrue : Qfalse;
4648 }
4649
4650 /* variables for recursive traversals */
4651 static ID recursive_key;
4652
4653 /*
4654 * Returns the current "recursive list" used to detect recursion.
4655 * This list is a hash table, unique for the current thread and for
4656 * the current __callee__.
4657 */
4658
4659 static VALUE
4660 recursive_list_access(void)
4661 {
4662 volatile VALUE hash = rb_thread_local_aref(rb_thread_current(), recursive_key);
4663 VALUE sym = ID2SYM(rb_frame_this_func());
4664 VALUE list;
4665 if (NIL_P(hash) || !RB_TYPE_P(hash, T_HASH)) {
4666 hash = rb_hash_new();
4667 OBJ_UNTRUST(hash);
4668 rb_thread_local_aset(rb_thread_current(), recursive_key, hash);
4669 list = Qnil;
4670 }
4671 else {
4672 list = rb_hash_aref(hash, sym);
4673 }
4674 if (NIL_P(list) || !RB_TYPE_P(list, T_HASH)) {
4675 list = rb_hash_new();
4676 OBJ_UNTRUST(list);
4677 rb_hash_aset(hash, sym, list);
4678 }
4679 return list;
4680 }
4681
4682 /*
4683 * Returns Qtrue iff obj_id (or the pair <obj, paired_obj>) is already
4684 * in the recursion list.
4685 * Assumes the recursion list is valid.
4686 */
4687
4688 static VALUE
4689 recursive_check(VALUE list, VALUE obj_id, VALUE paired_obj_id)
4690 {
4691 #if SIZEOF_LONG == SIZEOF_VOIDP
4692 #define OBJ_ID_EQL(obj_id, other) ((obj_id) == (other))
4693 #elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
4694 #define OBJ_ID_EQL(obj_id, other) (RB_TYPE_P((obj_id), T_BIGNUM) ? \
4695 rb_big_eql((obj_id), (other)) : ((obj_id) == (other)))
4696 #endif
4697
4698 VALUE pair_list = rb_hash_lookup2(list, obj_id, Qundef);
4699 if (pair_list == Qundef)
4700 return Qfalse;
4701 if (paired_obj_id) {
4702 if (!RB_TYPE_P(pair_list, T_HASH)) {
4703 if (!OBJ_ID_EQL(paired_obj_id, pair_list))
4704 return Qfalse;
4705 }
4706 else {
4707 if (NIL_P(rb_hash_lookup(pair_list, paired_obj_id)))
4708 return Qfalse;
4709 }
4710 }
4711 return Qtrue;
4712 }
4713
4714 /*
4715 * Pushes obj_id (or the pair <obj_id, paired_obj_id>) in the recursion list.
4716 * For a single obj_id, it sets list[obj_id] to Qtrue.
4717 * For a pair, it sets list[obj_id] to paired_obj_id if possible,
4718 * otherwise list[obj_id] becomes a hash like:
4719 * {paired_obj_id_1 => true, paired_obj_id_2 => true, ... }
4720 * Assumes the recursion list is valid.
4721 */
4722
4723 static void
4724 recursive_push(VALUE list, VALUE obj, VALUE paired_obj)
4725 {
4726 VALUE pair_list;
4727
4728 if (!paired_obj) {
4729 rb_hash_aset(list, obj, Qtrue);
4730 }
4731 else if ((pair_list = rb_hash_lookup2(list, obj, Qundef)) == Qundef) {
4732 rb_hash_aset(list, obj, paired_obj);
4733 }
4734 else {
4735 if (!RB_TYPE_P(pair_list, T_HASH)){
4736 VALUE other_paired_obj = pair_list;
4737 pair_list = rb_hash_new();
4738 OBJ_UNTRUST(pair_list);
4739 rb_hash_aset(pair_list, other_paired_obj, Qtrue);
4740 rb_hash_aset(list, obj, pair_list);
4741 }
4742 rb_hash_aset(pair_list, paired_obj, Qtrue);
4743 }
4744 }
4745
4746 /*
4747 * Pops obj_id (or the pair <obj_id, paired_obj_id>) from the recursion list.
4748 * For a pair, if list[obj_id] is a hash, then paired_obj_id is
4749 * removed from the hash and no attempt is made to simplify
4750 * list[obj_id] from {only_one_paired_id => true} to only_one_paired_id
4751 * Assumes the recursion list is valid.
4752 */
4753
4754 static void
4755 recursive_pop(VALUE list, VALUE obj, VALUE paired_obj)
4756 {
4757 if (paired_obj) {
4758 VALUE pair_list = rb_hash_lookup2(list, obj, Qundef);
4759 if (pair_list == Qundef) {
4760 VALUE symname = rb_inspect(ID2SYM(rb_frame_this_func()));
4761 VALUE thrname = rb_inspect(rb_thread_current());
4762 rb_raise(rb_eTypeError, "invalid inspect_tbl pair_list for %s in %s",
4763 StringValuePtr(symname), StringValuePtr(thrname));
4764 }
4765 if (RB_TYPE_P(pair_list, T_HASH)) {
4766 rb_hash_delete(pair_list, paired_obj);
4767 if (!RHASH_EMPTY_P(pair_list)) {
4768 return; /* keep hash until is empty */
4769 }
4770 }
4771 }
4772 rb_hash_delete(list, obj);
4773 }
4774
4775 struct exec_recursive_params {
4776 VALUE (*func) (VALUE, VALUE, int);
4777 VALUE list;
4778 VALUE obj;
4779 VALUE objid;
4780 VALUE pairid;
4781 VALUE arg;
4782 };
4783
4784 static VALUE
4785 exec_recursive_i(VALUE tag, struct exec_recursive_params *p)
4786 {
4787 VALUE result = Qundef;
4788 int state;
4789
4790 recursive_push(p->list, p->objid, p->pairid);
4791 PUSH_TAG();
4792 if ((state = EXEC_TAG()) == 0) {
4793 result = (*p->func)(p->obj, p->arg, FALSE);
4794 }
4795 POP_TAG();
4796 recursive_pop(p->list, p->objid, p->pairid);
4797 if (state)
4798 JUMP_TAG(state);
4799 return result;
4800 }
4801
4802 /*
4803 * Calls func(obj, arg, recursive), where recursive is non-zero if the
4804 * current method is called recursively on obj, or on the pair <obj, pairid>
4805 * If outer is 0, then the innermost func will be called with recursive set
4806 * to Qtrue, otherwise the outermost func will be called. In the latter case,
4807 * all inner func are short-circuited by throw.
4808 * Implementation details: the value thrown is the recursive list which is
4809 * proper to the current method and unlikely to be catched anywhere else.
4810 * list[recursive_key] is used as a flag for the outermost call.
4811 */
4812
4813 static VALUE
4814 exec_recursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE pairid, VALUE arg, int outer)
4815 {
4816 VALUE result = Qundef;
4817 struct exec_recursive_params p;
4818 int outermost;
4819 p.list = recursive_list_access();
4820 p.objid = rb_obj_id(obj);
4821 p.obj = obj;
4822 p.pairid = pairid;
4823 p.arg = arg;
4824 outermost = outer && !recursive_check(p.list, ID2SYM(recursive_key), 0);
4825
4826 if (recursive_check(p.list, p.objid, pairid)) {
4827 if (outer && !outermost) {
4828 rb_throw_obj(p.list, p.list);
4829 }
4830 return (*func)(obj, arg, TRUE);
4831 }
4832 else {
4833 p.func = func;
4834
4835 if (outermost) {
4836 recursive_push(p.list, ID2SYM(recursive_key), 0);
4837 result = rb_catch_obj(p.list, exec_recursive_i, (VALUE)&p);
4838 recursive_pop(p.list, ID2SYM(recursive_key), 0);
4839 if (result == p.list) {
4840 result = (*func)(obj, arg, TRUE);
4841 }
4842 }
4843 else {
4844 result = exec_recursive_i(0, &p);
4845 }
4846 }
4847 *(volatile struct exec_recursive_params *)&p;
4848 return result;
4849 }
4850
4851 /*
4852 * Calls func(obj, arg, recursive), where recursive is non-zero if the
4853 * current method is called recursively on obj
4854 */
4855
4856 VALUE
4857 rb_exec_recursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE arg)
4858 {
4859 return exec_recursive(func, obj, 0, arg, 0);
4860 }
4861
4862 /*
4863 * Calls func(obj, arg, recursive), where recursive is non-zero if the
4864 * current method is called recursively on the ordered pair <obj, paired_obj>
4865 */
4866
4867 VALUE
4868 rb_exec_recursive_paired(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE paired_obj, VALUE arg)
4869 {
4870 return exec_recursive(func, obj, rb_obj_id(paired_obj), arg, 0);
4871 }
4872
4873 /*
4874 * If recursion is detected on the current method and obj, the outermost
4875 * func will be called with (obj, arg, Qtrue). All inner func will be
4876 * short-circuited using throw.
4877 */
4878
4879 VALUE
4880 rb_exec_recursive_outer(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE arg)
4881 {
4882 return exec_recursive(func, obj, 0, arg, 1);
4883 }
4884
4885 /*
4886 * call-seq:
4887 * thr.backtrace -> array
4888 *
4889 * Returns the current backtrace of the target thread.
4890 *
4891 */
4892
4893 static VALUE
4894 rb_thread_backtrace_m(int argc, VALUE *argv, VALUE thval)
4895 {
4896 return vm_thread_backtrace(argc, argv, thval);
4897 }
4898
4899 /* call-seq:
4900 * thr.backtrace_locations(*args) -> array or nil
4901 *
4902 * Returns the execution stack for the target thread---an array containing
4903 * backtrace location objects.
4904 *
4905 * See Thread::Backtrace::Location for more information.
4906 *
4907 * This method behaves similarly to Kernel#caller_locations except it applies
4908 * to a specific thread.
4909 */
4910 static VALUE
4911 rb_thread_backtrace_locations_m(int argc, VALUE *argv, VALUE thval)
4912 {
4913 return vm_thread_backtrace_locations(argc, argv, thval);
4914 }
4915
4916 /*
4917 * Document-class: ThreadError
4918 *
4919 * Raised when an invalid operation is attempted on a thread.
4920 *
4921 * For example, when no other thread has been started:
4922 *
4923 * Thread.stop
4924 *
4925 * <em>raises the exception:</em>
4926 *
4927 * ThreadError: stopping only thread
4928 */
4929
4930 /*
4931 * +Thread+ encapsulates the behavior of a thread of
4932 * execution, including the main thread of the Ruby script.
4933 *
4934 * In the descriptions of the methods in this class, the parameter _sym_
4935 * refers to a symbol, which is either a quoted string or a
4936 * +Symbol+ (such as <code>:name</code>).
4937 */
4938
4939 void
4940 Init_Thread(void)
4941 {
4942 #undef rb_intern
4943 #define rb_intern(str) rb_intern_const(str)
4944
4945 VALUE cThGroup;
4946 rb_thread_t *th = GET_THREAD();
4947
4948 sym_never = ID2SYM(rb_intern("never"));
4949 sym_immediate = ID2SYM(rb_intern("immediate"));
4950 sym_on_blocking = ID2SYM(rb_intern("on_blocking"));
4951
4952 rb_define_singleton_method(rb_cThread, "new", thread_s_new, -1);
4953 rb_define_singleton_method(rb_cThread, "start", thread_start, -2);
4954 rb_define_singleton_method(rb_cThread, "fork", thread_start, -2);
4955 rb_define_singleton_method(rb_cThread, "main", rb_thread_s_main, 0);
4956 rb_define_singleton_method(rb_cThread, "current", thread_s_current, 0);
4957 rb_define_singleton_method(rb_cThread, "stop", rb_thread_stop, 0);
4958 rb_define_singleton_method(rb_cThread, "kill", rb_thread_s_kill, 1);
4959 rb_define_singleton_method(rb_cThread, "exit", rb_thread_exit, 0);
4960 rb_define_singleton_method(rb_cThread, "pass", thread_s_pass, 0);
4961 rb_define_singleton_method(rb_cThread, "list", rb_thread_list, 0);
4962 rb_define_singleton_method(rb_cThread, "abort_on_exception", rb_thread_s_abort_exc, 0);
4963 rb_define_singleton_method(rb_cThread, "abort_on_exception=", rb_thread_s_abort_exc_set, 1);
4964 #if THREAD_DEBUG < 0
4965 rb_define_singleton_method(rb_cThread, "DEBUG", rb_thread_s_debug, 0);
4966 rb_define_singleton_method(rb_cThread, "DEBUG=", rb_thread_s_debug_set, 1);
4967 #endif
4968 rb_define_singleton_method(rb_cThread, "handle_interrupt", rb_thread_s_handle_interrupt, 1);
4969 rb_define_singleton_method(rb_cThread, "pending_interrupt?", rb_thread_s_pending_interrupt_p, -1);
4970 rb_define_method(rb_cThread, "pending_interrupt?", rb_thread_pending_interrupt_p, -1);
4971
4972 rb_define_method(rb_cThread, "initialize", thread_initialize, -2);
4973 rb_define_method(rb_cThread, "raise", thread_raise_m, -1);
4974 rb_define_method(rb_cThread, "join", thread_join_m, -1);
4975 rb_define_method(rb_cThread, "value", thread_value, 0);
4976 rb_define_method(rb_cThread, "kill", rb_thread_kill, 0);
4977 rb_define_method(rb_cThread, "terminate", rb_thread_kill, 0);
4978 rb_define_method(rb_cThread, "exit", rb_thread_kill, 0);
4979 rb_define_method(rb_cThread, "run", rb_thread_run, 0);
4980 rb_define_method(rb_cThread, "wakeup", rb_thread_wakeup, 0);
4981 rb_define_method(rb_cThread, "[]", rb_thread_aref, 1);
4982 rb_define_method(rb_cThread, "[]=", rb_thread_aset, 2);
4983 rb_define_method(rb_cThread, "key?", rb_thread_key_p, 1);
4984 rb_define_method(rb_cThread, "keys", rb_thread_keys, 0);
4985 rb_define_method(rb_cThread, "priority", rb_thread_priority, 0);
4986 rb_define_method(rb_cThread, "priority=", rb_thread_priority_set, 1);
4987 rb_define_method(rb_cThread, "status", rb_thread_status, 0);
4988 rb_define_method(rb_cThread, "thread_variable_get", rb_thread_variable_get, 1);
4989 rb_define_method(rb_cThread, "thread_variable_set", rb_thread_variable_set, 2);
4990 rb_define_method(rb_cThread, "thread_variables", rb_thread_variables, 0);
4991 rb_define_method(rb_cThread, "thread_variable?", rb_thread_variable_p, 1);
4992 rb_define_method(rb_cThread, "alive?", rb_thread_alive_p, 0);
4993 rb_define_method(rb_cThread, "stop?", rb_thread_stop_p, 0);
4994 rb_define_method(rb_cThread, "abort_on_exception", rb_thread_abort_exc, 0);
4995 rb_define_method(rb_cThread, "abort_on_exception=", rb_thread_abort_exc_set, 1);
4996 rb_define_method(rb_cThread, "safe_level", rb_thread_safe_level, 0);
4997 rb_define_method(rb_cThread, "group", rb_thread_group, 0);
4998 rb_define_method(rb_cThread, "backtrace", rb_thread_backtrace_m, -1);
4999 rb_define_method(rb_cThread, "backtrace_locations", rb_thread_backtrace_locations_m, -1);
5000
5001 rb_define_method(rb_cThread, "inspect", rb_thread_inspect, 0);
5002
5003 closed_stream_error = rb_exc_new2(rb_eIOError, "stream closed");
5004 OBJ_TAINT(closed_stream_error);
5005 OBJ_FREEZE(closed_stream_error);
5006
5007 cThGroup = rb_define_class("ThreadGroup", rb_cObject);
5008 rb_define_alloc_func(cThGroup, thgroup_s_alloc);
5009 rb_define_method(cThGroup, "list", thgroup_list, 0);
5010 rb_define_method(cThGroup, "enclose", thgroup_enclose, 0);
5011 rb_define_method(cThGroup, "enclosed?", thgroup_enclosed_p, 0);
5012 rb_define_method(cThGroup, "add", thgroup_add, 1);
5013
5014 {
5015 th->thgroup = th->vm->thgroup_default = rb_obj_alloc(cThGroup);
5016 rb_define_const(cThGroup, "Default", th->thgroup);
5017 }
5018
5019 rb_cMutex = rb_define_class("Mutex", rb_cObject);
5020 rb_define_alloc_func(rb_cMutex, mutex_alloc);
5021 rb_define_method(rb_cMutex, "initialize", mutex_initialize, 0);
5022 rb_define_method(rb_cMutex, "locked?", rb_mutex_locked_p, 0);
5023 rb_define_method(rb_cMutex, "try_lock", rb_mutex_trylock, 0);
5024 rb_define_method(rb_cMutex, "lock", rb_mutex_lock, 0);
5025 rb_define_method(rb_cMutex, "unlock", rb_mutex_unlock, 0);
5026 rb_define_method(rb_cMutex, "sleep", mutex_sleep, -1);
5027 rb_define_method(rb_cMutex, "synchronize", rb_mutex_synchronize_m, 0);
5028 rb_define_method(rb_cMutex, "owned?", rb_mutex_owned_p, 0);
5029
5030 recursive_key = rb_intern("__recursive_key__");
5031 rb_eThreadError = rb_define_class("ThreadError", rb_eStandardError);
5032
5033 /* init thread core */
5034 {
5035 /* main thread setting */
5036 {
5037 /* acquire global vm lock */
5038 gvl_init(th->vm);
5039 gvl_acquire(th->vm, th);
5040 native_mutex_initialize(&th->vm->thread_destruct_lock);
5041 native_mutex_initialize(&th->interrupt_lock);
5042
5043 th->pending_interrupt_queue = rb_ary_tmp_new(0);
5044 th->pending_interrupt_queue_checked = 0;
5045 th->pending_interrupt_mask_stack = rb_ary_tmp_new(0);
5046
5047 th->interrupt_mask = 0;
5048 }
5049 }
5050
5051 rb_thread_create_timer_thread();
5052
5053 /* suppress warnings on cygwin, mingw and mswin.*/
5054 (void)native_mutex_trylock;
5055 }
5056
5057 int
5058 ruby_native_thread_p(void)
5059 {
5060 rb_thread_t *th = ruby_thread_from_native();
5061
5062 return th != 0;
5063 }
5064
5065 static int
5066 check_deadlock_i(st_data_t key, st_data_t val, int *found)
5067 {
5068 VALUE thval = key;
5069 rb_thread_t *th;
5070 GetThreadPtr(thval, th);
5071
5072 if (th->status != THREAD_STOPPED_FOREVER || RUBY_VM_INTERRUPTED(th)) {
5073 *found = 1;
5074 }
5075 else if (th->locking_mutex) {
5076 rb_mutex_t *mutex;
5077 GetMutexPtr(th->locking_mutex, mutex);
5078
5079 native_mutex_lock(&mutex->lock);
5080 if (mutex->th == th || (!mutex->th && mutex->cond_waiting)) {
5081 *found = 1;
5082 }
5083 native_mutex_unlock(&mutex->lock);
5084 }
5085
5086 return (*found) ? ST_STOP : ST_CONTINUE;
5087 }
5088
5089 #ifdef DEBUG_DEADLOCK_CHECK
5090 static int
5091 debug_i(st_data_t key, st_data_t val, int *found)
5092 {
5093 VALUE thval = key;
5094 rb_thread_t *th;
5095 GetThreadPtr(thval, th);
5096
5097 printf("th:%p %d %d", th, th->status, th->interrupt_flag);
5098 if (th->locking_mutex) {
5099 rb_mutex_t *mutex;
5100 GetMutexPtr(th->locking_mutex, mutex);
5101
5102 native_mutex_lock(&mutex->lock);
5103 printf(" %p %d\n", mutex->th, mutex->cond_waiting);
5104 native_mutex_unlock(&mutex->lock);
5105 }
5106 else
5107 puts("");
5108
5109 return ST_CONTINUE;
5110 }
5111 #endif
5112
5113 static void
5114 rb_check_deadlock(rb_vm_t *vm)
5115 {
5116 int found = 0;
5117
5118 if (vm_living_thread_num(vm) > vm->sleeper) return;
5119 if (vm_living_thread_num(vm) < vm->sleeper) rb_bug("sleeper must not be more than vm_living_thread_num(vm)");
5120 if (patrol_thread && patrol_thread != GET_THREAD()) return;
5121
5122 st_foreach(vm->living_threads, check_deadlock_i, (st_data_t)&found);
5123
5124 if (!found) {
5125 VALUE argv[2];
5126 argv[0] = rb_eFatal;
5127 argv[1] = rb_str_new2("No live threads left. Deadlock?");
5128 #ifdef DEBUG_DEADLOCK_CHECK
5129 printf("%d %d %p %p\n", vm->living_threads->num_entries, vm->sleeper, GET_THREAD(), vm->main_thread);
5130 st_foreach(vm->living_threads, debug_i, (st_data_t)0);
5131 #endif
5132 vm->sleeper--;
5133 rb_threadptr_raise(vm->main_thread, 2, argv);
5134 }
5135 }
5136
5137 static void
5138 update_coverage(rb_event_flag_t event, VALUE proc, VALUE self, ID id, VALUE klass)
5139 {
5140 VALUE coverage = GET_THREAD()->cfp->iseq->coverage;
5141 if (coverage && RBASIC(coverage)->klass == 0) {
5142 long line = rb_sourceline() - 1;
5143 long count;
5144 if (RARRAY_PTR(coverage)[line] == Qnil) {
5145 return;
5146 }
5147 count = FIX2LONG(RARRAY_PTR(coverage)[line]) + 1;
5148 if (POSFIXABLE(count)) {
5149 RARRAY_PTR(coverage)[line] = LONG2FIX(count);
5150 }
5151 }
5152 }
5153
5154 VALUE
5155 rb_get_coverages(void)
5156 {
5157 return GET_VM()->coverages;
5158 }
5159
5160 void
5161 rb_set_coverages(VALUE coverages)
5162 {
5163 GET_VM()->coverages = coverages;
5164 rb_add_event_hook(update_coverage, RUBY_EVENT_COVERAGE, Qnil);
5165 }
5166
5167 void
5168 rb_reset_coverages(void)
5169 {
5170 GET_VM()->coverages = Qfalse;
5171 rb_remove_event_hook(update_coverage);
5172 }
5173
5174 VALUE
5175 rb_uninterruptible(VALUE (*b_proc)(ANYARGS), VALUE data)
5176 {
5177 VALUE interrupt_mask = rb_hash_new();
5178 rb_thread_t *cur_th = GET_THREAD();
5179
5180 rb_hash_aset(interrupt_mask, rb_cObject, sym_never);
5181 rb_ary_push(cur_th->pending_interrupt_mask_stack, interrupt_mask);
5182
5183 return rb_ensure(b_proc, data, rb_ary_pop, cur_th->pending_interrupt_mask_stack);
5184 }
5185