/** * Copyright (C) Mellanox Technologies Ltd. 2012-2013. ALL RIGHTS RESERVED. * * See file LICENSE for terms. */ #include #include #include #include #include ucs_status_t ucs_twheel_init(ucs_twheel_t *twheel, ucs_time_t resolution, ucs_time_t current_time) { 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 = current_time; twheel->wheel = ucs_malloc(sizeof(*twheel->wheel) * twheel->num_slots, "twheel"); if (twheel->wheel == NULL) { return UCS_ERR_NO_MEMORY; } 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_twheel_cleanup(ucs_twheel_t *twheel) { ucs_free(twheel->wheel); } ucs_status_t ucs_wtimer_init(ucs_wtimer_t *t, ucs_twheel_callback_t cb) { t->cb = cb; t->is_active = 0; 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); } void __ucs_twheel_sweep(ucs_twheel_t *t, ucs_time_t current_time) { ucs_wtimer_t *timer; uint64_t slot; slot = (current_time - t->now) >> t->res_order; t->now = current_time; if (ucs_unlikely(slot >= t->num_slots)) { slot = t->num_slots - 1; } slot = (t->current + slot) % t->num_slots; for (; t->current != slot; t->current = (t->current+1) % t->num_slots) { while (!ucs_list_is_empty(&t->wheel[t->current])) { timer = ucs_list_extract_head(&t->wheel[t->current], ucs_wtimer_t, list); timer->is_active = 0; timer->cb(timer); } } }