12 #ifdef THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION
16 #ifdef HAVE_SYS_RESOURCE_H
17 #include <sys/resource.h>
19 #ifdef HAVE_THR_STKSEGMENT
24 #elif HAVE_SYS_FCNTL_H
25 #include <sys/fcntl.h>
27 #ifdef HAVE_SYS_PRCTL_H
28 #include <sys/prctl.h>
30 #if defined(__native_client__) && defined(NACL_NEWLIB)
33 #if defined(HAVE_SYS_TIME_H)
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);
47 static void rb_thread_wakeup_timer_thread_low(
void);
48 static pthread_t timer_thread_id;
50 #define RB_CONDATTR_CLOCK_MONOTONIC 1
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
57 #define USE_MONOTONIC_COND 0
60 #if defined(HAVE_POLL) && defined(HAVE_FCNTL) && defined(F_GETFL) && defined(F_SETFL) && defined(O_NONBLOCK) && !defined(__native_client__)
62 # define USE_SLEEPY_TIMER_THREAD 1
64 # define USE_SLEEPY_TIMER_THREAD 0
79 rb_thread_wakeup_timer_thread_low();
100 native_mutex_lock(&vm->
gvl.
lock);
101 gvl_acquire_common(vm);
102 native_mutex_unlock(&vm->
gvl.
lock);
106 gvl_release_common(
rb_vm_t *vm)
110 native_cond_signal(&vm->
gvl.
cond);
116 native_mutex_lock(&vm->
gvl.
lock);
117 gvl_release_common(vm);
118 native_mutex_unlock(&vm->
gvl.
lock);
124 native_mutex_lock(&vm->
gvl.
lock);
126 gvl_release_common(vm);
144 native_mutex_unlock(&vm->
gvl.
lock);
146 native_mutex_lock(&vm->
gvl.
lock);
151 gvl_acquire_common(vm);
152 native_mutex_unlock(&vm->
gvl.
lock);
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);
173 native_cond_destroy(&vm->
gvl.
cond);
174 native_mutex_destroy(&vm->
gvl.
lock);
184 #define NATIVE_MUTEX_LOCK_DEBUG 0
187 mutex_debug(
const char *
msg, pthread_mutex_t *lock)
189 if (NATIVE_MUTEX_LOCK_DEBUG) {
191 static pthread_mutex_t dbglock = PTHREAD_MUTEX_INITIALIZER;
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);}
200 native_mutex_lock(pthread_mutex_t *lock)
203 mutex_debug(
"lock", lock);
204 if ((r = pthread_mutex_lock(lock)) != 0) {
210 native_mutex_unlock(pthread_mutex_t *lock)
213 mutex_debug(
"unlock", lock);
214 if ((r = pthread_mutex_unlock(lock)) != 0) {
220 native_mutex_trylock(pthread_mutex_t *lock)
223 mutex_debug(
"trylock", lock);
224 if ((r = pthread_mutex_trylock(lock)) != 0) {
236 native_mutex_initialize(pthread_mutex_t *lock)
238 int r = pthread_mutex_init(lock, 0);
239 mutex_debug(
"init", lock);
246 native_mutex_destroy(pthread_mutex_t *lock)
248 int r = pthread_mutex_destroy(lock);
249 mutex_debug(
"destroy", lock);
258 #ifdef HAVE_PTHREAD_COND_INIT
260 # if USE_MONOTONIC_COND
261 pthread_condattr_t attr;
263 pthread_condattr_init(&attr);
266 if (flags & RB_CONDATTR_CLOCK_MONOTONIC) {
273 r = pthread_cond_init(&cond->
cond, &attr);
274 pthread_condattr_destroy(&attr);
276 r = pthread_cond_init(&cond->
cond,
NULL);
289 #ifdef HAVE_PTHREAD_COND_INIT
290 int r = pthread_cond_destroy(&cond->
cond);
312 r = pthread_cond_signal(&cond->
cond);
313 }
while (r == EAGAIN);
324 r = pthread_cond_broadcast(&cond->
cond);
325 }
while (r == EAGAIN);
334 int r = pthread_cond_wait(&cond->
cond, mutex);
352 r = pthread_cond_timedwait(&cond->
cond, mutex, ts);
353 }
while (r == EINTR);
370 #if USE_MONOTONIC_COND
385 now.tv_sec = tv.tv_sec;
386 now.tv_nsec = tv.tv_usec * 1000;
388 #if USE_MONOTONIC_COND
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;
396 if (timeout.tv_nsec >= 1000*1000*1000) {
398 timeout.tv_nsec -= 1000*1000*1000;
401 if (timeout.tv_sec < now.tv_sec)
402 timeout.tv_sec = TIMET_MAX;
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()
412 #define native_thread_yield() ((void)0)
415 #if defined(SIGVTALRM) && !defined(__CYGWIN__) && !defined(__SYMBIAN32__)
416 #define USE_SIGNAL_THREAD_LIST 1
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);
424 static pthread_key_t ruby_native_thread_key;
433 ruby_thread_from_native(
void)
435 return pthread_getspecific(ruby_native_thread_key);
441 return pthread_setspecific(ruby_native_thread_key, th) == 0;
451 pthread_key_create(&ruby_native_thread_key,
NULL);
453 native_thread_init(th);
454 #ifdef USE_SIGNAL_THREAD_LIST
455 native_mutex_initialize(&signal_thread_list_lock);
457 #ifndef __native_client__
466 ruby_thread_set_native(th);
475 #ifndef USE_THREAD_CACHE
476 #define USE_THREAD_CACHE 0
480 static rb_thread_t *register_cached_thread_and_wait(
void);
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>
498 #define STACKADDR_AVAILABLE 1
505 #undef PTHREAD_STACK_MIN
507 #define HAVE_PTHREAD_ATTR_GET_NP 1
508 #undef HAVE_PTHREAD_ATTR_GETSTACK
515 #define pthread_attr_get_np(thid, attr) 0
524 hpux_attr_getstackaddr(
const pthread_attr_t *attr,
void **addr)
530 if (gettune(
"vps_pagesize", &pagesize)) {
535 pthread_attr_getstacksize(attr, &size);
536 *addr = (
void *)((
size_t)((
char *)_Asm_get_sp() -
size) & ~(pagesize - 1));
539 #define pthread_attr_getstackaddr(attr, addr) hpux_attr_getstackaddr(attr, addr)
542 #ifndef MAINSTACKADDR_AVAILABLE
543 # ifdef STACKADDR_AVAILABLE
544 # define MAINSTACKADDR_AVAILABLE 1
546 # define MAINSTACKADDR_AVAILABLE 0
549 #if MAINSTACKADDR_AVAILABLE && !defined(get_main_stack)
550 # define get_main_stack(addr, size) get_stack(addr, size)
553 #ifdef STACKADDR_AVAILABLE
558 get_stack(
void **addr,
size_t *size)
560 #define CHECK_ERR(expr) \
561 {int err = (expr); if (err) return err;}
562 #ifdef HAVE_PTHREAD_GETATTR_NP
566 CHECK_ERR(pthread_getattr_np(pthread_self(), &attr));
567 # ifdef HAVE_PTHREAD_ATTR_GETSTACK
568 CHECK_ERR(pthread_attr_getstack(&attr, addr, size));
571 CHECK_ERR(pthread_attr_getstackaddr(&attr, addr));
572 CHECK_ERR(pthread_attr_getstacksize(&attr, size));
574 CHECK_ERR(pthread_attr_getguardsize(&attr, &guard));
576 pthread_attr_destroy(&attr);
577 #elif defined HAVE_PTHREAD_ATTR_GET_NP
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));
584 CHECK_ERR(pthread_attr_getstackaddr(&attr, addr));
585 CHECK_ERR(pthread_attr_getstacksize(&attr, size));
588 pthread_attr_destroy(&attr);
589 #elif (defined HAVE_PTHREAD_GET_STACKADDR_NP && defined HAVE_PTHREAD_GET_STACKSIZE_NP)
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
595 # if defined HAVE_THR_STKSEGMENT
596 CHECK_ERR(thr_stksegment(&stk));
598 CHECK_ERR(pthread_stackseg_np(pthread_self(), &stk));
602 #elif defined HAVE_PTHREAD_GETTHRDS_NP
603 pthread_t th = pthread_self();
604 struct __pthrdsinfo thinfo;
606 int regsiz=
sizeof(reg);
607 CHECK_ERR(pthread_getthrds_np(&th, PTHRDSINFO_QUERY_ALL,
608 &thinfo,
sizeof(thinfo),
610 *addr = thinfo.__pi_stackaddr;
611 *size = thinfo.__pi_stacksize;
614 #error STACKADDR_AVAILABLE is defined but not implemented.
623 size_t stack_maxsize;
626 VALUE *register_stack_start;
628 } native_main_thread;
630 #ifdef STACK_END_ADDRESS
631 extern void *STACK_END_ADDRESS;
635 RUBY_STACK_SPACE_LIMIT = 1024 * 1024,
636 RUBY_STACK_SPACE_RATIO = 5
640 space_size(
size_t stack_size)
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;
651 #undef ruby_init_stack
663 native_main_thread.id = pthread_self();
664 #if MAINSTACKADDR_AVAILABLE
665 if (native_main_thread.stack_maxsize)
return;
669 if (get_main_stack(&stackaddr, &size) == 0) {
670 native_main_thread.stack_maxsize =
size;
671 native_main_thread.stack_start = stackaddr;
676 #ifdef STACK_END_ADDRESS
677 native_main_thread.stack_start = STACK_END_ADDRESS;
679 if (!native_main_thread.stack_start ||
681 native_main_thread.stack_start > addr,
682 native_main_thread.stack_start < addr)) {
683 native_main_thread.stack_start = (
VALUE *)addr;
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;
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"
698 size_t size = PTHREAD_STACK_DEFAULT;
703 int pagesize = getpagesize();
706 if (
getrlimit(RLIMIT_STACK, &rlim) == 0) {
707 size = (size_t)rlim.rlim_cur;
709 addr = native_main_thread.stack_start;
711 space = ((size_t)((
char *)addr +
size) / pagesize) * pagesize - (size_t)addr;
714 space = (size_t)addr - ((
size_t)((
char *)addr - size) / pagesize + 1) * pagesize;
716 native_main_thread.stack_maxsize = space;
727 start = native_main_thread.stack_start;
728 end = (
char *)native_main_thread.stack_start + native_main_thread.stack_maxsize;
731 start = (
char *)native_main_thread.stack_start - native_main_thread.stack_maxsize;
732 end = native_main_thread.stack_start;
735 if ((
void *)addr < start || (void *)addr > end) {
737 native_main_thread.stack_start = (
VALUE *)addr;
738 native_main_thread.stack_maxsize = 0;
743 #define CHECK_ERR(expr) \
744 {int err = (expr); if (err) {rb_bug_errno(#expr, err);}}
751 if (pthread_equal(curr, native_main_thread.id)) {
756 #ifdef STACKADDR_AVAILABLE
760 if (get_stack(&start, &size) == 0) {
764 #elif defined get_stack_of
774 th->
machine.register_stack_start = native_main_thread.register_stack_start;
782 #define USE_NATIVE_THREAD_INIT 1
786 thread_start_func_1(
void *th_ptr)
793 #if !defined USE_NATIVE_THREAD_INIT
797 #if defined USE_NATIVE_THREAD_INIT
798 native_thread_init_stack(th);
800 native_thread_init(th);
802 #if defined USE_NATIVE_THREAD_INIT
812 if ((th = register_cached_thread_and_wait()) != 0) {
822 struct cached_thread_entry {
825 struct cached_thread_entry *next;
830 static pthread_mutex_t thread_cache_lock = PTHREAD_MUTEX_INITIALIZER;
831 struct cached_thread_entry *cached_thread_root;
834 register_cached_thread_and_wait(
void)
840 struct cached_thread_entry *entry =
841 (
struct cached_thread_entry *)
malloc(
sizeof(
struct cached_thread_entry));
848 ts.
tv_sec = tv.tv_sec + 60;
849 ts.
tv_nsec = tv.tv_usec * 1000;
851 pthread_mutex_lock(&thread_cache_lock);
853 entry->th_area = &th_area;
855 entry->next = cached_thread_root;
856 cached_thread_root = entry;
858 native_cond_timedwait(&cond, &thread_cache_lock, &ts);
861 struct cached_thread_entry *e, **prev = &cached_thread_root;
863 while ((e = *prev) != 0) {
873 native_cond_destroy(&cond);
875 pthread_mutex_unlock(&thread_cache_lock);
886 struct cached_thread_entry *entry;
888 if (cached_thread_root) {
889 pthread_mutex_lock(&thread_cache_lock);
890 entry = cached_thread_root;
892 if (cached_thread_root) {
893 cached_thread_root = entry->next;
894 *entry->th_area = th;
899 native_cond_signal(entry->cond);
901 pthread_mutex_unlock(&thread_cache_lock);
912 if (use_cached_thread(th)) {
913 thread_debug(
"create (use cached thread): %p\n", (
void *)th);
916 #ifdef HAVE_PTHREAD_ATTR_INIT
918 pthread_attr_t *
const attrp = &attr;
920 pthread_attr_t *
const attrp =
NULL;
923 const size_t space = space_size(stack_size);
931 #ifdef HAVE_PTHREAD_ATTR_INIT
932 CHECK_ERR(pthread_attr_init(&attr));
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));
939 # ifdef HAVE_PTHREAD_ATTR_SETINHERITSCHED
940 CHECK_ERR(pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED));
942 CHECK_ERR(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED));
947 err = pthread_create(&th->
thread_id, attrp, thread_start_func_1, th);
957 #ifdef HAVE_PTHREAD_ATTR_INIT
958 CHECK_ERR(pthread_attr_destroy(&attr));
965 native_thread_join(pthread_t th)
967 int err = pthread_join(th, 0);
974 #if USE_NATIVE_THREAD_PRIORITY
979 #if defined(_POSIX_PRIORITY_SCHEDULING) && (_POSIX_PRIORITY_SCHEDULING > 0)
980 struct sched_param sp;
984 pthread_getschedparam(th->
thread_id, &policy, &sp);
985 max = sched_get_priority_max(policy);
986 min = sched_get_priority_min(policy);
988 if (min > priority) {
991 else if (max < priority) {
995 sp.sched_priority = priority;
996 pthread_setschedparam(th->
thread_id, policy, &sp);
1007 return rb_fd_select(n, readfds, writefds, exceptfds, timeout);
1011 ubf_pthread_cond_signal(
void *ptr)
1014 thread_debug(
"ubf_pthread_cond_signal (%p)\n", (
void *)th);
1029 timeout_rel.tv_nsec = timeout_tv->
tv_usec * 1000;
1039 if (timeout_rel.tv_sec > 100000000) {
1040 timeout_rel.tv_sec = 100000000;
1041 timeout_rel.tv_nsec = 0;
1044 timeout = native_cond_timeout(cond, timeout_rel);
1049 pthread_mutex_lock(lock);
1055 thread_debug(
"native_sleep: interrupted before sleep\n");
1059 native_cond_wait(cond, lock);
1061 native_cond_timedwait(cond, lock, &timeout);
1066 pthread_mutex_unlock(lock);
1073 #ifdef USE_SIGNAL_THREAD_LIST
1074 struct signal_thread_list {
1076 struct signal_thread_list *prev;
1077 struct signal_thread_list *next;
1080 static struct signal_thread_list signal_thread_list_anchor = {
1084 #define FGLOCK(lock, body) do { \
1085 native_mutex_lock(lock); \
1089 native_mutex_unlock(lock); \
1094 print_signal_list(
char *str)
1096 struct signal_thread_list *
list =
1097 signal_thread_list_anchor.next;
1100 thread_debug(
"%p (%p), ", list->th, list->th->thread_id);
1111 FGLOCK(&signal_thread_list_lock, {
1112 struct signal_thread_list *list =
1113 malloc(
sizeof(
struct signal_thread_list));
1116 fprintf(stderr,
"[FATAL] failed to allocate memory\n");
1122 list->prev = &signal_thread_list_anchor;
1123 list->next = signal_thread_list_anchor.next;
1125 list->next->prev =
list;
1127 signal_thread_list_anchor.next =
list;
1137 FGLOCK(&signal_thread_list_lock, {
1138 struct signal_thread_list *list =
1139 (
struct signal_thread_list *)
1142 list->prev->next = list->next;
1144 list->next->prev = list->prev;
1163 ubf_select(
void *ptr)
1166 add_signal_thread_list(th);
1175 if (pthread_self() != timer_thread_id)
1177 ubf_select_each(th);
1181 ping_signal_thread_list(
void)
1183 if (signal_thread_list_anchor.next) {
1184 FGLOCK(&signal_thread_list_lock, {
1185 struct signal_thread_list *
list;
1187 list = signal_thread_list_anchor.next;
1189 ubf_select_each(list->th);
1197 check_signal_thread_list(
void)
1199 if (signal_thread_list_anchor.next)
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; }
1213 #define WRITE_CONST(fd, str) (void)(write((fd),(str),sizeof(str)-1)<0)
1218 #define TIME_QUANTUM_USEC (100 * 1000)
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};
1223 static int timer_thread_pipe_owner_process;
1227 rb_thread_wakeup_timer_thread_fd(
int fd)
1232 if (timer_thread_pipe_owner_process == getpid()) {
1233 const char *buff =
"!";
1235 if ((result = write(fd, buff, 1)) <= 0) {
1237 case EINTR:
goto retry;
1239 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
1247 if (TT_DEBUG)
WRITE_CONST(2,
"rb_thread_wakeup_timer_thread: write\n");
1257 rb_thread_wakeup_timer_thread_fd(timer_thread_pipe[1]);
1261 rb_thread_wakeup_timer_thread_low(
void)
1263 rb_thread_wakeup_timer_thread_fd(timer_thread_pipe_low[1]);
1268 consume_communication_pipe(
int fd)
1270 #define CCP_READ_BUFF_SIZE 1024
1272 static char buff[CCP_READ_BUFF_SIZE];
1276 result = read(fd, buff,
sizeof(buff));
1280 else if (result < 0) {
1294 close_communication_pipe(
int pipes[2])
1296 if (close(pipes[0]) < 0) {
1299 if (close(pipes[1]) < 0) {
1302 pipes[0] = pipes[1] = -1;
1306 set_nonblock(
int fd)
1311 oflags =
fcntl(fd, F_GETFL);
1321 setup_communication_pipe_internal(
int pipes[2])
1325 if (pipes[0] != -1) {
1327 close_communication_pipe(pipes);
1332 rb_bug_errno(
"setup_communication_pipe: Failed to create communication pipe for timer thread",
errno);
1336 set_nonblock(pipes[0]);
1337 set_nonblock(pipes[1]);
1342 setup_communication_pipe(
void)
1344 if (timer_thread_pipe_owner_process == getpid()) {
1348 setup_communication_pipe_internal(timer_thread_pipe);
1349 setup_communication_pipe_internal(timer_thread_pipe_low);
1352 timer_thread_pipe_owner_process = getpid();
1366 struct pollfd pollfds[2];
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;
1373 need_polling = check_signal_thread_list();
1375 if (gvl->
waiting > 0 || need_polling) {
1377 result = poll(pollfds, 1, TIME_QUANTUM_USEC/1000);
1381 result = poll(pollfds,
numberof(pollfds), -1);
1387 else if (result > 0) {
1388 consume_communication_pipe(timer_thread_pipe[0]);
1389 consume_communication_pipe(timer_thread_pipe_low[0]);
1405 # define PER_NANO 1000000000
1407 static void rb_thread_wakeup_timer_thread_low(
void) {}
1409 static pthread_mutex_t timer_thread_lock;
1417 ts.
tv_nsec = TIME_QUANTUM_USEC * 1000;
1418 ts = native_cond_timeout(&timer_thread_cond, ts);
1420 native_cond_timedwait(&timer_thread_cond, &timer_thread_lock, &ts);
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
1432 thread_timer(
void *p)
1436 if (TT_DEBUG)
WRITE_CONST(2,
"start timer thread\n");
1438 SET_THREAD_NAME(
"ruby-timer-thr");
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);
1448 ping_signal_thread_list();
1454 timer_thread_sleep(gvl);
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);
1462 if (TT_DEBUG)
WRITE_CONST(2,
"finish timer thread\n");
1467 rb_thread_create_timer_thread(
void)
1469 if (!timer_thread_id) {
1471 #ifdef HAVE_PTHREAD_ATTR_INIT
1472 pthread_attr_t attr;
1474 err = pthread_attr_init(&attr);
1476 fprintf(stderr,
"[FATAL] Failed to initialize pthread attr: %s\n",
strerror(err));
1479 # ifdef PTHREAD_STACK_MIN
1481 const size_t min_size = (4096 * 4);
1486 size_t stack_size = PTHREAD_STACK_MIN;
1487 if (stack_size < min_size) stack_size = min_size;
1489 pthread_attr_setstacksize(&attr, stack_size);
1494 #if USE_SLEEPY_TIMER_THREAD
1495 setup_communication_pipe();
1499 if (timer_thread_id) {
1500 rb_bug(
"rb_thread_create_timer_thread: Timer thread was already created\n");
1502 #ifdef HAVE_PTHREAD_ATTR_INIT
1503 err = pthread_create(&timer_thread_id, &attr, thread_timer, &
GET_VM()->gvl);
1505 err = pthread_create(&timer_thread_id,
NULL, thread_timer, &
GET_VM()->gvl);
1508 fprintf(stderr,
"[FATAL] Failed to create timer thread: %s\n",
strerror(err));
1511 #ifdef HAVE_PTHREAD_ATTR_INIT
1512 pthread_attr_destroy(&attr);
1518 native_stop_timer_thread(
int close_anyway)
1523 if (TT_DEBUG) fprintf(stderr,
"stop timer thread\n");
1527 native_thread_join(timer_thread_id);
1528 if (TT_DEBUG) fprintf(stderr,
"joined timer thread\n");
1529 timer_thread_id = 0;
1547 native_reset_timer_thread(
void)
1549 if (TT_DEBUG) fprintf(stderr,
"reset timer thread\n");
1552 #ifdef HAVE_SIGALTSTACK
1554 ruby_stack_overflowed_p(
const rb_thread_t *th,
const void *addr)
1558 const size_t water_mark = 1024 * 1024;
1561 #ifdef STACKADDR_AVAILABLE
1562 if (get_stack(&base, &size) == 0) {
1564 if (pthread_equal(th->
thread_id, native_main_thread.id)) {
1566 if (
getrlimit(RLIMIT_STACK, &rlim) == 0 && rlim.rlim_cur > size) {
1567 size = (size_t)rlim.rlim_cur;
1582 size /= RUBY_STACK_SPACE_RATIO;
1583 if (size > water_mark) size = water_mark;
1585 if (size > ~(
size_t)base+1) size = ~(
size_t)base+1;
1586 if (addr > base && addr <= (
void *)((
char *)base + size))
return 1;
1589 if (size > (
size_t)base) size = (
size_t)base;
1590 if (addr > (
void *)((
char *)base - size) && addr <= base)
return 1;
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]) {
1617 return pthread_self();
rb_nativethread_cond_t sleep_cond
RUBY_SYMBOL_EXPORT_BEGIN rb_nativethread_id_t rb_nativethread_self()
void rb_bug(const char *fmt,...)
int gettimeofday(struct timeval *, struct timezone *)
void rb_update_max_fd(int fd)
volatile unsigned long waiting
static int max(int a, int b)
void * signal_thread_list
rb_unblock_function_t * func
rb_nativethread_cond_t switch_cond
void rb_async_bug_errno(const char *mesg, int errno_arg)
#define STACK_UPPER(x, a, b)
void rb_raise(VALUE exc, const char *fmt,...)
pthread_mutex_t rb_nativethread_lock_t
static volatile int system_working
struct rb_thread_struct::@169 machine
sighandler_t posix_signal(int signum, sighandler_t handler)
unsigned long long uint64_t
#define RUBY_VM_THREAD_VM_STACK_SIZE
void rb_thread_wakeup_timer_thread(void)
int getrlimit(int resource, struct rlimit *rlp)
if((ID)(DISPID) nameid!=nameid)
#define GVL_UNLOCK_BEGIN()
rb_nativethread_cond_t cond
#define STACK_DIR_UPPER(a, b)
pthread_t rb_nativethread_id_t
int pthread_kill(pthread_t thread, int sig)
#define STACK_GROW_DIR_DETECTION
void Init_native_thread(void)
void rb_bug_errno(const char *mesg, int errno_arg)
int clock_gettime(clockid_t, struct timespec *)
void ruby_init_stack(volatile VALUE *)
rb_nativethread_cond_t switch_wait_cond
static void timer_thread_function(void *)
void rb_sys_fail(const char *mesg)
int rb_reserved_fd_p(int fd)
#define WRITE_CONST(fd, str)
int rb_cloexec_pipe(int fildes[2])
#define thread_start_func_2(th, st, rst)
struct rb_vm_struct::@168 default_params
struct rb_unblock_callback unblock
#define rb_fd_select(n, rfds, wfds, efds, timeout)
rb_nativethread_id_t thread_id
RUBY_EXTERN char * strerror(int)
struct rb_encoding_entry * list
native_thread_data_t native_thread_data
size_t thread_machine_stack_size
static VALUE thread_start(VALUE klass, VALUE args)
#define RUBY_VM_INTERRUPTED(th)
rb_nativethread_lock_t interrupt_lock
static rb_thread_t * GET_THREAD(void)
#define IS_STACK_DIR_UPPER()