mach_msg.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. /*
  2. * Mach Operating System
  3. * Copyright (c) 1991,1990,1989 Carnegie Mellon University.
  4. * Copyright (c) 1993,1994 The University of Utah and
  5. * the Computer Systems Laboratory (CSL).
  6. * All rights reserved.
  7. *
  8. * Permission to use, copy, modify and distribute this software and its
  9. * documentation is hereby granted, provided that both the copyright
  10. * notice and this permission notice appear in all copies of the
  11. * software, derivative works or modified versions, and any portions
  12. * thereof, and that both notices appear in supporting documentation.
  13. *
  14. * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF
  15. * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
  16. * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
  17. * THIS SOFTWARE.
  18. *
  19. * Carnegie Mellon requests users of this software to return to
  20. *
  21. * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
  22. * School of Computer Science
  23. * Carnegie Mellon University
  24. * Pittsburgh PA 15213-3890
  25. *
  26. * any improvements or extensions that they make and grant Carnegie Mellon
  27. * the rights to redistribute these changes.
  28. */
  29. /*
  30. */
  31. /*
  32. * File: ipc/mach_msg.c
  33. * Author: Rich Draves
  34. * Date: 1989
  35. *
  36. * Exported message traps. See mach/message.h.
  37. */
  38. #include <glue/gnulinux.h>
  39. #include <linux/printk.h>
  40. #include <mach/kern_return.h>
  41. #include <mach/port.h>
  42. #include <mach/message.h>
  43. #include <kern/assert.h>
  44. #include <kern/counters.h>
  45. #include <kern/debug.h>
  46. #include <kern/lock.h>
  47. #include <kern/printf.h>
  48. #include <kern/sched_prim.h>
  49. #include <kern/ipc_sched.h>
  50. #include <kern/exception.h>
  51. #include <vm/vm_map.h>
  52. #include <ipc/ipc_kmsg.h>
  53. #include <ipc/ipc_marequest.h>
  54. #include <ipc/ipc_mqueue.h>
  55. #include <ipc/ipc_object.h>
  56. #include <ipc/ipc_notify.h>
  57. #include <ipc/ipc_port.h>
  58. #include <ipc/ipc_pset.h>
  59. #include <ipc/ipc_space.h>
  60. #include <ipc/ipc_thread.h>
  61. #include <ipc/ipc_entry.h>
  62. #include <ipc/mach_msg.h>
  63. #include <glue/locore.h>
  64. #define thread_syscall_return(ret) return ret
  65. /*
  66. * Routine: mach_msg_send
  67. * Purpose:
  68. * Send a message.
  69. * Conditions:
  70. * Nothing locked.
  71. * Returns:
  72. * MACH_MSG_SUCCESS Sent the message.
  73. * MACH_SEND_MSG_TOO_SMALL Message smaller than a header.
  74. * MACH_SEND_NO_BUFFER Couldn't allocate buffer.
  75. * MACH_SEND_INVALID_DATA Couldn't copy message data.
  76. * MACH_SEND_INVALID_HEADER
  77. * Illegal value in the message header bits.
  78. * MACH_SEND_INVALID_DEST The space is dead.
  79. * MACH_SEND_INVALID_NOTIFY Bad notify port.
  80. * MACH_SEND_INVALID_DEST Can't copyin destination port.
  81. * MACH_SEND_INVALID_REPLY Can't copyin reply port.
  82. * MACH_SEND_TIMED_OUT Timeout expired without delivery.
  83. * MACH_SEND_INTERRUPTED Delivery interrupted.
  84. * MACH_SEND_NO_NOTIFY Can't allocate a msg-accepted request.
  85. * MACH_SEND_WILL_NOTIFY Msg-accepted notif. requested.
  86. * MACH_SEND_NOTIFY_IN_PROGRESS
  87. * This space has already forced a message to this port.
  88. */
  89. mach_msg_return_t
  90. mach_msg_send(
  91. mach_msg_header_t *msg,
  92. mach_msg_option_t option,
  93. mach_msg_size_t send_size,
  94. mach_msg_timeout_t time_out,
  95. mach_port_t notify)
  96. {
  97. ipc_space_t space = current_space();
  98. vm_map_t map = current_map();
  99. ipc_kmsg_t kmsg;
  100. mach_msg_return_t mr;
  101. mr = ipc_kmsg_get(msg, send_size, &kmsg);
  102. if (mr != MACH_MSG_SUCCESS)
  103. return mr;
  104. if (option & MACH_SEND_CANCEL) {
  105. if (notify == MACH_PORT_NULL)
  106. mr = MACH_SEND_INVALID_NOTIFY;
  107. else
  108. mr = ipc_kmsg_copyin(kmsg, space, map, notify);
  109. } else
  110. mr = ipc_kmsg_copyin(kmsg, space, map, MACH_PORT_NULL);
  111. if (mr != MACH_MSG_SUCCESS) {
  112. ikm_free(kmsg);
  113. return mr;
  114. }
  115. if (option & MACH_SEND_NOTIFY) {
  116. mr = ipc_mqueue_send(kmsg, MACH_SEND_TIMEOUT,
  117. ((option & MACH_SEND_TIMEOUT) ?
  118. time_out : MACH_MSG_TIMEOUT_NONE));
  119. if (mr == MACH_SEND_TIMED_OUT) {
  120. ipc_port_t dest = (ipc_port_t)
  121. kmsg->ikm_header.msgh_remote_port;
  122. if (notify == MACH_PORT_NULL)
  123. mr = MACH_SEND_INVALID_NOTIFY;
  124. else
  125. mr = ipc_marequest_create(space, dest,
  126. notify, &kmsg->ikm_marequest);
  127. if (mr == MACH_MSG_SUCCESS) {
  128. ipc_mqueue_send_always(kmsg);
  129. return MACH_SEND_WILL_NOTIFY;
  130. }
  131. }
  132. } else
  133. mr = ipc_mqueue_send(kmsg, option & MACH_SEND_TIMEOUT,
  134. time_out);
  135. if (mr != MACH_MSG_SUCCESS) {
  136. mr |= ipc_kmsg_copyout_pseudo(kmsg, space, map);
  137. assert(kmsg->ikm_marequest == IMAR_NULL);
  138. (void) ipc_kmsg_put(msg, kmsg, kmsg->ikm_header.msgh_size);
  139. }
  140. return mr;
  141. }
  142. /*
  143. * Routine: mach_msg_receive
  144. * Purpose:
  145. * Receive a message.
  146. * Conditions:
  147. * Nothing locked.
  148. * Returns:
  149. * MACH_MSG_SUCCESS Received a message.
  150. * MACH_RCV_INVALID_NAME The name doesn't denote a right,
  151. * or the denoted right is not receive or port set.
  152. * MACH_RCV_IN_SET Receive right is a member of a set.
  153. * MACH_RCV_TOO_LARGE Message wouldn't fit into buffer.
  154. * MACH_RCV_TIMED_OUT Timeout expired without a message.
  155. * MACH_RCV_INTERRUPTED Reception interrupted.
  156. * MACH_RCV_PORT_DIED Port/set died while receiving.
  157. * MACH_RCV_PORT_CHANGED Port moved into set while receiving.
  158. * MACH_RCV_INVALID_DATA Couldn't copy to user buffer.
  159. * MACH_RCV_INVALID_NOTIFY Bad notify port.
  160. * MACH_RCV_HEADER_ERROR
  161. */
  162. mach_msg_return_t
  163. mach_msg_receive(
  164. mach_msg_header_t *msg,
  165. mach_msg_option_t option,
  166. mach_msg_size_t rcv_size,
  167. mach_port_t rcv_name,
  168. mach_msg_timeout_t time_out,
  169. mach_port_t notify)
  170. {
  171. ipc_thread_t self = current_thread();
  172. ipc_space_t space = current_space();
  173. vm_map_t map = current_map();
  174. ipc_object_t object;
  175. ipc_mqueue_t mqueue;
  176. ipc_kmsg_t kmsg;
  177. mach_port_seqno_t seqno;
  178. mach_msg_return_t mr;
  179. mr = ipc_mqueue_copyin(space, rcv_name, &mqueue, &object);
  180. if (mr != MACH_MSG_SUCCESS)
  181. return mr;
  182. /* hold ref for object; mqueue is locked */
  183. /*
  184. * ipc_mqueue_receive may not return, because if we block
  185. * then our kernel stack may be discarded. So we save
  186. * state here for mach_msg_receive_continue to pick up.
  187. */
  188. self->ith_msg = msg;
  189. self->ith_option = option;
  190. self->ith_rcv_size = rcv_size;
  191. self->ith_timeout = time_out;
  192. self->ith_notify = notify;
  193. self->ith_object = object;
  194. self->ith_mqueue = mqueue;
  195. if (option & MACH_RCV_LARGE) {
  196. mr = ipc_mqueue_receive(mqueue, option & MACH_RCV_TIMEOUT,
  197. rcv_size, time_out,
  198. FALSE, mach_msg_receive_continue,
  199. &kmsg, &seqno);
  200. /* mqueue is unlocked */
  201. ipc_object_release(object);
  202. if (mr != MACH_MSG_SUCCESS) {
  203. if (mr == MACH_RCV_TOO_LARGE) {
  204. mach_msg_size_t real_size =
  205. (mach_msg_size_t) (vm_offset_t) kmsg;
  206. assert(real_size > rcv_size);
  207. (void) copyout(&real_size,
  208. &msg->msgh_size,
  209. sizeof(mach_msg_size_t));
  210. }
  211. return mr;
  212. }
  213. kmsg->ikm_header.msgh_seqno = seqno;
  214. assert(kmsg->ikm_header.msgh_size <= rcv_size);
  215. } else {
  216. mr = ipc_mqueue_receive(mqueue, option & MACH_RCV_TIMEOUT,
  217. MACH_MSG_SIZE_MAX, time_out,
  218. FALSE, mach_msg_receive_continue,
  219. &kmsg, &seqno);
  220. /* mqueue is unlocked */
  221. ipc_object_release(object);
  222. if (mr != MACH_MSG_SUCCESS)
  223. return mr;
  224. kmsg->ikm_header.msgh_seqno = seqno;
  225. if (kmsg->ikm_header.msgh_size > rcv_size) {
  226. ipc_kmsg_copyout_dest(kmsg, space);
  227. (void) ipc_kmsg_put(msg, kmsg, sizeof *msg);
  228. return MACH_RCV_TOO_LARGE;
  229. }
  230. }
  231. if (option & MACH_RCV_NOTIFY) {
  232. if (notify == MACH_PORT_NULL)
  233. mr = MACH_RCV_INVALID_NOTIFY;
  234. else
  235. mr = ipc_kmsg_copyout(kmsg, space, map, notify);
  236. } else
  237. mr = ipc_kmsg_copyout(kmsg, space, map, MACH_PORT_NULL);
  238. if (mr != MACH_MSG_SUCCESS) {
  239. if ((mr &~ MACH_MSG_MASK) == MACH_RCV_BODY_ERROR) {
  240. (void) ipc_kmsg_put(msg, kmsg,
  241. kmsg->ikm_header.msgh_size);
  242. } else {
  243. ipc_kmsg_copyout_dest(kmsg, space);
  244. (void) ipc_kmsg_put(msg, kmsg, sizeof *msg);
  245. }
  246. return mr;
  247. }
  248. return ipc_kmsg_put(msg, kmsg, kmsg->ikm_header.msgh_size);
  249. }
  250. /*
  251. * Routine: mach_msg_receive_continue
  252. * Purpose:
  253. * Continue after blocking for a message.
  254. * Conditions:
  255. * Nothing locked. We are running on a new kernel stack,
  256. * with the receive state saved in the thread. From here
  257. * control goes back to user space.
  258. */
  259. void
  260. mach_msg_receive_continue(void)
  261. {
  262. ipc_thread_t self = current_thread();
  263. ipc_space_t space = current_space();
  264. vm_map_t map = current_map();
  265. mach_msg_header_t *msg = self->ith_msg;
  266. mach_msg_option_t option = self->ith_option;
  267. mach_msg_size_t rcv_size = self->ith_rcv_size;
  268. mach_msg_timeout_t time_out = self->ith_timeout;
  269. mach_port_t notify = self->ith_notify;
  270. ipc_object_t object = self->ith_object;
  271. ipc_mqueue_t mqueue = self->ith_mqueue;
  272. ipc_kmsg_t kmsg;
  273. mach_port_seqno_t seqno;
  274. mach_msg_return_t mr;
  275. if (option & MACH_RCV_LARGE) {
  276. mr = ipc_mqueue_receive(mqueue, option & MACH_RCV_TIMEOUT,
  277. rcv_size, time_out,
  278. TRUE, mach_msg_receive_continue,
  279. &kmsg, &seqno);
  280. /* mqueue is unlocked */
  281. ipc_object_release(object);
  282. if (mr != MACH_MSG_SUCCESS) {
  283. if (mr == MACH_RCV_TOO_LARGE) {
  284. mach_msg_size_t real_size =
  285. (mach_msg_size_t) (vm_offset_t) kmsg;
  286. assert(real_size > rcv_size);
  287. (void) copyout(&real_size,
  288. &msg->msgh_size,
  289. sizeof(mach_msg_size_t));
  290. }
  291. thread_syscall_return(mr);
  292. /*NOTREACHED*/
  293. }
  294. kmsg->ikm_header.msgh_seqno = seqno;
  295. assert(kmsg->ikm_header.msgh_size <= rcv_size);
  296. } else {
  297. mr = ipc_mqueue_receive(mqueue, option & MACH_RCV_TIMEOUT,
  298. MACH_MSG_SIZE_MAX, time_out,
  299. TRUE, mach_msg_receive_continue,
  300. &kmsg, &seqno);
  301. /* mqueue is unlocked */
  302. ipc_object_release(object);
  303. if (mr != MACH_MSG_SUCCESS) {
  304. thread_syscall_return(mr);
  305. /*NOTREACHED*/
  306. }
  307. kmsg->ikm_header.msgh_seqno = seqno;
  308. if (kmsg->ikm_header.msgh_size > rcv_size) {
  309. ipc_kmsg_copyout_dest(kmsg, space);
  310. (void) ipc_kmsg_put(msg, kmsg, sizeof *msg);
  311. thread_syscall_return(MACH_RCV_TOO_LARGE);
  312. /*NOTREACHED*/
  313. }
  314. }
  315. if (option & MACH_RCV_NOTIFY) {
  316. if (notify == MACH_PORT_NULL)
  317. mr = MACH_RCV_INVALID_NOTIFY;
  318. else
  319. mr = ipc_kmsg_copyout(kmsg, space, map, notify);
  320. } else
  321. mr = ipc_kmsg_copyout(kmsg, space, map, MACH_PORT_NULL);
  322. if (mr != MACH_MSG_SUCCESS) {
  323. if ((mr &~ MACH_MSG_MASK) == MACH_RCV_BODY_ERROR) {
  324. (void) ipc_kmsg_put(msg, kmsg,
  325. kmsg->ikm_header.msgh_size);
  326. } else {
  327. ipc_kmsg_copyout_dest(kmsg, space);
  328. (void) ipc_kmsg_put(msg, kmsg, sizeof *msg);
  329. }
  330. thread_syscall_return(mr);
  331. /*NOTREACHED*/
  332. }
  333. mr = ipc_kmsg_put(msg, kmsg, kmsg->ikm_header.msgh_size);
  334. thread_syscall_return(mr);
  335. /*NOTREACHED*/
  336. }
  337. /*
  338. * Routine: mach_msg_trap [mach trap]
  339. * Purpose:
  340. * Possibly send a message; possibly receive a message.
  341. * Conditions:
  342. * Nothing locked.
  343. * Returns:
  344. * All of mach_msg_send and mach_msg_receive error codes.
  345. */
  346. mach_msg_return_t
  347. mach_msg_trap(
  348. mach_msg_header_t *msg,
  349. mach_msg_option_t option,
  350. mach_msg_size_t send_size,
  351. mach_msg_size_t rcv_size,
  352. mach_port_t rcv_name,
  353. mach_msg_timeout_t time_out,
  354. mach_port_t notify)
  355. {
  356. mach_msg_return_t mr;
  357. if (option & MACH_SEND_MSG) {
  358. printk(KERN_ERR "option & MACH_SEND_MSG\n");
  359. ipc_space_t space = current_space();
  360. vm_map_t map = current_map();
  361. ipc_kmsg_t kmsg;
  362. mr = ipc_kmsg_get(msg, send_size, &kmsg);
  363. if (mr != MACH_MSG_SUCCESS)
  364. return mr;
  365. mr = ipc_kmsg_copyin(kmsg, space, map, MACH_PORT_NULL);
  366. if (mr != MACH_MSG_SUCCESS) {
  367. ikm_free(kmsg);
  368. return mr;
  369. }
  370. mr = ipc_mqueue_send(kmsg, MACH_MSG_OPTION_NONE,
  371. MACH_MSG_TIMEOUT_NONE);
  372. if (mr != MACH_MSG_SUCCESS) {
  373. mr |= ipc_kmsg_copyout_pseudo(kmsg, space, map);
  374. assert(kmsg->ikm_marequest == IMAR_NULL);
  375. (void) ipc_kmsg_put(msg, kmsg,
  376. kmsg->ikm_header.msgh_size);
  377. return mr;
  378. }
  379. }
  380. if (option & MACH_RCV_MSG) {
  381. printk(KERN_ERR "option & MACH_SEND_MSG\n");
  382. ipc_thread_t self = current_thread();
  383. ipc_space_t space = current_space();
  384. vm_map_t map = current_map();
  385. ipc_object_t object;
  386. ipc_mqueue_t mqueue;
  387. ipc_kmsg_t kmsg;
  388. mach_port_seqno_t seqno;
  389. mr = ipc_mqueue_copyin(space, rcv_name, &mqueue, &object);
  390. if (mr != MACH_MSG_SUCCESS)
  391. return mr;
  392. //printk(KERN_DEBUG "ipc_mqueue_copyin\n");
  393. /* hold ref for object; mqueue is locked */
  394. /*
  395. * ipc_mqueue_receive may not return, because if we block
  396. * then our kernel stack may be discarded. So we save
  397. * state here for mach_msg_continue to pick up.
  398. */
  399. self->ith_msg = msg;
  400. self->ith_rcv_size = rcv_size;
  401. self->ith_object = object;
  402. self->ith_mqueue = mqueue;
  403. mr = ipc_mqueue_receive(mqueue,
  404. MACH_MSG_OPTION_NONE,
  405. MACH_MSG_SIZE_MAX,
  406. MACH_MSG_TIMEOUT_NONE,
  407. FALSE, mach_msg_continue,
  408. &kmsg, &seqno);
  409. /* mqueue is unlocked */
  410. ipc_object_release(object);
  411. if (mr != MACH_MSG_SUCCESS)
  412. return mr;
  413. kmsg->ikm_header.msgh_seqno = seqno;
  414. if (rcv_size < kmsg->ikm_header.msgh_size) {
  415. ipc_kmsg_copyout_dest(kmsg, space);
  416. (void) ipc_kmsg_put(msg, kmsg, sizeof *msg);
  417. return MACH_RCV_TOO_LARGE;
  418. }
  419. mr = ipc_kmsg_copyout(kmsg, space, map, MACH_PORT_NULL);
  420. if (mr != MACH_MSG_SUCCESS) {
  421. if ((mr &~ MACH_MSG_MASK) == MACH_RCV_BODY_ERROR) {
  422. (void) ipc_kmsg_put(msg, kmsg,
  423. kmsg->ikm_header.msgh_size);
  424. } else {
  425. ipc_kmsg_copyout_dest(kmsg, space);
  426. (void) ipc_kmsg_put(msg, kmsg, sizeof *msg);
  427. }
  428. return mr;
  429. }
  430. ipc_kmsg_put(msg, kmsg, kmsg->ikm_header.msgh_size);
  431. }
  432. return MACH_MSG_SUCCESS;
  433. }
  434. /*
  435. * Routine: mach_msg_continue
  436. * Purpose:
  437. * Continue after blocking for a message.
  438. * Conditions:
  439. * Nothing locked. We are running on a new kernel stack,
  440. * with the receive state saved in the thread. From here
  441. * control goes back to user space.
  442. */
  443. void
  444. mach_msg_continue(void)
  445. {
  446. ipc_thread_t thread = current_thread();
  447. task_t task = thread->task;
  448. ipc_space_t space = task->itk_space;
  449. vm_map_t map = task->map;
  450. mach_msg_header_t *msg = thread->ith_msg;
  451. mach_msg_size_t rcv_size = thread->ith_rcv_size;
  452. ipc_object_t object = thread->ith_object;
  453. ipc_mqueue_t mqueue = thread->ith_mqueue;
  454. ipc_kmsg_t kmsg;
  455. mach_port_seqno_t seqno;
  456. mach_msg_return_t mr;
  457. mr = ipc_mqueue_receive(mqueue, MACH_MSG_OPTION_NONE,
  458. MACH_MSG_SIZE_MAX, MACH_MSG_TIMEOUT_NONE,
  459. TRUE, mach_msg_continue, &kmsg, &seqno);
  460. /* mqueue is unlocked */
  461. ipc_object_release(object);
  462. if (mr != MACH_MSG_SUCCESS) {
  463. thread_syscall_return(mr);
  464. /*NOTREACHED*/
  465. }
  466. kmsg->ikm_header.msgh_seqno = seqno;
  467. if (kmsg->ikm_header.msgh_size > rcv_size) {
  468. ipc_kmsg_copyout_dest(kmsg, space);
  469. (void) ipc_kmsg_put(msg, kmsg, sizeof *msg);
  470. thread_syscall_return(MACH_RCV_TOO_LARGE);
  471. /*NOTREACHED*/
  472. }
  473. mr = ipc_kmsg_copyout(kmsg, space, map, MACH_PORT_NULL);
  474. if (mr != MACH_MSG_SUCCESS) {
  475. if ((mr &~ MACH_MSG_MASK) == MACH_RCV_BODY_ERROR) {
  476. (void) ipc_kmsg_put(msg, kmsg,
  477. kmsg->ikm_header.msgh_size);
  478. } else {
  479. ipc_kmsg_copyout_dest(kmsg, space);
  480. (void) ipc_kmsg_put(msg, kmsg, sizeof *msg);
  481. }
  482. thread_syscall_return(mr);
  483. /*NOTREACHED*/
  484. }
  485. mr = ipc_kmsg_put(msg, kmsg, kmsg->ikm_header.msgh_size);
  486. thread_syscall_return(mr);
  487. /*NOTREACHED*/
  488. }
  489. #if 0
  490. /*
  491. * Routine: mach_msg_interrupt
  492. * Purpose:
  493. * Attempts to force a thread waiting at mach_msg_continue or
  494. * mach_msg_receive_continue into a clean point. Returns TRUE
  495. * if this was possible.
  496. * Conditions:
  497. * Nothing locked. The thread must NOT be runnable.
  498. */
  499. boolean_t
  500. mach_msg_interrupt(thread_t thread)
  501. {
  502. ipc_mqueue_t mqueue;
  503. assert((thread->swap_func == (void (*)()) mach_msg_continue) ||
  504. (thread->swap_func == (void (*)()) mach_msg_receive_continue));
  505. mqueue = thread->ith_mqueue;
  506. imq_lock(mqueue);
  507. if (thread->ith_state != MACH_RCV_IN_PROGRESS) {
  508. /*
  509. * The thread is no longer waiting for a message.
  510. * It may have a message sitting in ith_kmsg.
  511. * We can't clean this up.
  512. */
  513. imq_unlock(mqueue);
  514. return FALSE;
  515. }
  516. ipc_thread_rmqueue(&mqueue->imq_threads, thread);
  517. imq_unlock(mqueue);
  518. ipc_object_release(thread->ith_object);
  519. thread_set_syscall_return(thread, MACH_RCV_INTERRUPTED);
  520. thread->swap_func = thread_exception_return;
  521. return TRUE;
  522. }
  523. #endif