bool rw_mutex::impl::write_lock(double sec) { #if defined(__linux__) || defined(__sparcv8) || defined(__sparcv9) if (!valid) return false; #ifdef JUBATUS_UTIL_CONCURRENT_RWMUTEX_ERRORCHECK assert(holders_lk.lock()==true); assert(holders.count(thread::id())==0); #endif bool result; if (sec<1e-9) { result = pthread_rwlock_trywrlock(&lk)==0; } else { timespec end=to_timespec(get_clock_time()+sec); result = pthread_rwlock_timedwrlock(&lk, &end)==0; } #ifdef JUBATUS_UTIL_CONCURRENT_RWMUTEX_ERRORCHECK if (result) holders.insert(thread::id()); assert(holders_lk.unlock()==true); #endif return result; #else return false; #endif }
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout) { struct epoll_event *ev = events; struct kevent evs[maxevents]; struct timespec tmspec; struct hash *coalesce; int i, r; r = kevent(epfd, NULL, 0, evs, maxevents, to_timespec(&tmspec, timeout)); if (UNLIKELY(r < 0)) return -1; coalesce = hash_int_new(NULL, NULL); if (!coalesce) return -1; for (i = 0; i < r; i++) { struct kevent *kev = &evs[i]; uint32_t mask = (uint32_t)(uintptr_t)hash_find(coalesce, (void*)(intptr_t)evs[i].ident); if (kev->flags & EV_ERROR) mask |= EPOLLERR; if (kev->flags & EV_EOF) mask |= EPOLLRDHUP; if (kev->filter == EVFILT_READ) mask |= EPOLLIN; else if (kev->filter == EVFILT_WRITE) mask |= EPOLLOUT; hash_add(coalesce, (void*)(intptr_t)evs[i].ident, (void *)(uintptr_t)mask); } for (i = 0; i < r; i++) { void *maskptr = hash_find(coalesce, (void*)(intptr_t)evs[i].ident); if (maskptr) { struct kevent *kev = &evs[i]; hash_del(coalesce, (void*)(intptr_t)evs[i].ident); ev->data.ptr = kev->udata; ev->events = (uint32_t)(uintptr_t)maskptr; ev++; } } hash_free(coalesce); return (int)(intptr_t)(ev - events); }
int linux_event_loop<handler>::add_timer( bool is_absolute, timestamp absolute_time, nanoseconds relative_time, nanoseconds freq, bool enabled) { int timer_fd = timerfd_create( CLOCK_REALTIME, TFD_NONBLOCK ); if( timer_fd == -1 ) { std::cerr << "cannot create timer" << std::endl; return -1; } if( set_nonblock(timer_fd) ) { std::cerr << "cannot set nonblock on timer" << std::endl; return -1; } struct itimerspec tspec; tspec.it_value = is_absolute ? to_timespec( absolute_time ) : to_timespec( relative_time ); if( freq != nanoseconds(0) ) { auto sec = std::chrono::duration_cast<seconds>(freq); tspec.it_interval.tv_sec = sec.count(); tspec.it_interval.tv_nsec = std::chrono::duration_cast<nanoseconds>( freq - sec ).count(); } else { tspec.it_interval.tv_sec = 0; tspec.it_interval.tv_nsec = 0; } int flags = is_absolute ? TFD_TIMER_ABSTIME : 0; if( timerfd_settime(timer_fd, flags, &tspec, NULL) != 0 ) { std::cerr << "cannot set timer" << std::endl; return -1; } connection c; c.type = TIMER; c.is_enabled = false; c.ev.events = EPOLLIN; c.ev.data.fd = timer_fd; _cons[timer_fd] = c; if( enabled ) { int err = enable(timer_fd); if( err < 0 ) { remove(timer_fd); std::cerr << "cannot enable timer: " << std::endl; return -1; } } return timer_fd; }
/* void test_ClockAccum(struct timespec *sum, struct timespec *b) */ static void test_ClockAccum(void) { /* INT_MIN/INT_MAX aren't corner cases, but are typical in writing errors. */ test_ClockAccum_validate(to_timespec(0, 0), to_timespec(0, 0), to_timespec(0, 0)); test_ClockAccum_validate(to_timespec(1, 0), to_timespec(1, 0), to_timespec(0, 0)); test_ClockAccum_validate(to_timespec(2, 0), to_timespec(1, 0), to_timespec(1, 0)); test_ClockAccum_validate(to_timespec(0, 1), to_timespec(0, 1), to_timespec(0, 0)); test_ClockAccum_validate(to_timespec(0, 1), to_timespec(0, 0), to_timespec(0, 1)); test_ClockAccum_validate(to_timespec(0, 2), to_timespec(0, 1), to_timespec(0, 1)); test_ClockAccum_validate(to_timespec(1, 2*(NSEC_PER_SEC/2 + 1) - NSEC_PER_SEC) , to_timespec(0, NSEC_PER_SEC/2 + 1), to_timespec(0, NSEC_PER_SEC/2 + 1)); }
static void test_ClockDiff(void) { test_ClockDiff_validate(to_timespec(0, 0), to_timespec(0, 0), to_timespec(0, 0), false); test_ClockDiff_validate(to_timespec(0, 0), to_timespec(1, 0), to_timespec(1, 0), false); test_ClockDiff_validate(to_timespec(1, 0), to_timespec(2, 0), to_timespec(1, 0), false); test_ClockDiff_validate(to_timespec(-1, 0), to_timespec(1, 0), to_timespec(2, 0), true); test_ClockDiff_validate(to_timespec(0, 0), to_timespec(0, 1), to_timespec(0, 1), false); test_ClockDiff_validate(to_timespec(0, 1), to_timespec(0, 2), to_timespec(0, 1), false); test_ClockDiff_validate(to_timespec(-1, NSEC_PER_SEC-1), to_timespec(0, 1), to_timespec(0, 2), true); test_ClockDiff_validate(to_timespec(-2, NSEC_PER_SEC-1), to_timespec(1, 1), to_timespec(2, 2), true); }
inline timespec timespec_plus(timespec const& lhs, timespec const& rhs) { return to_timespec(to_nanoseconds_int_max(lhs) + to_nanoseconds_int_max(rhs)); }