mach_msg.html   [plain text]


<h2>mach_msg</h2>
<hr>
<p>
<strong>System Trap</strong> / <strong>Function</strong> - Send and/or receive a message from the target port.
<h3>SYNOPSIS</h3>
<pre>
<strong>mach_msg_return_t   mach_msg</strong>
                    <strong>(mach_msg_header_t</strong>                <var>msg</var>,
                     <strong>mach_msg_option_t</strong>             <var>option</var>,
                     <strong>mach_msg_size_t</strong>            <var>send_size</var>,
                     <strong>mach_msg_size_t</strong>        <var>receive_limit</var>,
                     <strong>mach_port_t</strong>             <var>receive_name</var>,
                     <strong>mach_msg_timeout_t</strong>           <var>timeout</var>,
                     <strong>mach_port_t</strong>                   <var>notify</var><strong>);</strong>

<strong>mach_msg_return_t   mach_msg_overwrite</strong>
                    <strong>(mach_msg_header_t*</strong>          <var>send_msg</var>,
                     <strong>mach_msg_option_t</strong>             <var>option</var>,
                     <strong>mach_msg_size_t</strong>            <var>send_size</var>,
                     <strong>mach_msg_size_t</strong>        <var>receive_limit</var>,
                     <strong>mach_port_t</strong>             <var>receive_name</var>,
                     <strong>mach_msg_timeout_t</strong>           <var>timeout</var>,
                     <strong>mach_port_t</strong>                   <var>notify</var>,
                     <strong>mach_msg_header_t</strong>       <var>*receive_msg</var>,
                     <strong>mach_msg_size_t</strong>     <var>receive_msg_size</var><strong>);</strong>
</pre>
<h3>PARAMETERS</h3>
<dl>
<p>
<dt> <var>msg</var>
<dd>
[pointer to in/out structure containing random and reply rights] A
message buffer used by <strong>mach_msg</strong> both for send and receive. This must
be naturally aligned.
<p>
<dt> <var>send_msg</var>
<dd>
[pointer to in structure containing random and reply rights] The mes-
sage buffer to be sent. This must be naturally aligned.
<p>
<dt> <var>option</var>
<dd>
[in scalar] Message options are bit values, combined with bitwise-or.
One or both of MACH_SEND_MSG and MACH_RCV_MSG should be used. Other
options act as modifiers.
<p>
<dt> <var>send_size</var>
<dd>
[in scalar] When sending a message, specifies the size of the message
buffer to be sent (the size of the header and body) in
bytes. Otherwise zero should be supplied.
<p>
<dt> <var>receive_limit</var>
<dd>
[in scalar] When receiving a message, specifies the maximum size of
the msg or receive_msg buffer in bytes. Otherwise zero should be sup-
plied.
<p>
<dt> <var>receive_name</var>
<dd>
[in random right] When receiving a message, specifies the port or port
set. Otherwise MACH_PORT_NULL should be supplied.
<p>
<dt> <var>timeout</var>
<dd>
[in scalar] When using the MACH_SEND_TIMEOUT and MACH_RCV_TIMEOUT
options, specifies the time in milliseconds to wait before giving
up. Otherwise MACH_MSG_TIMEOUT_NONE should be supplied.
<p>
<dt> <var>notify</var>
<dd>
[in notify receive right] When using the MACH_SEND_CANCEL and
MACH_RCV_NOTIFY options, specifies the port used for the
notification. Otherwise MACH_PORT_NULL should be supplied.
<p>
<dt> <var>receive_msg</var>
<dd>
[pointer to in/out structure] A message buffer into which a message
(header and body) will be received. This must be naturally aligned. By
default (<strong>mach_msg</strong>), any received message will overwrite the send
message buffer. This buffer is in/out only if the MACH_RCV_OVERWRITE
option is used; otherwise this buffer is out only.
<p>
<dt> <var>receive_msg_size</var>
<dd>
[in scalar] When using the MACH_RCV_OVERWRITE option, specifies the
size (in bytes) of the receive "message" that is to be used by
<strong>mach_msg</strong> to indicate the disposition of received out-of-line regions.
</dl>
<h3>DESCRIPTION</h3>
<p>
The <strong>mach_msg</strong> system call sends and receives Mach messages. Mach
messages contain data, which can include port rights and addresses of
large regions of memory. <strong>mach_msg</strong> uses the same buffer for sending and
receiving a message; the other calls permit separate send and receive
buffers (although they may be specified to be the same).
If the option argument contains MACH_SEND_MSG, the call sends a
message.  The <var>send_size</var> argument specifies the size of the message
buffer (header and body) to send. The msgh_remote_port field of the
message header specifies the destination of the message.
If the option argument contains MACH_RCV_MSG, it receives a
message. The receive_limit argument specifies the size of a buffer
that will receive the message; messages that are larger are not
received. The receive_name argument specifies the port or port set
from which to receive.
<p>
If the option argument contains both MACH_SEND_MSG and MACH_RCV_MSG,
then <strong>mach_msg</strong> does both send and receive operations (in that
order). If the send operation encounters an error (any return code
other than MACH_MSG_SUCCESS), the call returns immediately
without attempting the receive operation. Semantically the combined
call is equivalent to separate send and receive calls, but it saves
a system call and enables other internal optimizations.

