parlib: Fix the use-after-func issue
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 18 Dec 2018 18:35:29 +0000 (13:35 -0500)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 18 Dec 2018 20:30:28 +0000 (15:30 -0500)
commitdfa2a002f9b8e1762351f7d9500169964e755f08
tree78b0662f613d201a5c745648d95c736dfb4dcb78
parent02b50413fd2902e6078adac5e3f4939bfef16a6f
parlib: Fix the use-after-func issue

Same as in the kernel, the parlib alarm service was touching the waiter
struct after the function ran.  We were doing this to know when the
function was complete when we were unsetting the alarm.  However, this
complicates the code of any client, since the completion of the function
isn't proof that the struct won't be reused.

See commit 47c2cf2efd4e ("futex: Call unset_alarm() before freeing the
awaiter") for a bug caused by this, and commit c62a28c78976 ("alarm:
Force unset_alarm to grab the CV lock")

The fix is the same as in the kernel - use the tchain->running variable
to track when a handler is running.

We're using the CV lock directly - userspace CVs don't have the same
interface as the kernel where you can tell it to use another lock.  And
we don't really need that interface, especially given that userspace CVs
are typically used for mutexes.

Given the slight nastiness associated with signalling a uth CV that uses
the CV lock, specifically that we want to unlock before waking the
uthread, I tried skipping the CV completely and just yielding - in
effect a busy-wait with a uthread_yield (sched_yield actually, which is
safe since we're an MCP if we ever unset during an alarm handler,
assuming one never unsets during their *own* alarm handle)).  However,
at least in qemu for some Go tests, some tests timed out too frequently.
My guess is that alarms were delayed too much by the busy waiting.

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