int timer_settime( timer_t id, int flags, const struct itimerspec* spec, struct itimerspec* ospec ) { if (spec == NULL) { errno = EINVAL; return -1; } if ( __likely(!TIMER_ID_IS_WRAPPED(id)) ) { return __timer_settime( id, flags, spec, ospec ); } else { thr_timer_t* timer = thr_timer_from_id(id); struct timespec expires, now; if (timer == NULL) { errno = EINVAL; return -1; } thr_timer_lock(timer); /* return current timer value if ospec isn't NULL */ if (ospec != NULL) { timer_gettime_internal(timer, ospec ); } /* compute next expiration time. note that if the * new it_interval is 0, we should disarm the timer */ expires = spec->it_value; if (!timespec_is_zero(&expires)) { clock_gettime( timer->clock, &now ); if (!(flags & TIMER_ABSTIME)) { timespec_add(&expires, &now); } else { if (timespec_cmp(&expires, &now) < 0) expires = now; } } timer->expires = expires; timer->period = spec->it_interval; thr_timer_unlock( timer ); /* signal the change to the thread */ pthread_cond_signal( &timer->cond ); } return 0; }
// http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_getoverrun.html int timer_settime(timer_t id, int flags, const itimerspec* ts, itimerspec* ots) { PosixTimer* timer= reinterpret_cast<PosixTimer*>(id); int rc = __timer_settime(timer->kernel_timer_id, flags, ts, ots); if (rc == 0) { // Mark the timer as either being armed or disarmed. This avoids the // callback being called after the disarm for SIGEV_THREAD timers only. if (ts->it_value.tv_sec != 0 || ts->it_value.tv_nsec != 0) { timer->armed = true; } else { timer->armed = false; } } return rc; }
// http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_getoverrun.html int timer_settime(timer_t id, int flags, const itimerspec* ts, itimerspec* ots) { return __timer_settime(to_kernel_timer_id(id), flags, ts, ots); }
// http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_settime.html // When using timer_settime to disarm a repeatable SIGEV_THREAD timer with a very small // period (like below 1ms), the kernel may continue to send events to the callback thread // for a few extra times. This behavior is fine because in POSIX standard: The effect of // disarming or resetting a timer with pending expiration notifications is unspecified. int timer_settime(timer_t id, int flags, const itimerspec* ts, itimerspec* ots) { PosixTimer* timer= reinterpret_cast<PosixTimer*>(id); return __timer_settime(timer->kernel_timer_id, flags, ts, ots); }