alarm: Do not hold the tchain lock during handlers
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 13 Aug 2018 20:38:21 +0000 (16:38 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 13 Aug 2018 20:38:21 +0000 (16:38 -0400)
commit3a8e0569b016e2676f3c2889d01967803c56e2c8
tree14b5475be835c457b6e07f8343314ea99d30adde
parente580233c6bcf4b7cbe0fc4c5fb027947b21ea310
alarm: Do not hold the tchain lock during handlers

It's a bad idea to hold the tchain lock when running handlers.  For the
kernel's alarms, this was the case for IRQ handlers.

The main issue is deadlock between the handler and set/unset.  You can see
how we tried to avoid this in the past - alarm handlers were allowed to
set_alarm(), since we'd track 'holds_tchain_lock'.  That flag would turn
off lock checking for set_alarm(), but only for that strcut alarm_waiter.
However, we could have a situation where the alarm handler spins on a lock
held by someone else who is trying to set an alarm.  Something similar
happened in userspace with futexes and the alarm service.  (Though
userspace didn't have the 'holds_tchain_lock').

We already had the ability to run alarm handlers outside the tchain lock
for RKM alarms, which IIRC are newer than 'holds_tchain_lock'.  Now IRQ
alarms are treated the same way.

I was also able to break the lock ordering between the waiter's CV lock and
the tchain lock, as well as clean up a few other cases.  For the most part,
IRQ handlers differ from RKM only in when they run and the type of the
function pointer.

Also, rendez peaks directly at on_tchain.  That's still OK, but a little
suspect.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/include/alarm.h
kern/src/alarm.c
kern/src/rendez.c