int _xtimer_set_absolute(xtimer_t *timer, uint32_t target) { uint32_t now = xtimer_now(); int res = 0; DEBUG("timer_set_absolute(): now=%" PRIu32 " target=%" PRIu32 "\n", now, target); timer->next = NULL; if ((target >= now) && ((target - XTIMER_BACKOFF) < now)) { /* backoff */ xtimer_spin_until(target + XTIMER_BACKOFF); _shoot(timer); return 0; } unsigned state = irq_disable(); if (_is_set(timer)) { _remove(timer); } timer->target = target; timer->long_target = _long_cnt; if (target < now) { timer->long_target++; } if ( (timer->long_target > _long_cnt) || !_this_high_period(target) ) { DEBUG("xtimer_set_absolute(): the timer doesn't fit into the low-level timer's mask.\n"); _add_timer_to_long_list(&long_list_head, timer); } else { if (_xtimer_lltimer_mask(now) >= target) { DEBUG("xtimer_set_absolute(): the timer will expire in the next timer period\n"); _add_timer_to_list(&overflow_list_head, timer); } else { DEBUG("timer_set_absolute(): timer will expire in this timer period.\n"); _add_timer_to_list(&timer_list_head, timer); if (timer_list_head == timer) { DEBUG("timer_set_absolute(): timer is new list head. updating lltimer.\n"); _lltimer_set(target - XTIMER_OVERHEAD); } } } irq_restore(state); return res; }
/** * @brief parse long timers list and copy those that will expire in the current * short timer period */ static void _select_long_timers(void) { xtimer_t *select_list_start = long_list_head; xtimer_t *select_list_last = NULL; /* advance long_list head so it points to the first timer of the next (not * just started) "long timer period" */ while (long_list_head) { if ((long_list_head->long_target <= _long_cnt) && _this_high_period(long_list_head->target)) { select_list_last = long_list_head; long_list_head = long_list_head->next; } else { /* remaining long_list timers belong to later long periods */ break; } } /* cut the "selected long timer list" at the end */ if (select_list_last) { select_list_last->next = NULL; } /* merge "current timer list" and "selected long timer list" */ if (timer_list_head) { if (select_list_last) { /* both lists are non-empty. merge. */ timer_list_head = _merge_lists(timer_list_head, select_list_start); } else { /* "selected long timer list" is empty, nothing to do */ } } else { /* current timer list is empty */ if (select_list_last) { /* there's no current timer list, but a non-empty "selected long * timer list". So just use that list as the new current timer * list.*/ timer_list_head = select_list_start; } } }