]>
Commit | Line | Data |
---|---|---|
9bccf70c | 1 | <h2>mach_msg</h2>\r<hr>\r<p>\r<strong>System Trap</strong> / <strong>Function</strong> - Send and/or receive a message from the target port.\r<h3>SYNOPSIS</h3>\r<pre>\r<strong>mach_msg_return_t mach_msg</strong>\r <strong>(mach_msg_header_t</strong> <var>msg</var>,\r <strong>mach_msg_option_t</strong> <var>option</var>,\r <strong>mach_msg_size_t</strong> <var>send_size</var>,\r <strong>mach_msg_size_t</strong> <var>receive_limit</var>,\r <strong>mach_port_t</strong> <var>receive_name</var>,\r <strong>mach_msg_timeout_t</strong> <var>timeout</var>,\r <strong>mach_port_t</strong> <var>notify</var><strong>);</strong>\r\r<strong>mach_msg_return_t mach_msg_overwrite</strong>\r <strong>(mach_msg_header_t*</strong> <var>send_msg</var>,\r <strong>mach_msg_option_t</strong> <var>option</var>,\r <strong>mach_msg_size_t</strong> <var>send_size</var>,\r <strong>mach_msg_size_t</strong> <var>receive_limit</var>,\r <strong>mach_port_t</strong> <var>receive_name</var>,\r <strong>mach_msg_timeout_t</strong> <var>timeout</var>,\r <strong>mach_port_t</strong> <var>notify</var>,\r <strong>mach_msg_header_t</strong> <var>*receive_msg</var>,\r <strong>mach_msg_size_t</strong> <var>receive_msg_size</var><strong>);</strong>\r</pre>\r<h3>PARAMETERS</h3>\r<dl>\r<p>\r<dt> <var>msg</var>\r<dd>\r[pointer to in/out structure containing random and reply rights] A\rmessage buffer used by <strong>mach_msg</strong> both for send and receive. This must\rbe naturally aligned.\r<p>\r<dt> <var>send_msg</var>\r<dd>\r[pointer to in structure containing random and reply rights] The mes-\rsage buffer to be sent. This must be naturally aligned.\r<p>\r<dt> <var>option</var>\r<dd>\r[in scalar] Message options are bit values, combined with bitwise-or.\rOne or both of MACH_SEND_MSG and MACH_RCV_MSG should be used. Other\roptions act as modifiers.\r<p>\r<dt> <var>send_size</var>\r<dd>\r[in scalar] When sending a message, specifies the size of the message\rbuffer to be sent (the size of the header and body) in\rbytes. Otherwise zero should be supplied.\r<p>\r<dt> <var>receive_limit</var>\r<dd>\r[in scalar] When receiving a message, specifies the maximum size of\rthe msg or receive_msg buffer in bytes. Otherwise zero should be sup-\rplied.\r<p>\r<dt> <var>receive_name</var>\r<dd>\r[in random right] When receiving a message, specifies the port or port\rset. Otherwise MACH_PORT_NULL should be supplied.\r<p>\r<dt> <var>timeout</var>\r<dd>\r[in scalar] When using the MACH_SEND_TIMEOUT and MACH_RCV_TIMEOUT\roptions, specifies the time in milliseconds to wait before giving\rup. Otherwise MACH_MSG_TIMEOUT_NONE should be supplied.\r<p>\r<dt> <var>notify</var>\r<dd>\r[in notify receive right] When using the MACH_SEND_CANCEL and\rMACH_RCV_NOTIFY options, specifies the port used for the\rnotification. Otherwise MACH_PORT_NULL should be supplied.\r<p>\r<dt> <var>receive_msg</var>\r<dd>\r[pointer to in/out structure] A message buffer into which a message\r(header and body) will be received. This must be naturally aligned. By\rdefault (<strong>mach_msg</strong>), any received message will overwrite the send\rmessage buffer. This buffer is in/out only if the MACH_RCV_OVERWRITE\roption is used; otherwise this buffer is out only.\r<p>\r<dt> <var>receive_msg_size</var>\r<dd>\r[in scalar] When using the MACH_RCV_OVERWRITE option, specifies the\rsize (in bytes) of the receive "message" that is to be used by\r<strong>mach_msg</strong> to indicate the disposition of received out-of-line regions.\r</dl>\r<h3>DESCRIPTION</h3>\r<p>\rThe <strong>mach_msg</strong> system call sends and receives Mach messages. Mach\rmessages contain data, which can include port rights and addresses of\rlarge regions of memory. <strong>mach_msg</strong> uses the same buffer for sending and\rreceiving a message; the other calls permit separate send and receive\rbuffers (although they may be specified to be the same).\rIf the option argument contains MACH_SEND_MSG, the call sends a\rmessage. The <var>send_size</var> argument specifies the size of the message\rbuffer (header and body) to send. The msgh_remote_port field of the\rmessage header specifies the destination of the message.\rIf the option argument contains MACH_RCV_MSG, it receives a\rmessage. The receive_limit argument specifies the size of a buffer\rthat will receive the message; messages that are larger are not\rreceived. The receive_name argument specifies the port or port set\rfrom which to receive.\r<p>\rIf the option argument contains both MACH_SEND_MSG and MACH_RCV_MSG,\rthen <strong>mach_msg</strong> does both send and receive operations (in that\rorder). If the send operation encounters an error (any return code\rother than MACH_MSG_SUCCESS), the call returns immediately\rwithout attempting the receive operation. Semantically the combined\rcall is equivalent to separate send and receive calls, but it saves\ra system call and enables other internal optimizations.\r\rIf the option argument specifies neither MACH_SEND_MSG nor\rMACH_RCV_MSG, <strong>mach_msg</strong> does nothing.\rSome options, like MACH_SEND_TIMEOUT and MACH_RCV_TIMEOUT, share a\rsupporting argument. If these options are used together, they make\rindependent use of the supporting argument's value.\r<h3>NOTES</h3>\r<p>\rThe Mach kernel provides message-oriented, capability-based\rinter-process communication. The inter-process communication (IPC)\rprimitives efficiently support many different styles of interaction,\rincluding remote procedure calls, object-oriented distributed\rprogramming, streaming of data, and sending very large amounts of\rdata.\r<h4>Major Concepts</h4>\r<p>\rThe IPC primitives operate on three abstractions: messages, ports, and\rport sets. User tasks access all other kernel services and\rabstractions via the IPC primitives.\r<p>\rThe message primitives let tasks send and receive messages. Tasks send\rmessages to ports. Messages sent to a port are delivered reliably\r(messages may not be lost) and are received in the order in which they\rwere sent via send rights by a given sending task (or a given\rkernel). (Messages sent to send-once rights are unordered.)\r<p>\rMessages\rcontain a fixed-size header and a variable-sized message body\rcontaining kernel and user data, and a variable-size trailer of kernel\rappended message attributes. The header describes the destination\rand the size of the message (header plus body). The message body\rcontains descriptions of additional port rights to be transmitted,\rdescriptions of "out-of-line" memory regions to be sent and a\rvariable amount of user data, which typically includes type conversion\rinformation. The out-of-line memory regions (including out-of-line\rport arrays) are (typically) disjoint from the message body.\rThe IPC implementation makes use of the VM system to efficiently\rtransfer large amounts of data. The message can contain the addresses\rof regions of the sender's address space which should be transferred\ras part of the message.\r<p>\rWhen a task receives a message containing\rsuch out-of-line regions of data, the data can appear in unused\rportions or overwrite an existing portion of the receiver's address\rspace (depending on the requested receive options). Under favorable\rcircumstances, the transmission of out-of-line data is optimized so\rthat sender and receiver share the physical pages of data\rcopy-on-write, and no actual data copy occurs unless the pages are\rwritten. Regions of memory up to 4 gigabytes may be sent in this\rmanner.\r<p>\rPorts hold a queue of messages. Tasks operate on a port to send and\rreceive messages by exercising capabilities (rights) for the\rport. Multiple tasks can hold send rights for a port.\rTasks can also\rhold send-once rights, which grant the ability to send a single\rmessage. Only one task can hold the receive capability (receive\rright) for a port.\r<p>\rPort rights can be transferred between tasks via\rmessages. The sender of a message can specify in the message that the\rmessage contains a port right. If a message contains a receive right\rfor a port, the receive right is removed from the sender of the\rmessage and transferred to the receiver of the\rmessage. While the receive right is in transit, tasks holding send\rrights can still send messages to the port, and they are queued until\ra task acquires the receive right and uses it to receive the messages.\r<p>\rTasks can receive messages from ports and port sets. The port set\rabstraction allows a single thread to wait for a message from any of\rseveral ports. Tasks manipulate port sets with a port set name,\rwhich is taken from the same name space as are the port rights. The\rport-set name may not be transferred in a message. A port set holds\rreceive rights, and a receive operation on a port set blocks waiting\rfor a message sent to any of the constituent ports. A port may not be-\rlong to more than one port set, and if a port is a member of a port\rset, the holder of the receive right can't receive directly from the\rport.\r<p>\rPort rights are a secure, location-independent way of naming\rports. The port queue is a protected data structure, only accessible\rvia the kernel's exported message primitives. Rights are also\rprotected by the kernel; there is no way for a malicious user task to\rguess a port's internal name and send a message to a port to which it\rshouldn't have access. Port rights do not carry any location in-\rformation. When a receive right for a port moves from task to task,\rand even between tasks on different machines, the send rights for\rthe port remain unchanged and continue to function.\r<h4>Port Rights</h4>\r<p>\rEach task has its own space of port rights. Port rights are named with\rpositive (unsigned) integers. For all architectures, sizeof\r(mach_port_t) = sizeof (mach_port_name_t) = sizeof (void*) and so user\rspace addresses may be used as port names, except for the reserved\rvalues MACH_PORT_NULL (0) and MACH_PORT_DEAD (all 1 bits). When the\rkernel chooses a name for a new right, however, it is free to pick any\runused name (one which denotes no right) in the space.\r<p>\rThere are three basic kinds of rights: receive rights, send rights and\rsend-once rights. A port name can name any of these types of rights,\ror name a port-set, be a dead name, or name nothing. Dead names are\rnot capabilities. They act as place-holders to prevent a name from\rbeing otherwise used.\r<p>\rA port is destroyed, or dies, when its receive right is\rde-allocated. When a port dies, send and send-once rights for the port\rturn into dead names. Any messages queued at the port are destroyed,\rwhich de-allocates the port rights and out-of-line memory in the\rmessages.\r<p>\rEach send-once right held by a task has a different name. In contrast,\rwhen a task holds send rights or a receive right for a port, the\rrights share a single name.\r<p>\rTasks may hold multiple user-references for send rights. When a task\rreceives a send right which it already holds, the kernel increments\rthe right's user-reference count. When a task de-allocates a send\rright, the kernel decrements its user-reference count, and the task\ronly loses the send right when the count goes to zero.\r<p>\rSend-once rights always have a user reference count of one. Tasks may\rhold multiple user references for dead names.\rEach send-once right generated guarantees the receipt of a single\rmessage, either a message sent to that send-once right or, if the\rsend-once right is in any way destroyed, a send-once notification.\r<p>\rA message can carry port rights; the msgh_remote or msgh_local fields\rin the message header or the disposition field in a message body\rdescriptor specify the type of port right and how the port right is to\rbe extracted from the caller. The values MACH_PORT_NULL and\rMACH_PORT_DEAD are valid in place of a port right in a message body.\r<p>\rIn a sent message, the following mach_msg_type_name_t values denote\rport rights:\r<dl>\r<dt> MACH_MSG_TYPE_MAKE_SEND\r <dd>\rThe message will carry a send right, but the caller must supply a\rreceive right. The send right is created from the receive right, and the\rreceive right's make-send count is incremented.\r<dt> MACH_MSG_TYPE_COPY_SEND\r <dd>\rThe message will carry a send right, and the caller must supply a send \rright. The user reference count for the supplied send right is not \rchanged. The caller may also supply a dead name and the receiving \rtask will get MACH_PORT_DEAD.\r<dt> MACH_MSG_TYPE_MOVE_SEND\r <dd>\rThe message will carry a send right, and the caller must supply a send\rright. The user reference count for the supplied send right is\rdecremented, and the right is destroyed if the count becomes\rzero. Unless a receive right remains, the name becomes available for\rrecycling. The caller may also supply a dead name, which loses a user\rreference, and the receiving task will get MACH_PORT_DEAD.\r<dt> MACH_MSG_TYPE_MAKE_SEND_ONCE\r<dd>\rThe message will carry a send-once right, but the caller must supply a\rreceive right. The send-once right is created from the receive right.\rNote that send once rights can only be created from the receive right.\r<dt> MACH_MSG_TYPE_MOVE_SEND_ONCE\r <dd>\rThe message will carry a send-once right, and the caller must supply a\rsend-once right. The caller loses the supplied send-once right. The\rcaller may also supply a dead name, which loses a user reference,\rand the receiving task will get MACH_PORT_DEAD.\r<dt> MACH_MSG_TYPE_MOVE_RECEIVE\r <dd>\rThe message will carry a receive right, and the caller must supply a\rreceive right. The caller loses the supplied receive right, but\rretains any send rights with the same name. The make-send count and\rsequence number of the receive right are reset to zero and\rno-more-senders notification requests are cancelled (with a\rsend-once notification being sent to the no-more-senders notification\rright), but the port retains other attributes like queued messages\rand extant send and send-once rights.\rIf a message carries a send or send-once right, and the port dies\rwhile the message is in transit, then the receiving task will get\rMACH_PORT_DEAD instead of a right.\r </dl>\r <p>\rThe following mach_msg_type_name_t values in a received message\rindicate that it carries port rights:\r <dl>\r<dt> MACH_MSG_TYPE_PORT_SEND\r <dd>\rThis value is an alias for MACH_MSG_TYPE_MOVE_SEND. The \rmessage carried a send right. If the receiving task already has send and/\ror receive rights for the port, then that name for the port will be reused. \rOtherwise, the right will have a new, previously unused, name. If the \rtask already has send rights, it gains a user reference for the right (un-\rless this would cause the user-reference count to overflow). Otherwise, \rit acquires send rights, with a user-reference count of one.\r<dt> MACH_MSG_TYPE_PORT_SEND_ONCE\r <dd>\rThis value is an alias for MACH_MSG_TYPE_MOVE_SEND_ONCE. The message\rcarried a send-once right. The right will have a new, previously\runused, name.\r<dt> MACH_MSG_TYPE_PORT_RECEIVE\r <dd>\rThis value is an alias for MACH_MSG_TYPE_MOVE_RECEIVE. The message\rcarried a receive right. If the receiving task already has send rights\rfor the port, then that name for the port will be reused; otherwise,\rthe right will have a new, previously unused name.\r </dl>\r <p>\rIt is also possible to send a (nearly unbounded) array of port rights\r"out-of-line". All of the rights named by the array must be of the\rsame type. The array is physically copied with the message body\rproper. The array of port right (names) can be received by the\rreceiver using the same options available for out-of-line data\rreception described below.\r<h4>Memory</h4>\r <p>\rA message can contain one or more regions of the sender's address\rspace which are to be transferred as part of the message. The message\rcarries a logical copy of the memory. For this "out-of-line" memory,\rthe kernel can copy the data or use virtual memory techniques to defer\rany actual page copies unless the sender or the receiver modifies\rthe data, the physical pages remain shared.\r<p>\r The sender of the message must explicitly request an out-of-line\rtransfer. Such a region is described as an arbitrary region of the\rsender's address space. The sender always sees this memory as being\rcopied to the receiver.\r<p>\r For each region, the sender has a de-allocate option. If the option is\rset and the out-of-line memory region is not null, then the region is\rimplicitly de-allocated from the sender, as if by vm_deallocate. In\rparticular, the start address is truncated down and the end address\rrounded up so that every page overlapped by the memory region is\rde-allocated (thereby possibly de-allocating more memory than is\reffectively transmitted). The use of this option effectively changes\rthe memory copy to a memory movement. Aside from possibly optimizing\rthe sender's use of memory, the de-allocation option allows the kernel\rto more efficiently handle the transfer of memory.\r <p>\rFor each region, the sender has the choice of permitting the kernel to\rchoose a transmission strategy or the choice of requiring physical\rcopy:\r <dl>\r<dt> MACH_MSG_VIRTUAL_COPY\r <dd>\rIn a sent message, this flag allows the kernel to choose any mechanism\rto transmit the data. For large regions, this involves constructing a\rvirtual copy of the pages containing the region. The portion of the\rfirst page preceding the data and the portion of the last page\rfollowing the data are not copied (and will appear as zero if the\rvirtual copy is dynamically allocated in the receiver).\r <p>\rIn a received message, this flag indicates that the kernel transmitted\ra virtual copy. Access to the received memory may involve interactions\rwith the memory manager managing the sender's original data. Integri-\rty-conscious receivers should exercise caution when dealing with out-\rof-line memory from un-trustworthy sources. Receivers concerned about\rdeterministic access time should also exercise caution. The dynamic\rallocation option guarantees that the virtual copy will not be di-\rrectly referenced during the act of receiving the message.\r<dt> MACH_MSG_PHYSICAL_COPY\r <dd>\rIn a sent message, this flag requires that the kernel construct an\ractual copy of the memory (either into wired kernel memory or default\rmemory managed space). There is a (fairly large) limit on the amount\rof data that can be physically copied in a message. Port arrays always\rassume this option when sent.\r <p>\rIn a received message, this flag indicates that the kernel did\rtransmit a physical copy.\r </dl>\r <p>\rThe receiver has two options for the reception of out-of-line memory\r(or "out-of-line" port arrays): allocation and overwrite.\rIn the absence of the MACH_RCV_OVERWRITE option, all out-of-line re-\rgions are dynamically allocated. Allocated out-of-line memory arrives\rsomewhere in the receiver's address space as new memory. It has the\rsame inheritance and protection attributes as newly vm_allocate'ed\rmemory. The receiver has the responsibility of de-allocating (with\rvm_deallocate) the memory when it is no longer needed. If the message\rcontains more than one region, each will be allocated its own region,\rnot necessarily contiguously. If the sender's data was transmitted as\ra virtual copy the allocated region will have the same data alignment\rwithin the page; otherwise, the received data will appear starting at\rthe beginning of a page.\r <p>\rIf the MACH_RCV_OVERWRITE option is set, the receiver can specify how\reach received region is to be processed (dynamically allocated as\rdescribed above, or written over existing memory). With this option,\rthe contents of the receive buffer (receive_msg) are examined by the\rkernel. The kernel scans the descriptors in the receive buffer\r"message" to determine how to handle each out-of-line region. (Note:\rwhereas receive_limit is the maximum size of the receive buffer,\rreceive_msg_size is the amount filled in with this "message".) The\rkernel uses each out-of-line data descriptor (in order) to specify\rthe processing for each received data region in turn, each out-of-line\rport array descriptor is used correspondingly. (Intermingled port\rdescriptors are ignored when matching descriptors between the\rincoming message and the receive buffer list.)\r<p>\rThe copy option in the\rmatching descriptor specifies the processing:\r <dl>\r<dt> MACH_MSG_OVERWRITE\r <dd>\rThis flag indicates that the region should write over a specified\rregion of the receiver's address space, as indicated by the address\rand size/ count fields of the descriptor. The full range overwritten\rmust already exist (be allocated or mapped) in the receiver's address\rspace. Depending on the nature of the data transmission this\roverwrite may involve virtual memory manipulations or it may involve\ractual data copy.\r<dt> MACH_MSG_ALLOCATE\r <dd>\rThis flag indicates that the region is to be dynamically allocated. No\rother descriptor values are relevant.\r </dl>\r <p>\rIf not enough descriptors appear in the receive buffer to describe all\rreceived regions, additional regions are dynamically allocated. If\rthe receiver specifies more descriptors than there are regions in the\rreceived message, the additional descriptors are ignored (and do not\rappear in the final received message).\r <p>\rNote that the receive buffer descriptors will be overwritten:\rThe size fields in descriptors will be updated (when scanned, they\rspecified the maximum sizes of regions, when received, they specify\rthe actual sizes of received regions).\rThe copy fields in descriptors will be updated (when scanned, they\rspecified allocate versus overwrite, when received, they indicate\rwhether the region was physically or virtually copied).\rThe descriptors may appear in different positions (given intermingled\rport descriptors).\rDescriptors that were not used (because there were not that many\rreceived regions) will be discarded.\r <p>\rNull out-of-line memory is legal. If the out-of-line region size is\rzero, then the region's specified address is ignored. A receive\rallocated null out-of-line memory region always has a zero address.\rUnaligned addresses and region sizes that are not page multiples are\rlegal. A received message can also contain regions with unaligned\raddresses and sizes which are not multiples of the page size.\r<h4>Message Send</h4>\r <p>\rThe send operation queues a message to a port. The message carries a\rcopy of the caller's data. After the send, the caller can freely\rmodify the message buffer or the out-of-line memory regions and the\rmessage contents will remain unchanged.\r <p>\rThe message carries with it the security ID of the sender, which the\rreceiver can request in the message trailer.\r <p>\rMessage delivery is reliable and sequenced. Reception of a message\rguarantees that all messages previously sent to the port by a single\rtask (or a single kernel) via send rights have been received and that\rthey are received in the order in which they were sent. Messages sent\rto send-once rights are unordered.\r <p>\rIf the destination port's queue is full, several things can happen. If\rthe message is sent to a send-once right (msgh_remote_port carries a\rsend-once right), then the kernel ignores the queue limit and delivers\rthe message. Otherwise the caller blocks until there is room in the\rqueue, unless the MACH_SEND_TIMEOUT option is used. If a port has\rseveral blocked senders, then any of them may queue the next message\rwhen space in the queue becomes available, with the proviso that a\rblocked sender will not be indefinitely starved.\rThese options modify MACH_SEND_MSG. If MACH_SEND_MSG is not also\rspecified, they are ignored.\r<dl>\r<dt> MACH_SEND_TIMEOUT\r <dd>\rThe timeout argument should specify a maximum time (in milliseconds)\rfor the call to block before giving up. If the message can't be queued\rbefore the timeout interval elapses, then the call returns\rMACH_SEND_TIMED_OUT. A zero timeout is legitimate.\r<dt> MACH_SEND_INTERRUPT\r <dd>\rIf specified, the <strong>mach_msg</strong> call will return \rMACH_SEND_INTERRUPTED if a software interrupt aborts the call. \rOtherwise, the send operation will be retried.\r<dt> MACH_SEND_TRAILER\r <dd>\rIf set, the kernel, instead of determining the message attributes\ritself, will accept a formatted message trailer from the sender. The\rsupplied trailer must be of the latest version supported by the\rkernel, and must contain all message attributes defined by the\rkernel. Only tasks with a security ID of KERNEL_SECURITY_ID can use\rthis option; the intended use of this option is in support of the\rNet Message server. The trailer must follow the message in memory as\rit would appear in a received message. (The send_size argument to\r<strong>mach_msg</strong> still indicates the size of the message proper, not including\rthis trailer.)\r </dl>\r <p>\rThe queueing of a message carrying receive rights may create a\rcircular loop of receive rights and messages, which can never be\rreceived. For example, a message carrying a receive right can be\rsent to that receive right. This situation is not an error, but the\rkernel will garbage-collect such loops, destroying the messages.\rSome return codes, like MACH_SEND_TIMED_OUT, imply that the message\rwas almost sent, but could not be queued. In these situations, the\rkernel tries to return the message contents to the caller with a\rpseudo-receive operation. This prevents the loss of port rights or\rmemory which only exist in the message, for example, a receive right\rwhich was moved into the message, or out-of-line memory sent with\rthe de-allocate option.\r <p>\rThe intent of the pseudo-receive operation is to restore, as best as\rpossible, the state prior to attempting the send. This involves\rrestoring the port rights and out-of-line memory regions contained in\rthe message. The port right names and out-of-line addresses in the\rmessage send buffer are updated to reflect the new values resulting\rfrom their effective reception. The pseudo-receive handles the des-\rtination and reply rights as any other rights; they are not reversed\ras is the appearance in a normal received message. Also, no trailer is\rappended to the message. After the pseudo-receive, the message is\rready to be resent. If the message is not resent, note that\rout-of-line memory regions may have moved and some port rights may\rhave changed names.\r <p>\rAlthough unlikely, the pseudo-receive operation may encounter resource\rshortages. This is similar to a MACH_RCV_BODY_ERROR return code from\ra receive operation. When this happens, the normal send return codes\rare augmented with the MACH_MSG_IPC_SPACE, MACH_MSG_VM_SPACE,\rMACH_MSG_IPC_KERNEL and MACH_MSG_VM_KERNEL bits to indicate the\rnature of the resource shortage.\r<h4>Message Receive</h4>\r <p>\rThe receive operation de-queues a message from a port. The receiving\rtask acquires the port rights and out-of-line memory regions carried\rin the message.\rThe receive_name argument specifies a port or port set from which to\rreceive. If a port is specified, the caller must possess the receive\rright for the port and the port must not be a member of a port set. If\rno message is present, the call blocks, subject to the\rMACH_RCV_TIMEOUT option.\r<p>\rIf a port set is specified, the call will receive a message sent to\rany of the member ports. It is permissible for the port set to have\rno member ports, and ports may be added and removed while a receive\rfrom the port set is in progress. The received message can come from\rany of the member ports which have messages, with the proviso that a\rmember port with messages will not be indefinitely starved. The\rmsgh_local_port field in the received message header specifies from\rwhich port in the port set the message came.\r<p>\rThe receive_limit argument specifies the size of the caller's message\rbuffer (which must be big enough for the message header, body and\rtrailer); the msgh_size field of the received message indicates the\ractual size of the received message header and body. The <strong>mach_msg</strong> call\rwill not receive a message larger than receive_limit. Messages that\rare too large are destroyed, unless the MACH_RCV_LARGE option is used.\rFollowing the received data, at the next natural boundary, is a\rmessage trailer. The msgh_size field of the received message does not\rinclude the length of this trailer; the trailer's length is given by\rthe msgh_trailer_size field within the trailer. The receiver of a\rmessage is given a choice as to what trailer format is desired, and,\rwithin that format, which of the leading trailer attributes are\rdesired (that is, to get trailer element three, the receiver must also\raccept elements one and two). For any given trailer format (of which\rthere is currently only one), the trailer is compatibly extended by\radding additional elements to the end.\r<p>\rReceived messages are stamped (in the trailer) with a sequence number,\rtaken from the port from which the message was received. (Messages\rreceived from a port set are stamped with a sequence number from the\rappropriate member port.) Newly created ports start with a zero\rsequence number, and the sequence number is reset to zero whenever the\rport's receive right moves between tasks. When a message is de-queued\rfrom the port, it is stamped with the port's sequence number and the\rport's sequence number is then incremented. (Note that this occurs\rwhether or not the receiver requests the sequence number in the trail-\rer.) The de-queue and increment operations are atomic, so that\rmultiple threads receiving messages from a port can use the msgh_seqno\rfield to reconstruct the original order of the messages.\r<p>\rThe destination and reply ports are reversed in a received message\rheader. The msgh_local_port field carries the name of the destination\rport, from which the message was received, and the msgh_remote_port\rfield carries the reply port right. The bits in msgh_bits are also\rreversed. The MACH_MSGH_BITS_LOCAL bits have a value of\rMACH_MSG_TYPE_PORT_SEND_ONCE or MACH_MSG_TYPE_PORT_SEND depending on\rthe type of right to which the message was sent. The\rMACH_MSGH_BITS_REMOTE bits describe the reply port right.\r<p>\rA received message can contain port rights and out-of-line memory. The\rmsgh_local_port field does not carry a port right; the act of\rreceiving the message consumes the send or send-once right for the\rdestination port. The msgh_remote_port field does carry a port right,\rand the message can carry additional port rights and memory if the\rMACH_MSGH_BITS_COMPLEX bit is set. Received port rights and memory\rshould be consumed or de-allocated in some fashion.\rIn almost all cases, msgh_local_port will specify the name of a\rreceive right, either receive_name, or, if receive_name is a port\rset, a member of receive_name.\r<p>\rIf other threads are concurrently\rmanipulating the receive right, the situation is more complicated. If\rthe receive right is renamed during the call, then msgh_local_port\rspecifies the right's new name. If the caller loses the receive right\rafter the message was de-queued from it, then <strong>mach_msg</strong> will proceed\rinstead of returning MACH_RCV_PORT_DIED. If the receive right was\rdestroyed, then msgh_local_port specifies MACH_PORT_DEAD. If the\rreceive right still exists, but isn't held by the caller, then\rmsgh_local_port specifies MACH_PORT_NULL.\r<p>\rThe following options modify MACH_RCV_MSG. If MACH_RCV_MSG is not also\rspecified, they are ignored.\r<dl>\r<dt> MACH_RCV_TIMEOUT\r <dd>\rThe timeout argument should specify a maximum time (in milliseconds)\rfor the call to block before giving up. If no message arrives before\rthe timeout interval elapses, then the call returns\rMACH_RCV_TIMED_OUT. A zero timeout is legitimate.\r<dt> MACH_RCV_NOTIFY\r <dd>\rThe notify argument should specify a receive right for a notify\rport. If receiving the reply port creates a new port right in the\rcaller, then the notify port is used to request a dead-name\rnotification for the new port right.\r<dt> MACH_RCV_INTERRUPT\r <dd>\rIf specified, the <strong>mach_msg</strong> call will return MACH_RCV_INTERRUPTED if a\rsoftware interrupt aborts the call. Otherwise, the receive operation\rwill be retried.\r<dt> MACH_RCV_OVERWRITE\r <dd>\rIf specified, the message buffer specified by receive_msg (or msg), of \rlength receive_msg_size, will be scanned for out-of-line descriptors to \rspecify the processing to be done when receiving out-of-line regions. \rThis option is only allowed for <strong>mach_msg_overwrite</strong>.\r<dt> MACH_RCV_LARGE\r <dd>\rIf the message is larger than receive_limit or an out-of-line region\ris larger than the size allowed by a corresponding receive descriptor\r(MACH_RCV_OVERWRITE), the message remains queued instead of being\rdestroyed. If the header, trailer and body would not fit into\rreceive_limit, only the message header (mach_msg_header) and trailer\rheader (mach_msg_trailer) are returned with the actual size of the\rmessage returned in the msgh_size field, the actual size of the\rtrailer returned in the msgh_trailer_size field and an error return\rvalue of MACH_RCV_TOO_LARGE. If receive_limit is sufficient but an\rout-of-line descriptor is not, the message header, trailer and body\rare received, with out-of-line descriptors set to indicate the\rnature and size of the out-of-line regions, with an error return of\rMACH_RCV_SCATTER_SMALL. No out-of-line regions or port rights\r(including the reply right) will be received. If this option is not\rspecified, messages too large will be de-queued and then destroyed;\rthe caller receives the message header, with all fields correct,\rincluding the destination port but excepting the reply port, which is\rMACH_PORT_NULL and an empty (no additional element) message trailer.\r<dt> MACH_RCV_TRAILER_TYPE(value)\r <dd>\rThis macro encodes the type of trailer the kernel must return with the\rmessage. If the kernel does not recognize this type, it returns\rMACH_RCV_INVALID_TRAILER. Currently, only MACH_MSG_TRAILER_FORMAT_0 is\rsupported.\r<dt> MACH_RCV_TRAILER_ELEMENTS(value)\r <dd>\rThis macro encodes the number of trailer elements desired. If the ker-\rnel does not support this number for the requested trailer type, the\rkernel returns MACH_RCV_INVALID_TRAILER. Zero is a legal value.\r </dl>\r <p>\r The following trailer elements are supported:\r <dl>\r<dt> MACH_RCV_TRAILER_SEQNO\r <dd>\rReturns the sequence number of the message relative to its port. This\rvalue is of type mach_port_seqno_t.\r<dt> MACH_RCV_TRAILER_SENDER\r <dd>\rReturns the security ID of the task that sent the message. This value\ris of type security_id_t.\r </dl>\r <p>\rIf a resource shortage prevents the reception of a port right, the\rport right is destroyed and the caller sees the name\rMACH_PORT_NULL. If a resource shortage prevents the reception of an\rout-of-line memory region, the region is destroyed and the caller sees\ra zero address. In addition, the corresponding element in the size\rarray is set to zero. A task never receives port rights or memory for\rwhich it is not told.\r <p>\rThe MACH_RCV_HEADER_ERROR return code indicates a resource shortage\rin the reception of the message header. The reply port and all port\rrights and memory in the message are destroyed. The caller receives\rthe message header with all fields correct except for the reply\rport.\r <p>\rThe MACH_RCV_BODY_ERROR return code indicates a resource shortage in\rthe reception of the message body. The message header, including the\rreply port, is correct. The kernel attempts to transfer all port\rrights and memory regions in the body, and only destroys those that\rcan't be transferred.\r<h4>Atomicity</h4>\r <p>\rThe <strong>mach_msg</strong> call handles port rights in the message header\ratomically. Out-of-line memory and port rights in the message body do\rnot enjoy this atomicity guarantee. These elements may be processed\rfront-to-back, back-to-front, in some random order, or even\ratomically.\r <p>\rFor example, consider sending a message with the destination port\rspecified as MACH_MSG_TYPE_MOVE_SEND and the reply port specified as\rMACH_MSG_TYPE_COPY_SEND. The same send right, with one user-refer-\rence, is supplied for both the msgh_remote_port and msgh_local_port\rfields. Because <strong>mach_msg</strong> processes the port rights atomically, this\rsucceeds. If msgh_remote_port were processed before msgh_local_port,\rthen <strong>mach_msg</strong> would return MACH_SEND_INVALID_REPLY in this situation.\r <p>\rOn the other hand, suppose the destination and reply port are both\rspecified as MACH_MSG_TYPE_MOVE_SEND, and again the same send right\rwith one user-reference is supplied for both. Now the send operation\rfails, but because it processes the rights atomically, <strong>mach_msg</strong> can\rreturn either MACH_SEND_INVALID_DEST or MACH_SEND_INVALID_REPLY.\r<p>\rFor example, consider receiving a message at the same time another\rthread is deallocating the destination receive right. Suppose the\rreply port field carries a send right for the destination port. If the\rde-allocation happens before the dequeuing, the receiver gets\rMACH_RCV_PORT_DIED. If the de-allocation happens after the receive,\rthe msgh_local_port and the msgh_remote_port fields both specify\rthe same right, which becomes a dead name when the receive right is\rde-allocated. If the de-allocation happens between the de-queue and\rthe receive, the msgh_local_port and msgh_remote_port fields both\rspecify MACH_PORT_DEAD. Because the rights are processed atomically,\rit is not possible for just one of the two fields to hold\rMACH_PORT_DEAD.\r<p>\rThe MACH_RCV_NOTIFY option provides a more likely example. Suppose a\rmessage carrying a send-once right reply port is received with\rMACH_RCV_NOTIFY at the same time the reply port is destroyed. If the\rreply port is destroyed first, then msgh_remote_port specifies\rMACH_PORT_DEAD and the kernel does not generate a dead-name\rnotification. If the reply port is destroyed after it is received,\rthen msgh_remote_port specifies a dead name for which the kernel\rgenerates a dead-name notification. Either the reply port is dead on\rarrival or notification is requested.\r<h4>Implementation</h4>\r<p>\r<strong>mach_msg</strong> and <strong>mach_msg_overwrite</strong> are wrappers for a system call. They\rhave the responsibility for repeating the interrupted system call.\r<h3>CAUTIONS</h3>\r<p>\rIf MACH_RCV_TIMEOUT is used without MACH_RCV_INTERRUPT, then the\rtimeout duration might not be accurate. When the call is interrupted\rand automatically retried, the original timeout is used. If\rinterrupts occur frequently enough, the timeout interval might never\rexpire. MACH_SEND_TIMEOUT without MACH_SEND_INTERRUPT suffers from the\rsame problem.\r<h3>RETURN VALUES</h3>\r<p>\rThe send operation can generate the following return codes. These\rreturn codes imply that the call did nothing:\r<dl>\r<p>\r<dt> MACH_SEND_MSG_TOO_SMALL\r <dd>\rThe specified send_size was smaller than the minimum size for a\rmessage.\r<p>\r<dt> MACH_SEND_NO_BUFFER\r <dd>\rA resource shortage prevented the kernel from allocating a message \rbuffer.\r<p>\r<dt> MACH_SEND_INVALID_DATA\r <dd>\rThe supplied message buffer was not readable.\r<p>\r<dt> MACH_SEND_INVALID_HEADER\r <dd>\rThe msgh_bits value was invalid.\r<p>\r<dt> MACH_SEND_INVALID_DEST\r <dd>\rThe msgh_remote_port value was invalid.\r<p>\r<dt> MACH_SEND_INVALID_NOTIFY\r <dd>\rWhen using MACH_SEND_CANCEL, the notify argument did not\rdenote a valid receive right.\r<p>\r<dt> MACH_SEND_INVALID_REPLY\r <dd>\rThe msgh_local_port value was invalid.\r<p>\r<dt> MACH_SEND_INVALID_TRAILER\r <dd>\rThe trailer to be sent does not correspond to the current kernel format, \ror the sending task does not have the privilege to supply the message \rattributes.\r </dl>\r <p>\rThese return codes imply that some or all of the message was destroyed:\r <dl>\r<p>\r<dt> MACH_SEND_INVALID_MEMORY\r <dd>\rThe message body specified out-of-line data that was not readable.\r<p>\r<dt> MACH_SEND_INVALID_RIGHT\r <dd>\rThe message body specified a port right which the caller didn't possess.\r<p>\r<dt> MACH_SEND_INVALID_TYPE\r <dd>\rA kernel processed descriptor was invalid.\r<p>\r<dt> MACH_SEND_MSG_TOO_SMALL\r <dd>\rThe last data item in the message ran over the end of the message.\r </dl>\r <p>\rThese return codes imply that the message was returned to the caller with a \rpseudo-receive operation:\r <dl>\r<p>\r<dt> MACH_SEND_TIMED_OUT\r <dd>\rThe timeout interval expired.\r<p>\r<dt> MACH_SEND_INTERRUPTED\r <dd>\rA software interrupt occurred.\r </dl>\r <p>\rThis return code implies that the message was queued:\r <dl>\r<p>\r<dt> MACH_MSG_SUCCESS\r <dd>\rThe message was queued.\r </dl>\r <p>\rThe receive operation can generate the following return codes. These return \rcodes imply that the call did not de-queue a message:\r <dl>\r<p>\r<dt> MACH_RCV_INVALID_NAME\r <dd>\rThe specified receive_name was invalid.\r<p>\r<dt> MACH_RCV_IN_SET\r <dd>\rThe specified port was a member of a port set.\r<p>\r<dt> MACH_RCV_TIMED_OUT\r <dd>\rThe timeout interval expired.\r<p>\r<dt> MACH_RCV_INTERRUPTED\r <dd>\rA software interrupt occurred.\r<p>\r<dt> MACH_RCV_PORT_DIED\r <dd>\rThe caller lost the rights specified by receive_name.\r<p>\r<dt> MACH_RCV_PORT_CHANGED\r <dd>\rreceive_name specified a receive right which was moved into a port set \rduring the call.\r<p>\r<dt> MACH_RCV_TOO_LARGE\r <dd>\rWhen using MACH_RCV_LARGE, the message was larger than \rreceive_limit. The message is left queued, and its actual size is\rreturned in the message header/message body.\r<p>\r<dt> MACH_RCV_SCATTER_SMALL\r <dd>\rWhen using MACH_RCV_LARGE with MACH_RCV_OVERWRITE, one or more scatter\rlist descriptors specified an overwrite region smaller than the\rcorresponding incoming region. The message is left queued, and the\rproper descriptors are returned in the message header/message body.\r<p>\r<dt> MACH_RCV_INVALID_TRAILER\r <dd>\rThe trailer type desired, or the number of trailer elements desired, is \rnot supported by the kernel.\r </dl>\r <p>\rThese return codes imply that a message was de-queued and destroyed:\r <dl>\r<p>\r<dt> MACH_RCV_HEADER_ERROR\r <dd>\rA resource shortage prevented the reception of the port rights in the \rmessage header.\r<p>\r<dt> MACH_RCV_INVALID_NOTIFY\r <dd>\rWhen using MACH_RCV_NOTIFY, the notify argument did not denote a\rvalid receive right.\r<p>\r<dt> MACH_RCV_INVALID_DATA\r <dd>\rThe specified message buffer was not writable.\r<p>\r<dt> MACH_RCV_TOO_LARGE\r <dd>\rWhen not using MACH_RCV_LARGE, a message larger than \rreceive_limit was de-queued and destroyed.\r<p>\r<dt> MACH_RCV_SCATTER_SMALL\r <dd>\rWhen not using MACH_RCV_LARGE with MACH_RCV_OVERWRITE, one or more\rscatter list descriptors specified an overwrite region smaller than\rthe corresponding incoming region. The message was de-queued and\rdestroyed.\r<p>\r<dt> MACH_RCV_OVERWRITE_ERROR\r <dd>\rA region specified by a receive overwrite descriptor\r(MACH_RCV_OVERWRITE) was not allocated or could not be written.\r<p>\r<dt> MACH_RCV_INVALID_TYPE\r <dd>\rWhen using MACH_RCV_OVERWRITE, one or more scatter list descriptors\rdid not have the type matching the corresponding incoming message\rdescriptor or had an invalid copy (disposition) field.\r<p>\r<dt> MACH_RCV_LIMITS\r <dd>\rThe combined size of all out-of-line memory regions or the total num-\rber of port rights in the message exceeds the limit set for the port.\rThese return codes imply that a message was received:\r<p>\r<dt> MACH_RCV_BODY_ERROR\r <dd>\rA resource shortage prevented the reception of a port right or out-of-\rline memory region in the message body.\r<p>\r<dt> MACH_MSG_SUCCESS\r <dd>\rA message was received.\r </dl>\r <p>\rResource shortages can occur after a message is de-queued, while\rtransferring port rights and out-of-line memory regions to the\rreceiving task. The <strong>mach_msg</strong> call returns MACH_RCV_HEADER_ERROR or\rMACH_RCV_BODY_ERROR in this situation. These return codes always carry\r extra bits (bitwise-or'ed) that indicate the nature of the resource\rshortage:\r <dl>\r<p>\r<dt> MACH_MSG_IPC_SPACE\r <dd>\rThere was no room in the task's IPC name space for another port name.\r<p>\r<dt> MACH_MSG_VM_SPACE\r <dd>\rThere was no room in the task's VM address space for an out-of-line \rmemory region.\r<p>\r<dt> MACH_MSG_IPC_KERNEL\r <dd>\rA kernel resource shortage prevented the reception of a port right.\r<p>\r<dt> MACH_MSG_VM_KERNEL\r <dd>\rA kernel resource shortage prevented the reception of an out-of-line \rmemory region.\r</dl>\r<h3>RELATED INFORMATION</h3>\r<p>\rFunctions:\r<a href="vm_allocate.html"><strong>vm_allocate</strong></a>,\r<a href="vm_deallocate.html"><strong>vm_deallocate</strong></a>,\r<a href="vm_write.html"><strong>vm_write</strong></a>,\r<a href="MP_request_notification.html"><strong>mach_port_request_notification</strong></a>,\r<p>\rData Structures:\rmach_msg_header.\r |