ipc_notify.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. /*
  2. * Mach Operating System
  3. * Copyright (c) 1991,1990,1989 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/ipc_notify.c
  28. * Author: Rich Draves
  29. * Date: 1989
  30. *
  31. * Notification-sending functions.
  32. */
  33. #pragma GCC diagnostic error "-Wundef"
  34. #include <glue/gnulinux.h>
  35. #include <kern/printf.h>
  36. #include <mach/port.h>
  37. #include <mach/message.h>
  38. #include <mach/notify.h>
  39. #include <kern/assert.h>
  40. #include <ipc/ipc_kmsg.h>
  41. #include <ipc/ipc_mqueue.h>
  42. #include <ipc/ipc_notify.h>
  43. #include <ipc/ipc_port.h>
  44. #include <ipc/ipc_machdep.h>
  45. mach_port_deleted_notification_t ipc_notify_port_deleted_template;
  46. mach_msg_accepted_notification_t ipc_notify_msg_accepted_template;
  47. mach_port_destroyed_notification_t ipc_notify_port_destroyed_template;
  48. mach_no_senders_notification_t ipc_notify_no_senders_template;
  49. mach_send_once_notification_t ipc_notify_send_once_template;
  50. mach_dead_name_notification_t ipc_notify_dead_name_template;
  51. #define NOTIFY_MSGH_SEQNO 0
  52. /*
  53. * Routine: ipc_notify_init_port_deleted
  54. * Purpose:
  55. * Initialize a template for port-deleted notifications.
  56. */
  57. void
  58. ipc_notify_init_port_deleted(mach_port_deleted_notification_t *n)
  59. {
  60. mach_msg_header_t *m = &n->not_header;
  61. mach_msg_type_t *t = &n->not_type;
  62. m->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0);
  63. m->msgh_size = sizeof *n;
  64. m->msgh_seqno = NOTIFY_MSGH_SEQNO;
  65. m->msgh_local_port = MACH_PORT_NULL;
  66. m->msgh_remote_port = MACH_PORT_NULL;
  67. m->msgh_id = MACH_NOTIFY_PORT_DELETED;
  68. t->msgt_name = MACH_MSG_TYPE_PORT_NAME;
  69. t->msgt_size = PORT_T_SIZE_IN_BITS;
  70. t->msgt_number = 1;
  71. t->msgt_inline = TRUE;
  72. t->msgt_longform = FALSE;
  73. t->msgt_deallocate = FALSE;
  74. t->msgt_unused = 0;
  75. n->not_port = MACH_PORT_NULL;
  76. }
  77. /*
  78. * Routine: ipc_notify_init_msg_accepted
  79. * Purpose:
  80. * Initialize a template for msg-accepted notifications.
  81. */
  82. void
  83. ipc_notify_init_msg_accepted(mach_msg_accepted_notification_t *n)
  84. {
  85. mach_msg_header_t *m = &n->not_header;
  86. mach_msg_type_t *t = &n->not_type;
  87. m->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0);
  88. m->msgh_size = sizeof *n;
  89. m->msgh_seqno = NOTIFY_MSGH_SEQNO;
  90. m->msgh_local_port = MACH_PORT_NULL;
  91. m->msgh_remote_port = MACH_PORT_NULL;
  92. m->msgh_id = MACH_NOTIFY_MSG_ACCEPTED;
  93. t->msgt_name = MACH_MSG_TYPE_PORT_NAME;
  94. t->msgt_size = PORT_T_SIZE_IN_BITS;
  95. t->msgt_number = 1;
  96. t->msgt_inline = TRUE;
  97. t->msgt_longform = FALSE;
  98. t->msgt_deallocate = FALSE;
  99. t->msgt_unused = 0;
  100. n->not_port = MACH_PORT_NULL;
  101. }
  102. /*
  103. * Routine: ipc_notify_init_port_destroyed
  104. * Purpose:
  105. * Initialize a template for port-destroyed notifications.
  106. */
  107. void
  108. ipc_notify_init_port_destroyed(mach_port_destroyed_notification_t *n)
  109. {
  110. mach_msg_header_t *m = &n->not_header;
  111. mach_msg_type_t *t = &n->not_type;
  112. m->msgh_bits = MACH_MSGH_BITS_COMPLEX |
  113. MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0);
  114. m->msgh_size = sizeof *n;
  115. m->msgh_seqno = NOTIFY_MSGH_SEQNO;
  116. m->msgh_local_port = MACH_PORT_NULL;
  117. m->msgh_remote_port = MACH_PORT_NULL;
  118. m->msgh_id = MACH_NOTIFY_PORT_DESTROYED;
  119. t->msgt_name = MACH_MSG_TYPE_PORT_RECEIVE;
  120. t->msgt_size = PORT_T_SIZE_IN_BITS;
  121. t->msgt_number = 1;
  122. t->msgt_inline = TRUE;
  123. t->msgt_longform = FALSE;
  124. t->msgt_deallocate = FALSE;
  125. t->msgt_unused = 0;
  126. n->not_port = MACH_PORT_NULL;
  127. }
  128. /*
  129. * Routine: ipc_notify_init_no_senders
  130. * Purpose:
  131. * Initialize a template for no-senders notifications.
  132. */
  133. void
  134. ipc_notify_init_no_senders(
  135. mach_no_senders_notification_t *n)
  136. {
  137. mach_msg_header_t *m = &n->not_header;
  138. mach_msg_type_t *t = &n->not_type;
  139. m->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0);
  140. m->msgh_size = sizeof *n;
  141. m->msgh_seqno = NOTIFY_MSGH_SEQNO;
  142. m->msgh_local_port = MACH_PORT_NULL;
  143. m->msgh_remote_port = MACH_PORT_NULL;
  144. m->msgh_id = MACH_NOTIFY_NO_SENDERS;
  145. t->msgt_name = MACH_MSG_TYPE_INTEGER_32;
  146. t->msgt_size = PORT_T_SIZE_IN_BITS;
  147. t->msgt_number = 1;
  148. t->msgt_inline = TRUE;
  149. t->msgt_longform = FALSE;
  150. t->msgt_deallocate = FALSE;
  151. t->msgt_unused = 0;
  152. n->not_count = 0;
  153. }
  154. /*
  155. * Routine: ipc_notify_init_send_once
  156. * Purpose:
  157. * Initialize a template for send-once notifications.
  158. */
  159. void
  160. ipc_notify_init_send_once(
  161. mach_send_once_notification_t *n)
  162. {
  163. mach_msg_header_t *m = &n->not_header;
  164. m->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0);
  165. m->msgh_size = sizeof *n;
  166. m->msgh_seqno = NOTIFY_MSGH_SEQNO;
  167. m->msgh_local_port = MACH_PORT_NULL;
  168. m->msgh_remote_port = MACH_PORT_NULL;
  169. m->msgh_id = MACH_NOTIFY_SEND_ONCE;
  170. }
  171. /*
  172. * Routine: ipc_notify_init_dead_name
  173. * Purpose:
  174. * Initialize a template for dead-name notifications.
  175. */
  176. void
  177. ipc_notify_init_dead_name(
  178. mach_dead_name_notification_t *n)
  179. {
  180. mach_msg_header_t *m = &n->not_header;
  181. mach_msg_type_t *t = &n->not_type;
  182. m->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0);
  183. m->msgh_size = sizeof *n;
  184. m->msgh_seqno = NOTIFY_MSGH_SEQNO;
  185. m->msgh_local_port = MACH_PORT_NULL;
  186. m->msgh_remote_port = MACH_PORT_NULL;
  187. m->msgh_id = MACH_NOTIFY_DEAD_NAME;
  188. t->msgt_name = MACH_MSG_TYPE_PORT_NAME;
  189. t->msgt_size = PORT_T_SIZE_IN_BITS;
  190. t->msgt_number = 1;
  191. t->msgt_inline = TRUE;
  192. t->msgt_longform = FALSE;
  193. t->msgt_deallocate = FALSE;
  194. t->msgt_unused = 0;
  195. n->not_port = MACH_PORT_NULL;
  196. }
  197. /*
  198. * Routine: ipc_notify_init
  199. * Purpose:
  200. * Initialize the notification subsystem.
  201. */
  202. void
  203. ipc_notify_init(void)
  204. {
  205. ipc_notify_init_port_deleted(&ipc_notify_port_deleted_template);
  206. ipc_notify_init_msg_accepted(&ipc_notify_msg_accepted_template);
  207. ipc_notify_init_port_destroyed(&ipc_notify_port_destroyed_template);
  208. ipc_notify_init_no_senders(&ipc_notify_no_senders_template);
  209. ipc_notify_init_send_once(&ipc_notify_send_once_template);
  210. ipc_notify_init_dead_name(&ipc_notify_dead_name_template);
  211. }
  212. /*
  213. * Routine: ipc_notify_port_deleted
  214. * Purpose:
  215. * Send a port-deleted notification.
  216. * Conditions:
  217. * Nothing locked.
  218. * Consumes a ref/soright for port.
  219. */
  220. void
  221. ipc_notify_port_deleted(
  222. ipc_port_t port,
  223. mach_port_t name)
  224. {
  225. ipc_kmsg_t kmsg;
  226. mach_port_deleted_notification_t *n;
  227. kmsg = ikm_alloc(sizeof *n);
  228. if (kmsg == IKM_NULL) {
  229. printf("dropped port-deleted (0x%p, 0x%lx)\n", port, name);
  230. ipc_port_release_sonce(port);
  231. return;
  232. }
  233. ikm_init(kmsg, sizeof *n);
  234. n = (mach_port_deleted_notification_t *) &kmsg->ikm_header;
  235. *n = ipc_notify_port_deleted_template;
  236. n->not_header.msgh_remote_port = (mach_port_t) port;
  237. n->not_port = name;
  238. ipc_mqueue_send_always(kmsg);
  239. }
  240. /*
  241. * Routine: ipc_notify_msg_accepted
  242. * Purpose:
  243. * Send a msg-accepted notification.
  244. * Conditions:
  245. * Nothing locked.
  246. * Consumes a ref/soright for port.
  247. */
  248. void
  249. ipc_notify_msg_accepted(
  250. ipc_port_t port,
  251. mach_port_t name)
  252. {
  253. ipc_kmsg_t kmsg;
  254. mach_msg_accepted_notification_t *n;
  255. kmsg = ikm_alloc(sizeof *n);
  256. if (kmsg == IKM_NULL) {
  257. printf("dropped msg-accepted (0x%p, 0x%lx)\n", port, name);
  258. ipc_port_release_sonce(port);
  259. return;
  260. }
  261. ikm_init(kmsg, sizeof *n);
  262. n = (mach_msg_accepted_notification_t *) &kmsg->ikm_header;
  263. *n = ipc_notify_msg_accepted_template;
  264. n->not_header.msgh_remote_port = (mach_port_t) port;
  265. n->not_port = name;
  266. ipc_mqueue_send_always(kmsg);
  267. }
  268. /*
  269. * Routine: ipc_notify_port_destroyed
  270. * Purpose:
  271. * Send a port-destroyed notification.
  272. * Conditions:
  273. * Nothing locked.
  274. * Consumes a ref/soright for port.
  275. * Consumes a ref for right, which should be a receive right
  276. * prepped for placement into a message. (In-transit,
  277. * or in-limbo if a circularity was detected.)
  278. */
  279. void
  280. ipc_notify_port_destroyed(
  281. ipc_port_t port,
  282. ipc_port_t right)
  283. {
  284. ipc_kmsg_t kmsg;
  285. mach_port_destroyed_notification_t *n;
  286. kmsg = ikm_alloc(sizeof *n);
  287. if (kmsg == IKM_NULL) {
  288. printf("dropped port-destroyed (0x%p, 0x%p)\n",
  289. port, right);
  290. ipc_port_release_sonce(port);
  291. ipc_port_release_receive(right);
  292. return;
  293. }
  294. ikm_init(kmsg, sizeof *n);
  295. n = (mach_port_destroyed_notification_t *) &kmsg->ikm_header;
  296. *n = ipc_notify_port_destroyed_template;
  297. n->not_header.msgh_remote_port = (mach_port_t) port;
  298. n->not_port = (mach_port_t) right;
  299. ipc_mqueue_send_always(kmsg);
  300. }
  301. /*
  302. * Routine: ipc_notify_no_senders
  303. * Purpose:
  304. * Send a no-senders notification.
  305. * Conditions:
  306. * Nothing locked.
  307. * Consumes a ref/soright for port.
  308. */
  309. void
  310. ipc_notify_no_senders(
  311. ipc_port_t port,
  312. mach_port_mscount_t mscount)
  313. {
  314. ipc_kmsg_t kmsg;
  315. mach_no_senders_notification_t *n;
  316. kmsg = ikm_alloc(sizeof *n);
  317. if (kmsg == IKM_NULL) {
  318. printf("dropped no-senders (0x%p, %u)\n", port, mscount);
  319. ipc_port_release_sonce(port);
  320. return;
  321. }
  322. ikm_init(kmsg, sizeof *n);
  323. n = (mach_no_senders_notification_t *) &kmsg->ikm_header;
  324. *n = ipc_notify_no_senders_template;
  325. n->not_header.msgh_remote_port = (mach_port_t) port;
  326. n->not_count = mscount;
  327. ipc_mqueue_send_always(kmsg);
  328. }
  329. /*
  330. * Routine: ipc_notify_send_once
  331. * Purpose:
  332. * Send a send-once notification.
  333. * Conditions:
  334. * Nothing locked.
  335. * Consumes a ref/soright for port.
  336. */
  337. void
  338. ipc_notify_send_once(ipc_port_t port)
  339. {
  340. ipc_kmsg_t kmsg;
  341. mach_send_once_notification_t *n;
  342. kmsg = ikm_alloc(sizeof *n);
  343. if (kmsg == IKM_NULL) {
  344. printf("dropped send-once (0x%p)\n", port);
  345. ipc_port_release_sonce(port);
  346. return;
  347. }
  348. ikm_init(kmsg, sizeof *n);
  349. n = (mach_send_once_notification_t *) &kmsg->ikm_header;
  350. *n = ipc_notify_send_once_template;
  351. n->not_header.msgh_remote_port = (mach_port_t) port;
  352. ipc_mqueue_send_always(kmsg);
  353. }
  354. /*
  355. * Routine: ipc_notify_dead_name
  356. * Purpose:
  357. * Send a dead-name notification.
  358. * Conditions:
  359. * Nothing locked.
  360. * Consumes a ref/soright for port.
  361. */
  362. void
  363. ipc_notify_dead_name(
  364. ipc_port_t port,
  365. mach_port_t name)
  366. {
  367. ipc_kmsg_t kmsg;
  368. mach_dead_name_notification_t *n;
  369. kmsg = ikm_alloc(sizeof *n);
  370. if (kmsg == IKM_NULL) {
  371. printf("dropped dead-name (0x%p, 0x%lx)\n", port, name);
  372. ipc_port_release_sonce(port);
  373. return;
  374. }
  375. ikm_init(kmsg, sizeof *n);
  376. n = (mach_dead_name_notification_t *) &kmsg->ikm_header;
  377. *n = ipc_notify_dead_name_template;
  378. n->not_header.msgh_remote_port = (mach_port_t) port;
  379. n->not_port = name;
  380. ipc_mqueue_send_always(kmsg);
  381. }