+
+ /*
+ * Set up to receive a message or the notification of a
+ * too large message. But never allow this call to wait.
+ * If the user provided aditional options, like trailer
+ * options, pass those through here. But we don't support
+ * scatter lists through this interface.
+ */
+ self->ith_object = (ipc_object_t)pset;
+ self->ith_msize = size;
+ self->ith_option = option;
+ self->ith_scatter_list_size = 0;
+ self->ith_receiver_name = MACH_PORT_NULL;
+ self->ith_continuation = NULL;
+ option |= MACH_RCV_TIMEOUT; // never wait
+ self->ith_state = MACH_RCV_IN_PROGRESS;
+
+ wresult = ipc_mqueue_receive_on_thread(
+ &pset->ips_messages,
+ option,
+ size, /* max_size */
+ 0, /* immediate timeout */
+ THREAD_INTERRUPTIBLE,
+ self);
+ assert(wresult == THREAD_NOT_WAITING);
+ assert(self->ith_state != MACH_RCV_IN_PROGRESS);
+
+ /*
+ * If we timed out, just release the reference on the
+ * portset and return zero.
+ */
+ if (self->ith_state == MACH_RCV_TIMED_OUT) {
+ ips_release(pset);
+ return 0;
+ }
+
+ /*
+ * If we weren't attempting to receive a message
+ * directly, we need to return the port name in
+ * the kevent structure.
+ */
+ if ((option & MACH_RCV_MSG) != MACH_RCV_MSG) {
+ assert(self->ith_state == MACH_RCV_TOO_LARGE);
+ assert(self->ith_kmsg == IKM_NULL);
+ kn->kn_data = self->ith_receiver_name;
+ ips_release(pset);
+ return 1;
+ }
+
+ /*
+ * Attempt to receive the message directly, returning
+ * the results in the fflags field.
+ */
+ assert(option & MACH_RCV_MSG);
+ kn->kn_ext[1] = self->ith_msize;
+ kn->kn_data = MACH_PORT_NULL;
+ kn->kn_fflags = mach_msg_receive_results();
+ /* kmsg and pset reference consumed */
+
+ /*
+ * if the user asked for the identity of ports containing a
+ * a too-large message, return it in the data field (as we
+ * do for messages we didn't try to receive).
+ */
+ if ((kn->kn_fflags == MACH_RCV_TOO_LARGE) &&
+ (option & MACH_RCV_LARGE_IDENTITY))
+ kn->kn_data = self->ith_receiver_name;
+
+ return 1;
+}
+
+static void
+filt_machporttouch(struct knote *kn, struct kevent64_s *kev, long type)
+{
+ switch (type) {
+ case EVENT_REGISTER:
+ kn->kn_sfflags = kev->fflags;
+ kn->kn_sdata = kev->data;
+ kn->kn_ext[0] = kev->ext[0];
+ kn->kn_ext[1] = kev->ext[1];
+ break;
+ case EVENT_PROCESS:
+ *kev = kn->kn_kevent;
+ if (kn->kn_flags & EV_CLEAR) {
+ kn->kn_data = 0;
+ kn->kn_fflags = 0;
+ }
+ break;
+ default:
+ panic("filt_machporttouch() - invalid type (%ld)", type);
+ break;
+ }