Fixes threading on NativeClient.
* thread_pthread.c (timer_thread_sleep): Extracted out a function from thread_timer(). Added an alternative implementation for platforms that lacks select(2) or pipe(2). (rb_thread_create_timer_thread, native_cond_initialize, native_cond_destroy): Replaced wrong HAVE_XXX checks. * configure.in (pthread_attr_init): New check. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36022 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
fa5cd00340
commit
c3f3d77225
12
ChangeLog
12
ChangeLog
@ -1,3 +1,15 @@
|
|||||||
|
Sun Jun 10 20:23:14 2012 Yuki Sonoda (Yugui) <yugui@yugui.jp>
|
||||||
|
|
||||||
|
Fixes threading on NativeClient.
|
||||||
|
|
||||||
|
* thread_pthread.c (timer_thread_sleep): Extracted out a function from
|
||||||
|
thread_timer(). Added an alternative implementation for platforms
|
||||||
|
that lacks select(2) or pipe(2).
|
||||||
|
(rb_thread_create_timer_thread, native_cond_initialize,
|
||||||
|
native_cond_destroy): Replaced wrong HAVE_XXX checks.
|
||||||
|
|
||||||
|
* configure.in (pthread_attr_init): New check.
|
||||||
|
|
||||||
Sun Jun 10 21:30:11 2012 Tanaka Akira <akr@fsij.org>
|
Sun Jun 10 21:30:11 2012 Tanaka Akira <akr@fsij.org>
|
||||||
|
|
||||||
* process.c (rb_exec_without_timer_thread): renamed from rb_exec_err.
|
* process.c (rb_exec_without_timer_thread): renamed from rb_exec_err.
|
||||||
|
@ -2015,6 +2015,11 @@ if test x"$enable_pthread" = xyes; then
|
|||||||
thr_stksegment pthread_stackseg_np pthread_getthrds_np \
|
thr_stksegment pthread_stackseg_np pthread_getthrds_np \
|
||||||
pthread_cond_init pthread_condattr_setclock pthread_condattr_init \
|
pthread_cond_init pthread_condattr_setclock pthread_condattr_init \
|
||||||
pthread_sigmask)
|
pthread_sigmask)
|
||||||
|
if test "${host_os}" = "nacl"; then
|
||||||
|
ac_cv_func_pthread_attr_init=no
|
||||||
|
else
|
||||||
|
AC_CHECK_FUNCS(pthread_attr_init)
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
if test x"$ac_cv_header_ucontext_h" = xyes; then
|
if test x"$ac_cv_header_ucontext_h" = xyes; then
|
||||||
if test x"$rb_with_pthread" = xyes; then
|
if test x"$rb_with_pthread" = xyes; then
|
||||||
|
197
thread_pthread.c
197
thread_pthread.c
@ -52,6 +52,14 @@ static pthread_t timer_thread_id;
|
|||||||
#define USE_MONOTONIC_COND 0
|
#define USE_MONOTONIC_COND 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __native_client__
|
||||||
|
/* Doesn't have select(1). */
|
||||||
|
# define USE_SLEEPY_TIMER_THREAD 0
|
||||||
|
#else
|
||||||
|
/* The timer thread sleeps while only one Ruby thread is running. */
|
||||||
|
# define USE_SLEEPY_TIMER_THREAD 1
|
||||||
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gvl_acquire_common(rb_vm_t *vm)
|
gvl_acquire_common(rb_vm_t *vm)
|
||||||
{
|
{
|
||||||
@ -140,11 +148,9 @@ static void
|
|||||||
gvl_init(rb_vm_t *vm)
|
gvl_init(rb_vm_t *vm)
|
||||||
{
|
{
|
||||||
native_mutex_initialize(&vm->gvl.lock);
|
native_mutex_initialize(&vm->gvl.lock);
|
||||||
#ifdef HAVE_PTHREAD_CONDATTR_INIT
|
|
||||||
native_cond_initialize(&vm->gvl.cond, RB_CONDATTR_CLOCK_MONOTONIC);
|
native_cond_initialize(&vm->gvl.cond, RB_CONDATTR_CLOCK_MONOTONIC);
|
||||||
native_cond_initialize(&vm->gvl.switch_cond, RB_CONDATTR_CLOCK_MONOTONIC);
|
native_cond_initialize(&vm->gvl.switch_cond, RB_CONDATTR_CLOCK_MONOTONIC);
|
||||||
native_cond_initialize(&vm->gvl.switch_wait_cond, RB_CONDATTR_CLOCK_MONOTONIC);
|
native_cond_initialize(&vm->gvl.switch_wait_cond, RB_CONDATTR_CLOCK_MONOTONIC);
|
||||||
#endif
|
|
||||||
vm->gvl.acquired = 0;
|
vm->gvl.acquired = 0;
|
||||||
vm->gvl.waiting = 0;
|
vm->gvl.waiting = 0;
|
||||||
vm->gvl.need_yield = 0;
|
vm->gvl.need_yield = 0;
|
||||||
@ -153,11 +159,9 @@ gvl_init(rb_vm_t *vm)
|
|||||||
static void
|
static void
|
||||||
gvl_destroy(rb_vm_t *vm)
|
gvl_destroy(rb_vm_t *vm)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_PTHREAD_CONDATTR_INIT
|
|
||||||
native_cond_destroy(&vm->gvl.switch_wait_cond);
|
native_cond_destroy(&vm->gvl.switch_wait_cond);
|
||||||
native_cond_destroy(&vm->gvl.switch_cond);
|
native_cond_destroy(&vm->gvl.switch_cond);
|
||||||
native_cond_destroy(&vm->gvl.cond);
|
native_cond_destroy(&vm->gvl.cond);
|
||||||
#endif
|
|
||||||
native_mutex_destroy(&vm->gvl.lock);
|
native_mutex_destroy(&vm->gvl.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,19 +243,17 @@ native_mutex_destroy(pthread_mutex_t *lock)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_PTHREAD_CONDATTR_INIT
|
|
||||||
int pthread_condattr_init(pthread_condattr_t *attr);
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
native_cond_initialize(rb_thread_cond_t *cond, int flags)
|
native_cond_initialize(rb_thread_cond_t *cond, int flags)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_PTHREAD_COND_INIT
|
#ifdef HAVE_PTHREAD_COND_INIT
|
||||||
int r;
|
int r;
|
||||||
|
# ifdef HAVE_PTHREAD_COND_ATTR_INIT
|
||||||
pthread_condattr_t attr;
|
pthread_condattr_t attr;
|
||||||
|
|
||||||
pthread_condattr_init(&attr);
|
pthread_condattr_init(&attr);
|
||||||
|
|
||||||
#if USE_MONOTONIC_COND
|
# if USE_MONOTONIC_COND
|
||||||
cond->clockid = CLOCK_REALTIME;
|
cond->clockid = CLOCK_REALTIME;
|
||||||
if (flags & RB_CONDATTR_CLOCK_MONOTONIC) {
|
if (flags & RB_CONDATTR_CLOCK_MONOTONIC) {
|
||||||
r = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
|
r = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
|
||||||
@ -259,9 +261,12 @@ native_cond_initialize(rb_thread_cond_t *cond, int flags)
|
|||||||
cond->clockid = CLOCK_MONOTONIC;
|
cond->clockid = CLOCK_MONOTONIC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
r = pthread_cond_init(&cond->cond, &attr);
|
r = pthread_cond_init(&cond->cond, &attr);
|
||||||
|
# else
|
||||||
|
r = pthread_cond_init(&cond->cond, NULL);
|
||||||
|
# endif
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
rb_bug_errno("pthread_cond_init", r);
|
rb_bug_errno("pthread_cond_init", r);
|
||||||
}
|
}
|
||||||
@ -280,7 +285,6 @@ native_cond_destroy(rb_thread_cond_t *cond)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In OS X 10.7 (Lion), pthread_cond_signal and pthread_cond_broadcast return
|
* In OS X 10.7 (Lion), pthread_cond_signal and pthread_cond_broadcast return
|
||||||
@ -819,21 +823,27 @@ native_thread_create(rb_thread_t *th)
|
|||||||
th->machine_register_stack_maxsize = th->machine_stack_maxsize;
|
th->machine_register_stack_maxsize = th->machine_stack_maxsize;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_PTHREAD_ATTR_INIT
|
||||||
CHECK_ERR(pthread_attr_init(&attr));
|
CHECK_ERR(pthread_attr_init(&attr));
|
||||||
|
|
||||||
#ifdef PTHREAD_STACK_MIN
|
# ifdef PTHREAD_STACK_MIN
|
||||||
thread_debug("create - stack size: %lu\n", (unsigned long)stack_size);
|
thread_debug("create - stack size: %lu\n", (unsigned long)stack_size);
|
||||||
CHECK_ERR(pthread_attr_setstacksize(&attr, stack_size));
|
CHECK_ERR(pthread_attr_setstacksize(&attr, stack_size));
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
#ifdef HAVE_PTHREAD_ATTR_SETINHERITSCHED
|
# ifdef HAVE_PTHREAD_ATTR_SETINHERITSCHED
|
||||||
CHECK_ERR(pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED));
|
CHECK_ERR(pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED));
|
||||||
#endif
|
# endif
|
||||||
CHECK_ERR(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED));
|
CHECK_ERR(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED));
|
||||||
|
|
||||||
err = pthread_create(&th->thread_id, &attr, thread_start_func_1, th);
|
err = pthread_create(&th->thread_id, &attr, thread_start_func_1, th);
|
||||||
|
#else
|
||||||
|
err = pthread_create(&th->thread_id, NULL, thread_start_func_1, th);
|
||||||
|
#endif
|
||||||
thread_debug("create: %p (%d)\n", (void *)th, err);
|
thread_debug("create: %p (%d)\n", (void *)th, err);
|
||||||
|
#ifdef HAVE_PTHREAD_ATTR_INIT
|
||||||
CHECK_ERR(pthread_attr_destroy(&attr));
|
CHECK_ERR(pthread_attr_destroy(&attr));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -1078,12 +1088,18 @@ static void ping_signal_thread_list(void) { return; }
|
|||||||
static int check_signal_thread_list(void) { return 0; }
|
static int check_signal_thread_list(void) { return 0; }
|
||||||
#endif /* USE_SIGNAL_THREAD_LIST */
|
#endif /* USE_SIGNAL_THREAD_LIST */
|
||||||
|
|
||||||
|
#define TT_DEBUG 0
|
||||||
|
#define WRITE_CONST(fd, str) (void)(write((fd),(str),sizeof(str)-1)<0)
|
||||||
|
|
||||||
|
/* 100ms. 10ms is too small for user level thread scheduling
|
||||||
|
* on recent Linux (tested on 2.6.35)
|
||||||
|
*/
|
||||||
|
#define TIME_QUANTUM_USEC (100 * 1000)
|
||||||
|
|
||||||
|
#if USE_SLEEPY_TIMER_THREAD
|
||||||
static int timer_thread_pipe[2] = {-1, -1};
|
static int timer_thread_pipe[2] = {-1, -1};
|
||||||
static int timer_thread_pipe_owner_process;
|
static int timer_thread_pipe_owner_process;
|
||||||
|
|
||||||
#define TT_DEBUG 0
|
|
||||||
|
|
||||||
#define WRITE_CONST(fd, str) (void)(write((fd),(str),sizeof(str)-1)<0)
|
|
||||||
|
|
||||||
/* only use signal-safe system calls here */
|
/* only use signal-safe system calls here */
|
||||||
void
|
void
|
||||||
@ -1146,17 +1162,77 @@ close_communication_pipe(void)
|
|||||||
timer_thread_pipe[0] = timer_thread_pipe[1] = -1;
|
timer_thread_pipe[0] = timer_thread_pipe[1] = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 100ms. 10ms is too small for user level thread scheduling
|
/**
|
||||||
* on recent Linux (tested on 2.6.35)
|
* Let the timer thread sleep a while.
|
||||||
|
*
|
||||||
|
* The timer thread sleeps until woken up by rb_thread_wakeup_timer_thread() if only one Ruby thread is running.
|
||||||
|
* @pre the calling context is in the timer thread.
|
||||||
*/
|
*/
|
||||||
#define TIME_QUANTUM_USEC (100 * 1000)
|
static inline void
|
||||||
|
timer_thread_sleep(rb_global_vm_lock_t* gvl)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
int need_polling;
|
||||||
|
struct timeval timeout;
|
||||||
|
fd_set rfds;
|
||||||
|
FD_ZERO(&rfds);
|
||||||
|
FD_SET(timer_thread_pipe[0], &rfds);
|
||||||
|
|
||||||
|
need_polling = check_signal_thread_list();
|
||||||
|
|
||||||
|
if (gvl->waiting > 0 || need_polling) {
|
||||||
|
timeout.tv_sec = 0;
|
||||||
|
timeout.tv_usec = TIME_QUANTUM_USEC;
|
||||||
|
|
||||||
|
/* polling (TIME_QUANTUM_USEC usec) */
|
||||||
|
result = select(timer_thread_pipe[0] + 1, &rfds, 0, 0, &timeout);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* wait (infinite) */
|
||||||
|
result = select(timer_thread_pipe[0] + 1, &rfds, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == 0) {
|
||||||
|
/* maybe timeout */
|
||||||
|
}
|
||||||
|
else if (result > 0) {
|
||||||
|
consume_communication_pipe();
|
||||||
|
}
|
||||||
|
else { /* result < 0 */
|
||||||
|
switch (errno) {
|
||||||
|
case EBADF:
|
||||||
|
case EINVAL:
|
||||||
|
case ENOMEM: /* from Linux man */
|
||||||
|
case EFAULT: /* from FreeBSD man */
|
||||||
|
rb_async_bug_errno("thread_timer: select", errno);
|
||||||
|
default:
|
||||||
|
/* ignore */;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* USE_SLEEPY_TIMER_THREAD */
|
||||||
|
# define PER_NANO 1000000000
|
||||||
|
void rb_thread_wakeup_timer_thread(void) {}
|
||||||
|
|
||||||
|
static pthread_mutex_t timer_thread_lock;
|
||||||
|
static rb_thread_cond_t timer_thread_cond;
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
timer_thread_sleep(rb_global_vm_lock_t* unused) {
|
||||||
|
struct timespec ts;
|
||||||
|
ts.tv_sec = 0;
|
||||||
|
ts.tv_nsec = TIME_QUANTUM_USEC * 1000;
|
||||||
|
ts = native_cond_timeout(&timer_thread_cond, ts);
|
||||||
|
|
||||||
|
native_cond_timedwait(&timer_thread_cond, &timer_thread_lock, &ts);
|
||||||
|
}
|
||||||
|
#endif /* USE_SLEEPY_TIMER_THREAD */
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
thread_timer(void *p)
|
thread_timer(void *p)
|
||||||
{
|
{
|
||||||
rb_global_vm_lock_t *gvl = (rb_global_vm_lock_t *)p;
|
rb_global_vm_lock_t *gvl = (rb_global_vm_lock_t *)p;
|
||||||
int result;
|
|
||||||
struct timeval timeout;
|
|
||||||
|
|
||||||
if (TT_DEBUG) WRITE_CONST(2, "start timer thread\n");
|
if (TT_DEBUG) WRITE_CONST(2, "start timer thread\n");
|
||||||
|
|
||||||
@ -1164,51 +1240,27 @@ thread_timer(void *p)
|
|||||||
prctl(PR_SET_NAME, "ruby-timer-thr");
|
prctl(PR_SET_NAME, "ruby-timer-thr");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !USE_SLEEPY_TIMER_THREAD
|
||||||
|
native_mutex_initialize(&timer_thread_lock);
|
||||||
|
native_cond_initialize(&timer_thread_cond, RB_CONDATTR_CLOCK_MONOTONIC);
|
||||||
|
native_mutex_lock(&timer_thread_lock);
|
||||||
|
#endif
|
||||||
while (system_working > 0) {
|
while (system_working > 0) {
|
||||||
fd_set rfds;
|
|
||||||
int need_polling;
|
|
||||||
|
|
||||||
/* timer function */
|
/* timer function */
|
||||||
ping_signal_thread_list();
|
ping_signal_thread_list();
|
||||||
timer_thread_function(0);
|
timer_thread_function(0);
|
||||||
need_polling = check_signal_thread_list();
|
|
||||||
|
|
||||||
if (TT_DEBUG) WRITE_CONST(2, "tick\n");
|
if (TT_DEBUG) WRITE_CONST(2, "tick\n");
|
||||||
|
|
||||||
/* wait */
|
/* wait */
|
||||||
FD_ZERO(&rfds);
|
timer_thread_sleep(gvl);
|
||||||
FD_SET(timer_thread_pipe[0], &rfds);
|
|
||||||
|
|
||||||
if (gvl->waiting > 0 || need_polling) {
|
|
||||||
timeout.tv_sec = 0;
|
|
||||||
timeout.tv_usec = TIME_QUANTUM_USEC;
|
|
||||||
|
|
||||||
/* polling (TIME_QUANTUM_USEC usec) */
|
|
||||||
result = select(timer_thread_pipe[0] + 1, &rfds, 0, 0, &timeout);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* wait (infinite) */
|
|
||||||
result = select(timer_thread_pipe[0] + 1, &rfds, 0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result == 0) {
|
|
||||||
/* maybe timeout */
|
|
||||||
}
|
|
||||||
else if (result > 0) {
|
|
||||||
consume_communication_pipe();
|
|
||||||
}
|
|
||||||
else { /* result < 0 */
|
|
||||||
switch (errno) {
|
|
||||||
case EBADF:
|
|
||||||
case EINVAL:
|
|
||||||
case ENOMEM: /* from Linux man */
|
|
||||||
case EFAULT: /* from FreeBSD man */
|
|
||||||
rb_async_bug_errno("thread_timer: select", errno);
|
|
||||||
default:
|
|
||||||
/* ignore */;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
#if !USE_SLEEPY_TIMER_THREAD
|
||||||
|
native_mutex_unlock(&timer_thread_lock);
|
||||||
|
native_cond_destroy(&timer_thread_cond);
|
||||||
|
native_mutex_destroy(&timer_thread_lock);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (TT_DEBUG) WRITE_CONST(2, "finish timer thread\n");
|
if (TT_DEBUG) WRITE_CONST(2, "finish timer thread\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1217,13 +1269,16 @@ thread_timer(void *p)
|
|||||||
static void
|
static void
|
||||||
rb_thread_create_timer_thread(void)
|
rb_thread_create_timer_thread(void)
|
||||||
{
|
{
|
||||||
#ifndef __native_client__
|
|
||||||
if (!timer_thread_id) {
|
if (!timer_thread_id) {
|
||||||
pthread_attr_t attr;
|
|
||||||
int err;
|
int err;
|
||||||
|
#ifdef HAVE_PTHREAD_ATTR_INIT
|
||||||
|
pthread_attr_t attr;
|
||||||
|
|
||||||
pthread_attr_init(&attr);
|
if (pthread_attr_init(&attr)) {
|
||||||
#ifdef PTHREAD_STACK_MIN
|
fprintf(stderr, "[FATAL] Failed to initialize pthread attr(errno: %d)\n", err);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
# ifdef PTHREAD_STACK_MIN
|
||||||
if (PTHREAD_STACK_MIN < 4096 * 3) {
|
if (PTHREAD_STACK_MIN < 4096 * 3) {
|
||||||
/* Allocate the machine stack for the timer thread
|
/* Allocate the machine stack for the timer thread
|
||||||
* at least 12KB (3 pages). FreeBSD 8.2 AMD64 causes
|
* at least 12KB (3 pages). FreeBSD 8.2 AMD64 causes
|
||||||
@ -1236,8 +1291,10 @@ rb_thread_create_timer_thread(void)
|
|||||||
pthread_attr_setstacksize(&attr,
|
pthread_attr_setstacksize(&attr,
|
||||||
PTHREAD_STACK_MIN + (THREAD_DEBUG ? BUFSIZ : 0));
|
PTHREAD_STACK_MIN + (THREAD_DEBUG ? BUFSIZ : 0));
|
||||||
}
|
}
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if USE_SLEEPY_TIMER_THREAD
|
||||||
/* communication pipe with timer thread and signal handler */
|
/* communication pipe with timer thread and signal handler */
|
||||||
if (timer_thread_pipe_owner_process != getpid()) {
|
if (timer_thread_pipe_owner_process != getpid()) {
|
||||||
if (timer_thread_pipe[0] != -1) {
|
if (timer_thread_pipe[0] != -1) {
|
||||||
@ -1251,7 +1308,7 @@ rb_thread_create_timer_thread(void)
|
|||||||
}
|
}
|
||||||
rb_update_max_fd(timer_thread_pipe[0]);
|
rb_update_max_fd(timer_thread_pipe[0]);
|
||||||
rb_update_max_fd(timer_thread_pipe[1]);
|
rb_update_max_fd(timer_thread_pipe[1]);
|
||||||
#if defined(HAVE_FCNTL) && defined(F_GETFL) && defined(F_SETFL) && defined(O_NONBLOCK)
|
# if defined(HAVE_FCNTL) && defined(F_GETFL) && defined(F_SETFL) && defined(O_NONBLOCK)
|
||||||
{
|
{
|
||||||
int oflags;
|
int oflags;
|
||||||
int err;
|
int err;
|
||||||
@ -1264,24 +1321,30 @@ rb_thread_create_timer_thread(void)
|
|||||||
if (err == -1)
|
if (err == -1)
|
||||||
rb_sys_fail(0);
|
rb_sys_fail(0);
|
||||||
}
|
}
|
||||||
#endif /* defined(HAVE_FCNTL) && defined(F_GETFL) && defined(F_SETFL) */
|
# endif /* defined(HAVE_FCNTL) && defined(F_GETFL) && defined(F_SETFL) */
|
||||||
|
|
||||||
/* validate pipe on this process */
|
/* validate pipe on this process */
|
||||||
timer_thread_pipe_owner_process = getpid();
|
timer_thread_pipe_owner_process = getpid();
|
||||||
}
|
}
|
||||||
|
#endif /* USE_SLEEPY_TIMER_THREAD */
|
||||||
|
|
||||||
/* create timer thread */
|
/* create timer thread */
|
||||||
if (timer_thread_id) {
|
if (timer_thread_id) {
|
||||||
rb_bug("rb_thread_create_timer_thread: Timer thread was already created\n");
|
rb_bug("rb_thread_create_timer_thread: Timer thread was already created\n");
|
||||||
}
|
}
|
||||||
|
#ifdef HAVE_PTHREAD_ATTR_INIT
|
||||||
err = pthread_create(&timer_thread_id, &attr, thread_timer, &GET_VM()->gvl);
|
err = pthread_create(&timer_thread_id, &attr, thread_timer, &GET_VM()->gvl);
|
||||||
|
#else
|
||||||
|
err = pthread_create(&timer_thread_id, NULL, thread_timer, &GET_VM()->gvl);
|
||||||
|
#endif
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
fprintf(stderr, "[FATAL] Failed to create timer thread (errno: %d)\n", err);
|
fprintf(stderr, "[FATAL] Failed to create timer thread (errno: %d)\n", err);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
#ifdef HAVE_PTHREAD_ATTR_INIT
|
||||||
pthread_attr_destroy(&attr);
|
pthread_attr_destroy(&attr);
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -1357,6 +1420,7 @@ ruby_stack_overflowed_p(const rb_thread_t *th, const void *addr)
|
|||||||
int
|
int
|
||||||
rb_reserved_fd_p(int fd)
|
rb_reserved_fd_p(int fd)
|
||||||
{
|
{
|
||||||
|
#if USE_SLEEPY_TIMER_THRAED
|
||||||
if (fd == timer_thread_pipe[0] ||
|
if (fd == timer_thread_pipe[0] ||
|
||||||
fd == timer_thread_pipe[1]) {
|
fd == timer_thread_pipe[1]) {
|
||||||
return 1;
|
return 1;
|
||||||
@ -1364,6 +1428,9 @@ rb_reserved_fd_p(int fd)
|
|||||||
else {
|
else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION */
|
#endif /* THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user