]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/ipc/ipc_mqueue.h
xnu-6153.41.3.tar.gz
[apple/xnu.git] / osfmk / ipc / ipc_mqueue.h
index 140ce1dfdee887833e6a48ff4b7ef83263b12158..f982ba6771e9706e8e26e2846a6bbca5e8ecc2f9 100644 (file)
@@ -90,6 +90,9 @@ typedef struct ipc_mqueue {
                        mach_port_name_t        receiver_name;
                        uint16_t                msgcount;
                        uint16_t                qlimit;
+#ifdef __LP64__
+                       uint32_t                qcontext;
+#endif
 #if MACH_FLIPC
                        struct flipc_port       *fport; // Null for local port, or ptr to flipc port
 #endif
@@ -99,30 +102,32 @@ typedef struct ipc_mqueue {
                } pset;
        } data;
        union {
+               /*
+                * Port Sets:
+                *   only use imq_klist
+                *
+                * Special Reply Ports (ip_specialreply == true):
+                *   only use imq_srp_owner_thread
+                *
+                * Ports, based on ip_sync_link_state, use:
+                * - PORT_SYNC_LINK_ANY:            imq_klist
+                * - PORT_SYNC_LINK_WORKLOOP_KNOTE: imq_inheritor_knote
+                * - PORT_SYNC_LINK_WORKLOOP_STASH: imq_inheritor_turnstile
+                * - PORT_SYNC_LINK_RCV_THREAD: imq_inheritor_thread_ref
+                */
                struct klist imq_klist;
-               uintptr_t imq_inheritor;
+               struct knote *imq_inheritor_knote;
+               struct turnstile *imq_inheritor_turnstile;
+               thread_t imq_inheritor_thread_ref;
+               thread_t imq_srp_owner_thread;
        };
+#ifndef __LP64__
+       uint32_t qcontext;
+#endif
 } *ipc_mqueue_t;
 
 #define IMQ_NULL                ((ipc_mqueue_t) 0)
 
-/*
- * When a receive right is in flight, before it can ever be registered with
- * a new knote, its imq_klist field can be overloaded to hold a pointer
- * to the knote that the port is pushing on through his turnstile.
- *
- * if IMQ_KLIST_VALID() returns true, then the imq_klist field can be used,
- * else IMQ_INHERITOR() can be used to get the pointer to the knote currently
- * being the port turnstile inheritor.
- */
-#define IMQ_KLIST_VALID(imq) (((imq)->imq_inheritor & 1) == 0)
-#define IMQ_INHERITOR(imq) ((struct turnstile *)((imq)->imq_inheritor ^ 1))
-#define IMQ_SET_INHERITOR(imq, inheritor) \
-MACRO_BEGIN                                                                   \
-               assert(((imq)->imq_inheritor & 1) || SLIST_EMPTY(&(imq)->imq_klist)); \
-               ((imq)->imq_inheritor = (uintptr_t)(inheritor) | 1);                  \
-MACRO_END
-
 #define imq_wait_queue          data.port.waitq
 #define imq_messages            data.port.messages
 #define imq_msgcount            data.port.msgcount
@@ -133,6 +138,16 @@ MACRO_END
 #define imq_fport               data.port.fport
 #endif
 
+/*
+ * The qcontext structure member fills in a 32-bit padding gap in ipc_mqueue.
+ * However, the 32-bits are in slightly different places on 32 and 64 bit systems.
+ */
+#ifdef __LP64__
+#define imq_context             data.port.qcontext
+#else
+#define imq_context             qcontext
+#endif
+
 /*
  * we can use the 'eventmask' bits of the waitq b/c
  * they are only used by global queues
@@ -144,30 +159,28 @@ MACRO_END
 #define imq_set_queue           data.pset.setq
 #define imq_is_set(mq)          waitqs_is_set(&(mq)->imq_set_queue)
 #define imq_is_queue(mq)        waitq_is_queue(&(mq)->imq_wait_queue)
+#define imq_is_turnstile_proxy(mq) \
+               waitq_is_turnstile_proxy(&(mq)->imq_wait_queue)
 #define imq_is_valid(mq)        waitq_is_valid(&(mq)->imq_wait_queue)
 
-#define imq_lock(mq)            waitq_lock(&(mq)->imq_wait_queue)
-#define imq_lock_try(mq)        waitq_lock_try(&(mq)->imq_wait_queue)
 #define imq_unlock(mq)          waitq_unlock(&(mq)->imq_wait_queue)
 #define imq_held(mq)            waitq_held(&(mq)->imq_wait_queue)
 #define imq_valid(mq)           waitq_valid(&(mq)->imq_wait_queue)
 
+extern void imq_lock(ipc_mqueue_t mq);
+extern unsigned int imq_lock_try(ipc_mqueue_t mq);
+
 /*
  * Get an ipc_mqueue pointer from a waitq pointer. These are traditionally the
  * same pointer, but this conversion makes no assumptions on union structure
  * member positions - it should allow the waitq to move around in either the
  * port-set mqueue or the port mqueue independently.
  */
-#define imq_from_waitq(waitq)   (waitq_is_set(waitq) ? \
-                                       ((struct ipc_mqueue *)((void *)( \
-                                               (uintptr_t)(waitq) - \
-                                               __offsetof(struct ipc_mqueue, imq_set_queue)) \
-                                       )) : \
-                                       ((struct ipc_mqueue *)((void *)( \
-                                               (uintptr_t)(waitq) - \
-                                               __offsetof(struct ipc_mqueue, imq_wait_queue)) \
-                                       )) \
-                                )
+#define imq_from_waitq(waitq)  (waitq_is_set(waitq) ? \
+               __container_of(waitq, struct ipc_mqueue, imq_set_queue.wqset_q) : \
+               __container_of(waitq, struct ipc_mqueue, imq_wait_queue))
+
+#define imq_to_object(mq) ip_to_object(ip_from_mq(mq))
 
 extern void imq_reserve_and_lock(ipc_mqueue_t mq,
     uint64_t *reserved_prepost);
@@ -188,10 +201,16 @@ extern int ipc_mqueue_full;
  * Exported interfaces
  */
 
+__enum_closed_decl(ipc_mqueue_kind_t, int, {
+       IPC_MQUEUE_KIND_NONE,   /* this mqueue really isn't used */
+       IPC_MQUEUE_KIND_PORT,   /* this queue is a regular port queue */
+       IPC_MQUEUE_KIND_SET,    /* this queue is a portset queue */
+});
+
 /* Initialize a newly-allocated message queue */
 extern void ipc_mqueue_init(
        ipc_mqueue_t            mqueue,
-       boolean_t               is_set);
+       ipc_mqueue_kind_t       kind);
 
 /* de-initialize / cleanup an mqueue (specifically waitq resources) */
 extern void ipc_mqueue_deinit(