pid_nth
authorBarret Rhoden <brho@cs.berkeley.edu>
Sat, 18 Jan 2014 00:10:23 +0000 (16:10 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Sat, 18 Jan 2014 00:10:23 +0000 (16:10 -0800)
Needed for devproc, eventually.

kern/src/process.c

index a7a7a10..418ea83 100644 (file)
@@ -28,6 +28,7 @@
 #include <elf.h>
 #include <arsc_server.h>
 #include <devfs.h>
+#include <kmalloc.h>
 
 struct kmem_cache *proc_cache;
 
@@ -165,6 +166,50 @@ struct proc *pid2proc(pid_t pid)
        return p;
 }
 
+/* Used by devproc for successive reads of the proc table.
+ * Returns a pointer to the nth proc, or 0 if there is none.
+ * This uses get_not_zero, since it is possible the refcnt is 0, which means the
+ * process is dying and we should not have the ref (and thus return 0).  We need
+ * to lock to protect us from getting p, (someone else removes and frees p),
+ * then get_not_zero() on p.
+ * Don't push the locking into the hashtable without dealing with this. */
+struct proc *pid_nth(unsigned int n)
+{
+       struct proc *p;
+       spin_lock(&pid_hash_lock);
+       if (!hashtable_count(pid_hash)) {
+               spin_unlock(&pid_hash_lock);
+               return NULL;
+       }
+       struct hashtable_itr *iter = hashtable_iterator(pid_hash);
+       p = hashtable_iterator_value(iter);
+
+       while (p) {
+               /* if this process is not valid, it doesn't count,
+                * so continue
+                */
+
+               if (kref_get_not_zero(&p->p_kref, 1)){
+                       /* this one counts */
+                       if (! n){
+                               printd("pid_nth: at end, p %p\n", p);
+                               break;
+                       }
+                       kref_put(&p->p_kref);
+                       n--;
+               }
+               if (!hashtable_iterator_advance(iter)){
+                       p = NULL;
+                       break;
+               }
+               p = hashtable_iterator_value(iter);
+       }
+
+       spin_unlock(&pid_hash_lock);
+       kfree(iter);
+       return p;
+}
+
 /* Performs any initialization related to processes, such as create the proc
  * cache, prep the scheduler, etc.  When this returns, we should be ready to use
  * any process related function. */