If the option argument specifies neither MACH_SEND_MSG nor
MACH_RCV_MSG, <strong>mach_msg</strong> does nothing.
Some options, like MACH_SEND_TIMEOUT and MACH_RCV_TIMEOUT, share a
supporting argument. If these options are used together, they make
independent use of the supporting argument's value.
<h3>NOTES</h3>
<p>
The Mach kernel provides message-oriented, capability-based
inter-process communication. The inter-process communication (IPC)
primitives efficiently support many different styles of interaction,
including remote procedure calls, object-oriented distributed
programming, streaming of data, and sending very large amounts of
data.
<h4>Major Concepts</h4>
<p>
The IPC primitives operate on three abstractions: messages, ports, and
port sets.  User tasks access all other kernel services and
abstractions via the IPC primitives.
<p>
The message primitives let tasks send and receive messages. Tasks send
messages to ports. Messages sent to a port are delivered reliably
(messages may not be lost) and are received in the order in which they
were sent via send rights by a given sending task (or a given
kernel). (Messages sent to send-once rights are unordered.)
<p>
Messages
contain a fixed-size header and a variable-sized message body
containing kernel and user data, and a variable-size trailer of kernel
appended message attributes. The header describes the destination
and the size of the message (header plus body). The message body
contains descriptions of additional port rights to be transmitted,
descriptions of "out-of-line" memory regions to be sent and a
variable amount of user data, which typically includes type conversion
information. The out-of-line memory regions (including out-of-line
port arrays) are (typically) disjoint from the message body.
The IPC implementation makes use of the VM system to efficiently
transfer large amounts of data. The message can contain the addresses
of regions of the sender's address space which should be transferred
as part of the message.
<p>
When a task receives a message containing
such out-of-line regions of data, the data can appear in unused
portions or overwrite an existing portion of the receiver's address
space (depending on the requested receive options). Under favorable
circumstances, the transmission of out-of-line data is optimized so
that sender and receiver share the physical pages of data
copy-on-write, and no actual data copy occurs unless the pages are
written. Regions of memory up to 4 gigabytes may be sent in this
manner.
<p>
Ports hold a queue of messages. Tasks operate on a port to send and
receive messages by exercising capabilities (rights) for the
port. Multiple tasks can hold send rights for a port.
Tasks can also
hold send-once rights, which grant the ability to send a single
message. Only one task can hold the receive capability (receive
right) for a port.
<p>
Port rights can be transferred between tasks via
messages. The sender of a message can specify in the message that the
message contains a port right. If a message contains a receive right
for a port, the receive right is removed from the sender of the
message and transferred to the receiver of the
message. While the receive right is in transit, tasks holding send
rights can still send messages to the port, and they are queued until
a task acquires the receive right and uses it to receive the messages.
<p>
Tasks can receive messages from ports and port sets. The port set
abstraction allows a single thread to wait for a message from any of
several ports. Tasks manipulate port sets with a port set name,
which is taken from the same name space as are the port rights. The
port-set name may not be transferred in a message. A port set holds
receive rights, and a receive operation on a port set blocks waiting
for a message sent to any of the constituent ports. A port may not be-
long to more than one port set, and if a port is a member of a port
set, the holder of the receive right can't receive directly from the
port.
<p>
Port rights are a secure, location-independent way of naming
ports. The port queue is a protected data structure, only accessible
via the kernel's exported message primitives. Rights are also
protected by the kernel; there is no way for a malicious user task to
guess a port's internal name and send a message to a port to which it
shouldn't have access. Port rights do not carry any location in-
formation. When a receive right for a port moves from task to task,
and even between tasks on different machines, the send rights for
the port remain unchanged and continue to function.
<h4>Port Rights</h4>
<p>
Each task has its own space of port rights. Port rights are named with
positive (unsigned) integers. For all architectures, sizeof
(mach_port_t) = sizeof (mach_port_name_t) = sizeof (void*) and so user
space addresses may be used as port names, except for the reserved
values MACH_PORT_NULL (0) and MACH_PORT_DEAD (all 1 bits). When the
kernel chooses a name for a new right, however, it is free to pick any
unused name (one which denotes no right) in the space.
<p>
There are three basic kinds of rights: receive rights, send rights and
send-once rights. A port name can name any of these types of rights,
or name a port-set, be a dead name, or name nothing. Dead names are
not capabilities. They act as place-holders to prevent a name from
being otherwise used.
<p>
A port is destroyed, or dies, when its receive right is
de-allocated. When a port dies, send and send-once rights for the port
turn into dead names. Any messages queued at the port are destroyed,
which de-allocates the port rights and out-of-line memory in the
messages.
<p>
Each send-once right held by a task has a different name. In contrast,
when a task holds send rights or a receive right for a port, the
rights share a single name.
<p>
Tasks may hold multiple user-references for send rights. When a task
receives a send right which it already holds, the kernel increments
the right's user-reference count. When a task de-allocates a send
right, the kernel decrements its user-reference count, and the task
only loses the send right when the count goes to zero.
<p>
Send-once rights always have a user reference count of one. Tasks may
hold multiple user references for dead names.
Each send-once right generated guarantees the receipt of a single
message, either a message sent to that send-once right or, if the
send-once right is in any way destroyed, a send-once notification.
<p>
A message can carry port rights; the msgh_remote or msgh_local fields
in the message header or the disposition field in a message body
descriptor specify the type of port right and how the port right is to
be extracted from the caller. The values MACH_PORT_NULL and
MACH_PORT_DEAD are valid in place of a port right in a message body.
<p>
In a sent message, the following mach_msg_type_name_t values denote
port rights:
<dl>
<dt> MACH_MSG_TYPE_MAKE_SEND
     <dd>
