alarm: Add a alarm_expired() The rendez code was looking at on_tchain to determine if it had expired or not. It is possible for the alarm to have expired even though the handler hasn't run yet. If an alarm runs as an RKM, its time might have come, but it is still on the tchain. In these cases, we want to timeout the rendez instead of waiting for the alarm service. Note that this is safe in regards to the alarm's memory. I was briefly worried that we're breaking out of the rendez loop before the alarm handler runs. But we do that all the time, such as when a condition fires, and we handle it by calling unset_alarm(). I noticed this when trying to debug a potential livelock. We might be able to go back to on_tchain or something else if that read_tsc() is a problem. In that case, we'll just change the helper. Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
diff --git a/kern/include/alarm.h b/kern/include/alarm.h index 97933fc..c9f6197 100644 --- a/kern/include/alarm.h +++ b/kern/include/alarm.h
@@ -119,6 +119,11 @@ /* Sets the timer chain interrupt according to the next timer in the chain. */ void set_pcpu_alarm_interrupt(struct timer_chain *tchain); +static inline bool alarm_expired(struct alarm_waiter *awaiter) +{ + return awaiter->wake_up_time <= read_tsc(); +} + /* Debugging */ #define ALARM_POISON_TIME 12345 /* could use some work */ void print_chain(struct timer_chain *tchain);
diff --git a/kern/src/rendez.c b/kern/src/rendez.c index 4313c9a..215e85f 100644 --- a/kern/src/rendez.c +++ b/kern/src/rendez.c
@@ -97,7 +97,7 @@ * condition (and we should exit), other alarms with different timeouts (and * we should go back to sleep), etc. Note it is possible for our alarm to * fire immediately upon setting it: before we even cv_lock. */ - while (!cond(arg) && awaiter.on_tchain) { + while (!cond(arg) && !alarm_expired(&awaiter)) { if (should_abort(&cle)) { cv_unlock_irqsave(&rv->cv, &irq_state); unset_alarm(pcpui_tchain, &awaiter);