sys_trywait() now blocks
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 21 Mar 2012 20:01:15 +0000 (13:01 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 21 Mar 2012 20:01:15 +0000 (13:01 -0700)
We actually need a real wait/waitpid() call, which will also allow us to
cleanup glibc's waitpid() and fork() calls.  For now, this will allow us
to have bb block on its children, instead of spinning.

kern/include/env.h
kern/src/process.c
kern/src/syscall.c

index c047ce4..35c5459 100644 (file)
@@ -33,6 +33,7 @@ struct proc {
        pid_t pid;
        pid_t ppid;                 // Parent's PID
        pid_t exitcode;                         // exit() param or main() return value
+       struct semaphore state_change;
        uint32_t state;                         // Status of the process
        struct kref p_kref;             /* Refcnt */
        uint32_t env_flags;
index b12130a..e8b8a63 100644 (file)
@@ -247,6 +247,7 @@ error_t proc_alloc(struct proc **pp, struct proc *parent)
        /* Set the basic status variables. */
        spinlock_init(&p->proc_lock);
        p->exitcode = 1337;     /* so we can see processes killed by the kernel */
+       init_sem(&p->state_change, 0);
        p->ppid = parent ? parent->pid : 0;
        p->state = PROC_CREATED; /* shouldn't go through state machine for init */
        p->env_flags = 0;
@@ -678,6 +679,7 @@ void proc_restartcore(void)
 void proc_destroy(struct proc *p)
 {
        uint32_t num_revoked = 0;
+       struct kthread *sleeper;
        spin_lock(&p->proc_lock);
        /* storage for pc_arr is alloced at decl, which is after grabbing the lock*/
        uint32_t pc_arr[p->procinfo->num_vcores];
@@ -735,6 +737,10 @@ void proc_destroy(struct proc *p)
        close_all_files(&p->open_files, FALSE);
        /* This decref is for the process's existence. */
        proc_decref(p);
+       /* Signal our state change.  Assuming we only have one waiter right now. */
+       sleeper = __up_sem(&p->state_change, TRUE);
+       if (sleeper)
+               kthread_runnable(sleeper);
        /* Unlock.  A death IPI should be on its way, either from the RUNNING_S one,
         * or from proc_take_cores with a __death.  in general, interrupts should be
         * on when you call proc_destroy locally, but currently aren't for all
index d1beec4..fd8321a 100644 (file)
@@ -562,6 +562,12 @@ all_out:
 
 static ssize_t sys_trywait(env_t* e, pid_t pid, int* status)
 {
+       /* TODO:
+        * - WAIT should handle stop and start via signal too
+        *      - what semantics?  need a wait for every change to state?  etc.
+        * - should have an option for WNOHANG, and a bunch of other things.
+        * - think about what functions we want to work with MCPS
+        *   */
        struct proc* p = pid2proc(pid);
 
        // TODO: this syscall is racy, so we only support for single-core procs
@@ -576,6 +582,10 @@ static ssize_t sys_trywait(env_t* e, pid_t pid, int* status)
 
                if(current->pid == p->ppid)
                {
+                       /* Block til there is some activity */
+                       if (!(p->state == PROC_DYING)) {
+                               sleep_on(&p->state_change);
+                       }
                        if(p->state == PROC_DYING)
                        {
                                memcpy_to_user(e,status,&p->exitcode,sizeof(int));
@@ -585,6 +595,7 @@ static ssize_t sys_trywait(env_t* e, pid_t pid, int* status)
                        }
                        else // not dead yet
                        {
+                               warn("Should not have reached here.");
                                set_errno(ESUCCESS);
                                ret = -1;
                        }