Formerly ../hurd/hurd.h.~50~
authorroland <roland>
Tue, 7 Dec 1993 00:09:11 +0000 (00:09 +0000)
committerroland <roland>
Tue, 7 Dec 1993 00:09:11 +0000 (00:09 +0000)
hurd/hurd.h

index 7a45991..bf8e762 100644 (file)
@@ -520,6 +520,51 @@ extern void _hurd_msgport_receive (void);
 /* Mask of signals that cannot be caught, blocked, or ignored.  */
 #define        _SIG_CANT_MASK  (__sigmask (SIGSTOP) | __sigmask (SIGKILL))
 
+/* Do an RPC to a process's message port.
+
+   Each argument is an expression which returns an error code; each
+   expression may be evaluated several times.  FETCH_MSGPORT_EXPR should
+   fetch the appropriate message port and store it in the local variable
+   `msgport'.  FETCH_REFPORT_EXPR should fetch the appropriate message port
+   and store it in the local variable `refport' (if no reference port is
+   needed in the call, then FETCH_REFPORT_EXPR should be simply
+   KERN_SUCCESS or 0).  Both of these are assumed to create user
+   references, which this macro deallocates.  RPC_EXPR should perform the
+   desired RPC operation using `msgport' and `refport'.
+
+   The reason for the complexity is that a process's message port and
+   reference port may change between fetching those ports and completing an
+   RPC using them (usually they change only when a process execs).  The RPC
+   will fail with MACH_SEND_INVALID_DEST if the msgport dies before we can
+   send the RPC request; or with MIG_SERVER_DIED if the msgport was
+   destroyed after we sent the RPC request but before it was serviced.  In
+   either of these cases, we retry the entire operation, discarding the old
+   message and reference ports and fetch them anew.  */
+
+#define _HURD_MSGPORT_RPC(fetch_msgport_expr, fetch_refport_expr, rpc_expr)   \
+({                                                                           \
+    error_t __err;                                                           \
+    mach_port_t msgport, refport = MACH_PORT_NULL;                           \
+    do                                                                       \
+      {                                                                              \
+       /* Get the message port.  */                                          \
+       if (__err = (fetch_msgport_expr))                                     \
+         break;                                                              \
+       /* Get the reference port.  */                                        \
+       if (__err = (fetch_refport_expr))                                     \
+         {                                                                   \
+           /* Couldn't get it; deallocate MSGPORT and fail.  */              \
+           mach_port_deallocate (__mach_task_self (), msgport);              \
+           break;                                                            \
+         }                                                                   \
+       __err = (rpc_expr);                                                   \
+       mach_port_deallocate (__mach_task_self (), msgport);                  \
+       if (refport != MACH_PORT_NULL)                                        \
+         mach_port_deallocate (__mach_task_self (), refport);                \
+      } while (__err != MACH_SEND_INVALID_DEST &&                            \
+              __err != MIG_SERVER_DIED);                                     \
+    __err;                                                                   \
+})
 \f
 
 /* Calls to get and set basic ports.  */