123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- #include <types.h>
- #include <kern/errno.h>
- #include <kern/unistd.h>
- #include <kern/wait.h>
- #include <mips/trapframe.h>
- #include <lib.h>
- #include <vfs.h>
- #include <vnode.h>
- #include <syscall.h>
- #include <current.h>
- #include <proc.h>
- #include <thread.h>
- #include <addrspace.h>
- #include <copyinout.h>
- #include <synch.h>
- /* 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);
- kprintf("TRYING TO DESTROY CWD\n");
- /* VFS fields */
- if (p->p_cwd)
- {
- VOP_DECREF(p->p_cwd);
- p->p_cwd = NULL;
- }
- kprintf("DESTROYED CWD\n");
- 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);
- 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);
-
- kprintf("This is the parent: %p\n", p->parent);
- if (p->parent)
- {
- kprintf("This is the exitcode: %d\n", p->parent->exitcode);
- }
- if (!(p->parent)) proc_destroy(p);
- else if (p->parent->exitcode != -1)
- {
- kprintf("This is the exitcode: %d\n", p->parent->exitcode);
- 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);
-
- kprintf("Exiting\n");
- 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);
- 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;
- }
|