ucs_status_t ucs_twheel_init(ucs_twheel_t *twheel, ucs_time_t resolution) { unsigned i; twheel->res = ucs_roundup_pow2(resolution); twheel->res_order = (unsigned) ucs_log2(twheel->res); twheel->num_slots = 1024; twheel->current = 0; twheel->now = ucs_get_time(); twheel->wheel = malloc(sizeof(*twheel->wheel) * twheel->num_slots); for (i = 0; i < twheel->num_slots; i++) { ucs_list_head_init(&twheel->wheel[i]); } ucs_debug("high res timer created log=%d resolution=%lf usec wanted: %lf usec", twheel->res_order, ucs_time_to_usec(twheel->res), ucs_time_to_usec(resolution)); return UCS_OK; }
void __ucs_wtimer_add(ucs_twheel_t *t, ucs_wtimer_t *timer, ucs_time_t delta) { uint64_t slot; timer->is_active = 1; slot = delta>>t->res_order; if (ucs_unlikely(slot == 0)) { /* nothing really wrong with adding timer to the current slot. However * we want to guard against the case we spend to much time in hi res * timer processing */ ucs_fatal("Timer resolution is too low. Min resolution %lf usec, wanted %lf usec", ucs_time_to_usec(t->res), ucs_time_to_usec(delta)); } ucs_assert(slot > 0); if (ucs_unlikely(slot >= t->num_slots)) { slot = t->num_slots - 1; } slot = (t->current + slot) % t->num_slots; ucs_assert(slot != t->current); ucs_list_add_tail(&t->wheel[slot], &timer->list); }
ucs_status_t ucs_timerq_add(ucs_timer_queue_t *timerq, int timer_id, ucs_time_t interval) { ucs_status_t status; ucs_timer_t *ptr; ucs_trace_func("timerq=%p interval=%.2fus timer_id=%d", timerq, ucs_time_to_usec(interval), timer_id); pthread_spin_lock(&timerq->lock); /* Make sure ID is unique */ for (ptr = timerq->timers; ptr < timerq->timers + timerq->num_timers; ++ptr) { if (ptr->id == timer_id) { status = UCS_ERR_ALREADY_EXISTS; goto out_unlock; } } /* Resize timer array */ ptr = ucs_realloc(timerq->timers, (timerq->num_timers + 1) * sizeof(ucs_timer_t), "timerq"); if (ptr == NULL) { status = UCS_ERR_NO_MEMORY; goto out_unlock; } timerq->timers = ptr; ++timerq->num_timers; timerq->min_interval = ucs_min(interval, timerq->min_interval); ucs_assert(timerq->min_interval != UCS_TIME_INFINITY); /* Initialize the new timer */ ptr = &timerq->timers[timerq->num_timers - 1]; ptr->expiration = 0; /* will fire the next time sweep is called */ ptr->interval = interval; ptr->id = timer_id; status = UCS_OK; out_unlock: pthread_spin_unlock(&timerq->lock); return status; }