int NdbCondition_WaitTimeoutAbs(struct NdbCondition* p_cond, NdbMutex* p_mutex, const struct timespec * abstime) { #ifdef NDB_WIN /** * mysys windows wrapper of pthread_cond_timedwait * does not have a const argument for the timespec */ struct timespec tmp = *abstime; struct timespec * waitarg = &tmp; #else const struct timespec * waitarg = abstime; #endif if (p_cond == NULL || p_mutex == NULL) return 1; #ifdef NDB_MUTEX_STRUCT return pthread_cond_timedwait(&p_cond->cond, &p_mutex->mutex, waitarg); #else return native_cond_timedwait(&p_cond->cond, p_mutex, waitarg); #endif }
static void native_sleep(rb_thread_t *th, struct timeval *timeout_tv) { struct timespec timeout; rb_nativethread_lock_t *lock = &th->interrupt_lock; rb_nativethread_cond_t *cond = &th->native_thread_data.sleep_cond; if (timeout_tv) { struct timespec timeout_rel; timeout_rel.tv_sec = timeout_tv->tv_sec; timeout_rel.tv_nsec = timeout_tv->tv_usec * 1000; /* Solaris cond_timedwait() return EINVAL if an argument is greater than * current_time + 100,000,000. So cut up to 100,000,000. This is * considered as a kind of spurious wakeup. The caller to native_sleep * should care about spurious wakeup. * * See also [Bug #1341] [ruby-core:29702] * http://download.oracle.com/docs/cd/E19683-01/816-0216/6m6ngupgv/index.html */ if (timeout_rel.tv_sec > 100000000) { timeout_rel.tv_sec = 100000000; timeout_rel.tv_nsec = 0; } timeout = native_cond_timeout(cond, timeout_rel); } GVL_UNLOCK_BEGIN(); { native_mutex_lock(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 (!timeout_tv) native_cond_wait(cond, lock); else native_cond_timedwait(cond, lock, &timeout); } th->unblock.func = 0; th->unblock.arg = 0; native_mutex_unlock(lock); } GVL_UNLOCK_END(); thread_debug("native_sleep done\n"); }
static rb_thread_t * register_cached_thread_and_wait(void) { rb_thread_cond_t cond = { PTHREAD_COND_INITIALIZER, }; volatile rb_thread_t *th_area = 0; struct timeval tv; struct timespec ts; struct cached_thread_entry *entry = (struct cached_thread_entry *)malloc(sizeof(struct cached_thread_entry)); if (entry == 0) { return 0; /* failed -> terminate thread immediately */ } gettimeofday(&tv, 0); ts.tv_sec = tv.tv_sec + 60; ts.tv_nsec = tv.tv_usec * 1000; pthread_mutex_lock(&thread_cache_lock); { entry->th_area = &th_area; entry->cond = &cond; entry->next = cached_thread_root; cached_thread_root = entry; native_cond_timedwait(&cond, &thread_cache_lock, &ts); { struct cached_thread_entry *e = cached_thread_root; struct cached_thread_entry *prev = cached_thread_root; while (e) { if (e == entry) { if (prev == cached_thread_root) { cached_thread_root = e->next; } else { prev->next = e->next; } break; } prev = e; e = e->next; } } free(entry); /* ok */ native_cond_destroy(&cond); } pthread_mutex_unlock(&thread_cache_lock); return (rb_thread_t *)th_area; }
static void native_sleep(rb_thread_t *th, struct timeval *timeout_tv) { struct timespec timeout; struct timeval tvn; pthread_mutex_t *lock = &th->interrupt_lock; rb_thread_cond_t *cond = &th->native_thread_data.sleep_cond; if (timeout_tv) { struct timespec timeout_rel; timeout_rel.tv_sec = timeout_tv->tv_sec; timeout_rel.tv_nsec = timeout_tv->tv_usec; timeout = native_cond_timeout(cond, timeout_rel); } GVL_UNLOCK_BEGIN(); { pthread_mutex_lock(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 (!timeout_tv) native_cond_wait(cond, lock); else native_cond_timedwait(cond, lock, &timeout); } th->unblock.func = 0; th->unblock.arg = 0; pthread_mutex_unlock(lock); } GVL_UNLOCK_END(); thread_debug("native_sleep done\n"); }
static int lock_func(rb_thread_t *th, rb_mutex_t *mutex, int timeout_ms) { int interrupted = 0; int err = 0; mutex->cond_waiting++; for (;;) { if (!mutex->th) { mutex->th = th; break; } if (RUBY_VM_INTERRUPTED(th)) { interrupted = 1; break; } if (err == ETIMEDOUT) { interrupted = 2; break; } if (timeout_ms) { struct timespec timeout_rel; struct timespec timeout; timeout_rel.tv_sec = 0; timeout_rel.tv_nsec = timeout_ms * 1000 * 1000; timeout = native_cond_timeout(&mutex->cond, timeout_rel); err = native_cond_timedwait(&mutex->cond, &mutex->lock, &timeout); } else { native_cond_wait(&mutex->cond, &mutex->lock); err = 0; } } mutex->cond_waiting--; return interrupted; }