Пример #1
0
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");
}
Пример #2
0
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;
}
Пример #3
0
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;
 }
Пример #4
0
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
}
Пример #5
0
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);
    }
}
Пример #6
0
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);
    }
}
Пример #7
0
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);
    }
}
Пример #8
0
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);
    }
}
Пример #9
0
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);
    }
}
Пример #10
0
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);
    }
}
Пример #11
0
/*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);
    }
}
Пример #12
0
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);
    }
}
Пример #13
0
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;
}
Пример #14
0
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);
    }
}
Пример #15
0
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
}
Пример #16
0
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);
    }
}
Пример #17
0
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);
    }
}
Пример #18
0
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;
}
Пример #19
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;
}