Fixes race and rewrites proc_yield()
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 12 Oct 2011 21:30:10 +0000 (14:30 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 15 Dec 2011 22:48:39 +0000 (14:48 -0800)
commit80bf465a15b208f6eb72ec608e1497382fc02305
treebb646c1f60788bffbc50262aa4e41f98a9b5f5f3
parent0d671dded58747bc6feef36aa268a3e98909d09b
Fixes race and rewrites proc_yield()

The race was with concurrent __preempts.  preempt_served would get
turned off and we'd be unmapped.  We needed to check for being unmapped
with irqs disabled.

preempt_served serves as a "preemption is on the way, but hasn't hit
yet".  In this case, we've been removed from the online list and just
need to return and take the preemption.  A process might see this as
yield failing, either immediately or when the vcore gets restarted.

A few notes on proc_yield, and the unfortunate fact that we lock in it
(making it a pain for scalability):

1) Yield needs to leave the core, just like __death.  unmap, abandon,
etc.

2) It is safe to do one unmap without the lock, but only if you were
told to by the lockholder (which is what __preempt and __death do).
Granting new ones requires the lock.  Other than in __preempt and
__death, you can't trust reading the vcoremap to get your vcoreid
without the lock, since you could see the result of a take_core then a
give_core to different a vcore.  This is probably true.

3) Adding the pcore to the idlecoremap involves locking too (though not
the proc_lock);

4) Yield needs to not conflict with KMSGs.

5) Yield needs to not miss a notif_pending (playing shmem games with the
lists and __alert_vcore()

6) Lacking any remote __preempt/__death/__myield, yield needs to remove
its vcore from the online_list, which requires locking.
kern/src/process.c