proc_syscalls.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  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. void sys__exit(int exitcode)
  17. {
  18. struct addrspace * as;
  19. struct proc * p = curproc;
  20. p->exitcode = exitcode;
  21. DEBUG(DB_SYSCALL,"Syscall: _exit(%d)\n",exitcode);
  22. KASSERT(curproc->p_addrspace != NULL);
  23. lock_acquire(proclock);
  24. int x = listpop(p->kids);
  25. while (x)
  26. {
  27. if(processes->pids[x])
  28. {
  29. processes->pids[x]->parent = NULL;
  30. if (processes->pids[x]->exitcode >= 0)
  31. {
  32. lock_release(proclock);
  33. proc_destroy(processes->pids[x]);
  34. lock_acquire(proclock);
  35. }
  36. }
  37. x = listpop(p->kids);
  38. }
  39. lock_release(proclock);
  40. listelete(p->kids);
  41. // VFS fields
  42. if (p->p_cwd)
  43. {
  44. VOP_DECREF(p->p_cwd);
  45. p->p_cwd = NULL;
  46. }
  47. as_deactivate();
  48. as = curproc_setas(NULL);
  49. as_destroy(as);
  50. /* detach this thread from its process */
  51. /* note: curproc cannot be used after this call */
  52. proc_remthread(curthread);
  53. threadarray_cleanup(&p->p_threads);
  54. spinlock_cleanup(&p->p_lock);
  55. lock_acquire(p->waitlock);
  56. cv_broadcast(p->waiting, p->waitlock);
  57. lock_release(p->waitlock);
  58. if (!(p->parent) || p->parent->exitcode >= 0 || p->parent == kproc) proc_destroy(p);
  59. thread_exit();
  60. /* thread_exit() does not return, so we should never get here */
  61. panic("return from thread_exit in sys_exit\n");
  62. }
  63. // basically, return an error code, and put the actual result in retval
  64. int sys_getpid(pid_t * retval)
  65. {
  66. if (!(curproc)) return 1;
  67. *retval = curproc->pid;
  68. return(0);
  69. }
  70. int sys_waitpid(pid_t pid, userptr_t status, int options, pid_t * retval)
  71. {
  72. (void)status;
  73. if (options != 0)
  74. {
  75. return(EINVAL);
  76. }
  77. if (pid < PID_MIN || pid > PID_MAX) return ESRCH;
  78. struct proc * target = getChild(curproc, pid);
  79. if (!(target)) return ECHILD;
  80. if (target->exitcode >= 0)
  81. {
  82. *retval = target->exitcode;
  83. return 0;
  84. }
  85. lock_acquire(target->waitlock);
  86. cv_wait(target->waiting, target->waitlock);
  87. lock_release(target->waitlock);
  88. *retval = target->exitcode;
  89. proc_destroy(target);
  90. return 0;
  91. }
  92. int sys_fork(struct trapframe * tf, int * retval)
  93. {
  94. // create new process' memory space
  95. struct proc * child = proc_create_runprogram("childproc");
  96. if ((!child)) return ENOMEM;
  97. struct trapframe * new_tf = kmalloc(sizeof(*tf));
  98. struct addrspace * new_as;
  99. as_copy(curproc_getas(), &new_as);
  100. if (!(new_as) || !(new_tf))
  101. {
  102. proc_destroy(child);
  103. kfree(new_as);
  104. kfree(new_tf);
  105. return ENOMEM;
  106. }
  107. // set PIDs, etc. copy data in to the new space
  108. child->p_addrspace = new_as;
  109. child->parent = curproc;
  110. add_child(curproc, child->pid);
  111. *new_tf = *tf;
  112. // start new thread
  113. thread_fork("childproc", child, enter_forked_process, new_tf, 0);
  114. // return correct values
  115. if (curproc->pid == child->pid) *retval = 0;
  116. else *retval = child->pid;
  117. return 0;
  118. }