Next: Message Receive, Previous: Memory, Up: Messaging Interface [Contents][Index]
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.
Message delivery is reliable and sequenced. Messages are not lost, and messages sent to a port, from a single thread, are received in the order in which they were sent.
If the destination port’s queue is full, then 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 or
MACH_SEND_NOTIFY options are 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.
MACH_SEND_TIMEOUTThe timeout argument should specify a maximum time (in milliseconds) for
the call to block before giving up.5 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.
MACH_SEND_NOTIFYThe notify argument should specify a receive right for a notify port.
If the send were to block, then instead the message is queued,
MACH_SEND_WILL_NOTIFY is returned, and a msg-accepted
notification is requested. If MACH_SEND_TIMEOUT is also
specified, then MACH_SEND_NOTIFY doesn’t take effect until the
timeout interval elapses.
With MACH_SEND_NOTIFY, a task can forcibly queue to a send right
one message at a time. A msg-accepted notification is sent to the
notify port when another message can be forcibly queued. If an attempt
is made to use MACH_SEND_NOTIFY before then, the call returns a
MACH_SEND_NOTIFY_IN_PROGRESS error.
The msg-accepted notification carries the name of the send right. If
the send right is deallocated before the msg-accepted notification is
generated, then the msg-accepted notification carries the value
MACH_PORT_NULL. If the destination port is destroyed before the
notification is generated, then a send-once notification is generated
instead.
MACH_SEND_INTERRUPTIf specified, the mach_msg call will return
MACH_SEND_INTERRUPTED if a software interrupt aborts the call.
Otherwise, the send operation will be retried.
MACH_SEND_CANCELThe notify argument should specify a receive right for a notify port. If the send operation removes the destination port right from the caller, and the removed right had a dead-name request registered for it, and notify is the notify port for the dead-name request, then the dead-name request may be silently canceled (instead of resulting in a port-deleted notification).
This option is typically used to cancel a dead-name request made with
the MACH_RCV_NOTIFY option. It should only be used as an optimization.
The send operation can generate the following return codes. These return codes imply that the call did nothing:
MACH_SEND_MSG_TOO_SMALLThe specified send_size was smaller than the minimum size for a message.
MACH_SEND_NO_BUFFERA resource shortage prevented the kernel from allocating a message buffer.
MACH_SEND_INVALID_DATAThe supplied message buffer was not readable.
MACH_SEND_INVALID_HEADERThe msgh_bits value was invalid.
MACH_SEND_INVALID_DESTThe msgh_remote_port value was invalid.
MACH_SEND_INVALID_REPLYThe msgh_local_port value was invalid.
MACH_SEND_INVALID_NOTIFYWhen using MACH_SEND_CANCEL, the notify argument did not denote a
valid receive right.
These return codes imply that some or all of the message was destroyed:
MACH_SEND_INVALID_MEMORYThe message body specified out-of-line data that was not readable.
MACH_SEND_INVALID_RIGHTThe message body specified a port right which the caller didn’t possess.
MACH_SEND_INVALID_TYPEA type descriptor was invalid.
MACH_SEND_MSG_TOO_SMALLThe last data item in the message ran over the end of the message.
These return codes imply that the message was returned to the caller with a pseudo-receive operation:
MACH_SEND_TIMED_OUTThe timeout interval expired.
MACH_SEND_INTERRUPTEDA software interrupt occurred.
MACH_SEND_INVALID_NOTIFYWhen using MACH_SEND_NOTIFY, the notify argument did not denote a
valid receive right.
MACH_SEND_NO_NOTIFYA resource shortage prevented the kernel from setting up a msg-accepted notification.
MACH_SEND_NOTIFY_IN_PROGRESSA msg-accepted notification was already requested, and hasn’t yet been generated.
These return codes imply that the message was queued:
MACH_SEND_WILL_NOTIFYThe message was forcibly queued, and a msg-accepted notification was requested.
MACH_MSG_SUCCESSThe message was queued.
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
deallocate bit.
The pseudo-receive operation is very similar to a normal receive operation. The pseudo-receive handles the port rights in the message header as if they were in the message body. They are not reversed. 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.
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.
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 and ports involved.
If MACH_SEND_TIMEOUT is used without MACH_SEND_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.
Next: Message Receive, Previous: Memory, Up: Messaging Interface [Contents][Index]