Linux Kernel Architecture

(Jacob Rumans) #1

Chapter 15: Time Management


if (expires.tv64 < expires_next.tv64)
expires_next = expires;
break;
}

If the next timer’s expiration time lies in the future, processing can be stopped by leaving thewhileloop.
The time of expiration is, however, remembered because it is later required to reprogram the clock event
device.

If the current timer has expired, it is moved to the callback list for later processing in the softIRQ if
this is allowed, that is, ifHRTIMER_CB_SOFTIRQis set.continueensures that the code moves to the next
timer. Erasing the timer with__remove_timeralso selects the next expiration candidate by updating
base->first. Additionally, this sets the timer state toHRTIMER_STATE_PENDING:

kernel/hrtimer.c
if (timer->cb_mode == HRTIMER_CB_SOFTIRQ) {
__remove_hrtimer(timer, base,
HRTIMER_STATE_PENDING, 0);
list_add_tail(&timer->cb_entry,
&base->cpu_base->cb_pending);
raise = 1;
continue;
}

Otherwise, the timer callback is directly executed in hard interrupt context. Note that this time
__remove_timersets the timer state toHRTIMER_STATE_CALLBACKbecause the callback handler is
executed immediately afterward:

kernel/hrtimer.c
__remove_hrtimer(timer, base,
HRTIMER_STATE_CALLBACK, 0);
...
if (timer->function(timer) != HRTIMER_NORESTART) {
enqueue_hrtimer(timer, base, 0);
}
timer->state &= ̃HRTIMER_STATE_CALLBACK;
}
base++;
}

The callback handler is executed bytimer->function(timer). If the handler requests to be restarted by
returningHRTIMER_RESTART,thenenqueue_hrtimerfulfills this request. TheHRTIMER_STATE_CALLBACK
flag can be removed once the handler has been executed.

When the pending timers of all clock bases have been selected, the kernel needs to reprogram the event
device to raise an interrupt when the next timer is due. Additionally, theHRTIMER_SOFTIRQmust be
raised if any timers are waiting on the callback list:

kernel/hrtimer.c
cpu_base->expires_next = expires_next;

/* Reprogramming necessary? */
if (expires_next.tv64 != KTIME_MAX) {
if (tick_program_event(expires_next, 0))
Free download pdf