object.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764
  1. /*
  2. * object.c
  3. *
  4. * Copyright (C) 2016 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 <object.h>
  20. #include <process.h>
  21. #include <thread.h>
  22. #include <heap.h>
  23. #include <pipe.h>
  24. typedef void (*object_cleanup_proc_t)(object_t*);
  25. typedef dword_t (*object_pre_wait_proc_t)(object_t*, void*, wait_condition_t*);
  26. typedef void (*object_post_wait_proc_t)(object_t*, void*, wait_result_t);
  27. extern void file_cleanup(object_t*);
  28. extern void file_instance_cleanup(object_t*);
  29. extern dword_t semaphore_pre_wait(object_t *obj, void *parameter, wait_condition_t *condition);
  30. extern void semaphore_post_wait(object_t *obj, void *parameter, wait_result_t result);
  31. static DECLARE_LOCK(obj_lock);
  32. static DECLARE_LIST(anonymous_objects);
  33. static list_entry_t named_objects[256];
  34. static list_entry_t objects_by_type[OBJECT_TYPE_MAX];
  35. static struct
  36. {
  37. object_cleanup_proc_t cleanup;
  38. object_pre_wait_proc_t pre_wait;
  39. object_post_wait_proc_t post_wait;
  40. } type_info[OBJECT_TYPE_MAX] =
  41. {
  42. { .cleanup = file_cleanup, .pre_wait = NULL, .post_wait = NULL },
  43. { .cleanup = file_instance_cleanup, .pre_wait = NULL, .post_wait = NULL },
  44. { .cleanup = NULL, .pre_wait = NULL, .post_wait = NULL },
  45. { .cleanup = pipe_cleanup, .pre_wait = pipe_pre_wait, .post_wait = NULL },
  46. { .cleanup = process_cleanup, .pre_wait = process_pre_wait, .post_wait = NULL },
  47. { .cleanup = thread_cleanup, .pre_wait = thread_pre_wait, .post_wait = NULL },
  48. { .cleanup = memory_cleanup, .pre_wait = NULL, .post_wait = NULL },
  49. { .cleanup = NULL, .pre_wait = semaphore_pre_wait, .post_wait = semaphore_post_wait },
  50. { .cleanup = NULL, .pre_wait = NULL, .post_wait = NULL },
  51. };
  52. static inline byte_t get_name_hash(const char *name)
  53. {
  54. byte_t sum = 0;
  55. while (*name) sum += *name++;
  56. return sum;
  57. }
  58. static handle_t insert_object(object_t *obj, access_flags_t access_flags)
  59. {
  60. handle_t i;
  61. process_t *proc = get_previous_mode() == USER_MODE ? get_current_process() : kernel_process;
  62. lock_acquire(&proc->handle_table_lock);
  63. for (i = 0; i < proc->handle_table_size; i++) if (!proc->handle_table[i].obj)
  64. {
  65. proc->handle_table[i].obj = obj;
  66. proc->handle_table[i].access_flags = access_flags;
  67. proc->handle_count++;
  68. goto cleanup;
  69. }
  70. handle_info_t *expanded_table = (handle_info_t*)heap_realloc(&evictable_heap, proc->handle_table, proc->handle_table_size * 2);
  71. if (expanded_table == NULL)
  72. {
  73. i = INVALID_HANDLE;
  74. goto cleanup;
  75. }
  76. expanded_table[proc->handle_table_size].obj = obj;
  77. for (i = proc->handle_table_size + 1; i < proc->handle_table_size * 2; i++) expanded_table[i].obj = NULL;
  78. proc->handle_table = expanded_table;
  79. i = proc->handle_table_size;
  80. proc->handle_table_size *= 2;
  81. cleanup:
  82. lock_release(&proc->handle_table_lock);
  83. return i;
  84. }
  85. static bool_t access_check(object_t *obj, access_flags_t access)
  86. {
  87. if (check_privileges(PRIVILEGE_ACCESS_ALL)) return TRUE;
  88. list_entry_t *ptr;
  89. dword_t uid = get_current_uid();
  90. for (ptr = obj->acl.next; ptr != &obj->acl; ptr = ptr->next)
  91. {
  92. access_control_entry_t *ace = CONTAINER_OF(ptr, access_control_entry_t, link);
  93. if ((ace->uid == ALL_USERS || ace->uid == uid) && access == (access & ace->access_mask)) return TRUE;
  94. }
  95. return FALSE;
  96. }
  97. void reference(object_t *object)
  98. {
  99. lock_acquire(&obj_lock);
  100. object->ref_count++;
  101. lock_release(&obj_lock);
  102. }
  103. void dereference(object_t *object)
  104. {
  105. lock_acquire(&obj_lock);
  106. dword_t ref_count = --object->ref_count;
  107. if (!ref_count)
  108. {
  109. list_remove(&object->by_name_list);
  110. list_remove(&object->by_type_list);
  111. }
  112. lock_release(&obj_lock);
  113. if (!ref_count)
  114. {
  115. if (type_info[object->type].cleanup != NULL) type_info[object->type].cleanup(object);
  116. free(object);
  117. }
  118. }
  119. bool_t reference_by_handle(handle_t handle, object_type_t type, object_t **object)
  120. {
  121. bool_t result = FALSE;
  122. process_t *proc = get_previous_mode() == USER_MODE ? get_current_process() : kernel_process;
  123. if (handle >= proc->handle_table_size) return FALSE;
  124. lock_acquire(&obj_lock);
  125. lock_acquire_shared(&proc->handle_table_lock);
  126. *object = proc->handle_table[handle].obj;
  127. if (*object != NULL && (type == OBJECT_ANY_TYPE || (*object)->type == type))
  128. {
  129. (*object)->ref_count++;
  130. result = TRUE;
  131. }
  132. lock_release(&proc->handle_table_lock);
  133. lock_release(&obj_lock);
  134. return result;
  135. }
  136. bool_t reference_by_name(const char *name, object_type_t type, object_t **object)
  137. {
  138. list_entry_t *ptr;
  139. bool_t result = FALSE;
  140. byte_t hash = get_name_hash(name);
  141. lock_acquire(&obj_lock);
  142. for (ptr = named_objects[hash].next; ptr != &named_objects[hash]; ptr = ptr->next)
  143. {
  144. object_t *obj = CONTAINER_OF(ptr, object_t, by_name_list);
  145. if ((obj->name != NULL) && (strcmp(obj->name, name) == 0) && (obj->type == type))
  146. {
  147. obj->ref_count++;
  148. *object = obj;
  149. result = TRUE;
  150. break;
  151. }
  152. }
  153. lock_release(&obj_lock);
  154. return result;
  155. }
  156. dword_t grant_access(object_t *obj, dword_t uid, access_flags_t access)
  157. {
  158. dword_t ret = ERR_SUCCESS;
  159. reference(obj);
  160. lock_acquire(&obj->acl_lock);
  161. if (!access_check(obj, access))
  162. {
  163. ret = ERR_FORBIDDEN;
  164. goto cleanup;
  165. }
  166. list_entry_t *ptr;
  167. bool_t done = FALSE;
  168. for (ptr = obj->acl.next; ptr != &obj->acl; ptr = ptr->next)
  169. {
  170. access_control_entry_t *ace = CONTAINER_OF(ptr, access_control_entry_t, link);
  171. if (ace->uid == uid && (ace->access_mask & access) == access)
  172. {
  173. ace->access_mask |= access;
  174. done = TRUE;
  175. break;
  176. }
  177. }
  178. if (!done)
  179. {
  180. access_control_entry_t *ace = malloc(sizeof(access_control_entry_t));
  181. if (ace == NULL)
  182. {
  183. ret = ERR_NOMEMORY;
  184. goto cleanup;
  185. }
  186. ace->uid = uid;
  187. ace->access_mask = access;
  188. list_append(&obj->acl, &ace->link);
  189. }
  190. cleanup:
  191. lock_release(&obj->acl_lock);
  192. dereference(obj);
  193. return ret;
  194. }
  195. dword_t revoke_access(object_t *obj, dword_t uid, access_flags_t access)
  196. {
  197. dword_t ret = ERR_SUCCESS;
  198. reference(obj);
  199. lock_acquire(&obj->acl_lock);
  200. if (get_current_uid() != obj->owner)
  201. {
  202. ret = ERR_FORBIDDEN;
  203. goto cleanup;
  204. }
  205. list_entry_t *ptr;
  206. for (ptr = obj->acl.next; ptr != &obj->acl; ptr = ptr->next)
  207. {
  208. access_control_entry_t *ace = CONTAINER_OF(ptr, access_control_entry_t, link);
  209. if (ace->uid == uid && (ace->access_mask & access) == ace->access_mask)
  210. {
  211. if (!(ace->access_mask &= ~access))
  212. {
  213. ptr = ptr->prev;
  214. list_remove(&ace->link);
  215. free(ace);
  216. ace = NULL;
  217. }
  218. }
  219. }
  220. cleanup:
  221. lock_release(&obj->acl_lock);
  222. dereference(obj);
  223. return ret;
  224. }
  225. dword_t create_object(object_t *obj)
  226. {
  227. if (obj->name != NULL)
  228. {
  229. object_t *other_obj;
  230. if (reference_by_name(obj->name, obj->type, &other_obj))
  231. {
  232. dereference(other_obj);
  233. return ERR_EXISTS;
  234. }
  235. }
  236. obj->ref_count = 1;
  237. obj->open_count = 0;
  238. obj->owner = get_current_uid();
  239. list_init(&obj->acl);
  240. access_control_entry_t *ace = malloc(sizeof(access_control_entry_t));
  241. ace->uid = get_current_uid();
  242. ace->access_mask = FULL_ACCESS;
  243. list_append(&obj->acl, &ace->link);
  244. lock_acquire(&obj_lock);
  245. if (obj->name) list_append(&named_objects[get_name_hash(obj->name)], &obj->by_name_list);
  246. else list_append(&anonymous_objects, &obj->by_name_list);
  247. list_append(&objects_by_type[obj->type], &obj->by_type_list);
  248. lock_release(&obj_lock);
  249. return ERR_SUCCESS;
  250. }
  251. dword_t open_object(object_t *obj, access_flags_t access_flags, handle_t *handle)
  252. {
  253. dword_t ret = ERR_SUCCESS;
  254. lock_acquire(&obj_lock);
  255. if (!access_check(obj, access_flags))
  256. {
  257. ret = ERR_FORBIDDEN;
  258. goto done;
  259. }
  260. handle_t new_handle = insert_object(obj, access_flags);
  261. if (new_handle == INVALID_HANDLE)
  262. {
  263. ret = ERR_NOMEMORY;
  264. goto done;
  265. }
  266. *handle = new_handle;
  267. obj->ref_count++;
  268. obj->open_count++;
  269. done:
  270. lock_release(&obj_lock);
  271. return ret;
  272. }
  273. dword_t open_object_by_name(const char *name, object_type_t type, access_flags_t access_flags, handle_t *handle)
  274. {
  275. dword_t ret = ERR_SUCCESS;
  276. object_t *obj;
  277. if (!reference_by_name(name, type, &obj)) return ERR_NOTFOUND;
  278. lock_acquire(&obj_lock);
  279. if (!access_check(obj, access_flags))
  280. {
  281. ret = ERR_FORBIDDEN;
  282. goto done;
  283. }
  284. handle_t new_handle = insert_object(obj, access_flags);
  285. if (new_handle == INVALID_HANDLE)
  286. {
  287. ret = ERR_NOMEMORY;
  288. goto done;
  289. }
  290. *handle = new_handle;
  291. obj->open_count++;
  292. done:
  293. lock_release(&obj_lock);
  294. if (ret != ERR_SUCCESS) dereference(obj);
  295. return ret;
  296. }
  297. void close_object_internal(object_t *obj)
  298. {
  299. lock_acquire(&obj_lock);
  300. obj->open_count--;
  301. qword_t ref_count = --obj->ref_count;
  302. if (!ref_count)
  303. {
  304. ASSERT(obj->open_count == 0);
  305. list_remove(&obj->by_name_list);
  306. list_remove(&obj->by_type_list);
  307. }
  308. lock_release(&obj_lock);
  309. if (!ref_count)
  310. {
  311. if (type_info[obj->type].cleanup != NULL) type_info[obj->type].cleanup(obj);
  312. free(obj);
  313. }
  314. }
  315. sysret_t syscall_close_object(handle_t handle)
  316. {
  317. dword_t ret = ERR_SUCCESS;
  318. process_t *proc = get_previous_mode() == USER_MODE ? get_current_process() : kernel_process;
  319. reference(&proc->header);
  320. lock_acquire(&proc->handle_table_lock);
  321. if (handle >= proc->handle_table_size)
  322. {
  323. lock_release(&proc->handle_table_lock);
  324. dereference(&proc->header);
  325. return ERR_NOTFOUND;
  326. }
  327. object_t *obj = proc->handle_table[handle].obj;
  328. if (obj != NULL)
  329. {
  330. close_object_internal(obj);
  331. proc->handle_table[handle].obj = NULL;
  332. proc->handle_count--;
  333. }
  334. else
  335. {
  336. ret = ERR_NOTFOUND;
  337. }
  338. lock_release(&proc->handle_table_lock);
  339. dereference(&proc->header);
  340. return ret;
  341. }
  342. sysret_t syscall_query_handle(handle_t handle, handle_info_type_t type, void *buffer, size_t size)
  343. {
  344. dword_t ret = ERR_SUCCESS;
  345. process_t *proc;
  346. void *safe_buffer = NULL;
  347. if (get_previous_mode() == USER_MODE)
  348. {
  349. proc = get_current_process();
  350. if (!check_usermode(buffer, size)) return ERR_BADPTR;
  351. safe_buffer = malloc(size);
  352. if (safe_buffer == NULL) return ERR_NOMEMORY;
  353. memset(safe_buffer, 0, size);
  354. }
  355. else
  356. {
  357. proc = kernel_process;
  358. safe_buffer = buffer;
  359. }
  360. reference(&proc->header);
  361. lock_acquire(&proc->handle_table_lock);
  362. object_t *obj = proc->handle_table[handle].obj;
  363. if (obj == NULL)
  364. {
  365. ret = ERR_NOTFOUND;
  366. goto cleanup;
  367. }
  368. char *name = obj->name ? obj->name : "<anonymous>";
  369. switch (type)
  370. {
  371. case HANDLE_INFO_NAME:
  372. strncpy(safe_buffer, name, size);
  373. if (size < strlen(name) + 1) ret = ERR_SMALLBUF;
  374. break;
  375. case HANDLE_INFO_TYPE:
  376. *((object_type_t*)safe_buffer) = obj->type;
  377. if (size < sizeof(object_type_t)) ret = ERR_SMALLBUF;
  378. break;
  379. default:
  380. ret = ERR_INVALID;
  381. }
  382. if (get_previous_mode() == USER_MODE)
  383. {
  384. EH_TRY memcpy(buffer, safe_buffer, size);
  385. EH_CATCH ret = ERR_BADPTR;
  386. EH_DONE;
  387. }
  388. cleanup:
  389. lock_release(&proc->handle_table_lock);
  390. dereference(&proc->header);
  391. if (get_previous_mode() == USER_MODE) free(safe_buffer);
  392. return ret;
  393. }
  394. sysret_t syscall_duplicate_handle(handle_t source_process, handle_t handle, handle_t dest_process, handle_t *duplicate)
  395. {
  396. process_t *proc;
  397. handle_t safe_handle;
  398. if (get_previous_mode() == USER_MODE && !check_usermode(duplicate, sizeof(handle_t)))
  399. {
  400. return ERR_BADPTR;
  401. }
  402. if (source_process != INVALID_HANDLE)
  403. {
  404. if (!reference_by_handle(source_process, OBJECT_PROCESS, (object_t**)&proc)) return ERR_INVALID;
  405. }
  406. else
  407. {
  408. proc = get_previous_mode() == USER_MODE ? get_current_process() : kernel_process;
  409. reference(&proc->header);
  410. }
  411. lock_acquire_shared(&proc->handle_table_lock);
  412. if (handle >= proc->handle_table_size)
  413. {
  414. lock_release(&proc->handle_table_lock);
  415. dereference(&proc->header);
  416. return ERR_INVALID;
  417. }
  418. object_t *obj = proc->handle_table[handle].obj;
  419. access_flags_t access_flags = proc->handle_table[handle].access_flags;
  420. if (obj == NULL)
  421. {
  422. lock_release(&proc->handle_table_lock);
  423. dereference(&proc->header);
  424. return ERR_INVALID;
  425. }
  426. reference(obj);
  427. lock_release(&proc->handle_table_lock);
  428. dereference(&proc->header);
  429. if (dest_process != INVALID_HANDLE)
  430. {
  431. if (!reference_by_handle(source_process, OBJECT_PROCESS, (object_t**)&proc))
  432. {
  433. dereference(obj);
  434. return ERR_INVALID;
  435. }
  436. }
  437. else
  438. {
  439. proc = get_previous_mode() == USER_MODE ? get_current_process() : kernel_process;
  440. reference(&proc->header);
  441. }
  442. process_t *old_process = switch_process(proc);
  443. dword_t ret = open_object(obj, access_flags, &safe_handle);
  444. switch_process(old_process);
  445. dereference(&proc->header);
  446. dereference(obj);
  447. EH_TRY
  448. {
  449. *duplicate = safe_handle;
  450. }
  451. EH_CATCH
  452. {
  453. ret = ERR_BADPTR;
  454. }
  455. EH_DONE;
  456. return ret;
  457. }
  458. dword_t enum_objects_by_type(object_type_t type, object_t **object)
  459. {
  460. dword_t ret = ERR_SUCCESS;
  461. list_entry_t *ptr;
  462. object_t *previous = *object;
  463. lock_acquire(&obj_lock);
  464. if (previous == NULL) ptr = objects_by_type[type].next;
  465. else ptr = previous->by_type_list.next;
  466. if (ptr != &objects_by_type[type])
  467. {
  468. *object = CONTAINER_OF(ptr, object_t, by_type_list);
  469. ret = ERR_SUCCESS;
  470. }
  471. else
  472. {
  473. *object = NULL;
  474. ret = ERR_NOMORE;
  475. }
  476. lock_release(&obj_lock);
  477. if (*object) reference(*object);
  478. if (previous) dereference(previous);
  479. return ret;
  480. }
  481. static sysret_t wait_for_objects(const handle_t *handles, void * const *parameters, size_t count, timeout_t timeout, wait_condition_type_t condition_type)
  482. {
  483. dword_t ret = ERR_SUCCESS;
  484. object_t **objects = NULL;
  485. wait_condition_t *condition = NULL;
  486. const handle_t *safe_handles;
  487. void * const *safe_parameters = NULL;
  488. processor_mode_t previous_mode = get_previous_mode();
  489. if (count == 0) return ERR_INVALID;
  490. if (previous_mode == USER_MODE)
  491. {
  492. if (!check_usermode(handles, count * sizeof(handle_t))) return ERR_BADPTR;
  493. if (parameters && !check_usermode(parameters, count * sizeof(void*))) return ERR_BADPTR;
  494. safe_handles = calloc(count, sizeof(handle_t));
  495. if (safe_handles == NULL) return ERR_NOMEMORY;
  496. if (parameters)
  497. {
  498. safe_parameters = calloc(count, sizeof(void*));
  499. if (safe_parameters == NULL)
  500. {
  501. free((void*)safe_handles);
  502. return ERR_NOMEMORY;
  503. }
  504. }
  505. EH_TRY
  506. {
  507. memcpy((handle_t*)safe_handles, handles, count * sizeof(handle_t));
  508. if (safe_parameters) memcpy((void*)safe_parameters, parameters, count * sizeof(void*));
  509. }
  510. EH_CATCH
  511. {
  512. free((void*)safe_handles);
  513. if (safe_parameters) free((void*)safe_parameters);
  514. EH_ESCAPE(return ERR_BADPTR);
  515. }
  516. EH_DONE;
  517. }
  518. else
  519. {
  520. safe_handles = handles;
  521. safe_parameters = parameters;
  522. }
  523. if (!(objects = calloc(count, sizeof(object_t*))))
  524. {
  525. ret = ERR_NOMEMORY;
  526. goto cleanup;
  527. }
  528. size_t i;
  529. for (i = 0; i < count; i++)
  530. {
  531. if (!reference_by_handle(safe_handles[i], OBJECT_ANY_TYPE, &objects[i]))
  532. {
  533. ret = ERR_INVALID;
  534. goto cleanup;
  535. }
  536. }
  537. if (!(condition = malloc(sizeof(wait_condition_t) + count * sizeof(wait_condition_t*))))
  538. {
  539. ret = ERR_NOMEMORY;
  540. goto cleanup;
  541. }
  542. memset(condition, 0, sizeof(wait_condition_t) + count * sizeof(wait_condition_t*));
  543. condition->type = condition_type;
  544. for (i = 0; i < count; i++)
  545. {
  546. if (!type_info[objects[i]->type].pre_wait)
  547. {
  548. ret = ERR_INVALID;
  549. goto cleanup;
  550. }
  551. wait_condition_t *cond = malloc(sizeof(wait_condition_t));
  552. if (!cond)
  553. {
  554. ret = ERR_NOMEMORY;
  555. goto cleanup;
  556. }
  557. ret = type_info[objects[i]->type].pre_wait(objects[i], safe_parameters[i], cond);
  558. if (ret != ERR_SUCCESS)
  559. {
  560. free(cond);
  561. goto cleanup;
  562. }
  563. condition->conditions[i] = cond;
  564. }
  565. wait_result_t result = scheduler_wait(condition, timeout);
  566. if (result == WAIT_CANCELED) ret = ERR_CANCELED;
  567. else if (result == WAIT_TIMED_OUT) ret = ERR_TIMEOUT;
  568. for (i = 0; i < count; i++)
  569. {
  570. if (type_info[objects[i]->type].post_wait)
  571. {
  572. type_info[objects[i]->type].post_wait(objects[i], safe_parameters ? safe_parameters[i] : NULL, result);
  573. }
  574. }
  575. cleanup:
  576. if (condition)
  577. {
  578. for (i = 0; i < count; i++) if (condition->conditions[i]) free(condition->conditions[i]);
  579. free(condition);
  580. }
  581. if (objects)
  582. {
  583. for (i = 0; i < count; i++) if (objects[i]) dereference(objects[i]);
  584. free(objects);
  585. }
  586. if (previous_mode == USER_MODE)
  587. {
  588. free((void*)safe_handles);
  589. if (safe_parameters) free((void*)safe_parameters);
  590. }
  591. return ret;
  592. }
  593. sysret_t syscall_wait_for_one(handle_t handle, void *parameter, timeout_t timeout)
  594. {
  595. dword_t ret = ERR_SUCCESS;
  596. object_t *object;
  597. if (!reference_by_handle(handle, OBJECT_ANY_TYPE, &object)) return ERR_INVALID;
  598. if (!type_info[object->type].pre_wait)
  599. {
  600. dereference(object);
  601. return ERR_INVALID;
  602. }
  603. wait_condition_t condition;
  604. ret = type_info[object->type].pre_wait(object, parameter, &condition);
  605. if (ret != ERR_SUCCESS) return ret;
  606. wait_result_t result = scheduler_wait(&condition, timeout);
  607. dereference(object);
  608. switch (result)
  609. {
  610. case WAIT_CONDITION_HIT:
  611. return ERR_SUCCESS;
  612. case WAIT_CANCELED:
  613. return ERR_CANCELED;
  614. case WAIT_TIMED_OUT:
  615. return ERR_TIMEOUT;
  616. default:
  617. KERNEL_CRASH("Unexpected scheduler wait result");
  618. return ERR_INVALID;
  619. }
  620. }
  621. sysret_t syscall_wait_for_any(const handle_t *handles, void * const *parameters, size_t count, timeout_t timeout)
  622. {
  623. return wait_for_objects(handles, parameters, count, timeout, WAIT_GROUP_ANY);
  624. }
  625. sysret_t syscall_wait_for_all(const handle_t *handles, void * const *parameters, size_t count, timeout_t timeout)
  626. {
  627. return wait_for_objects(handles, parameters, count, timeout, WAIT_GROUP_ALL);
  628. }
  629. void object_init(void)
  630. {
  631. list_init_array(named_objects, sizeof(named_objects) / sizeof(*named_objects));
  632. list_init_array(objects_by_type, sizeof(objects_by_type) / sizeof(*objects_by_type));
  633. }