int pthread_cond_timeout_np(pthread_cond_t *cond, pthread_mutex_t * mutex, unsigned msecs) { struct timespec ts; ts.tv_sec = msecs / 1000; ts.tv_nsec = (msecs % 1000) * 1000000; return __pthread_cond_timedwait_relative(cond, mutex, &ts); }
__LIBC_HIDDEN__ int __pthread_cond_timedwait(pthread_cond_t* cond, pthread_mutex_t* mutex, const struct timespec* abstime, clockid_t clock) { struct timespec ts; struct timespec* tsp; if (abstime != NULL) { if (__timespec_to_absolute(&ts, abstime, clock) < 0) { return ETIMEDOUT; } tsp = &ts; } else { tsp = NULL; } return __pthread_cond_timedwait_relative(cond, mutex, tsp); }
int pthread_cond_timeout_np(pthread_cond_t* cond, pthread_mutex_t* mutex, unsigned ms) { struct timespec ts; timespec_from_ms(&ts, ms); return __pthread_cond_timedwait_relative(cond, mutex, &ts); }
int pthread_cond_timedwait_relative_np(pthread_cond_t* cond, pthread_mutex_t* mutex, const struct timespec* reltime) { return __pthread_cond_timedwait_relative(cond, mutex, reltime); }
static void* timer_thread_start( void* _arg ) { thr_timer_t* timer = _arg; thr_timer_lock( timer ); /* we loop until timer->done is set in timer_delete() */ while (!timer->done) { struct timespec expires = timer->expires; struct timespec period = timer->period; struct timespec now; /* if the timer is stopped or disarmed, wait indefinitely * for a state change from timer_settime/_delete/_start_stop */ if ( timer->stopped || timespec_is_zero(&expires) ) { pthread_cond_wait( &timer->cond, &timer->mutex ); continue; } /* otherwise, we need to do a timed wait until either a * state change of the timer expiration time. */ clock_gettime(timer->clock, &now); if (timespec_cmp( &expires, &now ) > 0) { /* cool, there was no overrun, so compute the * relative timeout as 'expires - now', then wait */ int ret; struct timespec diff = expires; timespec_sub( &diff, &now ); ret = __pthread_cond_timedwait_relative( &timer->cond, &timer->mutex, &diff); /* if we didn't timeout, it means that a state change * occured, so reloop to take care of it. */ if (ret != ETIMEDOUT) continue; } else { /* overrun was detected before we could wait ! */ if (!timespec_is_zero( &period ) ) { /* for periodic timers, compute total overrun count */ do { timespec_add( &expires, &period ); if (timer->overruns < DELAYTIMER_MAX) timer->overruns += 1; } while ( timespec_cmp( &expires, &now ) < 0 ); /* backtrack the last one, because we're going to * add the same value just a bit later */ timespec_sub( &expires, &period ); } else { /* for non-periodic timer, things are simple */ timer->overruns = 1; } } /* if we get there, a timeout was detected. * first reload/disarm the timer has needed */ if ( !timespec_is_zero(&period) ) { timespec_add( &expires, &period ); } else { timespec_zero( &expires ); } timer->expires = expires; /* now call the timer callback function. release the * lock to allow the function to modify the timer setting * or call timer_getoverrun(). * * NOTE: at this point we trust the callback not to be a * total moron and pthread_kill() the timer thread */ thr_timer_unlock(timer); timer->callback( timer->value ); thr_timer_lock(timer); /* now clear the overruns counter. it only makes sense * within the callback */ timer->overruns = 0; } thr_timer_unlock( timer ); /* free the timer object now. there is no need to call * __timer_table_get() since we're guaranteed that __timer_table * is initialized in this thread */ thr_timer_table_free(__timer_table, timer); return NULL; }