The message will carry a send right, but the caller must supply a
receive right. The send right is created from the receive right, and the
receive right's make-send count is incremented.
<dt> MACH_MSG_TYPE_COPY_SEND
     <dd>
The message will carry a send right, and the caller must supply a send 
right. The user reference count for the supplied send right is not 
changed. The caller may also supply a dead name and the receiving 
task will get MACH_PORT_DEAD.
<dt> MACH_MSG_TYPE_MOVE_SEND
     <dd>
The message will carry a send right, and the caller must supply a send
right. The user reference count for the supplied send right is
decremented, and the right is destroyed if the count becomes
zero. Unless a receive right remains, the name becomes available for
recycling. The caller may also supply a dead name, which loses a user
reference, and the receiving task will get MACH_PORT_DEAD.
<dt> MACH_MSG_TYPE_MAKE_SEND_ONCE
<dd>
The message will carry a send-once right, but the caller must supply a
receive right. The send-once right is created from the receive right.
Note that send once rights can only be created from the receive right.
<dt> MACH_MSG_TYPE_MOVE_SEND_ONCE
     <dd>
The message will carry a send-once right, and the caller must supply a
send-once right. The caller loses the supplied send-once right. The
caller may also supply a dead name, which loses a user reference,
and the receiving task will get MACH_PORT_DEAD.
<dt> MACH_MSG_TYPE_MOVE_RECEIVE
     <dd>
The message will carry a receive right, and the caller must supply a
receive right. The caller loses the supplied receive right, but
retains any send rights with the same name. The make-send count and
sequence number of the receive right are reset to zero and
no-more-senders notification requests are cancelled (with a
send-once notification being sent to the no-more-senders notification
right), but the port retains other attributes like queued messages
and extant send and send-once rights.
If a message carries a send or send-once right, and the port dies
while the message is in transit, then the receiving task will get
MACH_PORT_DEAD instead of a right.
	  </dl>
	  <p>
The following mach_msg_type_name_t values in a received message
indicate that it carries port rights:
	  <dl>
<dt> MACH_MSG_TYPE_PORT_SEND
     <dd>
This value is an alias for MACH_MSG_TYPE_MOVE_SEND. The 
message carried a send right. If the receiving task already has send and/
or receive rights for the port, then that name for the port will be reused. 
Otherwise, the right will have a new, previously unused, name. If the 
task already has send rights, it gains a user reference for the right (un-
less this would cause the user-reference count to overflow). Otherwise, 
it acquires send rights, with a user-reference count of one.
<dt> MACH_MSG_TYPE_PORT_SEND_ONCE
     <dd>
This value is an alias for MACH_MSG_TYPE_MOVE_SEND_ONCE. The message
carried a send-once right. The right will have a new, previously
unused, name.
<dt> MACH_MSG_TYPE_PORT_RECEIVE
     <dd>
This value is an alias for MACH_MSG_TYPE_MOVE_RECEIVE.  The message
carried a receive right. If the receiving task already has send rights
for the port, then that name for the port will be reused; otherwise,
the right will have a new, previously unused name.
	  </dl>
	  <p>
It is also possible to send a (nearly unbounded) array of port rights
"out-of-line". All of the rights named by the array must be of the
same type. The array is physically copied with the message body
proper. The array of port right (names) can be received by the
receiver using the same options available for out-of-line data
reception described below.
<h4>Memory</h4>
	  <p>
A message can contain one or more regions of the sender's address
space which are to be transferred as part of the message. The message
carries a logical copy of the memory. For this "out-of-line" memory,
the kernel can copy the data or use virtual memory techniques to defer
any actual page copies unless the sender or the receiver modifies
the data, the physical pages remain shared.
<p>
	  The sender of the message must explicitly request an out-of-line
transfer. Such a region is described as an arbitrary region of the
sender's address space. The sender always sees this memory as being
copied to the receiver.
<p>
	  For each region, the sender has a de-allocate option. If the option is
set and the out-of-line memory region is not null, then the region is
implicitly de-allocated from the sender, as if by vm_deallocate. In
particular, the start address is truncated down and the end address
rounded up so that every page overlapped by the memory region is
de-allocated (thereby possibly de-allocating more memory than is
effectively transmitted). The use of this option effectively changes
the memory copy to a memory movement. Aside from possibly optimizing
the sender's use of memory, the de-allocation option allows the kernel
to more efficiently handle the transfer of memory.
	  <p>
For each region, the sender has the choice of permitting the kernel to
choose a transmission strategy or the choice of requiring physical
copy:
	  <dl>
<dt> MACH_MSG_VIRTUAL_COPY
     <dd>
