void vtimer_callback(void *ptr) { DEBUG("vtimer_callback ptr=%p\n", ptr); (void) ptr; in_callback = true; hwtimer_id = -1; /* get the vtimer that fired */ vtimer_t *timer = node_get_timer(priority_queue_remove_head(&shortterm_priority_queue_root)); if (timer) { #if ENABLE_DEBUG vtimer_print(timer); #endif DEBUG("vtimer_callback(): Shooting %" PRIu32 ".\n", timer->absolute.microseconds); /* shoot timer */ timer->action(timer); } else { DEBUG("vtimer_callback(): spurious call.\n"); } in_callback = false; update_shortterm(); }
static int update_shortterm(void) { if (shortterm_priority_queue_root.first == NULL) { /* there is no vtimer to schedule, queue is empty */ DEBUG("update_shortterm: shortterm_priority_queue_root.next == NULL - dont know what to do here\n"); return 0; } if (hwtimer_id != -1) { /* there is a running hwtimer for us */ if (hwtimer_next_absolute != shortterm_priority_queue_root.first->priority) { /* the next timer in the vtimer queue is not the next hwtimer */ /* we have to remove the running hwtimer (and schedule a new one) */ hwtimer_remove(hwtimer_id); } else { /* the next vtimer is the next hwtimer, nothing to do */ return 0; } } /* short term part of the next vtimer */ hwtimer_next_absolute = shortterm_priority_queue_root.first->priority; uint32_t next = hwtimer_next_absolute; /* current short term time */ uint32_t now = HWTIMER_TICKS_TO_US(hwtimer_now()); /* make sure the longterm_tick_timer does not get truncated */ if (node_get_timer(shortterm_priority_queue_root.first)->action != vtimer_callback_tick) { /* the next vtimer to schedule is the long term tick */ /* it has a shortterm offset of longterm_tick_start */ next += longterm_tick_start; } if((next - HWTIMER_TICKS_TO_US(VTIMER_THRESHOLD) - now) > MICROSECONDS_PER_TICK ) { DEBUG("truncating next (next - HWTIMER_TICKS_TO_US(VTIMER_THRESHOLD) - now): %lu\n", (next - HWTIMER_TICKS_TO_US(VTIMER_THRESHOLD) - now)); next = now + HWTIMER_TICKS_TO_US(VTIMER_BACKOFF); } DEBUG("update_shortterm: Set hwtimer to %" PRIu32 " (now=%lu)\n", next, HWTIMER_TICKS_TO_US(hwtimer_now())); hwtimer_id = hwtimer_set_absolute(HWTIMER_TICKS(next), vtimer_callback, NULL); return 0; }
void vtimer_callback_tick(vtimer_t *timer) { (void) timer; DEBUG("vtimer_callback_tick().\n"); longterm_tick_start += MICROSECONDS_PER_TICK; longterm_tick_timer.absolute.seconds += SECONDS_PER_TICK; longterm_tick_timer.absolute.microseconds = MICROSECONDS_PER_TICK; // Should never change, just for clarity. set_shortterm(&longterm_tick_timer); while (longterm_priority_queue_root.first) { vtimer_t *timer = node_get_timer(longterm_priority_queue_root.first); if (timer->absolute.seconds == longterm_tick_timer.absolute.seconds) { priority_queue_remove_head(&longterm_priority_queue_root); set_shortterm(timer); } else { break; } } }