void ipc_mqueue_move( ipc_mqueue_t dest, ipc_mqueue_t source, const ipc_port_t port) { ipc_kmsg_queue_t oldq, newq; ipc_thread_queue_t blockedq; ipc_kmsg_t kmsg, next; ipc_thread_t th; oldq = &source->imq_messages; newq = &dest->imq_messages; blockedq = &dest->imq_threads; for (kmsg = ipc_kmsg_queue_first(oldq); kmsg != IKM_NULL; kmsg = next) { next = ipc_kmsg_queue_next(oldq, kmsg); /* only move messages sent to port */ if (kmsg->ikm_header.msgh_remote_port != (mach_port_t) port) continue; ipc_kmsg_rmqueue(oldq, kmsg); /* before adding kmsg to newq, check for a blocked receiver */ while ((th = ipc_thread_dequeue(blockedq)) != ITH_NULL) { assert(ipc_kmsg_queue_empty(newq)); thread_go(th); /* check if the receiver can handle the message */ if (kmsg->ikm_header.msgh_size <= th->ith_msize) { th->ith_state = MACH_MSG_SUCCESS; th->ith_kmsg = kmsg; th->ith_seqno = port->ip_seqno++; goto next_kmsg; } th->ith_state = MACH_RCV_TOO_LARGE; th->ith_msize = kmsg->ikm_header.msgh_size; } /* didn't find a receiver to handle the message */ ipc_kmsg_enqueue(newq, kmsg); next_kmsg:; } }
void ipc_mqueue_move( ipc_mqueue_t dest, ipc_mqueue_t source, ipc_port_t port) { ipc_kmsg_queue_t oldq, newq; ipc_thread_queue_t blockedq; ipc_kmsg_t kmsg, next; ipc_thread_t th; oldq = &source->imq_messages; newq = &dest->imq_messages; blockedq = &dest->imq_threads; for (kmsg = ipc_kmsg_queue_first(oldq); kmsg != IKM_NULL; kmsg = next) { next = ipc_kmsg_queue_next(oldq, kmsg); /* only move messages sent to port */ if (kmsg->ikm_header.msgh_remote_port != (mach_port_t) port) continue; ipc_kmsg_rmqueue(oldq, kmsg); /* before adding kmsg to newq, check for a blocked receiver */ if ((th = ipc_thread_dequeue(blockedq)) != ITH_NULL) { assert(ipc_kmsg_queue_empty(newq)); /* * Got a receiver. Hand the receiver the message * and process the next one. */ th->ith_state = MACH_MSG_SUCCESS; th->ith_kmsg = kmsg; th->ith_seqno = port->ip_seqno++; thread_go(th); } else { /* didn't find a receiver; enqueue the message */ ipc_kmsg_enqueue(newq, kmsg); } } }