alarm: Handle the tchain in RKM context
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 13 Nov 2018 02:34:41 +0000 (21:34 -0500)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 18 Dec 2018 20:30:28 +0000 (15:30 -0500)
commitdfd46c31c6615091f7edd005ec2dd536a99453ae
tree1a043f451a3238013d35213b5442ed4063368819
parent5ec59521aca5a4d98afb08c1be8a7283f5e5cd9b
alarm: Handle the tchain in RKM context

The root issue is that we can't touch the alarm after it finished, yet
we also want to know when it has completed.  The way to do this is with
a layer of indirection!  (sort of - just with a pointer).  We can keep a
pointer that tracks the handler we're working on.

Don't forget - we want to run the handlers without holding the lock too,
which makes setting an alarm from a handler easier.  And it might avoid
deadlocks, such as the ones we saw in userspace with futexes.

To do all of this, we need to synchronize on that pointer, and it's
basically part of the tchain.  We want to manipulate the handlers and
the tchain while holding the lock, and run with the pointer set.  This
couples the execution of the locks with the processing of the tchain.
The old code just fired off a bunch of RKMs and forgot about them - we
can't forget now.

The answer here is to run the tchain handler as an RKM itself.  The
easiest way is to have __trigger_tchain send the core an RKM to
run_tchain.  Initially had a per-core ktask that looped and slept on a
CV, and the IRQ kicked the CV.  Just using the RKM directly is a little
faster and simpler.  It also means we won't have to worry about it if we
ever do special things with ktasks, like scheduling, priority, affinity,
etc.  The one slight downside is we might get multiple RKMs on the same
core to run the tchain.  That's pretty minor, and harmless from a
correctness perspective.

Also, since we're not touching the lock in IRQ ctx, we probably can make
it a non-irqsave one.

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