#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* this implementation of sys__exit does not do anything with the exit code */ /* this needs to be fixed to get exit() and waitpid() working properly */ /* logic for waiting: on exit: broadcast. then if you can (parent is exited, check exitcode), DELETE if not, this means you are waiting for a parent to die or call wait on you so, if they call wait, they can call the death for you if they just kill themselves, they can do that then kill you too on call of waitpid: wait on CV of child, it will broadcast when exiting when you wake up within waitpid, kid has exited. delete the kid. continue on your merry day */ /* void waitpid() { cv_wait(kid); // if valid thing to wait on, ofc fullDelete(kid); }*/ /* void fullDelete() // this should just be delete_proc or whatever { }*/ /* void(exit) { // at this point, all unneeded shit is gone cv_broadcast(this->waiting); if (parent->exitcode >= 0) fullDelete(this); else return; // parent will clean you up }*/ //////////////////////////////////////////////////////////////////////////// /*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); //as_deactivate(); //as = curproc_setas(NULL); //as_destroy(as); //kprintf("DESTROYED AS\n"); // detach this thread from its process // note: curproc cannot be used after this call proc_remthread(curthread); //listelete(p->kids); kprintf("DESTROYED KIDS\n"); //threadarray_cleanup(&p->p_threads); //spinlock_cleanup(&p->p_lock); lock_acquire(p->waitlock); cv_broadcast(p->waiting, p->waitlock); lock_release(p->waitlock); kprintf("BROADCASTED\n"); if (!(p->parent)) proc_destroy(p); if (p->parent->exitcode >= 0) proc_destroy(p); kprintf("EXITED THREAD\n"); thread_exit(); // thread_exit() does not return, so we should never get here panic("return from thread_exit in sys_exit\n"); }*/ /* 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) { processes->pids[x]->parent = NULL; 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); if (p->console) { vfs_close(p->console); } // 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); //kprintf("parent is %p\n", p->parent); //if (p->parent) kprintf("parent exitcode is %d\n", p->parent->exitcode); //if (p->parent) kprintf("parent pid is %d\n", p->parent->pid); 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"); }*/ 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) { int exitstatus; int result; if (options != 0) { return(EINVAL); } for now, just pretend the exitstatus is 0 exitstatus = 0; result = copyout((void *)&exitstatus,status,sizeof(int)); if (result) { return(result); } *retval = pid; return(0); } int sys_waitpid(pid_t pid, userptr_t status, int options, pid_t * retval) { int exitstatus; int result; (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; exitstatus = _MKWAIT_EXIT(target->exitcode); result = copyout((void *)&exitstatus, status, sizeof(int)); if (exitstatus >= 0) { // *retval = exitstatus; return result; } lock_acquire(target->waitlock); cv_wait(target->waiting, target->waitlock); lock_release(target->waitlock); *retval = exitstatus; proc_destroy(target); 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; }