proc_destroy() no longer requires edible refs
[akaros.git] / Documentation / processes.txt
index c435258..42f620a 100644 (file)
@@ -170,9 +170,11 @@ TLS/TCB descriptor and the floating point/silly state (if applicable) in the
 user-thread control block, and do whatever is needed to signal vcore0 to run the
 _S context when it starts up.  One way would be to mark vcore0's "active thread"
 variable to point to the _S thread.  When vcore0 starts up at
-_start/hart_entry() (like all vcores), it will see a thread was running there
-and restart it.  This will need to have some special casing for the FP/silly
-state.
+_start/vcore_entry() (like all vcores), it will see a thread was running there
+and restart it.  The kernel will migrate the _S thread's silly state (FP) to the
+new pcore, so that it looks like the process was simply running the _S thread
+and got notified.  Odds are, it will want to just restart that thread, but the
+kernel won't assume that (hence the notification).
 
 In general, all cores (and all subsequently allocated cores) start at the elf
 entry point, with vcoreid in eax or a suitable arch-specific manner.  There is
@@ -180,13 +182,13 @@ also a syscall to get the vcoreid, but this will save an extra trap at vcore
 start time.
 
 Future proc_runs(), like from RUNNABLE_M to RUNNING_M start all cores at the
-entry point, including vcore0.  The saving of a _S context to vcore0's notif_tf only happens on
-the transition from _S to _M (which the process needs to be aware of for a
-variety of reasons).  This also means that userspace needs to handle vcore0
-coming up at the entry point again (and not starting the program over).  This is
-currently done in sysdeps-ros/start.c, via the static variable init.  Note there
-are some tricky things involving dynamically linked programs, but it all works
-currently.
+entry point, including vcore0.  The saving of a _S context to vcore0's notif_tf
+only happens on the transition from _S to _M (which the process needs to be
+aware of for a variety of reasons).  This also means that userspace needs to
+handle vcore0 coming up at the entry point again (and not starting the program
+over).  This is currently done in sysdeps-ros/start.c, via the static variable
+init.  Note there are some tricky things involving dynamically linked programs,
+but it all works currently.
 
 When coming in to the entry point, whether as the result of a startcore or a
 notification, the kernel will set the stack pointer to whatever is requested
@@ -219,29 +221,40 @@ from _S to _M: at the entry point.
 
 2.4.4: Yielding
 --------------
-This will get revised soon, to account for different types of yields.
-
-Yielding gives up a core.  In _S mode, it will transition from RUNNING_S to
-RUNNABLE_S.  The context is saved in env_tf.  A yield will *not* transition
-from _M to _S.
-
-In _M mode, this yields the calling core.  The kernel will rip it out of your
-vcore list.  A process can yield its cores in any order.  The kernel will
-"fill in the holes of the vcoremap" when for any future newcores (e.g., proc A
-has 4 vcores, yields vcore2, and then asks for another vcore.  The new one
-will be vcore2).
-
-When you are in _M and yield your last core, it is an m_yield.  This
-completely suspends all cores, like a voluntary preemption.  When the process
-is run again, all cores will come up at the entry point (including vcore0 and
-the calling core).  This isn't implemented yet, and will wait on some work
-with preemption.
-
-We also need a type of yield (or a flag) that says the process is just giving
-up the core temporarily, but actually wants the core and does not want
-resource requests to be readjusted.  For example, in the event of a preemption
+sys_yield()/proc_yield() will give up the calling core, and may or may not
+adjust the desired number of cores, subject to its parameters.  Yield is
+performing two tasks, both of which result in giving up the core.  One is for
+not wanting the core anymore.  The other is in response to a preemption.  Yield
+may not be called remotely (ARSC).
+
+In _S mode, it will transition from RUNNING_S to RUNNABLE_S.  The context is
+saved in env_tf.
+
+In _M mode, this yields the calling core.  A yield will *not* transition from _M
+to _S.  The kernel will rip it out of your vcore list.  A process can yield its
+cores in any order.  The kernel will "fill in the holes of the vcoremap" for any
+future new cores requested (e.g., proc A has 4 vcores, yields vcore2, and then
+asks for another vcore.  The new one will be vcore2).  When any core starts in
+_M mode, even after a yield, it will come back at the vcore_entry()/_start point.
+
+Yield will normally adjust your desired amount of vcores to the amount after the
+calling core is taken.  This is the way a process gives its cores back.
+
+Yield can also be used to say the process is just giving up the core in response
+to a pending preemption, but actually wants the core and does not want resource
+requests to be readjusted.  For example, in the event of a preemption
 notification, a process may yield (ought to!) so that the kernel does not need
