proc_syscalls.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  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. }
  119. // args is an array of null terminated strings, with the last element being a null pointer so we don't overflow if iterating
  120. // since this is a userptr type, we need to use copyin and copyout to get data properly
  121. // hopefully the path in program is actually a full filepath
  122. int execv(const char * program, userptr_t args)
  123. {
  124. userptr_t ** temp = args;
  125. int argcount = 0;
  126. char ** argv;
  127. // see how long args is
  128. while (1)
  129. {
  130. char * temp2;
  131. if (copyin(temp, temp2, sizeof(char *))) return errno;
  132. if (!(temp2)) break;
  133. temp += sizeof(char *);
  134. ++argcount;
  135. }
  136. // allocate space for argv
  137. argv = kmalloc(argcount * sizeof(char *));
  138. if (!argv) return ENOMEM;
  139. // get kernel copy of args in argv
  140. temp = args;
  141. for (int i = 0; i < argcount; ++i)
  142. {
  143. if (copyin(args, argv[i], sizeof(char *)))
  144. {
  145. kfree(argv);
  146. return errno;
  147. }
  148. temp += sizeof(char *);
  149. }
  150. // allocate space for filepath
  151. const char * filepath = kmalloc(sizeof(program));
  152. if (!(filepath))
  153. {
  154. kfree(argv);
  155. return ENOMEM;
  156. }
  157. // get kernel copy of filepath
  158. size_t useless;
  159. if (copyinstr((const_userptr_t)program, filepath, strlen(program) + 1, &useless))
  160. {
  161. kfree(argv);
  162. kfree(filepath);
  163. return errno;
  164. }
  165. // open program file
  166. struct vnode * v;
  167. if (vfs_open(filepath, O_RDONLY, 0, &v))
  168. {
  169. kfree(argv);
  170. kfree(filepath);
  171. return errno;
  172. }
  173. // create new address space
  174. struct addrspace * as = as_create();
  175. if (!(as))
  176. {
  177. vfs_close(v);
  178. kfree(argv);
  179. kfree(filepath);
  180. return ENOMEM;
  181. }
  182. // Switch to the new as and activate. keep old in case we fail later
  183. struct addrspace * oldas = curproc_getas();
  184. curproc_setas(as);
  185. as_activate();
  186. // Load santa's favourite slave
  187. if (load_elf(v, &entrypoint))
  188. {
  189. vfs_close(v);
  190. kfree(argv);
  191. kfree(filepath);
  192. curproc_setas(oldas);
  193. as_destroy(as);
  194. return errno;
  195. }
  196. // close the file now that we're done
  197. vfs_close(v);
  198. // create the new stack
  199. vaddr_t newstack;
  200. if (as_define_stack(as, &newstack))
  201. {
  202. kfree(argv);
  203. kfree(filepath);
  204. curproc_setas(oldas);
  205. as_destroy(as);
  206. return errno;
  207. }
  208. userptr_t userArgv;
  209. // need to copy data over into the new address space, as rn it is all in kernel heap
  210. }