/* * timed_check_worker -- (internal) check consistency with mutex */ static void * timed_check_worker(void *arg) { for (unsigned run = 0; run < WORKER_RUNS; run++) { int mutex_id = (int)(uintptr_t)arg % 2; PMEMmutex *mtx = mutex_id == LOCKED_MUTEX ? &Test_obj->mutex_locked : &Test_obj->mutex; struct timespec t1, t2, t_diff, abs_time; os_clock_gettime(CLOCK_REALTIME, &t1); abs_time = t1; abs_time.tv_nsec += TIMEOUT; if (abs_time.tv_nsec >= NANO_PER_ONE) { abs_time.tv_sec += abs_time.tv_nsec / NANO_PER_ONE; abs_time.tv_nsec %= NANO_PER_ONE; } int ret = pmemobj_mutex_timedlock(&Mock_pop, mtx, &abs_time); os_clock_gettime(CLOCK_REALTIME, &t2); if (mutex_id == LOCKED_MUTEX) { UT_ASSERTeq(ret, ETIMEDOUT); t_diff.tv_sec = t2.tv_sec - t1.tv_sec; t_diff.tv_nsec = t2.tv_nsec - t1.tv_nsec; if (t_diff.tv_nsec < 0) { --t_diff.tv_sec; t_diff.tv_nsec += NANO_PER_ONE; } UT_ASSERT(t_diff.tv_sec * NANO_PER_ONE + t_diff.tv_nsec >= TIMEOUT); return NULL; } if (ret == 0) { UT_ASSERTne(mutex_id, LOCKED_MUTEX); pmemobj_mutex_unlock(&Mock_pop, mtx); } else if (ret == ETIMEDOUT) { t_diff.tv_sec = t2.tv_sec - t1.tv_sec; t_diff.tv_nsec = t2.tv_nsec - t1.tv_nsec; if (t_diff.tv_nsec < 0) { --t_diff.tv_sec; t_diff.tv_nsec += NANO_PER_ONE; } UT_ASSERT(t_diff.tv_sec * NANO_PER_ONE + t_diff.tv_nsec >= TIMEOUT); } else { errno = ret; UT_ERR("!pmemobj_mutex_timedlock"); } } return NULL; }
bool timedlock_impl(const std::chrono::time_point<Clock, Duration> &abs_time) { PMEMobjpool *pop = pmemobj_pool_by_ptr(this); /* convert to my clock */ const typename Clock::time_point their_now = Clock::now(); const clock_type::time_point my_now = clock_type::now(); const auto delta = abs_time - their_now; const auto my_abs = my_now + delta; struct timespec ts = detail::timepoint_to_timespec(my_abs); auto ret = pmemobj_mutex_timedlock(pop, &this->plock, &ts); if (ret == 0) return true; else if (ret == ETIMEDOUT) return false; else throw lock_error(ret, std::system_category(), "Failed to lock a mutex"); }