Linux Kernel Architecture

(Jacob Rumans) #1

Chapter 15: Time Management


The mechanism is not particularly complicated: After the coarse time is stored in the timer base by
hrtimer_get_softirq_time, the code loops over all clock bases (the monotonic and real-time clocks)
and processes the entries in each queue withrun_hrtimer_queue.

First of all, the function checks if any timers must be processed (ifhrtimer_cpu_baseis aNULLpointer,
then no first timer exists, and thus nothing needs to be done):

kernel/hrtimer.c
static inline void run_hrtimer_queue(struct hrtimer_cpu_base *cpu_base,
int index)
{
struct rb_node *node;
struct hrtimer_clock_base *base = &cpu_base->clock_base[index];

if (!base->first)
return;

if (base->get_softirq_time)
base->softirq_time = base->get_softirq_time();
...

Now the kernel has to find all timers that have expired and must be activated:

kernel/hrtimer.c
while ((node = base->first)) {
struct hrtimer *timer;
enum hrtimer_restart (*fn)(struct hrtimer *);
int restart;

timer = rb_entry(node, struct hrtimer, node);
if (base->softirq_time.tv64 <= timer->expires.tv64)
break;
...
fn = timer->function;
__remove_hrtimer(timer, base, HRTIMER_STATE_CALLBACK, 0);
...

Starting from the timer that is the first expiration candidate (base->first), the kernel checks if the timer
has already expired and calls the timer’s expiration function if this is the case. Recall that erasing the timer
with__remove_timeralso selects the next expiration candidate by updatingbase->first. Additionally,
the flagHRTIMER_STATE_CALLBACKis set in the timer because the callback function is about to be executed:

kernel/hrtimer.c
restart = fn(timer);

timer->state &= ̃HRTIMER_STATE_CALLBACK;
if (restart != HRTIMER_NORESTART) {
enqueue_hrtimer(timer, base, 0);
}
}
}
Free download pdf