In a sent message, this flag allows the kernel to choose any mechanism
to transmit the data. For large regions, this involves constructing a
virtual copy of the pages containing the region. The portion of the
first page preceding the data and the portion of the last page
following the data are not copied (and will appear as zero if the
virtual copy is dynamically allocated in the receiver).
	  <p>
In a received message, this flag indicates that the kernel transmitted
a virtual copy. Access to the received memory may involve interactions
with the memory manager managing the sender's original data. Integri-
ty-conscious receivers should exercise caution when dealing with out-
of-line memory from un-trustworthy sources. Receivers concerned about
deterministic access time should also exercise caution. The dynamic
allocation option guarantees that the virtual copy will not be di-
rectly referenced during the act of receiving the message.
<dt> MACH_MSG_PHYSICAL_COPY
     <dd>
In a sent message, this flag requires that the kernel construct an
actual copy of the memory (either into wired kernel memory or default
memory managed space). There is a (fairly large) limit on the amount
of data that can be physically copied in a message. Port arrays always
assume this option when sent.
	  <p>
In a received message, this flag indicates that the kernel did
transmit a physical copy.
	  </dl>
	  <p>
The receiver has two options for the reception of out-of-line memory
(or "out-of-line" port arrays): allocation and overwrite.
In the absence of the MACH_RCV_OVERWRITE option, all out-of-line re-
gions are dynamically allocated. Allocated out-of-line memory arrives
somewhere in the receiver's address space as new memory. It has the
same inheritance and protection attributes as newly vm_allocate'ed
memory. The receiver has the responsibility of de-allocating (with
vm_deallocate) the memory when it is no longer needed. If the message
contains more than one region, each will be allocated its own region,
not necessarily contiguously. If the sender's data was transmitted as
a virtual copy the allocated region will have the same data alignment
within the page; otherwise, the received data will appear starting at
the beginning of a page.
	  <p>
If the MACH_RCV_OVERWRITE option is set, the receiver can specify how
each received region is to be processed (dynamically allocated as
described above, or written over existing memory). With this option,
the contents of the receive buffer (receive_msg) are examined by the
kernel. The kernel scans the descriptors in the receive buffer
"message" to determine how to handle each out-of-line region. (Note:
whereas receive_limit is the maximum size of the receive buffer,
receive_msg_size is the amount filled in with this "message".) The
kernel uses each out-of-line data descriptor (in order) to specify
the processing for each received data region in turn, each out-of-line
port array descriptor is used correspondingly. (Intermingled port
descriptors are ignored when matching descriptors between the
incoming message and the receive buffer list.)
<p>
The copy option in the
matching descriptor specifies the processing:
	  <dl>
<dt> MACH_MSG_OVERWRITE
     <dd>
This flag indicates that the region should write over a specified
region of the receiver's address space, as indicated by the address
and size/ count fields of the descriptor. The full range overwritten
must already exist (be allocated or mapped) in the receiver's address
space. Depending on the nature of the data transmission this
overwrite may involve virtual memory manipulations or it may involve
actual data copy.
<dt> MACH_MSG_ALLOCATE
     <dd>
This flag indicates that the region is to be dynamically allocated. No
other descriptor values are relevant.
	  </dl>
	  <p>
If not enough descriptors appear in the receive buffer to describe all
received regions, additional regions are dynamically allocated. If
the receiver specifies more descriptors than there are regions in the
received message, the additional descriptors are ignored (and do not
appear in the final received message).
	  <p>
Note that the receive buffer descriptors will be overwritten:
The size fields in descriptors will be updated (when scanned, they
specified the maximum sizes of regions, when received, they specify
the actual sizes of received regions).
The copy fields in descriptors will be updated (when scanned, they
specified allocate versus overwrite, when received, they indicate
whether the region was physically or virtually copied).
The descriptors may appear in different positions (given intermingled
port descriptors).
Descriptors that were not used (because there were not that many
received regions) will be discarded.
	  <p>
Null out-of-line memory is legal. If the out-of-line region size is
zero, then the region's specified address is ignored. A receive
allocated null out-of-line memory region always has a zero address.
Unaligned addresses and region sizes that are not page multiples are
legal. A received message can also contain regions with unaligned
addresses and sizes which are not multiples of the page size.
<h4>Message Send</h4>
	  <p>
The send operation queues a message to a port. The message carries a
copy of the caller's data. After the send, the caller can freely
modify the message buffer or the out-of-line memory regions and the
message contents will remain unchanged.
	  	  <p>
The message carries with it the security ID of the sender, which the
receiver can request in the message trailer.
	  	  <p>
Message delivery is reliable and sequenced. Reception of a message
guarantees that all messages previously sent to the port by a single
task (or a single kernel) via send rights have been received and that
they are received in the order in which they were sent. Messages sent
to send-once rights are unordered.
	  <p>
If the destination port's queue is full, several things can happen. If
the message is sent to a send-once right (msgh_remote_port carries a
send-once right), then the kernel ignores the queue limit and delivers
the message. Otherwise the caller blocks until there is room in the
queue, unless the MACH_SEND_TIMEOUT option is used. If a port has
several blocked senders, then any of them may queue the next message
when space in the queue becomes available, with the proviso that a
blocked sender will not be indefinitely starved.
These options modify MACH_SEND_MSG. If MACH_SEND_MSG is not also
specified, they are ignored.
<dl>
<dt> MACH_SEND_TIMEOUT
     <dd>
