Next: Memory, Previous: Message Format, Up: Messaging Interface [Contents][Index]
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)
3 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
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.
MACH_MSG_TYPE_COPY_SEND
The message will carry a send right, and the caller should 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
.
MACH_MSG_TYPE_MOVE_SEND
The message will carry a send right, and the caller should 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
.
MACH_MSG_TYPE_MAKE_SEND_ONCE
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.
MACH_MSG_TYPE_MOVE_SEND_ONCE
The message will carry a send-once right, and the caller should 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
.
MACH_MSG_TYPE_MOVE_RECEIVE
The message will carry a receive right, and the caller should supply a receive right. The caller loses the supplied receive right, but retains any send rights with the same name.
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
This name 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 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
This name is an alias for 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
This name 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 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.
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
Next: Memory, Previous: Message Format, Up: Messaging Interface [Contents][Index]