ipc_tt.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134
  1. /*
  2. * Mach Operating System
  3. * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
  4. * All Rights Reserved.
  5. *
  6. * Permission to use, copy, modify and distribute this software and its
  7. * documentation is hereby granted, provided that both the copyright
  8. * notice and this permission notice appear in all copies of the
  9. * software, derivative works or modified versions, and any portions
  10. * thereof, and that both notices appear in supporting documentation.
  11. *
  12. * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
  13. * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
  14. * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  15. *
  16. * Carnegie Mellon requests users of this software to return to
  17. *
  18. * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
  19. * School of Computer Science
  20. * Carnegie Mellon University
  21. * Pittsburgh PA 15213-3890
  22. *
  23. * any improvements or extensions that they make and grant Carnegie Mellon
  24. * the rights to redistribute these changes.
  25. */
  26. /*
  27. * File: ipc_tt.c
  28. * Purpose:
  29. * Task and thread related IPC functions.
  30. */
  31. #include <glue/gnulinux.h>
  32. #include <linux/printk.h>
  33. #include <mach/message.h>
  34. #include <mach/boolean.h>
  35. #include <mach/kern_return.h>
  36. #include <mach/mach_param.h>
  37. #include <mach/task_special_ports.h>
  38. #include <mach/thread_special_ports.h>
  39. #include <vm/vm_kern.h>
  40. #include <kern/debug.h>
  41. #include <kern/kalloc.h>
  42. #include <kern/task.h>
  43. #include <kern/thread.h>
  44. #include <kern/ipc_kobject.h>
  45. #include <kern/ipc_tt.h>
  46. #include <ipc/ipc_space.h>
  47. #include <ipc/ipc_table.h>
  48. #include <ipc/ipc_port.h>
  49. #include <ipc/ipc_right.h>
  50. #include <ipc/ipc_entry.h>
  51. #include <ipc/ipc_object.h>
  52. /*
  53. * Routine: ipc_task_init
  54. * Purpose:
  55. * Initialize a task's IPC state.
  56. *
  57. * If non-null, some state will be inherited from the parent.
  58. * The parent must be appropriately initialized.
  59. * Conditions:
  60. * Nothing locked.
  61. */
  62. void
  63. ipc_task_init(
  64. task_t task,
  65. task_t parent)
  66. {
  67. ipc_space_t space;
  68. ipc_port_t kport;
  69. kern_return_t kr;
  70. int i;
  71. //printk(KERN_DEBUG "ipc_task_init %p %p\n",task,parent);
  72. kr = ipc_space_create(&ipc_table_entries[0],&space);
  73. if (kr != KERN_SUCCESS)
  74. panic("ipc_task_init");
  75. kport = ipc_port_alloc_kernel();
  76. if (kport == IP_NULL)
  77. panic("ipc_task_init");
  78. itk_lock_init(task);
  79. task->itk_self = kport;
  80. task->itk_sself = ipc_port_make_send(kport);
  81. task->itk_space = space;
  82. if (parent == TASK_NULL) {
  83. task->itk_exception = IP_NULL;
  84. task->itk_bootstrap = IP_NULL;
  85. for (i = 0; i < TASK_PORT_REGISTER_MAX; i++)
  86. task->itk_registered[i] = IP_NULL;
  87. } else {
  88. itk_lock(parent);
  89. assert(parent->itk_self != IP_NULL);
  90. /* inherit registered ports */
  91. for (i = 0; i < TASK_PORT_REGISTER_MAX; i++)
  92. task->itk_registered[i] =
  93. ipc_port_copy_send(parent->itk_registered[i]);
  94. /* inherit exception and bootstrap ports */
  95. task->itk_exception =
  96. ipc_port_copy_send(parent->itk_exception);
  97. task->itk_bootstrap =
  98. ipc_port_copy_send(parent->itk_bootstrap);
  99. itk_unlock(parent);
  100. }
  101. }
  102. /*
  103. * Routine: ipc_task_enable
  104. * Purpose:
  105. * Enable a task for IPC access.
  106. * Conditions:
  107. * Nothing locked.
  108. */
  109. void
  110. ipc_task_enable(
  111. task_t task)
  112. {
  113. ipc_port_t kport;
  114. itk_lock(task);
  115. kport = task->itk_self;
  116. if (kport != IP_NULL)
  117. ipc_kobject_set(kport, (ipc_kobject_t) task, IKOT_TASK);
  118. itk_unlock(task);
  119. }
  120. /*
  121. * Routine: ipc_task_disable
  122. * Purpose:
  123. * Disable IPC access to a task.
  124. * Conditions:
  125. * Nothing locked.
  126. */
  127. void
  128. ipc_task_disable(
  129. task_t task)
  130. {
  131. ipc_port_t kport;
  132. itk_lock(task);
  133. kport = task->itk_self;
  134. if (kport != IP_NULL)
  135. ipc_kobject_set(kport, IKO_NULL, IKOT_NONE);
  136. itk_unlock(task);
  137. }
  138. /*
  139. * Routine: ipc_task_terminate
  140. * Purpose:
  141. * Clean up and destroy a task's IPC state.
  142. * Conditions:
  143. * Nothing locked. The task must be suspended.
  144. * (Or the current thread must be in the task.)
  145. */
  146. void
  147. ipc_task_terminate(
  148. task_t task)
  149. {
  150. ipc_port_t kport;
  151. int i;
  152. itk_lock(task);
  153. kport = task->itk_self;
  154. if (kport == IP_NULL) {
  155. /* the task is already terminated (can this happen?) */
  156. itk_unlock(task);
  157. return;
  158. }
  159. task->itk_self = IP_NULL;
  160. itk_unlock(task);
  161. /* release the naked send rights */
  162. if (IP_VALID(task->itk_sself))
  163. ipc_port_release_send(task->itk_sself);
  164. if (IP_VALID(task->itk_exception))
  165. ipc_port_release_send(task->itk_exception);
  166. if (IP_VALID(task->itk_bootstrap))
  167. ipc_port_release_send(task->itk_bootstrap);
  168. for (i = 0; i < TASK_PORT_REGISTER_MAX; i++)
  169. if (IP_VALID(task->itk_registered[i]))
  170. ipc_port_release_send(task->itk_registered[i]);
  171. /* destroy the space, leaving just a reference for it */
  172. ipc_space_destroy(task->itk_space);
  173. /* destroy the kernel port */
  174. ipc_port_dealloc_kernel(kport);
  175. }
  176. /*
  177. * Routine: ipc_thread_init
  178. * Purpose:
  179. * Initialize a thread's IPC state.
  180. * Conditions:
  181. * Nothing locked.
  182. */
  183. void
  184. ipc_thread_init(thread_t thread)
  185. {
  186. ipc_port_t kport;
  187. kport = ipc_port_alloc_kernel();
  188. if (kport == IP_NULL)
  189. panic("ipc_thread_init");
  190. ipc_thread_links_init(thread);
  191. ipc_kmsg_queue_init(&thread->ith_messages);
  192. ith_lock_init(thread);
  193. thread->ith_self = kport;
  194. thread->ith_sself = ipc_port_make_send(kport);
  195. thread->ith_exception = IP_NULL;
  196. thread->ith_mig_reply = MACH_PORT_NULL;
  197. thread->ith_rpc_reply = IP_NULL;
  198. }
  199. /*
  200. * Routine: ipc_thread_enable
  201. * Purpose:
  202. * Enable a thread for IPC access.
  203. * Conditions:
  204. * Nothing locked.
  205. */
  206. void
  207. ipc_thread_enable(thread_t thread)
  208. {
  209. ipc_port_t kport;
  210. ith_lock(thread);
  211. kport = thread->ith_self;
  212. if (kport != IP_NULL)
  213. ipc_kobject_set(kport, (ipc_kobject_t) thread, IKOT_THREAD);
  214. ith_unlock(thread);
  215. }
  216. /*
  217. * Routine: ipc_thread_disable
  218. * Purpose:
  219. * Disable IPC access to a thread.
  220. * Conditions:
  221. * Nothing locked.
  222. */
  223. void
  224. ipc_thread_disable(thread_t thread)
  225. {
  226. ipc_port_t kport;
  227. ith_lock(thread);
  228. kport = thread->ith_self;
  229. if (kport != IP_NULL)
  230. ipc_kobject_set(kport, IKO_NULL, IKOT_NONE);
  231. ith_unlock(thread);
  232. }
  233. /*
  234. * Routine: ipc_thread_terminate
  235. * Purpose:
  236. * Clean up and destroy a thread's IPC state.
  237. * Conditions:
  238. * Nothing locked. The thread must be suspended.
  239. * (Or be the current thread.)
  240. */
  241. void
  242. ipc_thread_terminate(thread_t thread)
  243. {
  244. ipc_port_t kport;
  245. ith_lock(thread);
  246. kport = thread->ith_self;
  247. if (kport == IP_NULL) {
  248. /* the thread is already terminated (can this happen?) */
  249. ith_unlock(thread);
  250. return;
  251. }
  252. thread->ith_self = IP_NULL;
  253. ith_unlock(thread);
  254. assert(ipc_kmsg_queue_empty(&thread->ith_messages));
  255. /* release the naked send rights */
  256. if (IP_VALID(thread->ith_sself))
  257. ipc_port_release_send(thread->ith_sself);
  258. if (IP_VALID(thread->ith_exception))
  259. ipc_port_release_send(thread->ith_exception);
  260. /* destroy the kernel port */
  261. ipc_port_dealloc_kernel(kport);
  262. }
  263. #if 0
  264. /*
  265. * Routine: retrieve_task_self
  266. * Purpose:
  267. * Return a send right (possibly null/dead)
  268. * for the task's user-visible self port.
  269. * Conditions:
  270. * Nothing locked.
  271. */
  272. ipc_port_t
  273. retrieve_task_self(task)
  274. task_t task;
  275. {
  276. ipc_port_t port;
  277. assert(task != TASK_NULL);
  278. itk_lock(task);
  279. if (task->itk_self != IP_NULL)
  280. port = ipc_port_copy_send(task->itk_sself);
  281. else
  282. port = IP_NULL;
  283. itk_unlock(task);
  284. return port;
  285. }
  286. /*
  287. * Routine: retrieve_thread_self
  288. * Purpose:
  289. * Return a send right (possibly null/dead)
  290. * for the thread's user-visible self port.
  291. * Conditions:
  292. * Nothing locked.
  293. */
  294. ipc_port_t
  295. retrieve_thread_self(thread)
  296. thread_t thread;
  297. {
  298. ipc_port_t port;
  299. assert(thread != ITH_NULL);
  300. ith_lock(thread);
  301. if (thread->ith_self != IP_NULL)
  302. port = ipc_port_copy_send(thread->ith_sself);
  303. else
  304. port = IP_NULL;
  305. ith_unlock(thread);
  306. return port;
  307. }
  308. #endif /* 0 */
  309. /*
  310. * Routine: retrieve_task_self_fast
  311. * Purpose:
  312. * Optimized version of retrieve_task_self,
  313. * that only works for the current task.
  314. *
  315. * Return a send right (possibly null/dead)
  316. * for the task's user-visible self port.
  317. * Conditions:
  318. * Nothing locked.
  319. */
  320. ipc_port_t
  321. retrieve_task_self_fast(
  322. task_t task)
  323. {
  324. ipc_port_t port;
  325. assert(task == current_task());
  326. itk_lock(task);
  327. assert(task->itk_self != IP_NULL);
  328. if ((port = task->itk_sself) == task->itk_self) {
  329. /* no interposing */
  330. ip_lock(port);
  331. assert(ip_active(port));
  332. ip_reference(port);
  333. port->ip_srights++;
  334. ip_unlock(port);
  335. } else
  336. port = ipc_port_copy_send(port);
  337. itk_unlock(task);
  338. return port;
  339. }
  340. /*
  341. * Routine: retrieve_thread_self_fast
  342. * Purpose:
  343. * Optimized version of retrieve_thread_self,
  344. * that only works for the current thread.
  345. *
  346. * Return a send right (possibly null/dead)
  347. * for the thread's user-visible self port.
  348. * Conditions:
  349. * Nothing locked.
  350. */
  351. ipc_port_t
  352. retrieve_thread_self_fast(thread_t thread)
  353. {
  354. ipc_port_t port;
  355. assert(thread == current_thread());
  356. ith_lock(thread);
  357. assert(thread->ith_self != IP_NULL);
  358. if ((port = thread->ith_sself) == thread->ith_self) {
  359. /* no interposing */
  360. ip_lock(port);
  361. assert(ip_active(port));
  362. ip_reference(port);
  363. port->ip_srights++;
  364. ip_unlock(port);
  365. } else
  366. port = ipc_port_copy_send(port);
  367. ith_unlock(thread);
  368. return port;
  369. }
  370. #if 0
  371. /*
  372. * Routine: retrieve_task_exception
  373. * Purpose:
  374. * Return a send right (possibly null/dead)
  375. * for the task's exception port.
  376. * Conditions:
  377. * Nothing locked.
  378. */
  379. ipc_port_t
  380. retrieve_task_exception(task)
  381. task_t task;
  382. {
  383. ipc_port_t port;
  384. assert(task != TASK_NULL);
  385. itk_lock(task);
  386. if (task->itk_self != IP_NULL)
  387. port = ipc_port_copy_send(task->itk_exception);
  388. else
  389. port = IP_NULL;
  390. itk_unlock(task);
  391. return port;
  392. }
  393. /*
  394. * Routine: retrieve_thread_exception
  395. * Purpose:
  396. * Return a send right (possibly null/dead)
  397. * for the thread's exception port.
  398. * Conditions:
  399. * Nothing locked.
  400. */
  401. ipc_port_t
  402. retrieve_thread_exception(thread)
  403. thread_t thread;
  404. {
  405. ipc_port_t port;
  406. assert(thread != ITH_NULL);
  407. ith_lock(thread);
  408. if (thread->ith_self != IP_NULL)
  409. port = ipc_port_copy_send(thread->ith_exception);
  410. else
  411. port = IP_NULL;
  412. ith_unlock(thread);
  413. return port;
  414. }
  415. #endif /* 0 */
  416. /*
  417. * Routine: mach_task_self [mach trap]
  418. * Purpose:
  419. * Give the caller send rights for his own task port.
  420. * Conditions:
  421. * Nothing locked.
  422. * Returns:
  423. * MACH_PORT_NULL if there are any resource failures
  424. * or other errors.
  425. */
  426. mach_port_t
  427. mach_task_self(void)
  428. {
  429. task_t task = current_task();
  430. ipc_port_t sright;
  431. sright = retrieve_task_self_fast(task);
  432. return ipc_port_copyout_send(sright, task->itk_space);
  433. }
  434. /*
  435. * Routine: mach_thread_self [mach trap]
  436. * Purpose:
  437. * Give the caller send rights for his own thread port.
  438. * Conditions:
  439. * Nothing locked.
  440. * Returns:
  441. * MACH_PORT_NULL if there are any resource failures
  442. * or other errors.
  443. */
  444. mach_port_t
  445. mach_thread_self(void)
  446. {
  447. thread_t thread = current_thread();
  448. task_t task = thread->task;
  449. ipc_port_t sright;
  450. sright = retrieve_thread_self_fast(thread);
  451. return ipc_port_copyout_send(sright, task->itk_space);
  452. }
  453. /*
  454. * Routine: mach_reply_port [mach trap]
  455. * Purpose:
  456. * Allocate a port for the caller.
  457. * Conditions:
  458. * Nothing locked.
  459. * Returns:
  460. * MACH_PORT_NULL if there are any resource failures
  461. * or other errors.
  462. */
  463. mach_port_t
  464. mach_reply_port(void)
  465. {
  466. ipc_port_t port;
  467. mach_port_t name;
  468. kern_return_t kr;
  469. kr = ipc_port_alloc(current_task()->itk_space, &name, &port);
  470. if (kr == KERN_SUCCESS)
  471. ip_unlock(port);
  472. else
  473. name = MACH_PORT_NULL;
  474. return name;
  475. }
  476. /*
  477. * Routine: task_get_special_port [kernel call]
  478. * Purpose:
  479. * Clones a send right for one of the task's
  480. * special ports.
  481. * Conditions:
  482. * Nothing locked.
  483. * Returns:
  484. * KERN_SUCCESS Extracted a send right.
  485. * KERN_INVALID_ARGUMENT The task is null.
  486. * KERN_FAILURE The task/space is dead.
  487. * KERN_INVALID_ARGUMENT Invalid special port.
  488. */
  489. kern_return_t
  490. task_get_special_port(
  491. task_t task,
  492. int which,
  493. ipc_port_t *portp)
  494. {
  495. ipc_port_t *whichp;
  496. ipc_port_t port;
  497. if (task == TASK_NULL)
  498. return KERN_INVALID_ARGUMENT;
  499. switch (which) {
  500. case TASK_KERNEL_PORT:
  501. whichp = &task->itk_sself;
  502. break;
  503. case TASK_EXCEPTION_PORT:
  504. whichp = &task->itk_exception;
  505. break;
  506. case TASK_BOOTSTRAP_PORT:
  507. whichp = &task->itk_bootstrap;
  508. break;
  509. default:
  510. return KERN_INVALID_ARGUMENT;
  511. }
  512. itk_lock(task);
  513. if (task->itk_self == IP_NULL) {
  514. itk_unlock(task);
  515. return KERN_FAILURE;
  516. }
  517. port = ipc_port_copy_send(*whichp);
  518. itk_unlock(task);
  519. *portp = port;
  520. return KERN_SUCCESS;
  521. }
  522. /*
  523. * Routine: task_set_special_port [kernel call]
  524. * Purpose:
  525. * Changes one of the task's special ports,
  526. * setting it to the supplied send right.
  527. * Conditions:
  528. * Nothing locked. If successful, consumes
  529. * the supplied send right.
  530. * Returns:
  531. * KERN_SUCCESS Changed the special port.
  532. * KERN_INVALID_ARGUMENT The task is null.
  533. * KERN_FAILURE The task/space is dead.
  534. * KERN_INVALID_ARGUMENT Invalid special port.
  535. */
  536. kern_return_t
  537. task_set_special_port(
  538. task_t task,
  539. int which,
  540. const ipc_port_t port)
  541. {
  542. ipc_port_t *whichp;
  543. ipc_port_t old;
  544. if (task == TASK_NULL)
  545. return KERN_INVALID_ARGUMENT;
  546. switch (which) {
  547. case TASK_KERNEL_PORT:
  548. whichp = &task->itk_sself;
  549. break;
  550. case TASK_EXCEPTION_PORT:
  551. whichp = &task->itk_exception;
  552. break;
  553. case TASK_BOOTSTRAP_PORT:
  554. whichp = &task->itk_bootstrap;
  555. break;
  556. default:
  557. return KERN_INVALID_ARGUMENT;
  558. }
  559. itk_lock(task);
  560. if (task->itk_self == IP_NULL) {
  561. itk_unlock(task);
  562. return KERN_FAILURE;
  563. }
  564. old = *whichp;
  565. *whichp = port;
  566. itk_unlock(task);
  567. if (IP_VALID(old))
  568. ipc_port_release_send(old);
  569. return KERN_SUCCESS;
  570. }
  571. /*
  572. * Routine: thread_get_special_port [kernel call]
  573. * Purpose:
  574. * Clones a send right for one of the thread's
  575. * special ports.
  576. * Conditions:
  577. * Nothing locked.
  578. * Returns:
  579. * KERN_SUCCESS Extracted a send right.
  580. * KERN_INVALID_ARGUMENT The thread is null.
  581. * KERN_FAILURE The thread is dead.
  582. * KERN_INVALID_ARGUMENT Invalid special port.
  583. */
  584. kern_return_t
  585. thread_get_special_port(
  586. thread_t thread,
  587. int which,
  588. ipc_port_t *portp)
  589. {
  590. ipc_port_t *whichp;
  591. ipc_port_t port;
  592. if (thread == ITH_NULL)
  593. return KERN_INVALID_ARGUMENT;
  594. switch (which) {
  595. case THREAD_KERNEL_PORT:
  596. whichp = &thread->ith_sself;
  597. break;
  598. case THREAD_EXCEPTION_PORT:
  599. whichp = &thread->ith_exception;
  600. break;
  601. default:
  602. return KERN_INVALID_ARGUMENT;
  603. }
  604. ith_lock(thread);
  605. if (thread->ith_self == IP_NULL) {
  606. ith_unlock(thread);
  607. return KERN_FAILURE;
  608. }
  609. port = ipc_port_copy_send(*whichp);
  610. ith_unlock(thread);
  611. *portp = port;
  612. return KERN_SUCCESS;
  613. }
  614. /*
  615. * Routine: thread_set_special_port [kernel call]
  616. * Purpose:
  617. * Changes one of the thread's special ports,
  618. * setting it to the supplied send right.
  619. * Conditions:
  620. * Nothing locked. If successful, consumes
  621. * the supplied send right.
  622. * Returns:
  623. * KERN_SUCCESS Changed the special port.
  624. * KERN_INVALID_ARGUMENT The thread is null.
  625. * KERN_FAILURE The thread is dead.
  626. * KERN_INVALID_ARGUMENT Invalid special port.
  627. */
  628. kern_return_t
  629. thread_set_special_port(
  630. thread_t thread,
  631. int which,
  632. ipc_port_t port)
  633. {
  634. ipc_port_t *whichp;
  635. ipc_port_t old;
  636. if (thread == ITH_NULL)
  637. return KERN_INVALID_ARGUMENT;
  638. switch (which) {
  639. case THREAD_KERNEL_PORT:
  640. whichp = &thread->ith_sself;
  641. break;
  642. case THREAD_EXCEPTION_PORT:
  643. whichp = &thread->ith_exception;
  644. break;
  645. default:
  646. return KERN_INVALID_ARGUMENT;
  647. }
  648. ith_lock(thread);
  649. if (thread->ith_self == IP_NULL) {
  650. ith_unlock(thread);
  651. return KERN_FAILURE;
  652. }
  653. old = *whichp;
  654. *whichp = port;
  655. ith_unlock(thread);
  656. if (IP_VALID(old))
  657. ipc_port_release_send(old);
  658. return KERN_SUCCESS;
  659. }
  660. /*
  661. * Routine: mach_ports_register [kernel call]
  662. * Purpose:
  663. * Stash a handful of port send rights in the task.
  664. * Child tasks will inherit these rights, but they
  665. * must use mach_ports_lookup to acquire them.
  666. *
  667. * The rights are supplied in a (wired) kalloc'd segment.
  668. * Rights which aren't supplied are assumed to be null.
  669. * Conditions:
  670. * Nothing locked. If successful, consumes
  671. * the supplied rights and memory.
  672. * Returns:
  673. * KERN_SUCCESS Stashed the port rights.
  674. * KERN_INVALID_ARGUMENT The task is null.
  675. * KERN_INVALID_ARGUMENT The task is dead.
  676. * KERN_INVALID_ARGUMENT Too many port rights supplied.
  677. */
  678. kern_return_t
  679. mach_ports_register(
  680. task_t task,
  681. mach_port_array_t memory,
  682. mach_msg_type_number_t portsCnt)
  683. {
  684. ipc_port_t ports[TASK_PORT_REGISTER_MAX];
  685. unsigned i;
  686. if ((task == TASK_NULL) ||
  687. (portsCnt > TASK_PORT_REGISTER_MAX))
  688. return KERN_INVALID_ARGUMENT;
  689. /*
  690. * Pad the port rights with nulls.
  691. */
  692. for (i = 0; i < portsCnt; i++)
  693. ports[i] = (ipc_port_t)memory[i];
  694. for (; i < TASK_PORT_REGISTER_MAX; i++)
  695. ports[i] = IP_NULL;
  696. itk_lock(task);
  697. if (task->itk_self == IP_NULL) {
  698. itk_unlock(task);
  699. return KERN_INVALID_ARGUMENT;
  700. }
  701. /*
  702. * Replace the old send rights with the new.
  703. * Release the old rights after unlocking.
  704. */
  705. for (i = 0; i < TASK_PORT_REGISTER_MAX; i++) {
  706. ipc_port_t old;
  707. old = task->itk_registered[i];
  708. task->itk_registered[i] = ports[i];
  709. ports[i] = old;
  710. }
  711. itk_unlock(task);
  712. for (i = 0; i < TASK_PORT_REGISTER_MAX; i++)
  713. if (IP_VALID(ports[i]))
  714. ipc_port_release_send(ports[i]);
  715. /*
  716. * Now that the operation is known to be successful,
  717. * we can free the memory.
  718. */
  719. if (portsCnt != 0)
  720. kfree((vm_offset_t) memory,
  721. (vm_size_t) (portsCnt * sizeof(mach_port_t)));
  722. return KERN_SUCCESS;
  723. }
  724. /*
  725. * Routine: mach_ports_lookup [kernel call]
  726. * Purpose:
  727. * Retrieves (clones) the stashed port send rights.
  728. * Conditions:
  729. * Nothing locked. If successful, the caller gets
  730. * rights and memory.
  731. * Returns:
  732. * KERN_SUCCESS Retrieved the send rights.
  733. * KERN_INVALID_ARGUMENT The task is null.
  734. * KERN_INVALID_ARGUMENT The task is dead.
  735. * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
  736. */
  737. kern_return_t
  738. mach_ports_lookup(
  739. task_t task,
  740. ipc_port_t **portsp,
  741. mach_msg_type_number_t *portsCnt)
  742. {
  743. vm_offset_t memory;
  744. vm_size_t size;
  745. ipc_port_t *ports;
  746. int i;
  747. if (task == TASK_NULL)
  748. return KERN_INVALID_ARGUMENT;
  749. size = (vm_size_t) (TASK_PORT_REGISTER_MAX * sizeof(ipc_port_t));
  750. memory = kalloc(size);
  751. if (memory == 0)
  752. return KERN_RESOURCE_SHORTAGE;
  753. itk_lock(task);
  754. if (task->itk_self == IP_NULL) {
  755. itk_unlock(task);
  756. kfree(memory, size);
  757. return KERN_INVALID_ARGUMENT;
  758. }
  759. ports = (ipc_port_t *) memory;
  760. /*
  761. * Clone port rights. Because kalloc'd memory
  762. * is wired, we won't fault while holding the task lock.
  763. */
  764. for (i = 0; i < TASK_PORT_REGISTER_MAX; i++)
  765. ports[i] = ipc_port_copy_send(task->itk_registered[i]);
  766. itk_unlock(task);
  767. *portsp = ports;
  768. *portsCnt = TASK_PORT_REGISTER_MAX;
  769. return KERN_SUCCESS;
  770. }
  771. /*
  772. * Routine: convert_port_to_task
  773. * Purpose:
  774. * Convert from a port to a task.
  775. * Doesn't consume the port ref; produces a task ref,
  776. * which may be null.
  777. * Conditions:
  778. * Nothing locked.
  779. */
  780. #if 0
  781. task_t
  782. convert_port_to_task(
  783. ipc_port_t port)
  784. {
  785. task_t task = TASK_NULL;
  786. if (IP_VALID(port)) {
  787. ip_lock(port);
  788. if (ip_active(port) &&
  789. (ip_kotype(port) == IKOT_TASK)) {
  790. task = (task_t) port->ip_kobject;
  791. task_reference(task);
  792. }
  793. ip_unlock(port);
  794. }
  795. return task;
  796. }
  797. #endif
  798. /*
  799. * Routine: convert_port_to_space
  800. * Purpose:
  801. * Convert from a port to a space.
  802. * Doesn't consume the port ref; produces a space ref,
  803. * which may be null.
  804. * Conditions:
  805. * Nothing locked.
  806. */
  807. ipc_space_t
  808. convert_port_to_space(
  809. ipc_port_t port)
  810. {
  811. ipc_space_t space = IS_NULL;
  812. if (IP_VALID(port)) {
  813. ip_lock(port);
  814. if (ip_active(port) &&
  815. (ip_kotype(port) == IKOT_TASK)) {
  816. space = ((task_t) port->ip_kobject)->itk_space;
  817. is_reference(space);
  818. }
  819. ip_unlock(port);
  820. }
  821. return space;
  822. }
  823. /*
  824. * Routine: convert_port_to_map
  825. * Purpose:
  826. * Convert from a port to a map.
  827. * Doesn't consume the port ref; produces a map ref,
  828. * which may be null.
  829. * Conditions:
  830. * Nothing locked.
  831. */
  832. #if 0
  833. vm_map_t
  834. convert_port_to_map(ipc_port_t port)
  835. {
  836. vm_map_t map = VM_MAP_NULL;
  837. if (IP_VALID(port)) {
  838. ip_lock(port);
  839. if (ip_active(port) &&
  840. (ip_kotype(port) == IKOT_TASK)) {
  841. map = ((task_t) port->ip_kobject)->map;
  842. vm_map_reference(map);
  843. }
  844. ip_unlock(port);
  845. }
  846. return map;
  847. }
  848. #endif
  849. /*
  850. * Routine: convert_port_to_thread
  851. * Purpose:
  852. * Convert from a port to a thread.
  853. * Doesn't consume the port ref; produces a thread ref,
  854. * which may be null.
  855. * Conditions:
  856. * Nothing locked.
  857. */
  858. #if 0
  859. thread_t
  860. convert_port_to_thread(ipc_port_t port)
  861. {
  862. thread_t thread = THREAD_NULL;
  863. if (IP_VALID(port)) {
  864. ip_lock(port);
  865. if (ip_active(port) &&
  866. (ip_kotype(port) == IKOT_THREAD)) {
  867. thread = (thread_t) port->ip_kobject;
  868. thread_reference(thread);
  869. }
  870. ip_unlock(port);
  871. }
  872. return thread;
  873. }
  874. /*
  875. * Routine: convert_task_to_port
  876. * Purpose:
  877. * Convert from a task to a port.
  878. * Consumes a task ref; produces a naked send right
  879. * which may be invalid.
  880. * Conditions:
  881. * Nothing locked.
  882. */
  883. ipc_port_t
  884. convert_task_to_port(task_t task)
  885. {
  886. ipc_port_t port;
  887. itk_lock(task);
  888. if (task->itk_self != IP_NULL)
  889. port = ipc_port_make_send(task->itk_self);
  890. else
  891. port = IP_NULL;
  892. itk_unlock(task);
  893. task_deallocate(task);
  894. return port;
  895. }
  896. #endif
  897. /*
  898. * Routine: convert_thread_to_port
  899. * Purpose:
  900. * Convert from a thread to a port.
  901. * Consumes a thread ref; produces a naked send right
  902. * which may be invalid.
  903. * Conditions:
  904. * Nothing locked.
  905. */
  906. #if 0
  907. ipc_port_t
  908. convert_thread_to_port(thread_t thread)
  909. {
  910. ipc_port_t port;
  911. ith_lock(thread);
  912. if (thread->ith_self != IP_NULL)
  913. port = ipc_port_make_send(thread->ith_self);
  914. else
  915. port = IP_NULL;
  916. ith_unlock(thread);
  917. thread_deallocate(thread);
  918. return port;
  919. }
  920. #endif
  921. /*
  922. * Routine: space_deallocate
  923. * Purpose:
  924. * Deallocate a space ref produced by convert_port_to_space.
  925. * Conditions:
  926. * Nothing locked.
  927. */
  928. void
  929. space_deallocate(ipc_space_t space)
  930. {
  931. if (space != IS_NULL)
  932. is_release(space);
  933. }
  934. void* gnumach_task_create(void)
  935. {
  936. task_t task = 0;
  937. (void) task_create_kernel(kernel_task, FALSE, &task);
  938. return (void*)task;
  939. }