- wait_queue_peek64_locked(waitq, IPC_MQUEUE_RECEIVE, &receiver, &waitq);
- /* queue still locked, thread locked - but still on q */
-
- if (receiver == THREAD_NULL) {
- abort_send_receive:
- imq_unlock(dest_mqueue);
- splx(s);
- ip_unlock(dest_port);
- ipc_object_release(rcv_object);
- HOT(c_mmot_cold_032++);
- goto slow_send;
- }
-
- assert(receiver->wait_queue == waitq);
- assert(receiver->wait_event == IPC_MQUEUE_RECEIVE);
-
- /*
- * See if it is still running on another processor (trying to
- * block itself). If so, fall off.
- *
- * JMM - We have an opportunity here. Since the thread is locked
- * and we find it runnable, it must still be trying to get into
- * thread_block on itself. We could just "hand him the message"
- * and let him go (thread_go_locked()) and then fall down into a
- * slow receive for ourselves. Only his RECEIVE_TOO_LARGE handling
- * runs afoul of that. Clean this up!
- */
- if ((receiver->state & (TH_RUN|TH_WAIT)) != TH_WAIT) {
- assert(NCPUS > 1);
- HOT(c_mmot_cold_033++);
- fall_off:
- thread_unlock(receiver);
- if (waitq != &dest_mqueue->imq_wait_queue)
- wait_queue_unlock(waitq);
- goto abort_send_receive;
- }
-
- /*
- * Check that the receiver can stay on the hot path.
- */
- if (send_size + REQUESTED_TRAILER_SIZE(receiver->ith_option) >
- receiver->ith_msize) {
- /*
- * The receiver can't accept the message.
- */
- HOT(c_mmot_bad_rcvr++);
- goto fall_off;
- }
-
-#if THREAD_SWAPPER
- /*
- * Receiver looks okay -- is it swapped in?
- */
- rcv_act = receiver->top_act;
- if (rcv_act->swap_state != TH_SW_IN &&
- rcv_act->swap_state != TH_SW_UNSWAPPABLE) {
- HOT(c_mmot_rcvr_swapped++);
- goto fall_off;
- }
-
- /*
- * Make sure receiver stays swapped in (if we can).
- */
- if (!act_lock_try(rcv_act)) { /* out of order! */
- HOT(c_mmot_rcvr_locked++);
- goto fall_off;
- }
-
- /*
- * Check for task swapping in progress affecting
- * receiver. Since rcv_act is attached to a shuttle,
- * its swap_state is covered by shuttle's thread_lock()
- * (sigh).
- */
- if ((rcv_act->swap_state != TH_SW_IN &&
- rcv_act->swap_state != TH_SW_UNSWAPPABLE) ||
- rcv_act->ast & AST_SWAPOUT) {
- act_unlock(rcv_act);
- HOT(c_mmot_rcvr_tswapped++);
- goto fall_off;