The timeout argument should specify a maximum time (in milliseconds)
for the call to block before giving up. If the message can't be queued
before the timeout interval elapses, then the call returns
MACH_SEND_TIMED_OUT. A zero timeout is legitimate.
<dt> MACH_SEND_INTERRUPT
     <dd>
If specified, the <strong>mach_msg</strong> call will return 
MACH_SEND_INTERRUPTED if a software interrupt aborts the call. 
Otherwise, the send operation will be retried.
<dt> MACH_SEND_TRAILER
     <dd>
If set, the kernel, instead of determining the message attributes
itself, will accept a formatted message trailer from the sender. The
supplied trailer must be of the latest version supported by the
kernel, and must contain all message attributes defined by the
kernel. Only tasks with a security ID of KERNEL_SECURITY_ID can use
this option; the intended use of this option is in support of the
Net Message server. The trailer must follow the message in memory as
it would appear in a received message. (The send_size argument to
<strong>mach_msg</strong> still indicates the size of the message proper, not including
this trailer.)
	  </dl>
	  <p>
The queueing of a message carrying receive rights may create a
circular loop of receive rights and messages, which can never be
received. For example, a message carrying a receive right can be
sent to that receive right. This situation is not an error, but the
kernel will garbage-collect such loops, destroying the messages.
Some return codes, like MACH_SEND_TIMED_OUT, imply that the message
was almost sent, but could not be queued. In these situations, the
kernel tries to return the message contents to the caller with a
pseudo-receive operation. This prevents the loss of port rights or
memory which only exist in the message, for example, a receive right
which was moved into the message, or out-of-line memory sent with
the de-allocate option.
	  <p>
The intent of the pseudo-receive operation is to restore, as best as
possible, the state prior to attempting the send. This involves
restoring the port rights and out-of-line memory regions contained in
the message. The port right names and out-of-line addresses in the
message send buffer are updated to reflect the new values resulting
from their effective reception. The pseudo-receive handles the des-
tination and reply rights as any other rights; they are not reversed
as is the appearance in a normal received message. Also, no trailer is
appended to the message. After the pseudo-receive, the message is
ready to be resent. If the message is not resent, note that
out-of-line memory regions may have moved and some port rights may
have changed names.
	  <p>
Although unlikely, the pseudo-receive operation may encounter resource
shortages. This is similar to a MACH_RCV_BODY_ERROR return code from
a receive operation. When this happens, the normal send return codes
are augmented with the MACH_MSG_IPC_SPACE, MACH_MSG_VM_SPACE,
MACH_MSG_IPC_KERNEL and MACH_MSG_VM_KERNEL bits to indicate the
nature of the resource shortage.
<h4>Message Receive</h4>
	  <p>
The receive operation de-queues a message from a port. The receiving
task acquires the port rights and out-of-line memory regions carried
in the message.
The receive_name argument specifies a port or port set from which to
receive. If a port is specified, the caller must possess the receive
right for the port and the port must not be a member of a port set. If
no message is present, the call blocks, subject to the
MACH_RCV_TIMEOUT option.
<p>
If a port set is specified, the call will receive a message sent to
any of the member ports. It is permissible for the port set to have
no member ports, and ports may be added and removed while a receive
from the port set is in progress. The received message can come from
any of the member ports which have messages, with the proviso that a
member port with messages will not be indefinitely starved. The
msgh_local_port field in the received message header specifies from
which port in the port set the message came.
<p>
The receive_limit argument specifies the size of the caller's message
buffer (which must be big enough for the message header, body and
trailer); the msgh_size field of the received message indicates the
actual size of the received message header and body. The <strong>mach_msg</strong> call
will not receive a message larger than receive_limit. Messages that
are too large are destroyed, unless the MACH_RCV_LARGE option is used.
Following the received data, at the next natural boundary, is a
message trailer.  The msgh_size field of the received message does not
include the length of this trailer; the trailer's length is given by
the msgh_trailer_size field within the trailer. The receiver of a
message is given a choice as to what trailer format is desired, and,
within that format, which of the leading trailer attributes are
desired (that is, to get trailer element three, the receiver must also
accept elements one and two). For any given trailer format (of which
there is currently only one), the trailer is compatibly extended by
adding additional elements to the end.
<p>
Received messages are stamped (in the trailer) 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 port.) Newly created ports start with a zero
sequence number, and the sequence number is reset to zero whenever the
port's receive right moves between tasks.  When a message is de-queued
from the port, it is stamped with the port's sequence number and the
port's sequence number is then incremented. (Note that this occurs
whether or not the receiver requests the sequence number in the trail-
er.) The de-queue and increment operations are atomic, so that
multiple threads receiving messages from a port can use the msgh_seqno
field to reconstruct the original order of the messages.
<p>
The destination and reply ports are reversed in a received message
header. The msgh_local_port field carries the name of the destination
port, from which the message was received, and the msgh_remote_port
field carries the reply port right. The bits in msgh_bits are also
reversed. The MACH_MSGH_BITS_LOCAL bits have a value of
MACH_MSG_TYPE_PORT_SEND_ONCE or MACH_MSG_TYPE_PORT_SEND depending on
the type of right to which the message was sent. The
MACH_MSGH_BITS_REMOTE bits describe the reply port right.
<p>
A received message can contain port rights and out-of-line memory. The
msgh_local_port field does not carry a port right; the act of
receiving the message consumes the send or send-once right for the
destination port. The msgh_remote_port field does carry a port right,
and the message can carry additional port rights and memory if the
MACH_MSGH_BITS_COMPLEX bit is set. Received port rights and memory
should be consumed or de-allocated in some fashion.
In almost all cases, msgh_local_port will specify the name of a
receive right, either receive_name, or, if receive_name is a port
set, a member of receive_name.
<p>
If other threads are concurrently
manipulating the receive right, the situation is more complicated. If
the receive right is renamed during the call, then msgh_local_port
specifies the right's new name. If the caller loses the receive right
after the message was de-queued from it, then <strong>mach_msg</strong> will proceed
instead of returning MACH_RCV_PORT_DIED. If the receive right was
destroyed, then msgh_local_port specifies MACH_PORT_DEAD. If the
receive right still exists, but isn't held by the caller, then
msgh_local_port specifies MACH_PORT_NULL.
<p>
The following options modify MACH_RCV_MSG. If MACH_RCV_MSG is not also
specified, they are ignored.
<dl>
<dt> MACH_RCV_TIMEOUT
     <dd>
