Ruby  2.1.3p242(2014-09-19revision47630)
thread_pthread.c
Go to the documentation of this file.
1 /* -*-c-*- */
2 /**********************************************************************
3 
4  thread_pthread.c -
5 
6  $Author: nagachika $
7 
8  Copyright (C) 2004-2007 Koichi Sasada
9 
10 **********************************************************************/
11 
12 #ifdef THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION
13 
14 #include "gc.h"
15 
16 #ifdef HAVE_SYS_RESOURCE_H
17 #include <sys/resource.h>
18 #endif
19 #ifdef HAVE_THR_STKSEGMENT
20 #include <thread.h>
21 #endif
22 #if HAVE_FCNTL_H
23 #include <fcntl.h>
24 #elif HAVE_SYS_FCNTL_H
25 #include <sys/fcntl.h>
26 #endif
27 #ifdef HAVE_SYS_PRCTL_H
28 #include <sys/prctl.h>
29 #endif
30 #if defined(__native_client__) && defined(NACL_NEWLIB)
31 # include "nacl/select.h"
32 #endif
33 #if defined(HAVE_SYS_TIME_H)
34 #include <sys/time.h>
35 #endif
36 
37 static void native_mutex_lock(pthread_mutex_t *lock);
38 static void native_mutex_unlock(pthread_mutex_t *lock);
39 static int native_mutex_trylock(pthread_mutex_t *lock);
40 static void native_mutex_initialize(pthread_mutex_t *lock);
41 static void native_mutex_destroy(pthread_mutex_t *lock);
42 static void native_cond_signal(rb_nativethread_cond_t *cond);
43 static void native_cond_broadcast(rb_nativethread_cond_t *cond);
44 static void native_cond_wait(rb_nativethread_cond_t *cond, pthread_mutex_t *mutex);
45 static void native_cond_initialize(rb_nativethread_cond_t *cond, int flags);
46 static void native_cond_destroy(rb_nativethread_cond_t *cond);
47 static void rb_thread_wakeup_timer_thread_low(void);
48 static pthread_t timer_thread_id;
49 
50 #define RB_CONDATTR_CLOCK_MONOTONIC 1
51 
52 #if defined(HAVE_PTHREAD_CONDATTR_SETCLOCK) && defined(HAVE_CLOCKID_T) && \
53  defined(CLOCK_REALTIME) && defined(CLOCK_MONOTONIC) && \
54  defined(HAVE_CLOCK_GETTIME) && defined(HAVE_PTHREAD_CONDATTR_INIT)
55 #define USE_MONOTONIC_COND 1
56 #else
57 #define USE_MONOTONIC_COND 0
58 #endif
59 
60 #if defined(HAVE_POLL) && defined(HAVE_FCNTL) && defined(F_GETFL) && defined(F_SETFL) && defined(O_NONBLOCK) && !defined(__native_client__)
61 /* The timer thread sleeps while only one Ruby thread is running. */
62 # define USE_SLEEPY_TIMER_THREAD 1
63 #else
64 # define USE_SLEEPY_TIMER_THREAD 0
65 #endif
66 
67 static void
68 gvl_acquire_common(rb_vm_t *vm)
69 {
70  if (vm->gvl.acquired) {
71 
72  vm->gvl.waiting++;
73  if (vm->gvl.waiting == 1) {
74  /*
75  * Wake up timer thread iff timer thread is slept.
76  * When timer thread is polling mode, we don't want to
77  * make confusing timer thread interval time.
78  */
79  rb_thread_wakeup_timer_thread_low();
80  }
81 
82  while (vm->gvl.acquired) {
83  native_cond_wait(&vm->gvl.cond, &vm->gvl.lock);
84  }
85 
86  vm->gvl.waiting--;
87 
88  if (vm->gvl.need_yield) {
89  vm->gvl.need_yield = 0;
90  native_cond_signal(&vm->gvl.switch_cond);
91  }
92  }
93 
94  vm->gvl.acquired = 1;
95 }
96 
97 static void
98 gvl_acquire(rb_vm_t *vm, rb_thread_t *th)
99 {
100  native_mutex_lock(&vm->gvl.lock);
101  gvl_acquire_common(vm);
102  native_mutex_unlock(&vm->gvl.lock);
103 }
104 
105 static void
106 gvl_release_common(rb_vm_t *vm)
107 {
108  vm->gvl.acquired = 0;
109  if (vm->gvl.waiting > 0)
110  native_cond_signal(&vm->gvl.cond);
111 }
112 
113 static void
114 gvl_release(rb_vm_t *vm)
115 {
116  native_mutex_lock(&vm->gvl.lock);
117  gvl_release_common(vm);
118  native_mutex_unlock(&vm->gvl.lock);
119 }
120 
121 static void
122 gvl_yield(rb_vm_t *vm, rb_thread_t *th)
123 {
124  native_mutex_lock(&vm->gvl.lock);
125 
126  gvl_release_common(vm);
127 
128  /* An another thread is processing GVL yield. */
129  if (UNLIKELY(vm->gvl.wait_yield)) {
130  while (vm->gvl.wait_yield)
131  native_cond_wait(&vm->gvl.switch_wait_cond, &vm->gvl.lock);
132  goto acquire;
133  }
134 
135  if (vm->gvl.waiting > 0) {
136  /* Wait until another thread task take GVL. */
137  vm->gvl.need_yield = 1;
138  vm->gvl.wait_yield = 1;
139  while (vm->gvl.need_yield)
140  native_cond_wait(&vm->gvl.switch_cond, &vm->gvl.lock);
141  vm->gvl.wait_yield = 0;
142  }
143  else {
144  native_mutex_unlock(&vm->gvl.lock);
145  sched_yield();
146  native_mutex_lock(&vm->gvl.lock);
147  }
148 
149  native_cond_broadcast(&vm->gvl.switch_wait_cond);
150  acquire:
151  gvl_acquire_common(vm);
152  native_mutex_unlock(&vm->gvl.lock);
153 }
154 
155 static void
156 gvl_init(rb_vm_t *vm)
157 {
158  native_mutex_initialize(&vm->gvl.lock);
159  native_cond_initialize(&vm->gvl.cond, RB_CONDATTR_CLOCK_MONOTONIC);
160  native_cond_initialize(&vm->gvl.switch_cond, RB_CONDATTR_CLOCK_MONOTONIC);
161  native_cond_initialize(&vm->gvl.switch_wait_cond, RB_CONDATTR_CLOCK_MONOTONIC);
162  vm->gvl.acquired = 0;
163  vm->gvl.waiting = 0;
164  vm->gvl.need_yield = 0;
165  vm->gvl.wait_yield = 0;
166 }
167 
168 static void
169 gvl_destroy(rb_vm_t *vm)
170 {
171  native_cond_destroy(&vm->gvl.switch_wait_cond);
172  native_cond_destroy(&vm->gvl.switch_cond);
173  native_cond_destroy(&vm->gvl.cond);
174  native_mutex_destroy(&vm->gvl.lock);
175 }
176 
177 static void
178 gvl_atfork(rb_vm_t *vm)
179 {
180  gvl_init(vm);
181  gvl_acquire(vm, GET_THREAD());
182 }
183 
184 #define NATIVE_MUTEX_LOCK_DEBUG 0
185 
186 static void
187 mutex_debug(const char *msg, pthread_mutex_t *lock)
188 {
189  if (NATIVE_MUTEX_LOCK_DEBUG) {
190  int r;
191  static pthread_mutex_t dbglock = PTHREAD_MUTEX_INITIALIZER;
192 
193  if ((r = pthread_mutex_lock(&dbglock)) != 0) {exit(EXIT_FAILURE);}
194  fprintf(stdout, "%s: %p\n", msg, (void *)lock);
195  if ((r = pthread_mutex_unlock(&dbglock)) != 0) {exit(EXIT_FAILURE);}
196  }
197 }
198 
199 static void
200 native_mutex_lock(pthread_mutex_t *lock)
201 {
202  int r;
203  mutex_debug("lock", lock);
204  if ((r = pthread_mutex_lock(lock)) != 0) {
205  rb_bug_errno("pthread_mutex_lock", r);
206  }
207 }
208 
209 static void
210 native_mutex_unlock(pthread_mutex_t *lock)
211 {
212  int r;
213  mutex_debug("unlock", lock);
214  if ((r = pthread_mutex_unlock(lock)) != 0) {
215  rb_bug_errno("pthread_mutex_unlock", r);
216  }
217 }
218 
219 static inline int
220 native_mutex_trylock(pthread_mutex_t *lock)
221 {
222  int r;
223  mutex_debug("trylock", lock);
224  if ((r = pthread_mutex_trylock(lock)) != 0) {
225  if (r == EBUSY) {
226  return EBUSY;
227  }
228  else {
229  rb_bug_errno("pthread_mutex_trylock", r);
230  }
231  }
232  return 0;
233 }
234 
235 static void
236 native_mutex_initialize(pthread_mutex_t *lock)
237 {
238  int r = pthread_mutex_init(lock, 0);
239  mutex_debug("init", lock);
240  if (r != 0) {
241  rb_bug_errno("pthread_mutex_init", r);
242  }
243 }
244 
245 static void
246 native_mutex_destroy(pthread_mutex_t *lock)
247 {
248  int r = pthread_mutex_destroy(lock);
249  mutex_debug("destroy", lock);
250  if (r != 0) {
251  rb_bug_errno("pthread_mutex_destroy", r);
252  }
253 }
254 
255 static void
256 native_cond_initialize(rb_nativethread_cond_t *cond, int flags)
257 {
258 #ifdef HAVE_PTHREAD_COND_INIT
259  int r;
260 # if USE_MONOTONIC_COND
261  pthread_condattr_t attr;
262 
263  pthread_condattr_init(&attr);
264 
265  cond->clockid = CLOCK_REALTIME;
266  if (flags & RB_CONDATTR_CLOCK_MONOTONIC) {
267  r = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
268  if (r == 0) {
269  cond->clockid = CLOCK_MONOTONIC;
270  }
271  }
272 
273  r = pthread_cond_init(&cond->cond, &attr);
274  pthread_condattr_destroy(&attr);
275 # else
276  r = pthread_cond_init(&cond->cond, NULL);
277 # endif
278  if (r != 0) {
279  rb_bug_errno("pthread_cond_init", r);
280  }
281 
282  return;
283 #endif
284 }
285 
286 static void
287 native_cond_destroy(rb_nativethread_cond_t *cond)
288 {
289 #ifdef HAVE_PTHREAD_COND_INIT
290  int r = pthread_cond_destroy(&cond->cond);
291  if (r != 0) {
292  rb_bug_errno("pthread_cond_destroy", r);
293  }
294 #endif
295 }
296 
297 /*
298  * In OS X 10.7 (Lion), pthread_cond_signal and pthread_cond_broadcast return
299  * EAGAIN after retrying 8192 times. You can see them in the following page:
300  *
301  * http://www.opensource.apple.com/source/Libc/Libc-763.11/pthreads/pthread_cond.c
302  *
303  * The following native_cond_signal and native_cond_broadcast functions
304  * need to retrying until pthread functions don't return EAGAIN.
305  */
306 
307 static void
308 native_cond_signal(rb_nativethread_cond_t *cond)
309 {
310  int r;
311  do {
312  r = pthread_cond_signal(&cond->cond);
313  } while (r == EAGAIN);
314  if (r != 0) {
315  rb_bug_errno("pthread_cond_signal", r);
316  }
317 }
318 
319 static void
320 native_cond_broadcast(rb_nativethread_cond_t *cond)
321 {
322  int r;
323  do {
324  r = pthread_cond_broadcast(&cond->cond);
325  } while (r == EAGAIN);
326  if (r != 0) {
327  rb_bug_errno("native_cond_broadcast", r);
328  }
329 }
330 
331 static void
332 native_cond_wait(rb_nativethread_cond_t *cond, pthread_mutex_t *mutex)
333 {
334  int r = pthread_cond_wait(&cond->cond, mutex);
335  if (r != 0) {
336  rb_bug_errno("pthread_cond_wait", r);
337  }
338 }
339 
340 static int
341 native_cond_timedwait(rb_nativethread_cond_t *cond, pthread_mutex_t *mutex, struct timespec *ts)
342 {
343  int r;
344 
345  /*
346  * An old Linux may return EINTR. Even though POSIX says
347  * "These functions shall not return an error code of [EINTR]".
348  * http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_cond_timedwait.html
349  * Let's hide it from arch generic code.
350  */
351  do {
352  r = pthread_cond_timedwait(&cond->cond, mutex, ts);
353  } while (r == EINTR);
354 
355  if (r != 0 && r != ETIMEDOUT) {
356  rb_bug_errno("pthread_cond_timedwait", r);
357  }
358 
359  return r;
360 }
361 
362 static struct timespec
363 native_cond_timeout(rb_nativethread_cond_t *cond, struct timespec timeout_rel)
364 {
365  int ret;
366  struct timeval tv;
367  struct timespec timeout;
368  struct timespec now;
369 
370 #if USE_MONOTONIC_COND
371  if (cond->clockid == CLOCK_MONOTONIC) {
372  ret = clock_gettime(cond->clockid, &now);
373  if (ret != 0)
374  rb_sys_fail("clock_gettime()");
375  goto out;
376  }
377 
378  if (cond->clockid != CLOCK_REALTIME)
379  rb_bug("unsupported clockid %"PRIdVALUE, (SIGNED_VALUE)cond->clockid);
380 #endif
381 
382  ret = gettimeofday(&tv, 0);
383  if (ret != 0)
384  rb_sys_fail(0);
385  now.tv_sec = tv.tv_sec;
386  now.tv_nsec = tv.tv_usec * 1000;
387 
388 #if USE_MONOTONIC_COND
389  out:
390 #endif
391  timeout.tv_sec = now.tv_sec;
392  timeout.tv_nsec = now.tv_nsec;
393  timeout.tv_sec += timeout_rel.tv_sec;
394  timeout.tv_nsec += timeout_rel.tv_nsec;
395 
396  if (timeout.tv_nsec >= 1000*1000*1000) {
397  timeout.tv_sec++;
398  timeout.tv_nsec -= 1000*1000*1000;
399  }
400 
401  if (timeout.tv_sec < now.tv_sec)
402  timeout.tv_sec = TIMET_MAX;
403 
404  return timeout;
405 }
406 
407 #define native_cleanup_push pthread_cleanup_push
408 #define native_cleanup_pop pthread_cleanup_pop
409 #ifdef HAVE_SCHED_YIELD
410 #define native_thread_yield() (void)sched_yield()
411 #else
412 #define native_thread_yield() ((void)0)
413 #endif
414 
415 #if defined(SIGVTALRM) && !defined(__CYGWIN__) && !defined(__SYMBIAN32__)
416 #define USE_SIGNAL_THREAD_LIST 1
417 #endif
418 #ifdef USE_SIGNAL_THREAD_LIST
419 static void add_signal_thread_list(rb_thread_t *th);
420 static void remove_signal_thread_list(rb_thread_t *th);
421 static rb_nativethread_lock_t signal_thread_list_lock;
422 #endif
423 
424 static pthread_key_t ruby_native_thread_key;
425 
426 static void
427 null_func(int i)
428 {
429  /* null */
430 }
431 
432 static rb_thread_t *
433 ruby_thread_from_native(void)
434 {
435  return pthread_getspecific(ruby_native_thread_key);
436 }
437 
438 static int
439 ruby_thread_set_native(rb_thread_t *th)
440 {
441  return pthread_setspecific(ruby_native_thread_key, th) == 0;
442 }
443 
444 static void native_thread_init(rb_thread_t *th);
445 
446 void
447 Init_native_thread(void)
448 {
449  rb_thread_t *th = GET_THREAD();
450 
451  pthread_key_create(&ruby_native_thread_key, NULL);
452  th->thread_id = pthread_self();
453  native_thread_init(th);
454 #ifdef USE_SIGNAL_THREAD_LIST
455  native_mutex_initialize(&signal_thread_list_lock);
456 #endif
457 #ifndef __native_client__
458  posix_signal(SIGVTALRM, null_func);
459 #endif
460 }
461 
462 static void
463 native_thread_init(rb_thread_t *th)
464 {
465  native_cond_initialize(&th->native_thread_data.sleep_cond, RB_CONDATTR_CLOCK_MONOTONIC);
466  ruby_thread_set_native(th);
467 }
468 
469 static void
470 native_thread_destroy(rb_thread_t *th)
471 {
472  native_cond_destroy(&th->native_thread_data.sleep_cond);
473 }
474 
475 #ifndef USE_THREAD_CACHE
476 #define USE_THREAD_CACHE 0
477 #endif
478 
479 #if USE_THREAD_CACHE
480 static rb_thread_t *register_cached_thread_and_wait(void);
481 #endif
482 
483 #if defined HAVE_PTHREAD_GETATTR_NP || defined HAVE_PTHREAD_ATTR_GET_NP
484 #define STACKADDR_AVAILABLE 1
485 #elif defined HAVE_PTHREAD_GET_STACKADDR_NP && defined HAVE_PTHREAD_GET_STACKSIZE_NP
486 #define STACKADDR_AVAILABLE 1
487 #undef MAINSTACKADDR_AVAILABLE
488 #define MAINSTACKADDR_AVAILABLE 1
489 void *pthread_get_stackaddr_np(pthread_t);
490 size_t pthread_get_stacksize_np(pthread_t);
491 #elif defined HAVE_THR_STKSEGMENT || defined HAVE_PTHREAD_STACKSEG_NP
492 #define STACKADDR_AVAILABLE 1
493 #elif defined HAVE_PTHREAD_GETTHRDS_NP
494 #define STACKADDR_AVAILABLE 1
495 #elif defined __ia64 && defined _HPUX_SOURCE
496 #include <sys/dyntune.h>
497 
498 #define STACKADDR_AVAILABLE 1
499 
500 /*
501  * Do not lower the thread's stack to PTHREAD_STACK_MIN,
502  * otherwise one would receive a 'sendsig: useracc failed.'
503  * and a coredump.
504  */
505 #undef PTHREAD_STACK_MIN
506 
507 #define HAVE_PTHREAD_ATTR_GET_NP 1
508 #undef HAVE_PTHREAD_ATTR_GETSTACK
509 
510 /*
511  * As the PTHREAD_STACK_MIN is undefined and
512  * noone touches the default stacksize,
513  * it is just fine to use the default.
514  */
515 #define pthread_attr_get_np(thid, attr) 0
516 
517 /*
518  * Using value of sp is very rough... To make it more real,
519  * addr would need to be aligned to vps_pagesize.
520  * The vps_pagesize is 'Default user page size (kBytes)'
521  * and could be retrieved by gettune().
522  */
523 static int
524 hpux_attr_getstackaddr(const pthread_attr_t *attr, void **addr)
525 {
526  static uint64_t pagesize;
527  size_t size;
528 
529  if (!pagesize) {
530  if (gettune("vps_pagesize", &pagesize)) {
531  pagesize = 16;
532  }
533  pagesize *= 1024;
534  }
535  pthread_attr_getstacksize(attr, &size);
536  *addr = (void *)((size_t)((char *)_Asm_get_sp() - size) & ~(pagesize - 1));
537  return 0;
538 }
539 #define pthread_attr_getstackaddr(attr, addr) hpux_attr_getstackaddr(attr, addr)
540 #endif
541 
542 #ifndef MAINSTACKADDR_AVAILABLE
543 # ifdef STACKADDR_AVAILABLE
544 # define MAINSTACKADDR_AVAILABLE 1
545 # else
546 # define MAINSTACKADDR_AVAILABLE 0
547 # endif
548 #endif
549 #if MAINSTACKADDR_AVAILABLE && !defined(get_main_stack)
550 # define get_main_stack(addr, size) get_stack(addr, size)
551 #endif
552 
553 #ifdef STACKADDR_AVAILABLE
554 /*
555  * Get the initial address and size of current thread's stack
556  */
557 static int
558 get_stack(void **addr, size_t *size)
559 {
560 #define CHECK_ERR(expr) \
561  {int err = (expr); if (err) return err;}
562 #ifdef HAVE_PTHREAD_GETATTR_NP /* Linux */
563  pthread_attr_t attr;
564  size_t guard = 0;
566  CHECK_ERR(pthread_getattr_np(pthread_self(), &attr));
567 # ifdef HAVE_PTHREAD_ATTR_GETSTACK
568  CHECK_ERR(pthread_attr_getstack(&attr, addr, size));
569  STACK_DIR_UPPER((void)0, (void)(*addr = (char *)*addr + *size));
570 # else
571  CHECK_ERR(pthread_attr_getstackaddr(&attr, addr));
572  CHECK_ERR(pthread_attr_getstacksize(&attr, size));
573 # endif
574  CHECK_ERR(pthread_attr_getguardsize(&attr, &guard));
575  *size -= guard;
576  pthread_attr_destroy(&attr);
577 #elif defined HAVE_PTHREAD_ATTR_GET_NP /* FreeBSD, DragonFly BSD, NetBSD */
578  pthread_attr_t attr;
579  CHECK_ERR(pthread_attr_init(&attr));
580  CHECK_ERR(pthread_attr_get_np(pthread_self(), &attr));
581 # ifdef HAVE_PTHREAD_ATTR_GETSTACK
582  CHECK_ERR(pthread_attr_getstack(&attr, addr, size));
583 # else
584  CHECK_ERR(pthread_attr_getstackaddr(&attr, addr));
585  CHECK_ERR(pthread_attr_getstacksize(&attr, size));
586 # endif
587  STACK_DIR_UPPER((void)0, (void)(*addr = (char *)*addr + *size));
588  pthread_attr_destroy(&attr);
589 #elif (defined HAVE_PTHREAD_GET_STACKADDR_NP && defined HAVE_PTHREAD_GET_STACKSIZE_NP) /* MacOS X */
590  pthread_t th = pthread_self();
591  *addr = pthread_get_stackaddr_np(th);
592  *size = pthread_get_stacksize_np(th);
593 #elif defined HAVE_THR_STKSEGMENT || defined HAVE_PTHREAD_STACKSEG_NP
594  stack_t stk;
595 # if defined HAVE_THR_STKSEGMENT /* Solaris */
596  CHECK_ERR(thr_stksegment(&stk));
597 # else /* OpenBSD */
598  CHECK_ERR(pthread_stackseg_np(pthread_self(), &stk));
599 # endif
600  *addr = stk.ss_sp;
601  *size = stk.ss_size;
602 #elif defined HAVE_PTHREAD_GETTHRDS_NP /* AIX */
603  pthread_t th = pthread_self();
604  struct __pthrdsinfo thinfo;
605  char reg[256];
606  int regsiz=sizeof(reg);
607  CHECK_ERR(pthread_getthrds_np(&th, PTHRDSINFO_QUERY_ALL,
608  &thinfo, sizeof(thinfo),
609  &reg, &regsiz));
610  *addr = thinfo.__pi_stackaddr;
611  *size = thinfo.__pi_stacksize;
612  STACK_DIR_UPPER((void)0, (void)(*addr = (char *)*addr + *size));
613 #else
614 #error STACKADDR_AVAILABLE is defined but not implemented.
615 #endif
616  return 0;
617 #undef CHECK_ERR
618 }
619 #endif
620 
621 static struct {
623  size_t stack_maxsize;
624  VALUE *stack_start;
625 #ifdef __ia64
626  VALUE *register_stack_start;
627 #endif
628 } native_main_thread;
629 
630 #ifdef STACK_END_ADDRESS
631 extern void *STACK_END_ADDRESS;
632 #endif
633 
634 enum {
635  RUBY_STACK_SPACE_LIMIT = 1024 * 1024, /* 1024KB */
636  RUBY_STACK_SPACE_RATIO = 5
637 };
638 
639 static size_t
640 space_size(size_t stack_size)
641 {
642  size_t space_size = stack_size / RUBY_STACK_SPACE_RATIO;
643  if (space_size > RUBY_STACK_SPACE_LIMIT) {
644  return RUBY_STACK_SPACE_LIMIT;
645  }
646  else {
647  return space_size;
648  }
649 }
650 
651 #undef ruby_init_stack
652 /* Set stack bottom of Ruby implementation.
653  *
654  * You must call this function before any heap allocation by Ruby implementation.
655  * Or GC will break living objects */
656 void
657 ruby_init_stack(volatile VALUE *addr
658 #ifdef __ia64
659  , void *bsp
660 #endif
661  )
662 {
663  native_main_thread.id = pthread_self();
664 #if MAINSTACKADDR_AVAILABLE
665  if (native_main_thread.stack_maxsize) return;
666  {
667  void* stackaddr;
668  size_t size;
669  if (get_main_stack(&stackaddr, &size) == 0) {
670  native_main_thread.stack_maxsize = size;
671  native_main_thread.stack_start = stackaddr;
672  return;
673  }
674  }
675 #endif
676 #ifdef STACK_END_ADDRESS
677  native_main_thread.stack_start = STACK_END_ADDRESS;
678 #else
679  if (!native_main_thread.stack_start ||
680  STACK_UPPER((VALUE *)(void *)&addr,
681  native_main_thread.stack_start > addr,
682  native_main_thread.stack_start < addr)) {
683  native_main_thread.stack_start = (VALUE *)addr;
684  }
685 #endif
686 #ifdef __ia64
687  if (!native_main_thread.register_stack_start ||
688  (VALUE*)bsp < native_main_thread.register_stack_start) {
689  native_main_thread.register_stack_start = (VALUE*)bsp;
690  }
691 #endif
692  {
693 #if defined(HAVE_GETRLIMIT)
694 #if defined(PTHREAD_STACK_DEFAULT)
695 # if PTHREAD_STACK_DEFAULT < RUBY_STACK_SPACE*5
696 # error "PTHREAD_STACK_DEFAULT is too small"
697 # endif
698  size_t size = PTHREAD_STACK_DEFAULT;
699 #else
700  size_t size = RUBY_VM_THREAD_VM_STACK_SIZE;
701 #endif
702  size_t space;
703  int pagesize = getpagesize();
704  struct rlimit rlim;
706  if (getrlimit(RLIMIT_STACK, &rlim) == 0) {
707  size = (size_t)rlim.rlim_cur;
708  }
709  addr = native_main_thread.stack_start;
710  if (IS_STACK_DIR_UPPER()) {
711  space = ((size_t)((char *)addr + size) / pagesize) * pagesize - (size_t)addr;
712  }
713  else {
714  space = (size_t)addr - ((size_t)((char *)addr - size) / pagesize + 1) * pagesize;
715  }
716  native_main_thread.stack_maxsize = space;
717 #endif
718  }
719 
720  /* If addr is out of range of main-thread stack range estimation, */
721  /* it should be on co-routine (alternative stack). [Feature #2294] */
722  {
723  void *start, *end;
725 
726  if (IS_STACK_DIR_UPPER()) {
727  start = native_main_thread.stack_start;
728  end = (char *)native_main_thread.stack_start + native_main_thread.stack_maxsize;
729  }
730  else {
731  start = (char *)native_main_thread.stack_start - native_main_thread.stack_maxsize;
732  end = native_main_thread.stack_start;
733  }
734 
735  if ((void *)addr < start || (void *)addr > end) {
736  /* out of range */
737  native_main_thread.stack_start = (VALUE *)addr;
738  native_main_thread.stack_maxsize = 0; /* unknown */
739  }
740  }
741 }
742 
743 #define CHECK_ERR(expr) \
744  {int err = (expr); if (err) {rb_bug_errno(#expr, err);}}
745 
746 static int
747 native_thread_init_stack(rb_thread_t *th)
748 {
749  rb_nativethread_id_t curr = pthread_self();
750 
751  if (pthread_equal(curr, native_main_thread.id)) {
752  th->machine.stack_start = native_main_thread.stack_start;
753  th->machine.stack_maxsize = native_main_thread.stack_maxsize;
754  }
755  else {
756 #ifdef STACKADDR_AVAILABLE
757  void *start;
758  size_t size;
759 
760  if (get_stack(&start, &size) == 0) {
761  th->machine.stack_start = start;
762  th->machine.stack_maxsize = size;
763  }
764 #elif defined get_stack_of
765  if (!th->machine.stack_maxsize) {
766  native_mutex_lock(&th->interrupt_lock);
767  native_mutex_unlock(&th->interrupt_lock);
768  }
769 #else
770  rb_raise(rb_eNotImpError, "ruby engine can initialize only in the main thread");
771 #endif
772  }
773 #ifdef __ia64
774  th->machine.register_stack_start = native_main_thread.register_stack_start;
775  th->machine.stack_maxsize /= 2;
776  th->machine.register_stack_maxsize = th->machine.stack_maxsize;
777 #endif
778  return 0;
779 }
780 
781 #ifndef __CYGWIN__
782 #define USE_NATIVE_THREAD_INIT 1
783 #endif
784 
785 static void *
786 thread_start_func_1(void *th_ptr)
787 {
788 #if USE_THREAD_CACHE
789  thread_start:
790 #endif
791  {
792  rb_thread_t *th = th_ptr;
793 #if !defined USE_NATIVE_THREAD_INIT
794  VALUE stack_start;
795 #endif
796 
797 #if defined USE_NATIVE_THREAD_INIT
798  native_thread_init_stack(th);
799 #endif
800  native_thread_init(th);
801  /* run */
802 #if defined USE_NATIVE_THREAD_INIT
803  thread_start_func_2(th, th->machine.stack_start, rb_ia64_bsp());
804 #else
805  thread_start_func_2(th, &stack_start, rb_ia64_bsp());
806 #endif
807  }
808 #if USE_THREAD_CACHE
809  if (1) {
810  /* cache thread */
811  rb_thread_t *th;
812  if ((th = register_cached_thread_and_wait()) != 0) {
813  th_ptr = (void *)th;
814  th->thread_id = pthread_self();
815  goto thread_start;
816  }
817  }
818 #endif
819  return 0;
820 }
821 
822 struct cached_thread_entry {
823  volatile rb_thread_t **th_area;
825  struct cached_thread_entry *next;
826 };
827 
828 
829 #if USE_THREAD_CACHE
830 static pthread_mutex_t thread_cache_lock = PTHREAD_MUTEX_INITIALIZER;
831 struct cached_thread_entry *cached_thread_root;
832 
833 static rb_thread_t *
834 register_cached_thread_and_wait(void)
835 {
836  rb_nativethread_cond_t cond = { PTHREAD_COND_INITIALIZER, };
837  volatile rb_thread_t *th_area = 0;
838  struct timeval tv;
839  struct timespec ts;
840  struct cached_thread_entry *entry =
841  (struct cached_thread_entry *)malloc(sizeof(struct cached_thread_entry));
842 
843  if (entry == 0) {
844  return 0; /* failed -> terminate thread immediately */
845  }
846 
847  gettimeofday(&tv, 0);
848  ts.tv_sec = tv.tv_sec + 60;
849  ts.tv_nsec = tv.tv_usec * 1000;
850 
851  pthread_mutex_lock(&thread_cache_lock);
852  {
853  entry->th_area = &th_area;
854  entry->cond = &cond;
855  entry->next = cached_thread_root;
856  cached_thread_root = entry;
857 
858  native_cond_timedwait(&cond, &thread_cache_lock, &ts);
859 
860  {
861  struct cached_thread_entry *e, **prev = &cached_thread_root;
862 
863  while ((e = *prev) != 0) {
864  if (e == entry) {
865  *prev = e->next;
866  break;
867  }
868  prev = &e->next;
869  }
870  }
871 
872  free(entry); /* ok */
873  native_cond_destroy(&cond);
874  }
875  pthread_mutex_unlock(&thread_cache_lock);
876 
877  return (rb_thread_t *)th_area;
878 }
879 #endif
880 
881 static int
882 use_cached_thread(rb_thread_t *th)
883 {
884  int result = 0;
885 #if USE_THREAD_CACHE
886  struct cached_thread_entry *entry;
887 
888  if (cached_thread_root) {
889  pthread_mutex_lock(&thread_cache_lock);
890  entry = cached_thread_root;
891  {
892  if (cached_thread_root) {
893  cached_thread_root = entry->next;
894  *entry->th_area = th;
895  result = 1;
896  }
897  }
898  if (result) {
899  native_cond_signal(entry->cond);
900  }
901  pthread_mutex_unlock(&thread_cache_lock);
902  }
903 #endif
904  return result;
905 }
906 
907 static int
908 native_thread_create(rb_thread_t *th)
909 {
910  int err = 0;
911 
912  if (use_cached_thread(th)) {
913  thread_debug("create (use cached thread): %p\n", (void *)th);
914  }
915  else {
916 #ifdef HAVE_PTHREAD_ATTR_INIT
917  pthread_attr_t attr;
918  pthread_attr_t *const attrp = &attr;
919 #else
920  pthread_attr_t *const attrp = NULL;
921 #endif
922  const size_t stack_size = th->vm->default_params.thread_machine_stack_size;
923  const size_t space = space_size(stack_size);
924 
925  th->machine.stack_maxsize = stack_size - space;
926 #ifdef __ia64
927  th->machine.stack_maxsize /= 2;
928  th->machine.register_stack_maxsize = th->machine.stack_maxsize;
929 #endif
930 
931 #ifdef HAVE_PTHREAD_ATTR_INIT
932  CHECK_ERR(pthread_attr_init(&attr));
933 
934 # ifdef PTHREAD_STACK_MIN
935  thread_debug("create - stack size: %lu\n", (unsigned long)stack_size);
936  CHECK_ERR(pthread_attr_setstacksize(&attr, stack_size));
937 # endif
938 
939 # ifdef HAVE_PTHREAD_ATTR_SETINHERITSCHED
940  CHECK_ERR(pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED));
941 # endif
942  CHECK_ERR(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED));
943 #endif
944 #ifdef get_stack_of
945  native_mutex_lock(&th->interrupt_lock);
946 #endif
947  err = pthread_create(&th->thread_id, attrp, thread_start_func_1, th);
948 #ifdef get_stack_of
949  if (!err) {
950  get_stack_of(th->thread_id,
951  &th->machine.stack_start,
952  &th->machine.stack_maxsize);
953  }
954  native_mutex_unlock(&th->interrupt_lock);
955 #endif
956  thread_debug("create: %p (%d)\n", (void *)th, err);
957 #ifdef HAVE_PTHREAD_ATTR_INIT
958  CHECK_ERR(pthread_attr_destroy(&attr));
959 #endif
960  }
961  return err;
962 }
963 
964 static void
965 native_thread_join(pthread_t th)
966 {
967  int err = pthread_join(th, 0);
968  if (err) {
969  rb_raise(rb_eThreadError, "native_thread_join() failed (%d)", err);
970  }
971 }
972 
973 
974 #if USE_NATIVE_THREAD_PRIORITY
975 
976 static void
977 native_thread_apply_priority(rb_thread_t *th)
978 {
979 #if defined(_POSIX_PRIORITY_SCHEDULING) && (_POSIX_PRIORITY_SCHEDULING > 0)
980  struct sched_param sp;
981  int policy;
982  int priority = 0 - th->priority;
983  int max, min;
984  pthread_getschedparam(th->thread_id, &policy, &sp);
985  max = sched_get_priority_max(policy);
986  min = sched_get_priority_min(policy);
987 
988  if (min > priority) {
989  priority = min;
990  }
991  else if (max < priority) {
992  priority = max;
993  }
994 
995  sp.sched_priority = priority;
996  pthread_setschedparam(th->thread_id, policy, &sp);
997 #else
998  /* not touched */
999 #endif
1000 }
1001 
1002 #endif /* USE_NATIVE_THREAD_PRIORITY */
1003 
1004 static int
1005 native_fd_select(int n, rb_fdset_t *readfds, rb_fdset_t *writefds, rb_fdset_t *exceptfds, struct timeval *timeout, rb_thread_t *th)
1006 {
1007  return rb_fd_select(n, readfds, writefds, exceptfds, timeout);
1008 }
1009 
1010 static void
1011 ubf_pthread_cond_signal(void *ptr)
1012 {
1013  rb_thread_t *th = (rb_thread_t *)ptr;
1014  thread_debug("ubf_pthread_cond_signal (%p)\n", (void *)th);
1015  native_cond_signal(&th->native_thread_data.sleep_cond);
1016 }
1017 
1018 static void
1019 native_sleep(rb_thread_t *th, struct timeval *timeout_tv)
1020 {
1021  struct timespec timeout;
1022  pthread_mutex_t *lock = &th->interrupt_lock;
1024 
1025  if (timeout_tv) {
1026  struct timespec timeout_rel;
1027 
1028  timeout_rel.tv_sec = timeout_tv->tv_sec;
1029  timeout_rel.tv_nsec = timeout_tv->tv_usec * 1000;
1030 
1031  /* Solaris cond_timedwait() return EINVAL if an argument is greater than
1032  * current_time + 100,000,000. So cut up to 100,000,000. This is
1033  * considered as a kind of spurious wakeup. The caller to native_sleep
1034  * should care about spurious wakeup.
1035  *
1036  * See also [Bug #1341] [ruby-core:29702]
1037  * http://download.oracle.com/docs/cd/E19683-01/816-0216/6m6ngupgv/index.html
1038  */
1039  if (timeout_rel.tv_sec > 100000000) {
1040  timeout_rel.tv_sec = 100000000;
1041  timeout_rel.tv_nsec = 0;
1042  }
1043 
1044  timeout = native_cond_timeout(cond, timeout_rel);
1045  }
1046 
1047  GVL_UNLOCK_BEGIN();
1048  {
1049  pthread_mutex_lock(lock);
1050  th->unblock.func = ubf_pthread_cond_signal;
1051  th->unblock.arg = th;
1052 
1053  if (RUBY_VM_INTERRUPTED(th)) {
1054  /* interrupted. return immediate */
1055  thread_debug("native_sleep: interrupted before sleep\n");
1056  }
1057  else {
1058  if (!timeout_tv)
1059  native_cond_wait(cond, lock);
1060  else
1061  native_cond_timedwait(cond, lock, &timeout);
1062  }
1063  th->unblock.func = 0;
1064  th->unblock.arg = 0;
1065 
1066  pthread_mutex_unlock(lock);
1067  }
1068  GVL_UNLOCK_END();
1069 
1070  thread_debug("native_sleep done\n");
1071 }
1072 
1073 #ifdef USE_SIGNAL_THREAD_LIST
1074 struct signal_thread_list {
1075  rb_thread_t *th;
1076  struct signal_thread_list *prev;
1077  struct signal_thread_list *next;
1078 };
1079 
1080 static struct signal_thread_list signal_thread_list_anchor = {
1081  0, 0, 0,
1082 };
1083 
1084 #define FGLOCK(lock, body) do { \
1085  native_mutex_lock(lock); \
1086  { \
1087  body; \
1088  } \
1089  native_mutex_unlock(lock); \
1090 } while (0)
1091 
1092 #if 0 /* for debug */
1093 static void
1094 print_signal_list(char *str)
1095 {
1096  struct signal_thread_list *list =
1097  signal_thread_list_anchor.next;
1098  thread_debug("list (%s)> ", str);
1099  while (list) {
1100  thread_debug("%p (%p), ", list->th, list->th->thread_id);
1101  list = list->next;
1102  }
1103  thread_debug("\n");
1104 }
1105 #endif
1106 
1107 static void
1108 add_signal_thread_list(rb_thread_t *th)
1109 {
1111  FGLOCK(&signal_thread_list_lock, {
1112  struct signal_thread_list *list =
1113  malloc(sizeof(struct signal_thread_list));
1114 
1115  if (list == 0) {
1116  fprintf(stderr, "[FATAL] failed to allocate memory\n");
1117  exit(EXIT_FAILURE);
1118  }
1119 
1120  list->th = th;
1121 
1122  list->prev = &signal_thread_list_anchor;
1123  list->next = signal_thread_list_anchor.next;
1124  if (list->next) {
1125  list->next->prev = list;
1126  }
1127  signal_thread_list_anchor.next = list;
1129  });
1130  }
1131 }
1132 
1133 static void
1134 remove_signal_thread_list(rb_thread_t *th)
1135 {
1137  FGLOCK(&signal_thread_list_lock, {
1138  struct signal_thread_list *list =
1139  (struct signal_thread_list *)
1141 
1142  list->prev->next = list->next;
1143  if (list->next) {
1144  list->next->prev = list->prev;
1145  }
1147  list->th = 0;
1148  free(list); /* ok */
1149  });
1150  }
1151 }
1152 
1153 static void
1154 ubf_select_each(rb_thread_t *th)
1155 {
1156  thread_debug("ubf_select_each (%p)\n", (void *)th->thread_id);
1157  if (th) {
1158  pthread_kill(th->thread_id, SIGVTALRM);
1159  }
1160 }
1161 
1162 static void
1163 ubf_select(void *ptr)
1164 {
1165  rb_thread_t *th = (rb_thread_t *)ptr;
1166  add_signal_thread_list(th);
1167 
1168  /*
1169  * ubf_select_each() doesn't guarantee to wake up the target thread.
1170  * Therefore, we need to activate timer thread when called from
1171  * Thread#kill etc.
1172  * In the other hands, we shouldn't call rb_thread_wakeup_timer_thread()
1173  * if running on timer thread because it may make endless wakeups.
1174  */
1175  if (pthread_self() != timer_thread_id)
1177  ubf_select_each(th);
1178 }
1179 
1180 static void
1181 ping_signal_thread_list(void)
1182 {
1183  if (signal_thread_list_anchor.next) {
1184  FGLOCK(&signal_thread_list_lock, {
1185  struct signal_thread_list *list;
1186 
1187  list = signal_thread_list_anchor.next;
1188  while (list) {
1189  ubf_select_each(list->th);
1190  list = list->next;
1191  }
1192  });
1193  }
1194 }
1195 
1196 static int
1197 check_signal_thread_list(void)
1198 {
1199  if (signal_thread_list_anchor.next)
1200  return 1;
1201  else
1202  return 0;
1203 }
1204 #else /* USE_SIGNAL_THREAD_LIST */
1205 #define add_signal_thread_list(th) (void)(th)
1206 #define remove_signal_thread_list(th) (void)(th)
1207 #define ubf_select 0
1208 static void ping_signal_thread_list(void) { return; }
1209 static int check_signal_thread_list(void) { return 0; }
1210 #endif /* USE_SIGNAL_THREAD_LIST */
1211 
1212 #define TT_DEBUG 0
1213 #define WRITE_CONST(fd, str) (void)(write((fd),(str),sizeof(str)-1)<0)
1214 
1215 /* 100ms. 10ms is too small for user level thread scheduling
1216  * on recent Linux (tested on 2.6.35)
1217  */
1218 #define TIME_QUANTUM_USEC (100 * 1000)
1219 
1220 #if USE_SLEEPY_TIMER_THREAD
1221 static int timer_thread_pipe[2] = {-1, -1};
1222 static int timer_thread_pipe_low[2] = {-1, -1}; /* low priority */
1223 static int timer_thread_pipe_owner_process;
1224 
1225 /* only use signal-safe system calls here */
1226 static void
1227 rb_thread_wakeup_timer_thread_fd(int fd)
1228 {
1229  ssize_t result;
1230 
1231  /* already opened */
1232  if (timer_thread_pipe_owner_process == getpid()) {
1233  const char *buff = "!";
1234  retry:
1235  if ((result = write(fd, buff, 1)) <= 0) {
1236  switch (errno) {
1237  case EINTR: goto retry;
1238  case EAGAIN:
1239 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
1240  case EWOULDBLOCK:
1241 #endif
1242  break;
1243  default:
1244  rb_async_bug_errno("rb_thread_wakeup_timer_thread - write", errno);
1245  }
1246  }
1247  if (TT_DEBUG) WRITE_CONST(2, "rb_thread_wakeup_timer_thread: write\n");
1248  }
1249  else {
1250  /* ignore wakeup */
1251  }
1252 }
1253 
1254 void
1256 {
1257  rb_thread_wakeup_timer_thread_fd(timer_thread_pipe[1]);
1258 }
1259 
1260 static void
1261 rb_thread_wakeup_timer_thread_low(void)
1262 {
1263  rb_thread_wakeup_timer_thread_fd(timer_thread_pipe_low[1]);
1264 }
1265 
1266 /* VM-dependent API is not available for this function */
1267 static void
1268 consume_communication_pipe(int fd)
1269 {
1270 #define CCP_READ_BUFF_SIZE 1024
1271  /* buffer can be shared because no one refers to them. */
1272  static char buff[CCP_READ_BUFF_SIZE];
1273  ssize_t result;
1274 
1275  while (1) {
1276  result = read(fd, buff, sizeof(buff));
1277  if (result == 0) {
1278  return;
1279  }
1280  else if (result < 0) {
1281  switch (errno) {
1282  case EINTR:
1283  continue; /* retry */
1284  case EAGAIN:
1285  return;
1286  default:
1287  rb_async_bug_errno("consume_communication_pipe: read\n", errno);
1288  }
1289  }
1290  }
1291 }
1292 
1293 static void
1294 close_communication_pipe(int pipes[2])
1295 {
1296  if (close(pipes[0]) < 0) {
1297  rb_bug_errno("native_stop_timer_thread - close(ttp[0])", errno);
1298  }
1299  if (close(pipes[1]) < 0) {
1300  rb_bug_errno("native_stop_timer_thread - close(ttp[1])", errno);
1301  }
1302  pipes[0] = pipes[1] = -1;
1303 }
1304 
1305 static void
1306 set_nonblock(int fd)
1307 {
1308  int oflags;
1309  int err;
1310 
1311  oflags = fcntl(fd, F_GETFL);
1312  if (oflags == -1)
1313  rb_sys_fail(0);
1314  oflags |= O_NONBLOCK;
1315  err = fcntl(fd, F_SETFL, oflags);
1316  if (err == -1)
1317  rb_sys_fail(0);
1318 }
1319 
1320 static void
1321 setup_communication_pipe_internal(int pipes[2])
1322 {
1323  int err;
1324 
1325  if (pipes[0] != -1) {
1326  /* close pipe of parent process */
1327  close_communication_pipe(pipes);
1328  }
1329 
1330  err = rb_cloexec_pipe(pipes);
1331  if (err != 0) {
1332  rb_bug_errno("setup_communication_pipe: Failed to create communication pipe for timer thread", errno);
1333  }
1334  rb_update_max_fd(pipes[0]);
1335  rb_update_max_fd(pipes[1]);
1336  set_nonblock(pipes[0]);
1337  set_nonblock(pipes[1]);
1338 }
1339 
1340 /* communication pipe with timer thread and signal handler */
1341 static void
1342 setup_communication_pipe(void)
1343 {
1344  if (timer_thread_pipe_owner_process == getpid()) {
1345  /* already set up. */
1346  return;
1347  }
1348  setup_communication_pipe_internal(timer_thread_pipe);
1349  setup_communication_pipe_internal(timer_thread_pipe_low);
1350 
1351  /* validate pipe on this process */
1352  timer_thread_pipe_owner_process = getpid();
1353 }
1354 
1361 static inline void
1362 timer_thread_sleep(rb_global_vm_lock_t* gvl)
1363 {
1364  int result;
1365  int need_polling;
1366  struct pollfd pollfds[2];
1367 
1368  pollfds[0].fd = timer_thread_pipe[0];
1369  pollfds[0].events = POLLIN;
1370  pollfds[1].fd = timer_thread_pipe_low[0];
1371  pollfds[1].events = POLLIN;
1372 
1373  need_polling = check_signal_thread_list();
1374 
1375  if (gvl->waiting > 0 || need_polling) {
1376  /* polling (TIME_QUANTUM_USEC usec) */
1377  result = poll(pollfds, 1, TIME_QUANTUM_USEC/1000);
1378  }
1379  else {
1380  /* wait (infinite) */
1381  result = poll(pollfds, numberof(pollfds), -1);
1382  }
1383 
1384  if (result == 0) {
1385  /* maybe timeout */
1386  }
1387  else if (result > 0) {
1388  consume_communication_pipe(timer_thread_pipe[0]);
1389  consume_communication_pipe(timer_thread_pipe_low[0]);
1390  }
1391  else { /* result < 0 */
1392  switch (errno) {
1393  case EBADF:
1394  case EINVAL:
1395  case ENOMEM: /* from Linux man */
1396  case EFAULT: /* from FreeBSD man */
1397  rb_async_bug_errno("thread_timer: select", errno);
1398  default:
1399  /* ignore */;
1400  }
1401  }
1402 }
1403 
1404 #else /* USE_SLEEPY_TIMER_THREAD */
1405 # define PER_NANO 1000000000
1406 void rb_thread_wakeup_timer_thread(void) {}
1407 static void rb_thread_wakeup_timer_thread_low(void) {}
1408 
1409 static pthread_mutex_t timer_thread_lock;
1410 static rb_nativethread_cond_t timer_thread_cond;
1411 
1412 static inline void
1413 timer_thread_sleep(rb_global_vm_lock_t* unused)
1414 {
1415  struct timespec ts;
1416  ts.tv_sec = 0;
1417  ts.tv_nsec = TIME_QUANTUM_USEC * 1000;
1418  ts = native_cond_timeout(&timer_thread_cond, ts);
1419 
1420  native_cond_timedwait(&timer_thread_cond, &timer_thread_lock, &ts);
1421 }
1422 #endif /* USE_SLEEPY_TIMER_THREAD */
1423 
1424 #if defined(__linux__) && defined(PR_SET_NAME)
1425 # undef SET_THREAD_NAME
1426 # define SET_THREAD_NAME(name) prctl(PR_SET_NAME, name)
1427 #elif !defined(SET_THREAD_NAME)
1428 # define SET_THREAD_NAME(name) (void)0
1429 #endif
1430 
1431 static void *
1432 thread_timer(void *p)
1433 {
1435 
1436  if (TT_DEBUG) WRITE_CONST(2, "start timer thread\n");
1437 
1438  SET_THREAD_NAME("ruby-timer-thr");
1439 
1440 #if !USE_SLEEPY_TIMER_THREAD
1441  native_mutex_initialize(&timer_thread_lock);
1442  native_cond_initialize(&timer_thread_cond, RB_CONDATTR_CLOCK_MONOTONIC);
1443  native_mutex_lock(&timer_thread_lock);
1444 #endif
1445  while (system_working > 0) {
1446 
1447  /* timer function */
1448  ping_signal_thread_list();
1450 
1451  if (TT_DEBUG) WRITE_CONST(2, "tick\n");
1452 
1453  /* wait */
1454  timer_thread_sleep(gvl);
1455  }
1456 #if !USE_SLEEPY_TIMER_THREAD
1457  native_mutex_unlock(&timer_thread_lock);
1458  native_cond_destroy(&timer_thread_cond);
1459  native_mutex_destroy(&timer_thread_lock);
1460 #endif
1461 
1462  if (TT_DEBUG) WRITE_CONST(2, "finish timer thread\n");
1463  return NULL;
1464 }
1465 
1466 static void
1467 rb_thread_create_timer_thread(void)
1468 {
1469  if (!timer_thread_id) {
1470  int err;
1471 #ifdef HAVE_PTHREAD_ATTR_INIT
1472  pthread_attr_t attr;
1473 
1474  err = pthread_attr_init(&attr);
1475  if (err != 0) {
1476  fprintf(stderr, "[FATAL] Failed to initialize pthread attr: %s\n", strerror(err));
1477  exit(EXIT_FAILURE);
1478  }
1479 # ifdef PTHREAD_STACK_MIN
1480  {
1481  const size_t min_size = (4096 * 4);
1482  /* Allocate the machine stack for the timer thread
1483  * at least 16KB (4 pages). FreeBSD 8.2 AMD64 causes
1484  * machine stack overflow only with PTHREAD_STACK_MIN.
1485  */
1486  size_t stack_size = PTHREAD_STACK_MIN; /* may be dynamic, get only once */
1487  if (stack_size < min_size) stack_size = min_size;
1488  if (THREAD_DEBUG) stack_size += BUFSIZ;
1489  pthread_attr_setstacksize(&attr, stack_size);
1490  }
1491 # endif
1492 #endif
1493 
1494 #if USE_SLEEPY_TIMER_THREAD
1495  setup_communication_pipe();
1496 #endif /* USE_SLEEPY_TIMER_THREAD */
1497 
1498  /* create timer thread */
1499  if (timer_thread_id) {
1500  rb_bug("rb_thread_create_timer_thread: Timer thread was already created\n");
1501  }
1502 #ifdef HAVE_PTHREAD_ATTR_INIT
1503  err = pthread_create(&timer_thread_id, &attr, thread_timer, &GET_VM()->gvl);
1504 #else
1505  err = pthread_create(&timer_thread_id, NULL, thread_timer, &GET_VM()->gvl);
1506 #endif
1507  if (err != 0) {
1508  fprintf(stderr, "[FATAL] Failed to create timer thread: %s\n", strerror(err));
1509  exit(EXIT_FAILURE);
1510  }
1511 #ifdef HAVE_PTHREAD_ATTR_INIT
1512  pthread_attr_destroy(&attr);
1513 #endif
1514  }
1515 }
1516 
1517 static int
1518 native_stop_timer_thread(int close_anyway)
1519 {
1520  int stopped;
1521  stopped = --system_working <= 0;
1522 
1523  if (TT_DEBUG) fprintf(stderr, "stop timer thread\n");
1524  if (stopped) {
1525  /* join */
1527  native_thread_join(timer_thread_id);
1528  if (TT_DEBUG) fprintf(stderr, "joined timer thread\n");
1529  timer_thread_id = 0;
1530 
1531  /* close communication pipe */
1532  if (close_anyway) {
1533  /* TODO: Uninstall all signal handlers or mask all signals.
1534  * This pass is cleaning phase (terminate ruby process).
1535  * To avoid such race, we skip to close communication
1536  * pipe. OS will close it at process termination.
1537  * It may not good practice, but pragmatic.
1538  * We remain it is TODO.
1539  */
1540  /* close_communication_pipe(); */
1541  }
1542  }
1543  return stopped;
1544 }
1545 
1546 static void
1547 native_reset_timer_thread(void)
1548 {
1549  if (TT_DEBUG) fprintf(stderr, "reset timer thread\n");
1550 }
1551 
1552 #ifdef HAVE_SIGALTSTACK
1553 int
1554 ruby_stack_overflowed_p(const rb_thread_t *th, const void *addr)
1555 {
1556  void *base;
1557  size_t size;
1558  const size_t water_mark = 1024 * 1024;
1560 
1561 #ifdef STACKADDR_AVAILABLE
1562  if (get_stack(&base, &size) == 0) {
1563 # ifdef __APPLE__
1564  if (pthread_equal(th->thread_id, native_main_thread.id)) {
1565  struct rlimit rlim;
1566  if (getrlimit(RLIMIT_STACK, &rlim) == 0 && rlim.rlim_cur > size) {
1567  size = (size_t)rlim.rlim_cur;
1568  }
1569  }
1570 # endif
1571  base = (char *)base + STACK_DIR_UPPER(+size, -size);
1572  }
1573  else
1574 #endif
1575  if (th) {
1576  size = th->machine.stack_maxsize;
1577  base = (char *)th->machine.stack_start - STACK_DIR_UPPER(0, size);
1578  }
1579  else {
1580  return 0;
1581  }
1582  size /= RUBY_STACK_SPACE_RATIO;
1583  if (size > water_mark) size = water_mark;
1584  if (IS_STACK_DIR_UPPER()) {
1585  if (size > ~(size_t)base+1) size = ~(size_t)base+1;
1586  if (addr > base && addr <= (void *)((char *)base + size)) return 1;
1587  }
1588  else {
1589  if (size > (size_t)base) size = (size_t)base;
1590  if (addr > (void *)((char *)base - size) && addr <= base) return 1;
1591  }
1592  return 0;
1593 }
1594 #endif
1595 
1596 int
1597 rb_reserved_fd_p(int fd)
1598 {
1599 #if USE_SLEEPY_TIMER_THREAD
1600  if (fd == timer_thread_pipe[0] ||
1601  fd == timer_thread_pipe[1] ||
1602  fd == timer_thread_pipe_low[0] ||
1603  fd == timer_thread_pipe_low[1]) {
1604  return 1;
1605  }
1606  else {
1607  return 0;
1608  }
1609 #else
1610  return 0;
1611 #endif
1612 }
1613 
1616 {
1617  return pthread_self();
1618 }
1619 
1620 #endif /* THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION */
#define cond(node)
Definition: ripper.c:427
rb_nativethread_cond_t sleep_cond
RUBY_SYMBOL_EXPORT_BEGIN rb_nativethread_id_t rb_nativethread_self()
rb_vm_t * vm
Definition: vm_core.h:526
void rb_bug(const char *fmt,...)
Definition: error.c:327
int gettimeofday(struct timeval *, struct timezone *)
Definition: win32.c:4307
void rb_update_max_fd(int fd)
Definition: io.c:183
volatile unsigned long waiting
static int max(int a, int b)
Definition: strftime.c:141
rb_unblock_function_t * func
Definition: vm_core.h:500
#define THREAD_DEBUG
Definition: thread.c:74
rb_nativethread_cond_t switch_cond
#define CLOCK_MONOTONIC
Definition: win32.h:129
const int id
Definition: nkf.c:209
long tv_sec
Definition: ossl_asn1.c:17
int fcntl(int, int,...)
Definition: win32.c:4085
void rb_async_bug_errno(const char *mesg, int errno_arg)
Definition: error.c:371
#define STACK_UPPER(x, a, b)
Definition: gc.h:74
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1854
pthread_mutex_t rb_nativethread_lock_t
static volatile int system_working
Definition: thread.c:95
struct rb_thread_struct::@169 machine
time_t tv_sec
Definition: missing.h:51
sighandler_t posix_signal(int signum, sighandler_t handler)
Definition: missing-pips.c:43
unsigned long long uint64_t
Definition: sha2.h:102
fd_set rb_fdset_t
Definition: intern.h:348
#define RUBY_VM_THREAD_VM_STACK_SIZE
Definition: vm_core.h:431
void rb_thread_wakeup_timer_thread(void)
int getrlimit(int resource, struct rlimit *rlp)
Definition: missing-pips.c:48
#define F_SETFL
Definition: win32.h:622
long tv_usec
Definition: ossl_asn1.c:18
#define PRIdVALUE
Definition: ruby.h:132
long tv_nsec
Definition: missing.h:52
#define UNLIKELY(x)
Definition: vm_core.h:109
static char msg[50]
Definition: strerror.c:8
#define thread_debug
Definition: thread.c:210
if((ID)(DISPID) nameid!=nameid)
Definition: win32ole.c:770
int err
Definition: win32.c:114
#define EXIT_FAILURE
Definition: eval_intern.h:24
#define GVL_UNLOCK_BEGIN()
Definition: thread.c:136
rb_nativethread_cond_t cond
#define numberof(array)
Definition: etc.c:595
int errno
#define STACK_DIR_UPPER(a, b)
Definition: gc.h:82
#define CLOCK_REALTIME
Definition: win32.h:128
pthread_t rb_nativethread_id_t
#define malloc
Definition: ripper.c:96
int pthread_kill(pthread_t thread, int sig)
Definition: missing-pips.c:37
#define GVL_UNLOCK_END()
Definition: thread.c:141
unsigned long VALUE
Definition: ruby.h:88
#define STACK_GROW_DIR_DETECTION
Definition: gc.h:81
static VALUE result
Definition: nkf.c:40
void Init_native_thread(void)
void rb_bug_errno(const char *mesg, int errno_arg)
Definition: error.c:350
int clock_gettime(clockid_t, struct timespec *)
Definition: win32.c:4319
void ruby_init_stack(volatile VALUE *)
rb_nativethread_cond_t switch_wait_cond
static void timer_thread_function(void *)
Definition: thread.c:3825
void rb_sys_fail(const char *mesg)
Definition: error.c:1973
int rb_reserved_fd_p(int fd)
#define WRITE_CONST(fd, str)
Definition: error.c:368
int rb_cloexec_pipe(int fildes[2])
Definition: io.c:286
#define thread_start_func_2(th, st, rst)
Definition: thread.c:214
int size
Definition: encoding.c:49
struct rb_vm_struct::@168 default_params
VALUE * stack_start
Definition: vm_core.h:621
struct rb_unblock_callback unblock
Definition: vm_core.h:589
#define rb_fd_select(n, rfds, wfds, efds, timeout)
Definition: intern.h:361
rb_nativethread_id_t thread_id
Definition: vm_core.h:561
RUBY_EXTERN char * strerror(int)
Definition: strerror.c:11
#define O_NONBLOCK
Definition: win32.h:626
struct rb_encoding_entry * list
Definition: encoding.c:47
#define ETIMEDOUT
Definition: win32.h:584
native_thread_data_t native_thread_data
Definition: vm_core.h:566
#define EWOULDBLOCK
Definition: rubysocket.h:126
size_t thread_machine_stack_size
Definition: vm_core.h:421
static VALUE thread_start(VALUE klass, VALUE args)
Definition: thread.c:713
pthread_cond_t cond
VALUE rb_eNotImpError
Definition: error.c:558
rb_global_vm_lock_t gvl
Definition: vm_core.h:351
#define RUBY_VM_INTERRUPTED(th)
Definition: vm_core.h:960
rb_nativethread_lock_t interrupt_lock
Definition: vm_core.h:587
size_t stack_maxsize
Definition: vm_core.h:623
#define NULL
Definition: _sdbm.c:103
static rb_thread_t * GET_THREAD(void)
Definition: vm_core.h:924
free(psz)
VALUE rb_eThreadError
Definition: eval.c:730
#define IS_STACK_DIR_UPPER()
Definition: gc.h:84
#define SIGNED_VALUE
Definition: ruby.h:90
#define GET_VM()
Definition: vm_core.h:917