diff options
-rw-r--r-- | doc/mach.texi | 19 | ||||
-rw-r--r-- | ipc/ipc_kmsg.c | 58 | ||||
-rw-r--r-- | ipc/mach_msg.c | 53 |
3 files changed, 104 insertions, 26 deletions
diff --git a/doc/mach.texi b/doc/mach.texi index b187888..c57e607 100644 --- a/doc/mach.texi +++ b/doc/mach.texi @@ -1949,6 +1949,25 @@ loses the receive right after the message was dequeued from it, then right still exists, but isn't held by the caller, then @code{msgh_local_port} specifies @code{MACH_PORT_NULL}. +Servers usually associate some state with a receive right. To that +end, they might use a hash table to look up the state for the port a +message was sent to. To optimize this, a task may associate an opaque +@var{payload} with a receive right using the +@code{mach_port_set_protected_payload} function. Once this is done, +the kernel will set the @code{msgh_protected_payload} field to +@var{payload} when delivering a message to this right and indicate +this by setting the local part of @code{msgh_bits} to +@code{MACH_MSG_TYPE_PROTECTED_PAYLOAD}. + +The support for protected payloads was added to GNU Mach. To preserve +binary compatibility, the @code{msgh_local_port} and +@code{msgh_local_port} share the same location. This makes it +possible to add the payload information without increasing the size of +@code{mach_msg_header_t}. This is an implementation detail. Which +field is valid is determined by the local part of the +@code{msgh_bits}. Existing software is not affected. When a receive +right is transferred to another task, its payload is cleared. + Received messages are stamped with a sequence number, taken from the port from which the message was received. (Messages received from a port set are stamped with a sequence number from the appropriate member diff --git a/ipc/ipc_kmsg.c b/ipc/ipc_kmsg.c index 06cec72..71a0d74 100644 --- a/ipc/ipc_kmsg.c +++ b/ipc/ipc_kmsg.c @@ -1799,9 +1799,17 @@ ipc_kmsg_copyout_header( } else ip_unlock(dest); - msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) | - MACH_MSGH_BITS(0, MACH_MSG_TYPE_PORT_SEND)); - msg->msgh_local_port = dest_name; + if (! ipc_port_flag_protected_payload(dest)) { + msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) | + MACH_MSGH_BITS(0, MACH_MSG_TYPE_PORT_SEND)); + msg->msgh_local_port = dest_name; + } else { + msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) | + MACH_MSGH_BITS( + 0, MACH_MSG_TYPE_PROTECTED_PAYLOAD)); + msg->msgh_protected_payload = + dest->ip_protected_payload; + } msg->msgh_remote_port = MACH_PORT_NULL; return MACH_MSG_SUCCESS; } @@ -1897,10 +1905,18 @@ ipc_kmsg_copyout_header( } else ip_unlock(dest); - msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) | - MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, - MACH_MSG_TYPE_PORT_SEND)); - msg->msgh_local_port = dest_name; + if (! ipc_port_flag_protected_payload(dest)) { + msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) | + MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, + MACH_MSG_TYPE_PORT_SEND)); + msg->msgh_local_port = dest_name; + } else { + msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) | + MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, + MACH_MSG_TYPE_PROTECTED_PAYLOAD)); + msg->msgh_protected_payload = + dest->ip_protected_payload; + } msg->msgh_remote_port = reply_name; return MACH_MSG_SUCCESS; } @@ -1932,9 +1948,18 @@ ipc_kmsg_copyout_header( dest_name = MACH_PORT_NULL; } - msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) | - MACH_MSGH_BITS(0, MACH_MSG_TYPE_PORT_SEND_ONCE)); - msg->msgh_local_port = dest_name; + if (! ipc_port_flag_protected_payload(dest)) { + msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) | + MACH_MSGH_BITS(0, + MACH_MSG_TYPE_PORT_SEND_ONCE)); + msg->msgh_local_port = dest_name; + } else { + msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) | + MACH_MSGH_BITS(0, + MACH_MSG_TYPE_PROTECTED_PAYLOAD)); + msg->msgh_protected_payload = + dest->ip_protected_payload; + } msg->msgh_remote_port = MACH_PORT_NULL; return MACH_MSG_SUCCESS; } @@ -2224,9 +2249,16 @@ ipc_kmsg_copyout_header( if (IP_VALID(reply)) ipc_port_release(reply); - msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) | - MACH_MSGH_BITS(reply_type, dest_type)); - msg->msgh_local_port = dest_name; + if (! ipc_port_flag_protected_payload(dest)) { + msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) | + MACH_MSGH_BITS(reply_type, dest_type)); + msg->msgh_local_port = dest_name; + } else { + msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) | + MACH_MSGH_BITS(reply_type, + MACH_MSG_TYPE_PROTECTED_PAYLOAD)); + msg->msgh_protected_payload = dest->ip_protected_payload; + } msg->msgh_remote_port = reply_name; } diff --git a/ipc/mach_msg.c b/ipc/mach_msg.c index 01d974b..1e122c7 100644 --- a/ipc/mach_msg.c +++ b/ipc/mach_msg.c @@ -1132,11 +1132,19 @@ mach_msg_trap( } else ip_unlock(dest_port); - kmsg->ikm_header.msgh_bits = - MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, - MACH_MSG_TYPE_PORT_SEND); + if (! ipc_port_flag_protected_payload(dest_port)) { + kmsg->ikm_header.msgh_bits = MACH_MSGH_BITS( + MACH_MSG_TYPE_PORT_SEND_ONCE, + MACH_MSG_TYPE_PORT_SEND); + kmsg->ikm_header.msgh_local_port = dest_name; + } else { + kmsg->ikm_header.msgh_bits = MACH_MSGH_BITS( + MACH_MSG_TYPE_PORT_SEND_ONCE, + MACH_MSG_TYPE_PROTECTED_PAYLOAD); + kmsg->ikm_header.msgh_protected_payload = + dest_port->ip_protected_payload; + } kmsg->ikm_header.msgh_remote_port = reply_name; - kmsg->ikm_header.msgh_local_port = dest_name; goto fast_put; abort_request_copyout: @@ -1170,11 +1178,19 @@ mach_msg_trap( dest_name = MACH_PORT_NULL; } - kmsg->ikm_header.msgh_bits = - MACH_MSGH_BITS(0, - MACH_MSG_TYPE_PORT_SEND_ONCE); + if (! ipc_port_flag_protected_payload(dest_port)) { + kmsg->ikm_header.msgh_bits = MACH_MSGH_BITS( + 0, + MACH_MSG_TYPE_PORT_SEND_ONCE); + kmsg->ikm_header.msgh_local_port = dest_name; + } else { + kmsg->ikm_header.msgh_bits = MACH_MSGH_BITS( + 0, + MACH_MSG_TYPE_PROTECTED_PAYLOAD); + kmsg->ikm_header.msgh_protected_payload = + dest_port->ip_protected_payload; + } kmsg->ikm_header.msgh_remote_port = MACH_PORT_NULL; - kmsg->ikm_header.msgh_local_port = dest_name; goto fast_put; } @@ -1204,12 +1220,23 @@ mach_msg_trap( dest_name = MACH_PORT_NULL; } - kmsg->ikm_header.msgh_bits = - MACH_MSGH_BITS_COMPLEX | - MACH_MSGH_BITS(0, - MACH_MSG_TYPE_PORT_SEND_ONCE); + if (! ipc_port_flag_protected_payload(dest_port)) { + kmsg->ikm_header.msgh_bits = + MACH_MSGH_BITS_COMPLEX + | MACH_MSGH_BITS( + 0, + MACH_MSG_TYPE_PORT_SEND_ONCE); + kmsg->ikm_header.msgh_local_port = dest_name; + } else { + kmsg->ikm_header.msgh_bits = + MACH_MSGH_BITS_COMPLEX + | MACH_MSGH_BITS( + 0, + MACH_MSG_TYPE_PROTECTED_PAYLOAD); + kmsg->ikm_header.msgh_protected_payload = + dest_port->ip_protected_payload; + } kmsg->ikm_header.msgh_remote_port = MACH_PORT_NULL; - kmsg->ikm_header.msgh_local_port = dest_name; mr = ipc_kmsg_copyout_body( (vm_offset_t) (&kmsg->ikm_header + 1), |