The timeout argument should specify a maximum time (in milliseconds)
for the call to block before giving up. If no message arrives before
the timeout interval elapses, then the call returns
MACH_RCV_TIMED_OUT. A zero timeout is legitimate.
<dt> MACH_RCV_NOTIFY
     <dd>
The notify argument should specify a receive right for a notify
port. If receiving the reply port creates a new port right in the
caller, then the notify port is used to request a dead-name
notification for the new port right.
<dt> MACH_RCV_INTERRUPT
     <dd>
If specified, the <strong>mach_msg</strong> call will return MACH_RCV_INTERRUPTED if a
software interrupt aborts the call.  Otherwise, the receive operation
will be retried.
<dt> MACH_RCV_OVERWRITE
     <dd>
If specified, the message buffer specified by receive_msg (or msg), of 
length receive_msg_size, will be scanned for out-of-line descriptors to 
specify the processing to be done when receiving out-of-line regions. 
This option is only allowed for <strong>mach_msg_overwrite</strong>.
<dt> MACH_RCV_LARGE
     <dd>
If the message is larger than receive_limit or an out-of-line region
is larger than the size allowed by a corresponding receive descriptor
(MACH_RCV_OVERWRITE), the message remains queued instead of being
destroyed. If the header, trailer and body would not fit into
receive_limit, only the message header (mach_msg_header) and trailer
header (mach_msg_trailer) are returned with the actual size of the
message returned in the msgh_size field, the actual size of the
trailer returned in the msgh_trailer_size field and an error return
value of MACH_RCV_TOO_LARGE. If receive_limit is sufficient but an
out-of-line descriptor is not, the message header, trailer and body
are received, with out-of-line descriptors set to indicate the
nature and size of the out-of-line regions, with an error return of
MACH_RCV_SCATTER_SMALL. No out-of-line regions or port rights
(including the reply right) will be received. If this option is not
specified, messages too large will be de-queued and then destroyed;
the caller receives the message header, with all fields correct,
including the destination port but excepting the reply port, which is
MACH_PORT_NULL and an empty (no additional element) message trailer.
<dt> MACH_RCV_TRAILER_TYPE(value)
     <dd>
This macro encodes the type of trailer the kernel must return with the
message. If the kernel does not recognize this type, it returns
MACH_RCV_INVALID_TRAILER. Currently, only MACH_MSG_TRAILER_FORMAT_0 is
supported.
<dt> MACH_RCV_TRAILER_ELEMENTS(value)
     <dd>
This macro encodes the number of trailer elements desired. If the ker-
nel does not support this number for the requested trailer type, the
kernel returns MACH_RCV_INVALID_TRAILER. Zero is a legal value.
	  </dl>
	  <p>
	  The following trailer elements are supported:
	  <dl>
<dt> MACH_RCV_TRAILER_SEQNO
     <dd>
Returns the sequence number of the message relative to its port. This
value is of type mach_port_seqno_t.
<dt> MACH_RCV_TRAILER_SENDER
     <dd>
Returns the security ID of the task that sent the message. This value
is of type security_id_t.
	  </dl>
	  <p>
If a resource shortage prevents the reception of a port right, the
port right is destroyed and the caller sees the name
MACH_PORT_NULL. If a resource shortage prevents the reception of an
out-of-line memory region, the region is destroyed and the caller sees
a zero address. In addition, the corresponding element in the size
array is set to zero. A task never receives port rights or memory for
which it is not told.
	  <p>
The MACH_RCV_HEADER_ERROR return code indicates a resource shortage
in the reception of the message header. The reply port and all port
rights and memory in the message are destroyed. The caller receives
the message header with all fields correct except for the reply
port.
	  <p>
