// calculates x-y in nanoseconds, then converts to seconds before returning the float double timespec_diff(const struct timespec *x, const struct timespec *y) { int64_t x_in_nano = (SEC_TO_NSEC(x->tv_sec) + x->tv_nsec); int64_t y_in_nano = (SEC_TO_NSEC(y->tv_sec) + y->tv_nsec); return ((x_in_nano - y_in_nano) / 1e9); }
int ARSAL_Cond_Timedwait(ARSAL_Cond_t *cond, ARSAL_Mutex_t *mutex, int timeout) { int result = 0; struct timespec ts; ARSAL_Time_GetLocalTime(&ts, NULL); ts.tv_nsec += MSEC_TO_NSEC(timeout % SEC_TO_MSEC(1)); ts.tv_sec += MSEC_TO_SEC(timeout); ts.tv_sec += NSEC_TO_SEC(ts.tv_nsec); ts.tv_nsec %= SEC_TO_NSEC(1); #if defined(HAVE_PTHREAD_H) result = pthread_cond_timedwait((pthread_cond_t *)*cond, (pthread_mutex_t *)*mutex, &ts); if ( (result != 0) && (result != ETIMEDOUT) ) { ARSAL_PRINT(ARSAL_PRINT_FATAL, ARSAL_MUTEX_TAG, "Mutex/Cond operation failed! errno = %d , %s ; thread_id = %d", result, strerror(result), #if HAVE_DECL_SYS_GETTID syscall(SYS_gettid) #else 0 #endif ); } #endif return result; }
static clock_t get_cpu_time(void) { struct timespec ts; if (clock_gettime(CLOCK_MONOTONIC, &ts)) { ploop_err(errno, "clock_gettime"); return (clock_t)-1; } return SEC_TO_NSEC(ts.tv_sec) + ts.tv_nsec; }
static int do_lock(const char *fname, unsigned int timeout) { int fd, r, _errno; timer_t tid; clock_t end = 0; struct sigaction osa; struct sigaction sa = { .sa_handler = timer_handler, }; if ((fd = open(fname, O_RDWR)) == -1) { ploop_err(errno, "Can't open lock file %s", fname); return -1; } /* Set FD_CLOEXEC explicitly */ fcntl(fd, F_SETFD, FD_CLOEXEC); if (timeout) { end = get_cpu_time(); if (end == (clock_t)-1) goto err; end += SEC_TO_NSEC(timeout); sigaction(SIGRTMIN, &sa, &osa); if (set_timer(&tid, timeout)) goto err; } while ((r = flock(fd, LOCK_EX)) == -1) { _errno = errno; if (_errno != EINTR) break; if (timeout == 0 || get_cpu_time() < end) continue; _errno = EAGAIN; break; } if (timeout) { timer_delete(tid); sigaction(SIGRTMIN, &osa, NULL); } if (r != 0) { if (_errno == EAGAIN) { ploop_err(_errno, "The %s is locked", fname); goto err; } else { ploop_err(_errno, "Error in flock(%s)", fname); goto err; } } return fd; err: close(fd); return -1; }
int ARSAL_Sem_Timedwait(ARSAL_Sem_t *sem, const struct timespec *timeout) { int result = -1; if (NULL == sem || NULL == *sem) { errno = EINVAL; return result; } /* MUST BE INIT TO -1 */ /* No else. */ #if __SAL_USE_POSIX_SEM struct timespec finalTime = {0}; ARSAL_Time_GetLocalTime(&finalTime, NULL); finalTime.tv_nsec += timeout->tv_nsec; finalTime.tv_sec += timeout->tv_sec + NSEC_TO_SEC(finalTime.tv_nsec); finalTime.tv_nsec %= SEC_TO_NSEC(1); result = sem_timedwait((sem_t *)*sem, &finalTime); #else /* * Custom timedwait algo: * Lock mutex * Check if counter is > 0 * NO YES * | | - Decrement counter * | \ - Unlock mutex * | - Timedwait on condition * | - If timeout -> set result to -1 and errno to ETIMEDOUT * | - Else -> Decrement counter * \ - Unlock mutex */ ARSAL_Sem_CustomImpl_t *psem = (ARSAL_Sem_CustomImpl_t *)*sem; int unlockRes = 0; result = ARSAL_Mutex_Lock (&(psem->lock)); ARSAL_SEM_ERRNO_TRANSFORM (result); if (0 == result && 0 >= psem->count) { int msToWait = SEC_TO_MSEC(timeout->tv_sec) + NSEC_TO_MSEC(timeout->tv_nsec); result = ARSAL_Cond_Timedwait (&(psem->cond), &(psem->lock), msToWait); ARSAL_SEM_ERRNO_TRANSFORM (result); } /* No else. */ if (0 == result) { if (0 < psem->count) { (psem->count)--; } /* No else: don't decrement count below 0. */ } /* No else. */ unlockRes = ARSAL_Mutex_Unlock (&(psem->lock)); if (0 != unlockRes) { result = -1; errno = unlockRes; } /* No else. */ #endif return result; }