#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include void sys__exit(int exitcode) { struct addrspace * as; struct proc * p = curproc; p->exitcode = exitcode; DEBUG(DB_SYSCALL,"Syscall: _exit(%d)\n",exitcode); KASSERT(curproc->p_addrspace != NULL); lock_acquire(proclock); int x = listpop(p->kids); while (x) { if(processes->pids[x]) { processes->pids[x]->parent = NULL; if (processes->pids[x]->exitcode >= 0) { lock_release(proclock); proc_destroy(processes->pids[x]); lock_acquire(proclock); } } x = listpop(p->kids); } lock_release(proclock); listelete(p->kids); // VFS fields if (p->p_cwd) { VOP_DECREF(p->p_cwd); p->p_cwd = NULL; } as_deactivate(); as = curproc_setas(NULL); as_destroy(as); /* detach this thread from its process */ /* note: curproc cannot be used after this call */ proc_remthread(curthread); threadarray_cleanup(&p->p_threads); spinlock_cleanup(&p->p_lock); lock_acquire(p->waitlock); cv_broadcast(p->waiting, p->waitlock); lock_release(p->waitlock); if (!(p->parent) || p->parent->exitcode >= 0 || p->parent == kproc) proc_destroy(p); thread_exit(); /* thread_exit() does not return, so we should never get here */ panic("return from thread_exit in sys_exit\n"); } // basically, return an error code, and put the actual result in retval int sys_getpid(pid_t * retval) { if (!(curproc)) return 1; *retval = curproc->pid; return(0); } int sys_waitpid(pid_t pid, userptr_t status, int options, pid_t * retval) { (void)status; if (options != 0) { return(EINVAL); } if (pid < PID_MIN || pid > PID_MAX) return ESRCH; struct proc * target = getChild(curproc, pid); if (!(target)) return ECHILD; if (target->exitcode >= 0) { *retval = target->exitcode; return 0; } lock_acquire(target->waitlock); cv_wait(target->waiting, target->waitlock); lock_release(target->waitlock); *retval = target->exitcode; proc_destroy(target); return 0; } int sys_fork(struct trapframe * tf, int * retval) { // create new process' memory space struct proc * child = proc_create_runprogram("childproc"); if ((!child)) return ENOMEM; struct trapframe * new_tf = kmalloc(sizeof(*tf)); struct addrspace * new_as; as_copy(curproc_getas(), &new_as); if (!(new_as) || !(new_tf)) { proc_destroy(child); kfree(new_as); kfree(new_tf); return ENOMEM; } // set PIDs, etc. copy data in to the new space child->p_addrspace = new_as; child->parent = curproc; add_child(curproc, child->pid); *new_tf = *tf; // start new thread thread_fork("childproc", child, enter_forked_process, new_tf, 0); // return correct values if (curproc->pid == child->pid) *retval = 0; else *retval = child->pid; return 0; }