The MACH_RCV_BODY_ERROR return code indicates a resource shortage in
the reception of the message body. The message header, including the
reply port, is correct. The kernel attempts to transfer all port
rights and memory regions in the body, and only destroys those that
can't be transferred.
<h4>Atomicity</h4>
	  <p>
The <strong>mach_msg</strong> call handles port rights in the message header
atomically. Out-of-line memory and port rights in the message body do
not enjoy this atomicity guarantee. These elements may be processed
front-to-back, back-to-front, in some random order, or even
atomically.
	  <p>
For example, consider sending a message with the destination port
specified as MACH_MSG_TYPE_MOVE_SEND and the reply port specified as
MACH_MSG_TYPE_COPY_SEND. The same send right, with one user-refer-
ence, is supplied for both the msgh_remote_port and msgh_local_port
fields.  Because <strong>mach_msg</strong> processes the port rights atomically, this
succeeds. If msgh_remote_port were processed before msgh_local_port,
then <strong>mach_msg</strong> would return MACH_SEND_INVALID_REPLY in this situation.
	  <p>
On the other hand, suppose the destination and reply port are both
specified as MACH_MSG_TYPE_MOVE_SEND, and again the same send right
with one user-reference is supplied for both. Now the send operation
fails, but because it processes the rights atomically, <strong>mach_msg</strong> can
return either MACH_SEND_INVALID_DEST or MACH_SEND_INVALID_REPLY.
<p>
For example, consider receiving a message at the same time another
thread is deallocating the destination receive right. Suppose the
reply port field carries a send right for the destination port. If the
de-allocation happens before the dequeuing, the receiver gets
MACH_RCV_PORT_DIED. If the de-allocation happens after the receive,
the msgh_local_port and the msgh_remote_port fields both specify
the same right, which becomes a dead name when the receive right is
de-allocated. If the de-allocation happens between the de-queue and
the receive, the msgh_local_port and msgh_remote_port fields both
specify MACH_PORT_DEAD. Because the rights are processed atomically,
it is not possible for just one of the two fields to hold
MACH_PORT_DEAD.
<p>
The MACH_RCV_NOTIFY option provides a more likely example. Suppose a
message carrying a send-once right reply port is received with
MACH_RCV_NOTIFY at the same time the reply port is destroyed. If the
reply port is destroyed first, then msgh_remote_port specifies
MACH_PORT_DEAD and the kernel does not generate a dead-name
notification. If the reply port is destroyed after it is received,
then msgh_remote_port specifies a dead name for which the kernel
generates a dead-name notification. Either the reply port is dead on
arrival or notification is requested.
<h4>Implementation</h4>
<p>
<strong>mach_msg</strong> and <strong>mach_msg_overwrite</strong> are wrappers for a system call. They
have the responsibility for repeating the interrupted system call.
<h3>CAUTIONS</h3>
<p>
If MACH_RCV_TIMEOUT is used without MACH_RCV_INTERRUPT, then the
timeout duration might not be accurate. When the call is interrupted
and automatically retried, the original timeout is used. If
interrupts occur frequently enough, the timeout interval might never
expire. MACH_SEND_TIMEOUT without MACH_SEND_INTERRUPT suffers from the
same problem.
<h3>RETURN VALUES</h3>
<p>
The send operation can generate the following return codes. These
return codes imply that the call did nothing:
<dl>
<p>
<dt> MACH_SEND_MSG_TOO_SMALL
     <dd>
The specified send_size was smaller than the minimum size for a
message.
<p>
<dt> MACH_SEND_NO_BUFFER
     <dd>
A resource shortage prevented the kernel from allocating a message 
buffer.
<p>
<dt> MACH_SEND_INVALID_DATA
     <dd>
The supplied message buffer was not readable.
<p>
<dt> MACH_SEND_INVALID_HEADER
     <dd>
The msgh_bits value was invalid.
<p>
<dt> MACH_SEND_INVALID_DEST
     <dd>
The msgh_remote_port value was invalid.
<p>
<dt> MACH_SEND_INVALID_NOTIFY
     <dd>
When using MACH_SEND_CANCEL, the notify argument did not
denote a valid receive right.
<p>
<dt> MACH_SEND_INVALID_REPLY
     <dd>
The msgh_local_port value was invalid.
<p>
<dt> MACH_SEND_INVALID_TRAILER
     <dd>
The trailer to be sent does not correspond to the current kernel format, 
or the sending task does not have the privilege to supply the message 
attributes.
	  </dl>
	  <p>
These return codes imply that some or all of the message was destroyed:
	  <dl>
<p>
<dt> MACH_SEND_INVALID_MEMORY
     <dd>
The message body specified out-of-line data that was not readable.
<p>
<dt> MACH_SEND_INVALID_RIGHT
     <dd>
The message body specified a port right which the caller didn't possess.
<p>
<dt> MACH_SEND_INVALID_TYPE
     <dd>
A kernel processed descriptor was invalid.
<p>
<dt> MACH_SEND_MSG_TOO_SMALL
     <dd>
The last data item in the message ran over the end of the message.
	  </dl>
	  <p>
These return codes imply that the message was returned to the caller with a 
pseudo-receive operation:
	  <dl>
