proc_syscalls.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. #include <types.h>
  2. #include <kern/errno.h>
  3. #include <kern/unistd.h>
  4. #include <kern/wait.h>
  5. #include <mips/trapframe.h>
  6. #include <lib.h>
  7. #include <vfs.h>
  8. #include <vnode.h>
  9. #include <syscall.h>
  10. #include <current.h>
  11. #include <proc.h>
  12. #include <thread.h>
  13. #include <addrspace.h>
  14. #include <copyinout.h>
  15. #include <synch.h>
  16. /* this implementation of sys__exit does not do anything with the exit code */
  17. /* this needs to be fixed to get exit() and waitpid() working properly */
  18. /*
  19. logic for waiting:
  20. on exit: broadcast. then
  21. if you can (parent is exited, check exitcode), DELETE
  22. if not, this means you are waiting for a parent to die or call wait on you
  23. so, if they call wait, they can call the death for you
  24. if they just kill themselves, they can do that then kill you too
  25. on call of waitpid:
  26. wait on CV of child, it will broadcast when exiting
  27. when you wake up within waitpid, kid has exited. delete the kid.
  28. continue on your merry day
  29. */
  30. /*
  31. void waitpid()
  32. {
  33. cv_wait(kid); // if valid thing to wait on, ofc
  34. fullDelete(kid);
  35. }*/
  36. /*
  37. void fullDelete() // this should just be delete_proc or whatever
  38. {
  39. }*/
  40. /*
  41. void(exit)
  42. {
  43. // at this point, all unneeded shit is gone
  44. cv_broadcast(this->waiting);
  45. if (parent->exitcode >= 0) fullDelete(this);
  46. else return; // parent will clean you up
  47. }*/
  48. ////////////////////////////////////////////////////////////////////////////
  49. /*void sys__exit(int exitcode)
  50. {
  51. //struct addrspace * as;
  52. struct proc * p = curproc;
  53. p->exitcode = exitcode;
  54. DEBUG(DB_SYSCALL,"Syscall: _exit(%d)\n",exitcode);
  55. //KASSERT(curproc->p_addrspace != NULL);
  56. //as_deactivate();
  57. //as = curproc_setas(NULL);
  58. //as_destroy(as);
  59. //kprintf("DESTROYED AS\n");
  60. // detach this thread from its process
  61. // note: curproc cannot be used after this call
  62. proc_remthread(curthread);
  63. //listelete(p->kids);
  64. kprintf("DESTROYED KIDS\n");
  65. //threadarray_cleanup(&p->p_threads);
  66. //spinlock_cleanup(&p->p_lock);
  67. lock_acquire(p->waitlock);
  68. cv_broadcast(p->waiting, p->waitlock);
  69. lock_release(p->waitlock);
  70. kprintf("BROADCASTED\n");
  71. if (!(p->parent)) proc_destroy(p);
  72. if (p->parent->exitcode >= 0) proc_destroy(p);
  73. kprintf("EXITED THREAD\n");
  74. thread_exit();
  75. // thread_exit() does not return, so we should never get here
  76. panic("return from thread_exit in sys_exit\n");
  77. }*/
  78. void sys__exit(int exitcode)
  79. {
  80. struct addrspace * as;
  81. struct proc * p = curproc;
  82. p->exitcode = exitcode;
  83. DEBUG(DB_SYSCALL,"Syscall: _exit(%d)\n",exitcode);
  84. KASSERT(curproc->p_addrspace != NULL);
  85. kprintf("TRYING TO DESTROY CWD\n");
  86. /* VFS fields */
  87. if (p->p_cwd)
  88. {
  89. VOP_DECREF(p->p_cwd);
  90. p->p_cwd = NULL;
  91. }
  92. kprintf("DESTROYED CWD\n");
  93. as_deactivate();
  94. as = curproc_setas(NULL);
  95. as_destroy(as);
  96. if (p->console)
  97. {
  98. vfs_close(p->console);
  99. }
  100. /* detach this thread from its process */
  101. /* note: curproc cannot be used after this call */
  102. proc_remthread(curthread);
  103. listelete(p->kids);
  104. threadarray_cleanup(&p->p_threads);
  105. spinlock_cleanup(&p->p_lock);
  106. lock_acquire(p->waitlock);
  107. cv_broadcast(p->waiting, p->waitlock);
  108. lock_release(p->waitlock);
  109. kprintf("This is the parent: %p\n", p->parent);
  110. if (p->parent)
  111. {
  112. kprintf("This is the exitcode: %d\n", p->parent->exitcode);
  113. }
  114. if (!(p->parent)) proc_destroy(p);
  115. else if (p->parent->exitcode != -1)
  116. {
  117. kprintf("This is the exitcode: %d\n", p->parent->exitcode);
  118. proc_destroy(p);
  119. }
  120. /* if this is the last user process in the system, proc_destroy()
  121. will wake up the kernel menu thread */
  122. //proc_destroy(p);
  123. kprintf("Exiting\n");
  124. thread_exit();
  125. /* thread_exit() does not return, so we should never get here */
  126. panic("return from thread_exit in sys_exit\n");
  127. }
  128. // basically, return an error code, and put the actual result in retval
  129. int sys_getpid(pid_t * retval)
  130. {
  131. if (!(curproc)) return 1;
  132. *retval = curproc->pid;
  133. return(0);
  134. }
  135. /*
  136. void waitpid()
  137. {
  138. cv_wait(kid); // if valid thing to wait on, ofc
  139. fullDelete(kid);
  140. }*/
  141. /* stub handler for waitpid() system call */
  142. int sys_waitpid(pid_t pid, userptr_t status, int options, pid_t * retval)
  143. {
  144. kprintf("Waiting on: %d\n", pid);
  145. (void)status;
  146. if (options != 0)
  147. {
  148. return(EINVAL);
  149. }
  150. if (pid < PID_MIN || pid > PID_MAX) return ESRCH;
  151. struct proc * target = getChild(curproc, pid);
  152. if (!(target)) return ECHILD;
  153. if (target->exitcode >= 0)
  154. {
  155. *retval = target->exitcode;
  156. return 0;
  157. }
  158. lock_acquire(target->waitlock);
  159. cv_wait(target->waiting, target->waitlock);
  160. lock_release(target->waitlock);
  161. proc_destroy(target);
  162. return 0;
  163. }
  164. int sys_fork(struct trapframe * tf, int * retval)
  165. {
  166. // create new process' memory space
  167. struct proc * child = proc_create_runprogram("childproc");
  168. struct addrspace * new_as;
  169. struct trapframe * new_tf = kmalloc(sizeof(*tf));
  170. if ((!child)) return ENOMEM;
  171. as_copy(curproc_getas(), &new_as);
  172. if (!(new_as) || !(new_tf))
  173. {
  174. proc_destroy(child);
  175. kfree(new_as);
  176. kfree(new_tf);
  177. return ENOMEM;
  178. }
  179. // set PIDs, etc. copy data in to the new space
  180. child->p_addrspace = new_as;
  181. child->parent = curproc;
  182. add_child(curproc, child->pid);
  183. *new_tf = *tf;
  184. // start new thread
  185. thread_fork("childproc", child, enter_forked_process, new_tf, 0);
  186. // return correct values
  187. if (curproc->pid == child->pid) *retval = 0;
  188. else *retval = child->pid;
  189. return 0;
  190. }