proc_syscalls.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  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. /*
  79. void sys__exit(int exitcode)
  80. {
  81. struct addrspace * as;
  82. struct proc * p = curproc;
  83. p->exitcode = exitcode;
  84. DEBUG(DB_SYSCALL,"Syscall: _exit(%d)\n",exitcode);
  85. KASSERT(curproc->p_addrspace != NULL);
  86. lock_acquire(proclock);
  87. int x = listpop(p->kids);
  88. while (x)
  89. {
  90. processes->pids[x]->parent = NULL;
  91. x = listpop(p->kids);
  92. }
  93. lock_release(proclock);
  94. listelete(p->kids);
  95. // VFS fields
  96. if (p->p_cwd)
  97. {
  98. VOP_DECREF(p->p_cwd);
  99. p->p_cwd = NULL;
  100. }
  101. as_deactivate();
  102. as = curproc_setas(NULL);
  103. as_destroy(as);
  104. if (p->console)
  105. {
  106. vfs_close(p->console);
  107. }
  108. // detach this thread from its process
  109. // note: curproc cannot be used after this call
  110. proc_remthread(curthread);
  111. threadarray_cleanup(&p->p_threads);
  112. spinlock_cleanup(&p->p_lock);
  113. lock_acquire(p->waitlock);
  114. cv_broadcast(p->waiting, p->waitlock);
  115. lock_release(p->waitlock);
  116. //kprintf("parent is %p\n", p->parent);
  117. //if (p->parent) kprintf("parent exitcode is %d\n", p->parent->exitcode);
  118. //if (p->parent) kprintf("parent pid is %d\n", p->parent->pid);
  119. if (!(p->parent) || p->parent->exitcode >= 0 || p->parent == kproc) proc_destroy(p);
  120. thread_exit();
  121. // thread_exit() does not return, so we should never get here
  122. panic("return from thread_exit in sys_exit\n");
  123. }*/
  124. void sys__exit(int exitcode)
  125. {
  126. struct addrspace * as;
  127. struct proc * p = curproc;
  128. p->exitcode = exitcode;
  129. DEBUG(DB_SYSCALL,"Syscall: _exit(%d)\n",exitcode);
  130. KASSERT(curproc->p_addrspace != NULL);
  131. lock_acquire(proclock);
  132. int x = listpop(p->kids);
  133. while (x)
  134. {
  135. if(processes->pids[x])
  136. {
  137. processes->pids[x]->parent = NULL;
  138. if (processes->pids[x]->exitcode >= 0)
  139. {
  140. lock_release(proclock);
  141. proc_destroy(processes->pids[x]);
  142. lock_acquire(proclock);
  143. }
  144. }
  145. x = listpop(p->kids);
  146. }
  147. lock_release(proclock);
  148. listelete(p->kids);
  149. // VFS fields
  150. if (p->p_cwd)
  151. {
  152. VOP_DECREF(p->p_cwd);
  153. p->p_cwd = NULL;
  154. }
  155. as_deactivate();
  156. as = curproc_setas(NULL);
  157. as_destroy(as);
  158. /* detach this thread from its process */
  159. /* note: curproc cannot be used after this call */
  160. proc_remthread(curthread);
  161. threadarray_cleanup(&p->p_threads);
  162. spinlock_cleanup(&p->p_lock);
  163. lock_acquire(p->waitlock);
  164. cv_broadcast(p->waiting, p->waitlock);
  165. lock_release(p->waitlock);
  166. if (!(p->parent) || p->parent->exitcode >= 0 || p->parent == kproc) proc_destroy(p);
  167. thread_exit();
  168. /* thread_exit() does not return, so we should never get here */
  169. panic("return from thread_exit in sys_exit\n");
  170. }
  171. // basically, return an error code, and put the actual result in retval
  172. int sys_getpid(pid_t * retval)
  173. {
  174. if (!(curproc)) return 1;
  175. *retval = curproc->pid;
  176. return(0);
  177. }
  178. /*
  179. int sys_waitpid(pid_t pid, userptr_t status, int options, pid_t * retval)
  180. {
  181. int exitstatus;
  182. int result;
  183. if (options != 0) {
  184. return(EINVAL);
  185. }
  186. for now, just pretend the exitstatus is 0
  187. exitstatus = 0;
  188. result = copyout((void *)&exitstatus,status,sizeof(int));
  189. if (result) {
  190. return(result);
  191. }
  192. *retval = pid;
  193. return(0);
  194. }
  195. int sys_waitpid(pid_t pid, userptr_t status, int options, pid_t * retval)
  196. {
  197. int exitstatus;
  198. int result;
  199. (void)status;
  200. if (options != 0)
  201. {
  202. return(EINVAL);
  203. }
  204. if (pid < PID_MIN || pid > PID_MAX) return ESRCH;
  205. struct proc * target = getChild(curproc, pid);
  206. if (!(target)) return ECHILD;
  207. exitstatus = _MKWAIT_EXIT(target->exitcode);
  208. result = copyout((void *)&exitstatus, status, sizeof(int));
  209. if (exitstatus >= 0)
  210. {
  211. // *retval = exitstatus;
  212. return result;
  213. }
  214. lock_acquire(target->waitlock);
  215. cv_wait(target->waiting, target->waitlock);
  216. lock_release(target->waitlock);
  217. *retval = exitstatus;
  218. proc_destroy(target);
  219. return 0;
  220. }*/
  221. int sys_waitpid(pid_t pid, userptr_t status, int options, pid_t * retval)
  222. {
  223. (void)status;
  224. if (options != 0)
  225. {
  226. return(EINVAL);
  227. }
  228. if (pid < PID_MIN || pid > PID_MAX) return ESRCH;
  229. struct proc * target = getChild(curproc, pid);
  230. if (!(target)) return ECHILD;
  231. if (target->exitcode >= 0)
  232. {
  233. *retval = target->exitcode;
  234. return 0;
  235. }
  236. lock_acquire(target->waitlock);
  237. cv_wait(target->waiting, target->waitlock);
  238. lock_release(target->waitlock);
  239. *retval = target->exitcode;
  240. proc_destroy(target);
  241. return 0;
  242. }
  243. int sys_fork(struct trapframe * tf, int * retval)
  244. {
  245. // create new process' memory space
  246. struct proc * child = proc_create_runprogram("childproc");
  247. if ((!child)) return ENOMEM;
  248. struct trapframe * new_tf = kmalloc(sizeof(*tf));
  249. struct addrspace * new_as;
  250. as_copy(curproc_getas(), &new_as);
  251. if (!(new_as) || !(new_tf))
  252. {
  253. proc_destroy(child);
  254. kfree(new_as);
  255. kfree(new_tf);
  256. return ENOMEM;
  257. }
  258. // set PIDs, etc. copy data in to the new space
  259. child->p_addrspace = new_as;
  260. child->parent = curproc;
  261. add_child(curproc, child->pid);
  262. *new_tf = *tf;
  263. // start new thread
  264. thread_fork("childproc", child, enter_forked_process, new_tf, 0);
  265. // return correct values
  266. if (curproc->pid == child->pid) *retval = 0;
  267. else *retval = child->pid;
  268. return 0;
  269. }