<p>
<dt> MACH_SEND_TIMED_OUT
     <dd>
The timeout interval expired.
<p>
<dt> MACH_SEND_INTERRUPTED
     <dd>
A software interrupt occurred.
	  </dl>
	  <p>
This return code implies that the message was queued:
	  <dl>
<p>
<dt> MACH_MSG_SUCCESS
     <dd>
The message was queued.
	  </dl>
	  <p>
The receive operation can generate the following return codes. These return 
codes imply that the call did not de-queue a message:
	  <dl>
<p>
<dt> MACH_RCV_INVALID_NAME
     <dd>
The specified receive_name was invalid.
<p>
<dt> MACH_RCV_IN_SET
     <dd>
The specified port was a member of a port set.
<p>
<dt> MACH_RCV_TIMED_OUT
     <dd>
The timeout interval expired.
<p>
<dt> MACH_RCV_INTERRUPTED
     <dd>
A software interrupt occurred.
<p>
<dt> MACH_RCV_PORT_DIED
     <dd>
The caller lost the rights specified by receive_name.
<p>
<dt> MACH_RCV_PORT_CHANGED
     <dd>
receive_name specified a receive right which was moved into a port set 
during the call.
<p>
<dt> MACH_RCV_TOO_LARGE
     <dd>
When using MACH_RCV_LARGE, the message was larger than 
receive_limit. The message is left queued, and its actual size is
returned in the message header/message body.
<p>
<dt> MACH_RCV_SCATTER_SMALL
     <dd>
When using MACH_RCV_LARGE with MACH_RCV_OVERWRITE, one or more scatter
list descriptors specified an overwrite region smaller than the
corresponding incoming region. The message is left queued, and the
proper descriptors are returned in the message header/message body.
<p>
<dt> MACH_RCV_INVALID_TRAILER
     <dd>
The trailer type desired, or the number of trailer elements desired, is 
not supported by the kernel.
	  </dl>
	  <p>
These return codes imply that a message was de-queued and destroyed:
	  <dl>
<p>
<dt> MACH_RCV_HEADER_ERROR
     <dd>
A resource shortage prevented the reception of the port rights in the 
message header.
<p>
<dt> MACH_RCV_INVALID_NOTIFY
     <dd>
When using MACH_RCV_NOTIFY, the notify argument did not denote a
valid receive right.
<p>
<dt> MACH_RCV_INVALID_DATA
     <dd>
The specified message buffer was not writable.
<p>
<dt> MACH_RCV_TOO_LARGE
     <dd>
When not using MACH_RCV_LARGE, a message larger than 
receive_limit was de-queued and destroyed.
<p>
<dt> MACH_RCV_SCATTER_SMALL
     <dd>
When not using MACH_RCV_LARGE with MACH_RCV_OVERWRITE, one or more
scatter list descriptors specified an overwrite region smaller than
the corresponding incoming region. The message was de-queued and
destroyed.
<p>
<dt> MACH_RCV_OVERWRITE_ERROR
     <dd>
A region specified by a receive overwrite descriptor
(MACH_RCV_OVERWRITE) was not allocated or could not be written.
<p>
<dt> MACH_RCV_INVALID_TYPE
     <dd>
When using MACH_RCV_OVERWRITE, one or more scatter list descriptors
did not have the type matching the corresponding incoming message
descriptor or had an invalid copy (disposition) field.
<p>
<dt> MACH_RCV_LIMITS
     <dd>
The combined size of all out-of-line memory regions or the total num-
ber of port rights in the message exceeds the limit set for the port.
These return codes imply that a message was received:
<p>
<dt> MACH_RCV_BODY_ERROR
     <dd>
A resource shortage prevented the reception of a port right or out-of-
line memory region in the message body.
<p>
<dt> MACH_MSG_SUCCESS
     <dd>
A message was received.
	  </dl>
	  <p>
Resource shortages can occur after a message is de-queued, while
transferring port rights and out-of-line memory regions to the
receiving task. The <strong>mach_msg</strong> call returns MACH_RCV_HEADER_ERROR or
MACH_RCV_BODY_ERROR in this situation. These return codes always carry
	  extra bits (bitwise-or'ed) that indicate the nature of the resource
shortage:
	  <dl>
<p>
<dt> MACH_MSG_IPC_SPACE
     <dd>
There was no room in the task's IPC name space for another port name.
<p>
<dt> MACH_MSG_VM_SPACE
     <dd>
There was no room in the task's VM address space for an out-of-line 
memory region.
<p>
<dt> MACH_MSG_IPC_KERNEL
     <dd>
A kernel resource shortage prevented the reception of a port right.
<p>
<dt> MACH_MSG_VM_KERNEL
     <dd>
A kernel resource shortage prevented the reception of an out-of-line 
memory region.
</dl>
<h3>RELATED INFORMATION</h3>
<p>
Functions:
<a href="vm_allocate.html"><strong>vm_allocate</strong></a>,
<a href="vm_deallocate.html"><strong>vm_deallocate</strong></a>,
<a href="vm_write.html"><strong>vm_write</strong></a>,
<a href="MP_request_notification.html"><strong>mach_port_request_notification</strong></a>,
<p>
Data Structures:
mach_msg_header.