-to waste effort with full preemption.
+to waste effort with full preemption.  This is done by passing in a bool
+(being_nice), which signals the kernel that it is in response to a preemption.
+The kernel will not readjust the amt_wanted, and if there is no preemption
+pending, the kernel will ignore the yield.
+
+There may be an m_yield(), which will yield all or some of the cores of an MPC,
+remotely.  This is discussed farther down a bit.  It's not clear what exactly
+it's purpose would be.
+
+We also haven't addressed other reasons to yield, or more specifically to wait,
+such as for an interrupt or an event of some sort.
 
 2.4.5: Others
 --------------
@@ -477,15 +490,16 @@ trapframe.  The reason is that a preemption can come in at any time (such as
 right after returning from a preemption).
 
 To maintain this invariant, when the kernel starts a vcore, it will run the
-context that is in the preempt trapframe if the "preempt_tf_sorted" (name will
-change) flag is not set.  A process needs to be careful of a race here.  If
-they are trying to deal with a preempt trapframe (must be from another vcore,
-btw), the kernel could start to run that trapframe (in case it is granting a
-core request / proc_startcore()ing).  When the kernel prepares to use the
-trapframe (which it will do regardless of userspace activities), it will up
-the flag/counter.  If the process notices a change in that flag, it ought to
-abort its operation.  It can up the counter on its own when it no longer wants
-the kernel to run that context (this means it can get clobbered).
+context that is in the preempt trapframe if the "preempt_tf_valid" seq_ctr is
+not set.  A process needs to be careful of a race here.  If they are trying to
+deal with a preempt trapframe (must be from another vcore, btw), the kernel
+could start to run that trapframe (in case it is granting a core request /
+proc_startcore()ing).  When the kernel prepares to use the trapframe (which it
+will do regardless of userspace activities), it will up the seq_ctr.  We use a
+seq_ctr (mostly just a counter) to avoid ABA-related issues.  If the process
+notices a change in that flag, it ought to abort its operation.  It can up the
+counter on its own when it no longer wants the kernel to run that context (this
+means the preempt_tf can get clobbered).
 
 4.4: Other trickiness
 -------------------------------
@@ -542,17 +556,17 @@ hardware interrupts (on x86, at least).
 There will be cases where the trapframe in the preempt_tf slot is actually a
 notification handler, which was running on the transition stack of that
 particular vcore.  Userspace needs to be careful about restarting contexts
-that were on those cores.  They can tell by examining the stack pointer to see
-if it was on a transition stack.  Alternatively, if notifications are masked,
-it is also likely they in a notification handler.  The real concern is the
-transition stack.  If a vcore is processing on the transition stack of another
-vcore, there is a risk that the vcore comes back up and starts clobbering the
-transition stack.
-
-To avoid this, userspace should allocate a new transition stack and switch the
+that were on those cores on different cores.  They can tell by examining the
+stack pointer to see if it was on a transition stack.  Alternatively, if
+notifications are masked, it is also likely they in a notification handler.  The
+real concern is the transition stack.  If a vcore is processing on the
+transition stack of another vcore, there is a risk that the vcore comes back up
+and starts clobbering the transition stack.
+
+To avoid this, userspace could allocate a new transition stack and switch the
 target vcore to use that new stack (in procdata).  The only time (for now)
 that the kernel cares about a transition stack is when it is popping a tf on a
-new or freshly notified vcore.
+new or freshly notified vcore.  Something similar will need to be done with TLS.
 
 This all should be a rare occurance, since the vcore should see the
 preempt_pending when it starts its notification and yield, instead of being
@@ -565,6 +579,10 @@ also may need only one trapframe slot).  Userspace probably cannot guarantee
 that, so we'll have to deal with it.  Avoiding the deadlock on a spinlock is
 much more reasonable (and we can provide the locking function).
 
+Another thing to keep in mind is that userspace probably won't want to restart a
+notification handler on a different core.  It's conceivable that they want to
+take a regular user thread and context and restart it, not a transition context.
+
 4.4.4: Userspace Yield Races
 -------------------------------
 Imagine a vcore realizes it is getting preempted soon, so it starts to yield.
@@ -579,9 +597,9 @@ yield and simply return to userspace.
 4.4.5: Userspace m_yield
 -------------------------------
 There are a variety of ways to implement an m_yield (yield the entire MCP).
-We could have a "no niceness" yield - just immediately preempt, but there is a danger of the
-locking business.  We could do the usual delay game, though if userspace is
-requesting its yield, arguably we don't need to give warning. 
+We could have a "no niceness" yield - just immediately preempt, but there is a
+danger of the locking business.  We could do the usual delay game, though if
+userspace is requesting its yield, arguably we don't need to give warning. 
 
 Another approach would be to not have an explicit m_yield call.  Instead, we
 can provide a notify_all call, where the notification sent to every vcore is