Next: Memory, Previous: Message Format, Up: Messaging Interface
Each task has its own space of port rights. Port rights are named with
positive integers. Except for the reserved values
MACH_PORT_NULL (0)
1 and MACH_PORT_DEAD (~0)
, this is a full 32-bit
name space. When the kernel chooses a name for a new right, it is free
to pick any unused name (one which denotes no right) in the space.
There are five basic kinds of rights: receive rights, send rights, send-once rights, port-set rights, and dead names. Dead names are not capabilities. They act as place-holders to prevent a name from being otherwise used.
A port is destroyed, or dies, when its receive right is deallocated. 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 deallocates the port rights and out-of-line memory in the messages.
Tasks may hold multiple user-references for send rights and dead names. When a task receives a send right which it already holds, the kernel increments the right's user-reference count. When a task deallocates a send right, the kernel decrements its user-reference count, and the task only loses the send right when the count goes to zero.
Send-once rights always have a user-reference count of one, although a port can have multiple send-once rights, because 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.
A message body can carry port rights; the msgt_name
(msgtl_name
) field in a type descriptor specifies 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 always
valid in place of a port right in a message body. In a sent message,
the following msgt_name
values denote port rights:
MACH_MSG_TYPE_MAKE_SEND
MACH_MSG_TYPE_COPY_SEND
MACH_PORT_DEAD
.
MACH_MSG_TYPE_MOVE_SEND
MACH_PORT_DEAD
.
MACH_MSG_TYPE_MAKE_SEND_ONCE
MACH_MSG_TYPE_MOVE_SEND_ONCE
MACH_PORT_DEAD
.
MACH_MSG_TYPE_MOVE_RECEIVE
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. The following
msgt_name
values in a received message indicate that it carries
port rights:
MACH_MSG_TYPE_PORT_SEND
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 new right will have a new name. If the task already has
send rights, it gains a user reference for the right (unless this would
cause the user-reference count to overflow). Otherwise, it acquires the
send right, with a user-reference count of one.
MACH_MSG_TYPE_PORT_SEND_ONCE
MACH_MSG_TYPE_MOVE_SEND_ONCE
. The
message carried a send-once right. The right will have a new name.
MACH_MSG_TYPE_PORT_RECEIVE
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 name. The make-send count of the
receive right is reset to zero, but the port retains other attributes
like queued messages, extant send and send-once rights, and requests for
port-destroyed and no-senders notifications.
When the kernel chooses a new name for a port right, it can choose any
name, other than MACH_PORT_NULL
and MACH_PORT_DEAD
, which
is not currently being used for a port right or dead name. It might
choose a name which at some previous time denoted a port right, but is
currently unused.
[1] In the Hurd system, we don't make
the assumption that MACH_PORT_NULL
is zero and evaluates to
false, but rather compare port names to MACH_PORT_NULL
explicitly