Removed event overflow handling
[akaros.git] / Documentation / process-internals.txt
index 3ef4e58..87b9c73 100644 (file)
@@ -20,23 +20,21 @@ Contents:
 ===========================
 1.1 Basics:
 ---------------------------
-Reference counts (proc_refcnt) exist to keep a process alive.  Eventually, this
-will probably turn into a regular "kernel design pattern", like it is in Linux
-(http://lwn.net/Articles/336224/).  The style of reference counting we use for
-processes is similar to a kref:
+Reference counts exist to keep a process alive.  We use krefs for this, similar
+to Linux's kref:
 - Can only incref if the current value is greater than 0, meaning there is
   already a reference to it.  It is a bug to try to incref on something that has
   no references, so always make sure you incref something that you know has a
-  reference.  If you don't know, you need to get it manually (CAREFULLY!) or use
-  pid2proc (which is a careful way of doing this).  If you incref and there are
-  0 references, the kernel will panic.  Fix your bug / don't incref random
-  pointers.
+  reference.  If you don't know, you need to get it from pid2proc (which is a
+  careful way of doing this - pid2proc kref_get_not_zero()s on the reference that is
+  stored inside it).  If you incref and there are 0 references, the kernel will
+  panic.  Fix your bug / don't incref random pointers.
 - Can always decref.
 - When the decref returns 0, perform some operation.  This does some final
   cleanup on the object.
-
-For a process, proc_destroy() decrefs, and other codes using the proc also
-decref.  The last one to decref calls proc_free to do the final cleanup.
+- Process code is trickier since we frequently make references from 'current'
+  (which isn't too bad), but also because we often do not return and need to be
+  careful about the references we passed in to a no-return function.
 
 1.2 Brief History of the Refcnt:
 ---------------------------
@@ -60,7 +58,15 @@ protected by a refcnt.
 ---------------------------
 +1 for existing.
 - The fact that the process is supposed to exist is worth +1.  When it is time
-  to die, we decref, and it will eventually be cleaned up.
+  to die, we decref, and it will eventually be cleaned up.  This existence is
+  explicitly kref_put()d in proc_destroy().
+- The hash table is a bit tricky.  We need to kref_get_not_zero() when it is
+  locked, so we know we aren't racing with proc_free freeing the proc and
+  removing it from the list.  After removing it from the hash, we don't need to
+  kref_put it, since it was an internal ref.  The kref (i.e. external) isn't for
+  being on the hash list, it's for existing.  This separation allows us to
+  remove the proc from the hash list in the "release" function.  See kref.txt
+  for more details.
 
 +1 for someone using it or planning to use it.
 - This includes simply having a pointer to the proc, since presumably you will
@@ -73,7 +79,11 @@ protected by a refcnt.
 
 +1 for current.
 - current counts as someone using it (expressing interest in the core), but is
-  also a source of the pointer, so its a bit different.
+  also a source of the pointer, so its a bit different.  Note that all kref's
+  are sources of a pointer.  Technically, to even use 'current', we should kref
+  it and pass it around as a proc.  We don't for performance reasons.  When we
+  are running on a core that has current loaded, the ref is both for its usage
+  as well as for being the current process.
 - You have a reference from current and can use it without refcnting, but
   anything that needs to eat a reference or store/use it needs an incref first.
   To be clear, your reference is *NOT* edible.  It protects the cr3, guarantees
@@ -82,8 +92,9 @@ protected by a refcnt.
   an IO continuation request), then clearly you must incref, since it's both
   current and stored/used.
 - If you don't know what might be downstream from your function, then incref
-  before passing the reference, and decref when it returns.  Like when handling
-  syscalls, for example.
+  before passing the reference, and decref when it returns.  We used to do this
+  for all syscalls, but now only do it for calls that might not return and
+  expect to receive reference (like proc_yield).
 
 All functions that take a *proc have a refcnt'd reference, though it may not be
 edible (it could be current).  It is the callers responsibility to make sure
@@ -102,6 +113,11 @@ This means that you must have a reference when you call them (like always), and
 that reference will be consumed / decref'd for you if the function doesn't
 return.  Or something similarly appropriate.
 
+Arguably, for functions that MAY not return, but will always be called with
+current's reference (proc_yield()), we could get away without giving it an
+edible reference, and then never eating the ref.  Yield needs to be reworked
+anyway, so it's not a bit deal yet.
+
 We do this because when the function does not return, you will not have the
 chance to decref (your decref code will never run).  We need the reference when
 going in to keep the object alive (like with any other refcnt).  We can't have