Next: Message Receive, Previous: Memory, Up: Messaging Interface
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_TIMEOUT
MACH_SEND_TIMED_OUT
. A zero timeout is legitimate.
MACH_SEND_NOTIFY
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_INTERRUPT
mach_msg
call will return
MACH_SEND_INTERRUPTED
if a software interrupt aborts the call.
Otherwise, the send operation will be retried.
MACH_SEND_CANCEL
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_SMALL
MACH_SEND_NO_BUFFER
MACH_SEND_INVALID_DATA
MACH_SEND_INVALID_HEADER
msgh_bits
value was invalid.
MACH_SEND_INVALID_DEST
msgh_remote_port
value was invalid.
MACH_SEND_INVALID_REPLY
msgh_local_port
value was invalid.
MACH_SEND_INVALID_NOTIFY
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_MEMORY
MACH_SEND_INVALID_RIGHT
MACH_SEND_INVALID_TYPE
MACH_SEND_MSG_TOO_SMALL
These return codes imply that the message was returned to the caller with a pseudo-receive operation:
MACH_SEND_TIMED_OUT
MACH_SEND_INTERRUPTED
MACH_SEND_INVALID_NOTIFY
MACH_SEND_NOTIFY
, the notify argument did not denote a
valid receive right.
MACH_SEND_NO_NOTIFY
MACH_SEND_NOTIFY_IN_PROGRESS
These return codes imply that the message was queued:
MACH_SEND_WILL_NOTIFY
MACH_MSG_SUCCESS
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.
[1] 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.