static void native_sleep(rb_thread_t *th, struct timeval *tv) { struct timespec ts; struct timeval tvn; if (tv) { gettimeofday(&tvn, NULL); ts.tv_sec = tvn.tv_sec + tv->tv_sec; ts.tv_nsec = (tvn.tv_usec + tv->tv_usec) * 1000; if (ts.tv_nsec >= PER_NANO){ ts.tv_sec += 1; ts.tv_nsec -= PER_NANO; } } thread_debug("native_sleep %ld\n", (long)(tv ? tv->tv_sec : -1)); GVL_UNLOCK_BEGIN(); { pthread_mutex_lock(&th->interrupt_lock); th->unblock.func = ubf_pthread_cond_signal; th->unblock.arg = th; if (RUBY_VM_INTERRUPTED(th)) { /* interrupted. return immediate */ thread_debug("native_sleep: interrupted before sleep\n"); } else { if (tv == 0 || ts.tv_sec < tvn.tv_sec /* overflow */ ) { int r; thread_debug("native_sleep: pthread_cond_wait start\n"); r = pthread_cond_wait(&th->native_thread_data.sleep_cond, &th->interrupt_lock); if (r) rb_bug_errno("pthread_cond_wait", r); thread_debug("native_sleep: pthread_cond_wait end\n"); } else { int r; thread_debug("native_sleep: pthread_cond_timedwait start (%ld, %ld)\n", (unsigned long)ts.tv_sec, ts.tv_nsec); r = pthread_cond_timedwait(&th->native_thread_data.sleep_cond, &th->interrupt_lock, &ts); if (r && r != ETIMEDOUT) rb_bug_errno("pthread_cond_timedwait", r); thread_debug("native_sleep: pthread_cond_timedwait end (%d)\n", r); } } th->unblock.func = 0; th->unblock.arg = 0; pthread_mutex_unlock(&th->interrupt_lock); } GVL_UNLOCK_END(); thread_debug("native_sleep done\n"); }
static sighandler_t ruby_signal(int signum, sighandler_t handler) { struct sigaction sigact, old; #if 0 rb_trap_accept_nativethreads[signum] = 0; #endif sigemptyset(&sigact.sa_mask); #ifdef USE_SIGALTSTACK sigact.sa_sigaction = (ruby_sigaction_t*)handler; sigact.sa_flags = SA_SIGINFO; #else sigact.sa_handler = handler; sigact.sa_flags = 0; #endif #ifdef SA_NOCLDWAIT if (signum == SIGCHLD && handler == SIG_IGN) sigact.sa_flags |= SA_NOCLDWAIT; #endif #if defined(SA_ONSTACK) && defined(USE_SIGALTSTACK) if (signum == SIGSEGV) sigact.sa_flags |= SA_ONSTACK; #endif if (sigaction(signum, &sigact, &old) < 0) { if (errno != 0 && errno != EINVAL) { rb_bug_errno("sigaction", errno); } } return old.sa_handler; }
static void native_cond_initialize(rb_thread_cond_t *cond, int flags) { int r; pthread_condattr_t attr; pthread_condattr_init(&attr); #if USE_MONOTONIC_COND cond->clockid = CLOCK_REALTIME; if (flags & RB_CONDATTR_CLOCK_MONOTONIC) { r = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); if (r == 0) { cond->clockid = CLOCK_MONOTONIC; } } #endif r = pthread_cond_init(&cond->cond, &attr); if (r != 0) { rb_bug_errno("pthread_cond_init", r); } return; }
static void native_cond_initialize(rb_nativethread_cond_t *cond, int flags) { #ifdef HAVE_PTHREAD_COND_INIT int r; # if USE_MONOTONIC_COND pthread_condattr_t attr; pthread_condattr_init(&attr); cond->clockid = CLOCK_REALTIME; if (flags & RB_CONDATTR_CLOCK_MONOTONIC) { r = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); if (r == 0) { cond->clockid = CLOCK_MONOTONIC; } } r = pthread_cond_init(&cond->cond, &attr); pthread_condattr_destroy(&attr); # else r = pthread_cond_init(&cond->cond, NULL); # endif if (r != 0) { rb_bug_errno("pthread_cond_init", r); } return; #endif }
static void native_cond_destroy(rb_thread_cond_t *cond) { int r = pthread_cond_destroy(&cond->cond); if (r != 0) { rb_bug_errno("pthread_cond_destroy", r); } }
static void native_cond_initialize(pthread_cond_t *cond) { int r = pthread_cond_init(cond, 0); if (r != 0) { rb_bug_errno("pthread_cond_init", r); } }
static void native_mutex_destroy(pthread_mutex_t *lock) { int r = pthread_mutex_destroy(lock); if (r != 0) { rb_bug_errno("pthread_mutex_destroy", r); } }
static void native_mutex_initialize(pthread_mutex_t *lock) { int r = pthread_mutex_init(lock, 0); if (r != 0) { rb_bug_errno("pthread_mutex_init", r); } }
static void native_cond_broadcast(rb_thread_cond_t *cond) { int r = pthread_cond_broadcast(&cond->cond); if (r != 0) { rb_bug_errno("native_cond_broadcast", r); } }
static void native_cond_signal(rb_thread_cond_t *cond) { int r = pthread_cond_signal(&cond->cond); if (r != 0) { rb_bug_errno("pthread_cond_signal", r); } }
/*static*/ void native_mutex_unlock(pthread_mutex_t *lock) { int r; if ((r = pthread_mutex_unlock(lock)) != 0) { rb_bug_errno("pthread_mutex_unlock", r); } }
static void native_cond_wait(rb_nativethread_cond_t *cond, pthread_mutex_t *mutex) { int r = pthread_cond_wait(&cond->cond, mutex); if (r != 0) { rb_bug_errno("pthread_cond_wait", r); } }
static int native_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, struct timespec *ts) { int r = pthread_cond_timedwait(cond, mutex, ts); if (r != 0 && r != ETIMEDOUT && r != EINTR /* Linux */) { rb_bug_errno("pthread_cond_timedwait", r); } return r; }
static void native_mutex_unlock(pthread_mutex_t *lock) { int r; mutex_debug("unlock", lock); if ((r = pthread_mutex_unlock(lock)) != 0) { rb_bug_errno("pthread_mutex_unlock", r); } }
static void native_cond_destroy(rb_nativethread_cond_t *cond) { #ifdef HAVE_PTHREAD_COND_INIT int r = pthread_cond_destroy(&cond->cond); if (r != 0) { rb_bug_errno("pthread_cond_destroy", r); } #endif }
static void native_cond_broadcast(rb_nativethread_cond_t *cond) { int r; do { r = pthread_cond_broadcast(&cond->cond); } while (r == EAGAIN); if (r != 0) { rb_bug_errno("native_cond_broadcast", r); } }
static void native_cond_signal(rb_nativethread_cond_t *cond) { int r; do { r = pthread_cond_signal(&cond->cond); } while (r == EAGAIN); if (r != 0) { rb_bug_errno("pthread_cond_signal", r); } }
static inline int native_mutex_trylock(pthread_mutex_t *lock) { int r; if ((r = pthread_mutex_trylock(lock)) != 0) { if (r == EBUSY) { return EBUSY; } else { rb_bug_errno("pthread_mutex_trylock", r); } } return 0; }
static int native_cond_timedwait(rb_nativethread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *ts) { int r; /* * An old Linux may return EINTR. Even though POSIX says * "These functions shall not return an error code of [EINTR]". * http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_cond_timedwait.html * Let's hide it from arch generic code. */ do { r = pthread_cond_timedwait(&cond->cond, mutex, ts); } while (r == EINTR); if (r != 0 && r != ETIMEDOUT) { rb_bug_errno("pthread_cond_timedwait", r); } return r; }