#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); /* 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); int x = listpop(p->kids); while (x) { lock_acquire(proclock); processes->pids[x]->parent = NULL; lock_release(proclock); x = listpop(p->kids); } listelete(p->kids); 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)) proc_destroy(p); else if (p->parent->exitcode >= 0) { proc_destroy(p); } /* if this is the last user process in the system, proc_destroy() will wake up the kernel menu thread */ //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); } /* void waitpid() { cv_wait(kid); // if valid thing to wait on, ofc fullDelete(kid); }*/ /* stub handler for waitpid() system call */ int sys_waitpid(pid_t pid, userptr_t status, int options, pid_t * retval) { kprintf("Waiting on: %d\n", pid); (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"); struct addrspace * new_as; struct trapframe * new_tf = kmalloc(sizeof(*tf)); if ((!child)) return ENOMEM; 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; }