parlib: Run alarm handlers outside the tchain lock
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 14 Aug 2018 14:54:44 +0000 (10:54 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 14 Aug 2018 14:54:44 +0000 (10:54 -0400)
commit9969434fee6b7b8d7ef6584cdfc4657cabd88eca
tree4c380ef639359fd26897e164cdaa7cb27ae083c0
parentcbb3622e027c13b7e36f751650d2e4ca4ddb05a9
parlib: Run alarm handlers outside the tchain lock

This follows the same pattern as the kernel's alarm service.  Note the use
of uth_cond_var_lock(), since our tchain is kicked from vcore context.

Anyone calling __set_alarm() needs to just call set_alarm().  The old
special casing of code that was run from an alarm handler is gone.

This should resolve a deadlock between the futex code and the alarm code.
__futex_block() holds the futex's spinlock and tries to set an alarm, which
grabs the alarm's tchain lock.  The lock ordering is futex -> alarm/tchain.
__futex_timeout(), which is an alarm handler, grabs the futex lock.  Prior
to this patch, alarm handlers held the tchain lock.  That required a lock
ordering of alarm/tchain->futex, which causes a deadlock.  Alarm handlers
no longer hold the tchain lock, which breaks the circular wait.

Fun tidbit: the alarm utest failed on hardware, since the time was exactly
right (rounded to the nearest usec).

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
tests/vmm/vmrunkernel.c
user/parlib/alarm.c
user/parlib/include/parlib/alarm.h
user/utest/alarm.c