process.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769
  1. /*
  2. * process.c
  3. *
  4. * Copyright (C) 2017 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Affero General Public License as
  8. * published by the Free Software Foundation, either version 3 of the
  9. * License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Affero General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Affero General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <process.h>
  20. #include <thread.h>
  21. #include <heap.h>
  22. #include <syscalls.h>
  23. #include <exception.h>
  24. #include <exec/aout.h>
  25. #include <cpu.h>
  26. typedef dword_t (*loader_proc)(handle_t, process_params_t*, thread_state_t*);
  27. static dword_t pid_alloc_bitmap[MAX_PROCESSES / 32];
  28. static lock_t pid_bitmap_lock = 0;
  29. static loader_proc loaders[] =
  30. {
  31. load_aout,
  32. NULL
  33. };
  34. process_t *kernel_process;
  35. static dword_t alloc_pid()
  36. {
  37. int i;
  38. dword_t pid = (dword_t)-1;
  39. acquire_lock(&pid_bitmap_lock);
  40. for (i = 0; i < MAX_PROCESSES; i++)
  41. {
  42. if (!test_bit(pid_alloc_bitmap, i))
  43. {
  44. pid = i;
  45. set_bit(pid_alloc_bitmap, pid);
  46. break;
  47. }
  48. }
  49. release_lock(&pid_bitmap_lock);
  50. return pid;
  51. }
  52. void destroy_process(process_t *proc)
  53. {
  54. int i;
  55. proc->terminating = TRUE;
  56. delete_address_space(&proc->memory_space);
  57. acquire_resource_exclusive(&proc->handle_table_res);
  58. for (i = 0; i < proc->handle_table_size / sizeof(object_t*); i++)
  59. {
  60. if (proc->handle_table[i].obj)
  61. {
  62. close_object_internal(proc->handle_table[i].obj);
  63. proc->handle_table[i].obj = NULL;
  64. proc->handle_count--;
  65. }
  66. }
  67. release_resource(&proc->handle_table_res);
  68. proc->terminated = TRUE;
  69. dereference(&proc->header);
  70. }
  71. void process_cleanup(object_t *obj)
  72. {
  73. process_t *proc = (process_t*)obj;
  74. free(proc->name);
  75. dereference(&proc->current_user->header);
  76. acquire_lock(&pid_bitmap_lock);
  77. clear_bit(pid_alloc_bitmap, proc->pid);
  78. release_lock(&pid_bitmap_lock);
  79. }
  80. process_t *get_current_process()
  81. {
  82. thread_t *thread = get_current_thread();
  83. if (thread == NULL) return NULL;
  84. return thread->owner_process;
  85. }
  86. sysret_t syscall_open_process(dword_t pid, handle_t *handle)
  87. {
  88. dword_t ret;
  89. process_t *proc = NULL;
  90. ret = enum_objects_by_type(OBJECT_PROCESS, (object_t**)&proc);
  91. ASSERT(ret == ERR_SUCCESS || ret == ERR_NOMORE);
  92. while (ret == ERR_SUCCESS)
  93. {
  94. if (proc->pid == pid) break;
  95. ret = enum_objects_by_type(OBJECT_PROCESS, (object_t**)&proc);
  96. }
  97. ASSERT(ret == ERR_SUCCESS || ret == ERR_NOMORE);
  98. if (ret == ERR_NOMORE) ret = ERR_NOTFOUND;
  99. if (ret == ERR_SUCCESS)
  100. {
  101. if (proc->current_user->uid == syscall_get_user_id() || check_privileges(PRIVILEGE_PROCESS_CONTROL))
  102. {
  103. ret = open_object(&proc->header, 0, handle);
  104. }
  105. else
  106. {
  107. ret = ERR_FORBIDDEN;
  108. }
  109. dereference(&proc->header);
  110. }
  111. return ret;
  112. }
  113. dword_t load_executable(handle_t file, process_params_t *parameters, thread_state_t *initial_state)
  114. {
  115. loader_proc *loader = loaders;
  116. while (*loader)
  117. {
  118. dword_t ret = (*loader++)(file, parameters, initial_state);
  119. if (ret == ERR_INVALID) continue;
  120. return ret;
  121. }
  122. return ERR_INVALID;
  123. }
  124. void init_user_stack(uintptr_t *stack_pointer, process_params_t *parameters)
  125. {
  126. static const byte_t program_end_code[] = {
  127. /* push eax */
  128. 0x50,
  129. /* push INVALID_HANDLE */
  130. 0x68,
  131. INVALID_HANDLE & 0xFF,
  132. (INVALID_HANDLE >> 8) & 0xFF,
  133. (INVALID_HANDLE >> 16) & 0xFF,
  134. (INVALID_HANDLE >> 24) & 0xFF,
  135. /* mov eax, SYSCALL_TERMINATE */
  136. 0xB8,
  137. SYSCALL_TERMINATE & 0xFF,
  138. (SYSCALL_TERMINATE >> 8) & 0xFF,
  139. (SYSCALL_TERMINATE >> 16) & 0xFF,
  140. SYSCALL_TERMINATE >> 24,
  141. /* mov edx, esp */
  142. 0x8B, 0xD4,
  143. /* int SYSCALL_INTERRUPT */
  144. 0xCD, SYSCALL_INTERRUPT
  145. };
  146. uintptr_t stack_top = *stack_pointer;
  147. *stack_pointer -= (sizeof(process_params_t) + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1);
  148. *(process_params_t*)*stack_pointer = *parameters;
  149. uintptr_t parameters_addr = *stack_pointer;
  150. *stack_pointer -= (sizeof(program_end_code) + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1);
  151. memcpy((void*)*stack_pointer, program_end_code, sizeof(program_end_code));
  152. uintptr_t end_code_addr = *stack_pointer;
  153. if ((stack_top - *stack_pointer) < MAX_PARAMETERS * sizeof(uintptr_t))
  154. {
  155. *stack_pointer = stack_top - MAX_PARAMETERS * sizeof(uintptr_t);
  156. }
  157. push_to_stack(stack_pointer, parameters_addr);
  158. push_to_stack(stack_pointer, end_code_addr);
  159. }
  160. sysret_t syscall_create_process(const char *path, dword_t flags, process_params_t *parameters, handle_t *process_handle, handle_t *thread_handle)
  161. {
  162. dword_t ret;
  163. handle_t file = INVALID_HANDLE;
  164. process_t *current = get_current_process();
  165. char *safe_path = NULL;
  166. process_params_t safe_params;
  167. handle_t safe_process_handle = INVALID_HANDLE;
  168. handle_t safe_thread_handle = INVALID_HANDLE;
  169. bool_t object_created = FALSE;
  170. if (get_previous_mode() == USER_MODE)
  171. {
  172. if (!check_usermode(process_handle, sizeof(handle_t))) return ERR_BADPTR;
  173. if (!check_usermode(thread_handle, sizeof(handle_t))) return ERR_BADPTR;
  174. if (path)
  175. {
  176. safe_path = copy_user_string(path);
  177. if (safe_path == NULL) return ERR_BADPTR;
  178. }
  179. if (parameters)
  180. {
  181. if (!check_usermode(parameters, sizeof(process_params_t))) return ERR_BADPTR;
  182. EH_TRY safe_params = *parameters;
  183. EH_CATCH EH_ESCAPE(return ERR_BADPTR);
  184. EH_DONE;
  185. }
  186. }
  187. else
  188. {
  189. safe_path = (char*)path;
  190. if (parameters) safe_params = *parameters;
  191. }
  192. if (safe_path)
  193. {
  194. ret = syscall(SYSCALL_OPEN_FILE, safe_path, &file, FILE_MODE_READ, 0);
  195. if (ret != ERR_SUCCESS) return ret;
  196. }
  197. process_t *proc = (process_t*)malloc(sizeof(process_t));
  198. if (proc == NULL) return ERR_NOMEMORY;
  199. memset(proc, 0, sizeof(process_t));
  200. proc->header.name = NULL;
  201. proc->header.type = OBJECT_PROCESS;
  202. proc->pid = alloc_pid();
  203. if (proc->pid == (dword_t)-1)
  204. {
  205. ret = ERR_NOMEMORY;
  206. goto cleanup;
  207. }
  208. proc->name = strdup(path ? path : get_current_process()->name);
  209. list_init(&proc->threads);
  210. proc->thread_list_res = 0;
  211. reference(&current->current_user->header);
  212. proc->original_user = proc->current_user = current->current_user;
  213. if (!(flags & PROCESS_CREATE_NO_INHERIT) && current != kernel_process)
  214. {
  215. dword_t i;
  216. acquire_resource_shared(&current->handle_table_res);
  217. proc->handle_table = (handle_info_t*)malloc(current->handle_table_size);
  218. memset(proc->handle_table, 0, current->handle_table_size);
  219. proc->handle_table_size = current->handle_table_size;
  220. proc->handle_count = current->handle_count;
  221. proc->handle_table_res = 0;
  222. for (i = 0; i < current->handle_table_size; i++)
  223. {
  224. if (current->handle_table[i].obj)
  225. {
  226. reference(current->handle_table[i].obj);
  227. current->handle_table[i].obj->open_count++;
  228. proc->handle_table[i] = current->handle_table[i];
  229. }
  230. }
  231. release_resource(&current->handle_table_res);
  232. }
  233. else
  234. {
  235. proc->handle_table = (handle_info_t*)heap_alloc(&evictable_heap, STARTUP_HANDLE_TABLE_SIZE);
  236. memset(proc->handle_table, 0, STARTUP_HANDLE_TABLE_SIZE);
  237. proc->handle_table_size = STARTUP_HANDLE_TABLE_SIZE;
  238. proc->handle_count = 0;
  239. proc->handle_table_res = 0;
  240. }
  241. if (safe_path)
  242. {
  243. ret = create_address_space(PROCESS_POOL_ADDRESS, PROCESS_POOL_SIZE, &proc->memory_space);
  244. if (ret != ERR_SUCCESS) goto cleanup;
  245. }
  246. else
  247. {
  248. ret = clone_address_space(&current->memory_space, &proc->memory_space);
  249. if (ret != ERR_SUCCESS) goto cleanup;
  250. }
  251. syscall_clock_get_time(&proc->start_time);
  252. ret = create_object(&proc->header);
  253. if (ret != ERR_SUCCESS) goto cleanup;
  254. object_created = TRUE;
  255. thread_state_t initial_state;
  256. memset(&initial_state, 0, sizeof(initial_state));
  257. ret = open_object(&proc->header, 0, &safe_process_handle);
  258. if (ret != ERR_SUCCESS) goto cleanup;
  259. if (file != INVALID_HANDLE)
  260. {
  261. process_t *old_process = switch_process(proc);
  262. ret = load_executable(file, parameters ? &safe_params : NULL, &initial_state);
  263. switch_process(old_process);
  264. if (ret != ERR_SUCCESS) goto cleanup;
  265. }
  266. else
  267. {
  268. initial_state.regs = *get_current_thread()->syscall_regs;
  269. fpu_save(initial_state.fpu_state);
  270. initial_state.regs.eax = CLONE_MAGIC;
  271. }
  272. if (!(flags & PROCESS_CREATE_NO_THREADS))
  273. {
  274. thread_t *thread;
  275. void *kernel_stack = malloc(KERNEL_STACK_SIZE + sizeof(uintptr_t) - 1);
  276. if (kernel_stack == NULL)
  277. {
  278. ret = ERR_NOMEMORY;
  279. goto cleanup;
  280. }
  281. ret = commit_pages(kernel_stack, KERNEL_STACK_SIZE);
  282. if (ret != ERR_SUCCESS) goto cleanup;
  283. ret = create_thread_internal(proc,
  284. &initial_state,
  285. (flags & PROCESS_CREATE_FROZEN_THREAD) ? THREAD_CREATE_FROZEN : 0,
  286. THREAD_PRIORITY_MID,
  287. kernel_stack,
  288. &thread);
  289. if (ret != ERR_SUCCESS)
  290. {
  291. free(kernel_stack);
  292. goto cleanup;
  293. }
  294. ret = open_object(&thread->header, 0, &safe_thread_handle);
  295. if (ret != ERR_SUCCESS)
  296. {
  297. dereference(&thread->header);
  298. goto cleanup;
  299. }
  300. }
  301. EH_TRY
  302. {
  303. *process_handle = safe_process_handle;
  304. *thread_handle = safe_thread_handle;
  305. }
  306. EH_CATCH
  307. {
  308. ret = ERR_BADPTR;
  309. }
  310. EH_DONE;
  311. cleanup:
  312. if (file != INVALID_HANDLE) syscall(SYSCALL_CLOSE_OBJECT, file);
  313. if (object_created)
  314. {
  315. if (ret != ERR_SUCCESS)
  316. {
  317. syscall(SYSCALL_TERMINATE, proc->pid, 1);
  318. if (safe_process_handle != INVALID_HANDLE) syscall_close_object(safe_process_handle);
  319. if (safe_thread_handle != INVALID_HANDLE) syscall_close_object(safe_thread_handle);
  320. }
  321. dereference(&proc->header);
  322. }
  323. else
  324. {
  325. ASSERT(ret != ERR_SUCCESS);
  326. if (proc->pid != (dword_t)-1)
  327. {
  328. acquire_lock(&pid_bitmap_lock);
  329. clear_bit(pid_alloc_bitmap, proc->pid);
  330. release_lock(&pid_bitmap_lock);
  331. }
  332. if (proc->name) free(proc->name);
  333. free(proc);
  334. }
  335. if (get_previous_mode() == USER_MODE && path != NULL) free(safe_path);
  336. return ret;
  337. }
  338. sysret_t syscall_terminate(handle_t handle, dword_t exit_code)
  339. {
  340. process_t *proc;
  341. thread_t *current_thread = get_current_thread();
  342. if (handle == INVALID_HANDLE)
  343. {
  344. proc = get_current_process();
  345. reference(&proc->header);
  346. }
  347. else
  348. {
  349. if (!reference_by_handle(handle, OBJECT_PROCESS, (object_t**)&proc)) return ERR_INVALID;
  350. }
  351. proc->terminating = TRUE;
  352. proc->exit_code = exit_code;
  353. syscall_clock_get_time(&proc->end_time);
  354. acquire_resource_shared(&proc->thread_list_res);
  355. while (proc->threads.next != &proc->threads)
  356. {
  357. list_entry_t *ptr;
  358. thread_t *thread = NULL;
  359. for (ptr = proc->threads.next; ptr != &proc->threads; ptr = ptr->next)
  360. {
  361. thread = CONTAINER_OF(ptr, thread_t, in_process_list);
  362. if (thread != current_thread) break;
  363. }
  364. if (ptr != &proc->threads)
  365. {
  366. release_resource(&proc->thread_list_res);
  367. terminate_thread_internal(thread, exit_code);
  368. acquire_resource_shared(&proc->thread_list_res);
  369. }
  370. else
  371. {
  372. break;
  373. }
  374. }
  375. release_resource(&proc->thread_list_res);
  376. if (proc->threads.next == &proc->threads) destroy_process(proc);
  377. dereference(&proc->header);
  378. if (proc->threads.next == &proc->threads) return ERR_SUCCESS;
  379. else return terminate_thread_internal(current_thread, exit_code);
  380. }
  381. sysret_t syscall_get_process_id()
  382. {
  383. process_t *proc = get_current_process();
  384. return proc->pid;
  385. }
  386. sysret_t syscall_query_process(handle_t handle, process_info_t info_type, void *buffer, dword_t size)
  387. {
  388. dword_t ret = ERR_SUCCESS;
  389. void *safe_buffer;
  390. if (get_previous_mode() == USER_MODE)
  391. {
  392. if (!check_usermode(buffer, size)) return ERR_BADPTR;
  393. safe_buffer = malloc(size);
  394. if (safe_buffer == NULL) return ERR_NOMEMORY;
  395. memset(safe_buffer, 0, size);
  396. }
  397. else
  398. {
  399. safe_buffer = buffer;
  400. }
  401. process_t *proc;
  402. if (handle == INVALID_HANDLE)
  403. {
  404. proc = get_current_process();
  405. reference(&proc->header);
  406. }
  407. else
  408. {
  409. if (!reference_by_handle(handle, OBJECT_PROCESS, (object_t**)&proc))
  410. {
  411. if (get_previous_mode() == USER_MODE) free(safe_buffer);
  412. return ERR_INVALID;
  413. }
  414. }
  415. switch (info_type)
  416. {
  417. case PROCESS_PID_INFO:
  418. {
  419. if (size >= sizeof(dword_t)) *((dword_t*)safe_buffer) = proc->pid;
  420. else ret = ERR_SMALLBUF;
  421. break;
  422. }
  423. case PROCESS_NAME_INFO:
  424. {
  425. if (size >= strlen(proc->name) + 1) strcpy(safe_buffer, proc->name);
  426. else ret = ERR_SMALLBUF;
  427. break;
  428. }
  429. case PROCESS_MEMORY_INFO:
  430. {
  431. ret = ERR_NOSYSCALL; // TODO
  432. break;
  433. }
  434. case PROCESS_START_TIME_INFO:
  435. {
  436. if (size >= sizeof(clock_time_t)) *((clock_time_t*)safe_buffer) = proc->start_time;
  437. else ret = ERR_SMALLBUF;
  438. break;
  439. }
  440. case PROCESS_EXIT_CODE_INFO:
  441. {
  442. if (size >= sizeof(dword_t)) *((dword_t*)safe_buffer) = proc->exit_code;
  443. else ret = ERR_SMALLBUF;
  444. break;
  445. }
  446. case PROCESS_USER_INFO:
  447. {
  448. if (size >= 2 * sizeof(dword_t))
  449. {
  450. ((dword_t*)safe_buffer)[0] = proc->original_user->uid;
  451. ((dword_t*)safe_buffer)[1] = proc->current_user->uid;
  452. }
  453. else
  454. {
  455. ret = ERR_SMALLBUF;
  456. }
  457. break;
  458. }
  459. case PROCESS_THREAD_INFO:
  460. {
  461. if (size >= sizeof(dword_t))
  462. {
  463. list_entry_t *ptr;
  464. dword_t i = 1, count = 0;
  465. acquire_resource_shared(&proc->thread_list_res);
  466. for (ptr = proc->threads.next; ptr != &proc->threads; ptr = ptr->next) count++;
  467. *((dword_t*)safe_buffer) = count;
  468. for (ptr = proc->threads.next; ptr != &proc->threads && i < (size / sizeof(dword_t)); ptr = ptr->next)
  469. {
  470. ((dword_t*)safe_buffer)[i++] = CONTAINER_OF(ptr, thread_t, in_process_list)->tid;
  471. }
  472. if (ptr != &proc->threads) ret = ERR_SMALLBUF;
  473. release_resource(&proc->thread_list_res);
  474. }
  475. else
  476. {
  477. ret = ERR_SMALLBUF;
  478. }
  479. break;
  480. }
  481. case PROCESS_HANDLE_INFO:
  482. {
  483. if (size >= sizeof(dword_t))
  484. {
  485. dword_t i, j = 1;
  486. acquire_resource_shared(&proc->handle_table_res);
  487. *((dword_t*)safe_buffer) = proc->handle_count;
  488. for (i = 0; i < proc->handle_table_size && j < (size / sizeof(dword_t)); i++)
  489. {
  490. if (proc->handle_table[i].obj) ((dword_t*)safe_buffer)[j++] = i;
  491. }
  492. if (i != proc->handle_table_size) ret = ERR_SMALLBUF;
  493. release_resource(&proc->handle_table_res);
  494. }
  495. else
  496. {
  497. ret = ERR_SMALLBUF;
  498. }
  499. break;
  500. }
  501. default:
  502. {
  503. ret = ERR_INVALID;
  504. }
  505. }
  506. if (get_previous_mode() == USER_MODE)
  507. {
  508. EH_TRY memcpy(buffer, safe_buffer, size);
  509. EH_CATCH ret = ERR_BADPTR;
  510. EH_DONE;
  511. free(safe_buffer);
  512. }
  513. dereference(&proc->header);
  514. return ret;
  515. }
  516. sysret_t syscall_enum_processes(dword_t *pid_array, dword_t *count)
  517. {
  518. dword_t ret = ERR_SUCCESS;
  519. dword_t safe_count;
  520. dword_t cnt = 0;
  521. if (get_previous_mode() == USER_MODE)
  522. {
  523. if (!check_usermode(count, sizeof(*count))) return ERR_BADPTR;
  524. EH_TRY safe_count = *count;
  525. EH_CATCH EH_ESCAPE(return ERR_BADPTR);
  526. EH_DONE;
  527. if (!check_usermode(pid_array, sizeof(*pid_array) * safe_count))
  528. {
  529. ret = ERR_BADPTR;
  530. goto cleanup;
  531. }
  532. }
  533. else
  534. {
  535. safe_count = *count;
  536. }
  537. process_t *proc = NULL;
  538. ret = enum_objects_by_type(OBJECT_PROCESS, (object_t**)&proc);
  539. while (ret == ERR_SUCCESS)
  540. {
  541. if (cnt == safe_count)
  542. {
  543. ret = ERR_SMALLBUF;
  544. break;
  545. }
  546. EH_TRY
  547. {
  548. pid_array[cnt++] = proc->pid;
  549. }
  550. EH_CATCH
  551. {
  552. ret = ERR_BADPTR;
  553. EH_ESCAPE(break);
  554. }
  555. EH_DONE;
  556. ret = enum_objects_by_type(OBJECT_PROCESS, (object_t**)&proc);
  557. }
  558. if (ret == ERR_NOMORE)
  559. {
  560. ret = ERR_SUCCESS;
  561. }
  562. else if (ret == ERR_SUCCESS)
  563. {
  564. dereference(&proc->header);
  565. ret = ERR_SMALLBUF;
  566. }
  567. cleanup:
  568. EH_TRY *count = cnt;
  569. EH_CATCH ret = ERR_BADPTR;
  570. EH_DONE;
  571. return ret;
  572. }
  573. sysret_t syscall_wait_process(handle_t handle, dword_t timeout)
  574. {
  575. dword_t ret;
  576. process_t *proc;
  577. if (handle == INVALID_HANDLE)
  578. {
  579. proc = get_current_process();
  580. reference(&proc->header);
  581. }
  582. else
  583. {
  584. if (!reference_by_handle(handle, OBJECT_PROCESS, (object_t**)&proc)) return ERR_INVALID;
  585. }
  586. ret = scheduler_wait(WAIT_UNTIL_NOT_EQUAL, timeout, &proc->terminated, 0);
  587. dereference(&proc->header);
  588. return ret;
  589. }
  590. process_t *switch_process(process_t *new_process)
  591. {
  592. thread_t *thread = get_current_thread();
  593. process_t *old_process = get_current_process();
  594. while (!__sync_bool_compare_and_swap(&thread->owner_process, old_process, new_process))
  595. {
  596. old_process = get_current_process();
  597. }
  598. set_page_directory(new_process->memory_space.page_directory);
  599. return old_process;
  600. }
  601. void process_init(char *root_directory)
  602. {
  603. memset(pid_alloc_bitmap, 0, sizeof(pid_alloc_bitmap));
  604. kernel_process = (process_t*)malloc(sizeof(process_t));
  605. ASSERT(kernel_process != NULL);
  606. memset(kernel_process, 0, sizeof(process_t));
  607. kernel_process->header.name = NULL;
  608. kernel_process->header.type = OBJECT_PROCESS;
  609. ASSERT(create_object(&kernel_process->header) == ERR_SUCCESS);
  610. kernel_process->pid = 0;
  611. set_bit(pid_alloc_bitmap, 0);
  612. kernel_process->name = strdup("system");
  613. memset(&kernel_process->memory_space, 0, sizeof(memory_address_space_t));
  614. kernel_process->memory_space.page_directory = get_page_directory();
  615. kernel_process->exit_code = 0;
  616. kernel_process->terminating = FALSE;
  617. kernel_process->terminated = FALSE;
  618. syscall_clock_get_time(&kernel_process->start_time);
  619. list_init(&kernel_process->threads);
  620. kernel_process->thread_list_res = 0;
  621. kernel_process->handle_table = (handle_info_t*)heap_alloc(&evictable_heap, STARTUP_HANDLE_TABLE_SIZE);
  622. kernel_process->handle_table_size = STARTUP_HANDLE_TABLE_SIZE;
  623. kernel_process->handle_count = 0;
  624. kernel_process->handle_table_res = 0;
  625. }