home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 14 Text
/
14-Text.zip
/
machdocs.zip
/
manual1.doc
< prev
next >
Wrap
Internet Message Format
|
1993-02-26
|
65KB
From Pa.dec.com!nobody Thu Feb 25 20:15:32 1993
Return-Path: <Pa.dec.com!nobody>
Received: by ukelele.GCR.COM (Smail3.1.28.1 #1)
id m0nRtfn-0001S1a; Thu, 25 Feb 93 20:15 EST
Received: from inet-gw-2.pa.dec.com by uu5.psi.com (5.65b/4.0.071791-PSI/PSINet) via SMTP;
id AA01551 for spj@ukelele.GCR.COM; Thu, 25 Feb 93 19:08:59 -0500
Received: by inet-gw-2.pa.dec.com; id AA28393; Thu, 25 Feb 93 16:09:02 -0800
Date: Thu, 25 Feb 93 16:09:02 -0800
Message-Id: <9302260009.AA28393@inet-gw-2.pa.dec.com>
From: "ftpmail service on inet-gw-2.pa.dec.com" <nobody@Pa.dec.com>
To: spj@ukelele.GCR.COM
Subject: part 001 of /.0/Mach/doc/manual.doc (@gatekeeper.dec.com) [Mach Dox] (ascii)
X-Complaints-To: ftpmail-admin@inet-gw-2.pa.dec.com
X-Service-Address: ftpmail@inet-gw-2.pa.dec.com
X-Job-Number: 730680718.24209
Precedence: bulk
Reply-To: <nobody@inet-gw-2.pa.dec.com>
Content-Type: text
Content-Length: 64046
Status: O
MACH KERNEL INTERFACE MANUAL
Robert V. Baron
David Black
William Bolosky
Jonathan Chew
Richard P. Draves
David B. Golub
Richard F. Rashid
Avadis Tevanian, Jr.
Michael Wayne Young
Department of Computer Science
Carnegie-Mellon University
Pittsburgh, PA 15213
Version of:
9 January 1990
ABSTRACT
MACH is an operating system kernel under development at Carnegie-Mellon
University to support distributed and parallel computation. MACH is designed
to support computing environments consisting of networks of uniprocessors and
multiprocessors. This manual describes the interface to the MACH kernel in
detail. The MACH system currently runs on a wide variety of uniprocessor and
multiprocessor architectures.
This research was sponsored by the Defense Advanced Research Projects Agency
(DOD), ARPA Order No. 4864, monitored by the Space and Naval Warfare Systems
Command under contract N00039-84-C-0467.
The views and conclusions contained in this document are those of the authors
and should not be interpreted as representing official policies, either
expressed or implied, of the Defense Advanced Research Projects Agency or of
the U.S. Government.
1. Introduction
MACH is a communication-oriented operating system kernel providing:
- multiple tasks, each with a large, paged virtual memory space,
- multiple threads of execution within each task, with a flexible
scheduling facility,
- flexible sharing of memory between tasks,
- message-based interprocess communication,
- transparent network extensibility, and
- a flexible capability-based approach to security and protection.
MACH supports multiprocessor scheduling and is currently in use on both
general purpose multiprocessor and uniprocessor systems. MACH is currently
supported at CMU on the DEC VAX 8650, 8600, 11/785, 11/780, 11/750 and MicroVAX
II, the IBM RT/PC and the SUN 3. It also will run as a shared memory
multiprocessor system on the four processor VAX 11/784 and two processor VAX
11/782, the two processor VAX 8300, the VAX 8200 with one or more CPUs, the 20
processor Encore MultiMax and the 30 processor Sequent Balance 21000. Ports of
MACH to other computers are in progress.
1.1. Overall system organization
As a working environment for developing application programs, MACH can be
viewed as being split into two components:
- a small, extensible system kernel which provides scheduling, virtual
memory and interprocess communications and
- several, possibly parallel, operating system support environments
which provide the following two items: 1) distributed file access and
remote execution 2) emulation for established operating system
environments such as UNIX.
The extensibility of the basic MACH kernel facilitates the incorporation of
new operating system functions; user-state programs can simply be added to the
existing kernel without the need to modify the underlying kernel base. The
basic kernel abstractions have been designed in such a way as to provide for
completely transparent network extensibility of all kernel functions.
MACH is 4.3bsd UNIX binary compatible on VAX architecture machines. In
addition, the MACH environment includes an internal kernel debugger,
transparent network interprocess communication, remote execution facilities, a
transparent remote UNIX file system and support for graphics workstations.
1.2. Basic kernel functionality
The MACH kernel supports the following basic abstractions:
- A task is an execution environment and is the basic unit of resource
allocation. A task includes a paged virtual address space
(potentially sparse) and protected access to system resources (such
as processors, port capabilities and virtual memory).
- A thread is the basic unit of execution. It consists of all
processor state (e.g.hardware registers) necessary for independent
execution. A thread executes in the virtual memory and port rights
context of a single task. The conventional notion of a process is,
in MACH, represented by a task with a single thread of control.
- A port is a simplex communication channel -- implemented as a message
queue managed and protected by the kernel. A port is also the basic
object reference mechanism in MACH. Ports are used to refer to
objects; operations on objects are requested by sending messages to
the ports which represent them.
- A port set is a group of ports, implemented as a queue combining the
message queues of the constituent ports. A thread may use a port set
to receive a message sent to any of several ports.
- A message is a typed collection of data objects used in communication
between threads. Messages may be of any size and may contain inline
data, pointers to data, and capabilities for ports.
- A memory object is a secondary storage object that is mapped into a
task's virtual memory. Memory objects are commonly files managed by a
file server, but as far as the MACH kernel is concerned, a memory
object may be implemented by any object (i.e. port) that can handle
requests to read and write data.
Message-passing is the primary means of communication both among tasks, and
between tasks and the operating system kernel itself. The only functions
implemented by system traps are those directly concerned with message
communication; all the rest are implemented by messages to a task's task_port.
The MACH kernel functions can be divided into the following catagories:
- basic message primitives and support facilities,
- port and port set management facilities,
- task and thread creation and management facilities,
- virtual memory management functions,
- operations on memory objects.
MACH and other server interfaces are defined in a high-level remote procedure
call language called MIG; from that definition, interfaces for C are generated.
In the future, MIG may generate interfaces in other languages. In this manual,
calls are shown in the C language.
All MACH kernel procedures return a value indicating the success or reason
for failure of that request. The errors unique to each function are described
with those functions; however, since all requests involve primitive message
operations, errors described in that section may also apply.
1.3. User operating system environments
In addition to the facilities provided directly by the kernel, MACH also
provides for complete emulation of all 4.3bsd functions as described in the
4.3bsd manual. This emulation is completely transparent to user programs and
requires no special libraries or other utilities. On all VAX hardware MACH is
binary compatible with 4.3bsd.
This manual does not reproduce descriptions of the UNIX system calls.
Programmers wishing to use the functions provided within these environments
should consult the relevant UNIX system manuals.
2. Message primitives
2.1. Basic terms
MACH message primitives manipulate three distinct objects:
1. ports - protected kernel objects to which messages may be sent and
logically queued until reception,
2. port sets - protected kernel objects which combine multiple port
queues and from which messages may be dequeued, and
3. messages - ordered collections of typed data consisting of a fixed
size message header and a variable size message body.
2.2. Ports
Access rights to a port consist of the ability to send to, receive from, or
own that port. A task may hold just send rights or any combination of receive
and ownership rights plus send rights. Threads within a task may only refer to
ports to which that task has been given access. When a new port is created
within a task, that task is given all three access rights to that port.
The port access rights are operationally defined as follows:
Send access to a port implies that a message can be sent to that port.
Should the port be destroyed during the time a task has send
access, a message will be sent to that task by the kernel
indicating that the port has disappeared.
Receive access to a port allows a message to be dequeued from that port.
Only one task may have receive access for a given port at a
time; however, more than one thread within that task may
concurrently attempt to receive messages from a given port.
Receive access implies send rights.
Ownership of a port implies that, should the task with receive access
to that port relinquish its receive access, the receive
access to the port will be sent to the owner task. Likewise,
should ownership be relinquished, the ownership rights are
sent by the kernel to the receiving task. The name ownership
is somewhat misleading as all it really means is that the
task is a backup reciever if the current receiver gives up
its rights. As with receive access, only one task may hold
ownership access to any given port. Ownership implies send
rights. NOTE: the ownership abstraction is considered
obsolete and has been replaced with the use of a backup port.
This is a port associated with a primary port, to which the
receive rights of the primary port will be sent in the event
of an attempted destruction of the primary port. Current
versions of MACH implement both mechanisms, but the ownership
rights may disappear in future releases.
Port access rights can be passed in messages. They are interpreted by the
kernel and transferred from the sender to the kernel upon message transmission
and to the receiver upon message reception. Send rights are kept by the
original task as well as being transmitted to the receiver task, but receive
rights and ownership rights are removed from the orignal task at the time of
the send, and appear in the user task when the receive is done. During the
time between a send and receive, the kernel holds the rights and any messages
sent to the port will be queued awaiting a new task to receive on the port. If
the task that was intended to receive the rights dies before it does the
receive, the rights are handled as though the receive had been done before the
task died; that is receive rights are transferred to the owner or ownership is
transferred to the receiver. If the receiver and owner are both dead, the port
is destroyed.
The message queue associated with a port is of finite length and thus may
become full. Threads may exercise several options for handling the case of
message transmission to a full queue (see msg_send below). Unless a specific
option is set, msg_send will block until the message can be queued.
2.3. Port sets
Conceptually, a port set is a bag holding zero or more receive rights. A
port set allows a thread to block waiting for a message sent to any of several
ports. A port may be a member of at most one port set at any time.
A task's port set right, created by port_set_allocate, allows the task to
receive a message from the port set with msg_receive and manipulate the port
set with port_set_add, port_set_remove, port_set_status, and
port_set_deallocate. Unlike port rights, a port set right may not be passed in
messages.
2.4. Port names
Every task has its own port name space, used for port and port set names.
For example, one task with receive and ownership rights for a port may know the
port by the name 13, while another task with send rights for the same port may
know it by the name 17. A task only has one name for a port, so if the task
with send rights named 17 receives another message carrying send rights for the
same port, the arriving rights will also be named 17.
Typically these names are small integers, but that is implementation
dependent. When a task receives a message carrying rights for a new port, the
MACH kernel is free to choose any unused name. The port_rename call can be
used to change a task's name for a port.
2.5. Port types
There are several type defintions for ports used in this manual and defined
in <mach/port.h>. The type port_name_t is used to refer to a port to which the
task may have no rights. When this type is used in a message definition no port
rights are sent in the message and the kernel does no mapping of ports. The
type port_set_name_t is used to refer to a port set and does not imply any
rights to the set. Only port set names can be passed in messages. In order to
pass the rights to a port set, a task must pass each port separately and the
receiving port must then define a new port set with consisting of those ports.
The types port_t, port_rcv_t and port_all_t are used to imply a port to which
the task has the specified rights. Typically port_t is used for a port with any
rights. One of these types must be used in the message definition if ports
rights are to be sent in the message. All of these types are defined to be the
same basic C types, so that they can be used interchangeably in calls to
primitives.
Most of the MACH calls take a task or thread as their first argument where
this agrument is said to be the target task/thread. In most cases the task or
thread is the one doing the call. In those cases any port_name_t arguments
represent ports to which the task has or receives rights. But in the case where
task is not the caller, then the target task gets the rights but doesn't know
the name, and the caller gets the name but does not have any rights to the
port.
2.6. Messages
A message consists of a fixed header, followed by a variable amount of data.
The C type definition for the message header is as follows:
typedef struct {
int :24,
msg_simple : 8;
int msg_size;
int msg_type;
port_t msg_local_port;
port_t msg_remote_port;
int msg_id;
} msg_header_t;
The msg_local_port and msg_remote_port fields are used to name the ports on
which a message is to be received or sent. In the case of msg_receive this may
be either a port or a port set. The msg_size field is used to describe the
size of the message to be sent, or the maximum size of the message which can be
received. The size includes the header and inline data and is given in bytes.
The msg_simple field is used to indicate that no ports or out-of-line data are
contained in the body. The msg_id field may be used by user programs to
identify the meaning of this message to the intended recipient.
The variable data part of a message consists of an array of descriptors and
data. Each data descriptor is of the form:
typedef struct {
unsigned int msg_type_name : 8,
/* What kind of data */
msg_type_size : 8,
/* How many bits is each item */
msg_type_number : 12,
/* How many items are there */
msg_type_inline : 1,
/* If true, actual data follows;
* else a pointer to the data */
msg_type_longform : 1,
/* Name, size, number follow */
msg_type_deallocate : 1;
/* Deallocate port rights or memory */
} msg_type_t;
msg_type_name describes the basic type of data comprising this object.
There are several system-defined data types, including:
- Ports, including combinations of send, receive, and
ownership rights,
- Port and port set names. This is the same language
data type as port rights, but the message only
carries a task's name for a port and doesn't cause
any transferal of rights.
- Simple data types, such as integers, characters, and
floating point values.
msg_type_size indicates the size in bits of the basic object named in the
msg_type_name field.
msg_type_number indicates the number of items of the basic data type present
after the type descriptor.
msg_type_inline indicates that the actual data is included after the type
descriptor; otherwise, the word following the descriptor is a
pointer to the data to be sent.
msg_type_deallocate
indicates that the port rights and/or data pointed to in this
object are to be deallocated after the queueing of this
message. Receive and ownership rights may not be deallocated
with msg_type_deallocate.
msg_type_longform
indicates that the name, size, and number fields were too long
to fit in the structure described above. Instead, the data
type descriptor is described by the following structure:
typedef struct {
msg_type_t msg_type_header;
short msg_type_long_name;
short msg_type_long_size;
int msg_type_long_number;
} msg_type_long_t;
A data item or a pointer to data follows each data descriptor.
All the C types and constants needed to use the message functions are defined
in <mach/message.h>. The declarations in this section are taken from this file.
msg_send
#include <mach/message.h>
msg_return_t msg_send(header, option, timeout)
msg_header_t *header;
msg_option_t option;
msg_timeout_t timeout;
Arguments
header The address of the message to be sent. A message consists of
a fixed sized header followed by a variable number of data
descriptors and data items. See <mach/message.h> for a
definition of the message structure.
timeout In the event that the destination port is full and the
SEND_TIMEOUT option has been specified, this value specifies
the maximum wait time (in milliseconds).
option The failure conditions under which msg_send should terminate;
the value of this parameter is an or'ed combination of the
following two options. Unless one of the two following
values for the option parameter is explicitly specified,
msg_send does not return until the message is successfully
queued for the intended receiver.
SEND_TIMEOUT specifies that the msg_send request should terminate after
the timeout period has elapsed, even if the kernel has been
unable to queue the message.
SEND_NOTIFY allows the sender to give exactly one message to the
operating system without being suspended should the
destination port be full. When that message can in fact be
posted to the receiving port's queue, the sending task
receives a message which notifies it that another message can
be sent. A second attempt to send a message with the notify
option before the first notification arrives results in an
error. If SEND_TIMEOUT is also specified, msg_send will wait
until the specified timeout has elapsed before invoking the
SEND_NOTIFY option.
SEND_INTERRUPT Specifies that msg_send should return if a software interrupt
occurs in this thread.
MSG_OPTION_NONE A constant defined as zero which may be used to specify that
neither of the previous options are wanted.
Description
msg_send transmits a message from the current task to the remote port
specified in the message header field (msg_remote_port). The message consists
of its header, followed by a variable number of data descriptors and data
items. (See the introduction to this section for details on message
formatting.)
If the msg_local_port field is not set to PORT_NULL, send rights to that port
will be passed to the receiver of this message. The receiver task may use that
port to send a reply to this message.
If the SEND_NOTIFY option is used and this call returns a SEND_WILL_NOTIFY
code, then the user can expect to receive a notify message from the kernel.
This message will either be a NOTIFY_MSG_ACCEPTED or a NOTIFY_PORT_DELETED
message depending on what happened to the queued message. The first and only
data item in these messages is the port to which the original message was sent.
The ids and formats for these messages are defined in <mach/notify.h>.
Returns
SEND_SUCCESS The message has been queued for the destination port.
SEND_INVALID_MEMORY
The message header or body was not readable by the calling
task, or the message body specified out-of-line data which
was not readable.
SEND_INVALID_PORT
The message refers to a name for which the current task does
not have access, or to which access was explicitly removed
from the current task (see port_deallocate) while waiting for
the message to be posted, or a msg_type_name field in the
message specifies rights that the name doesn't denote in the
task (eg, specifying MSG_TYPE_SEND and supplying a port set's
name).
SEND_TIMED_OUT The message was not sent since the destination port was still
full after timeout milliseconds.
SEND_WILL_NOTIFY
The destination port was full but the SEND_NOTIFY option was
specified. A notification message will be sent when the
message can be posted.
SEND_NOTIFY_IN_PROGRESS
The SEND_NOTIFY option was specified but a notification
request is already outstanding for this thread and given
destination port.
See Also
msg_receive, msg_rpc
msg_receive
#include <mach/message.h>
#include <mach/port.h>
msg_return_t msg_receive(header, option, timeout)
msg_header_t *header; /* in/out */
msg_option_t option;
msg_timeout_t timeout;
Arguments
header The address of a buffer in which the message is to be
received. Two fields of the message header must be set
before the call is made: msg_local_port is set to the name
of the port or port set from which the message is to be
received and msg_size must be set to the maximum size of the
message that may be received. It must be less than or equal
to the size of the buffer.
timeout If RCV_TIMEOUT is specified this value is the maximum time in
milliseconds to wait for a message before giving up.
option The failure conditions under which msg_receive should
terminate; the value of this parameter is a bit or'd
combination the following two options. Unless one of the two
following values for the option parameter is explicitly
specified, msg_receive does not return until a message has
been received.
RCV_TIMEOUT Specifies that msg_receive should return when the specified
timeout elapses, if a message has not arrived by that time;
if not specified, the timeout will be ignored (i.e.
infinite).
RCV_NO_SENDERS Specifies that msg_receive should return if the receiver and
owner tasks have the only access rights to the port specified
in the message header. (Not implemented yet)
RCV_INTERRUPT Specifies that msg_receive should return when a software
interrupt has occurred in this thread.
MSG_OPTION_NONE Specifies that none of the above options are desired.
Description
msg_receive retrieves the next message from a port or port set specified in
the msg_local_port field of the specified message header. If a port is
specified, the port may not be a member of a port set. The msg_local_port
field will be set to the specific port on which the message was found.
If a port set is specified, the msg_receive will retrieve messages sent to
any of the set's member ports. It is not an error for the port set to have no
members, or for members to be added and removed from a port set while a
msg_receive on the port set is in progress.
The message consists of its header, followed by a variable amount of data;
the message header supplied to msg_receive must specify the maximum size of the
message which can be received into the buffer provided. (See the introduction
to this section for details on message formatting).
If no messages are present on the port(s) in question, msg_receive will wait
until a message arrives, or until one of the specified termination conditions
is met (see above for discussion of the option parameter).
If the received messages contains out-of-line data (i.e. for which the
msg_type_inline attribute was specified as FALSE), the data will be returned in
a newly-allocated region of memory; the message body will contain a pointer to
that new region. (See vm_allocate call for a description of the state of
newly-allocated memory.) The user may wish to deallocte this memory when the
data is no longer needed.
Returns
RCV_SUCCESS The message has been received.
RCV_INVALID_MEMORY
The message specified was not writable by the calling task.
RCV_INVALID_PORT
An attempt was made to receive on a port to which the calling
task does not have the proper access, or which was
deallocated (see port_deallocate) while waiting for a
message.
RCV_TOO_LARGE The message header and body combined are larger than the size
specified by msg_size.
RCV_NOT_ENOUGH_MEMORY
The message to be received contains more out-of-line data
than can be allocated in the receiving task.
RCV_TIMED_OUT The message was not received after timeout milliseconds.
RCV_ONLY_SENDER An attempt was made to receive on a port to which only the
receive and/or owner have access, and the RCV_NO_SENDERS
option was specified.
RCV_INTERRUPTED A software interrupt occurred.
RCV_PORT_CHANGE The port specified was moved into a port set during the
duration of the msg_receive call.
See Also
msg_rpc, msg_send
msg_rpc
#include <mach/message.h>
#include <mach/port.h>
msg_return_t msg_rpc(header, option, rcv_size,
send_timeout, rcv_timeout)
msg_header_t *header; /* in/out */
msg_option_t option;
msg_size_t rcv_size;
msg_timeout_t send_timeout;
msg_timeout_t rcv_timeout;
Arguments
header Address of a message buffer which will be used for both
msg_send and msg_receive. This buffer contains a message
header followed by the data for the message to be sent. The
msg_remote_port field specifies the port to which the message
is to be sent. The msg_local_port field specifies the port
on which a message is then to be received; if this port is
the special value PORT_DEFAULT, it will be replaced by the
value PORT_NULL for the purposes of the msg_send operation.
option A union of the option parameters for the component
operations. (see msg_send and msg_receive)
rcv_size The maximum size allowed for the received message; this must
be less than or equal to the size of the message buffer. The
msg_size field in the header specifies the size of the
message to be sent.
send_timeout;rcv_timeout
The timeout values to be applied to the component operations.
These are only used if the options SEND_TIMEOUT and/or
RCV_TIMEOUT are specified.
Description
msg_rpc is a hybrid call which performs a msg_send followed by a msg_receive,
using the same message buffer.
Returns
RPC_SUCCESS message was successfully sent and a reply was recived.
FAILURES are the same as those for msg_send and msg_receive; any error
during the msg_send portion will terminate the call.
See Also
msg_receive, msg_send
3. Port and port set primitives
port_names
#include <mach.h>
kern_return_t port_names(task,
port_names, port_namesCnt,
port_types, port_typesCnt)
task_t task;
port_name_array_t *port_names; /* out array */
unsigned int *port_namesCnt; /* out */
port_type_array_t *port_types; /* out array */
unsigned int *port_typesCnt; /* out */
Arguments
task The task whose port name space is queried.
port_names The names of the ports and port sets in the task's port name
space, in no particular order.
port_namesCnt The number of names returned.
port_types The type of each corresponding name. Indicates what kind of
right the task holds for the port or port set.
port_typesCnt Should be the same as port_namesCnt.
Description
port_names returns the currently valid ports and port set names of task. For
each name, it also returns what type of rights task holds. port_names and
port_types are arrays that are automatically allocated when the reply message
is received. The user may wish to vm_deallocate them when the data is no longer
needed.
Returns
KERN_SUCCESS The call succeeded.
KERN_INVALID_ARGUMENT
task was invalid.
See Also
port_type, port_status, port_set_status
port_type
#include <mach.h>
kern_return_t port_type(task, port_name, port_type)
task_t task;
port_name_t port_name;
port_type_t *port_type; /* out */
Arguments
task The task whose port name space is queried.
port_name The name being queried.
port_type The type of the name. Indicates what kind of right the task
holds for the port or port set.
Description
port_type returns information about task's rights for a specific name in its
port name space.
Returns
KERN_SUCCESS The call succeeded.
KERN_INVALID_ARGUMENT
task was invalid or task did not have any rights named
port_name.
See Also
port_names, port_status, port_set_status
port_rename
#include <mach.h>
kern_return_t port_rename(task, old_name, new_name)
task_t task;
port_name_t old_name;
port_name_t new_name;
Arguments
task The task whose port name space is changed.
old_name The name being changed.
new_name The new value for old_name.
Description
port_rename changes the name by which a port or port set is known to task.
new_name must not already be in use, and it can't be a distinguished value like
PORT_NULL.
Returns
KERN_SUCCESS The call succeeded.
KERN_NAME_EXISTS
task already has a right named new_name.
KERN_INVALID_ARGUMENT
task was invalid or task did not have any rights named
old_name or new_name was an invalid name.
See Also
port_names
port_allocate
#include <mach.h>
kern_return_t port_allocate(task, port_name)
task_t task;
port_name_t *port_name; /* out */
Arguments
task The task in which the new port is created.
port_name The task's name for the new port.
Description
port_allocate causes a port to be created for the specified task; the
resulting port's name is returned in port_name. The target task initially has
all three access rights to the port. If the caller is not the task specified
by task, then it does not have any rights to the port. The new port is not a
member of any port set.
Returns
KERN_SUCCESS The call succeeded.
KERN_INVALID_ARGUMENT
task was invalid.
KERN_RESOURCE_SHORTAGE
The kernel ran out of memory.
See Also
port_deallocate
port_deallocate
#include <mach.h>
kern_return_t port_deallocate(task, port_name)
task_t task;
port_name_t port_name;
Arguments
task The task from which to remove the port rights.
port_name task's name for the rights to be removed.
Description
port_deallocate requests that the target task's rights for a port be removed.
If task has receive rights for the port, and the port is a member of a port
set, the port is removed from the port set.
If the target task is both the receiver and owner for the port, then the port
is destroyed and all other tasks with send access are notified of the port's
destruction. If the task is only the receiver for the port, receive rights are
sent to the owner. If the task is only the owner of the port, ownership rights
are sent to the receiver.
Returns
KERN_SUCCESS The call succeeded.
KERN_INVALID_ARGUMENT
task was invalid or port_name does not name a valid port.
See Also
port_allocate
port_status
#include <mach.h>
kern_return_t port_status(task, port_name, enabled,
num_msgs, backlog, owner, receiver)
task_t task;
port_name_t port_name;
port_set_name_t *enabled; /* out */
int *num_msgs; /* out */
int *backlog; /* out */
boolean_t *owner; /* out */
boolean_t *receiver; /* out */
Arguments
task The task owning the port right in question.
port_name task's name for the port right.
enabled Returns task's name for the port set which the named port
belongs to, or PORT_NULL if it isn't in a set.
num_msgs The number of messages queued on this port.
backlog The number of messages which may be queued to this port
without causing the sender to block.
owner Returned as true iff the task is the owner of the port.
receiver Returned as true iff the task is the receive of the port.
Description
port_status returns the current status associated with task's port right
named port_name. If receiver isn't true, then the enabled, num_msg, and
backlog arguments don't return anything meaningful.
Returns
KERN_SUCCESS The call succeeded.
KERN_INVALID_ARGUMENT
task was invalid or port_name does not name a valid port.
See Also
port_set_backlog, port_set_status
port_set_backlog
#include <mach.h>
kern_return_t port_set_backlog(task, port_name, backlog)
task_t task;
port_name_t port_name;
int backlog;
Arguments
task The task owning the named port right.
port_name task's name for the port right.
backlog The new backlog to be set.
Description
The port's backlog value is the number of unreceived messages that are
allowed in its message queue before the kernel will refuse to accept any more
sends to that port. port_set_backlog changes the backlog value on the
specified port.
task must have receive rights for the named port.
The file <mach/mach_param.h> exports the system default value for a port's
backlog as the constant PORT_BACKLOG_DEFAULT and the maximum backlog value as
the constant PORT_BACKLOG_MAX.
Returns
KERN_SUCCESS The call succeeded.
KERN_NOT_RECEIVER
port_name doesn't name receive rights in task.
KERN_INVALID_ARGUMENT
task was invalid or port_name does not name a valid port or
the desired backlog was non-positive or the desired backlog
was greater than PORT_BACKLOG_MAX.
See Also
msg_send, port_status
port_set_backup
#include <mach.h>
kern_return_t port_set_backup(task, primary, backup, previous)
task_t task;
port_name_t primary;
port_t backup;
port_t *previous; /* out */
Arguments
task The task owning the named port right.
primary task's name for the primary port.
backup The new backup port to be set.
previous The previous backup port.
Description
A backup port provides a automatic mechanism to transfer port receive rights
to another task or thread in the event of a primary port's attempted death. To
be more precise, if a primary port has a backup port, and the primary would
have been destroyed by the deallocation of its receive rights, then instead the
receive right for the primary port is sent in a notify message
(NOTIFY_PORT_DESTROYED) to the backup port.
A newly allocated port does not have a backup port. The port_set_backup call
changes the backup of the primary port. The target task must hold receive
rights for the primary port. The caller supplies send rights for the new backup
port to which notification will be sent. The caller receives send rights for
the previous backup port or PORT_NULL if the target did not have a backup.
port_set_backup works atomically, so that if one backup port is exchanged for
another, the primary port is never left without a backup.
When the primary port is sent in a notify message to the backup port, the
primary port is left without a backup port. When the task receives the
notification and the receive rights to the primary port, it may wish to use
port_set_backup to reestablish the same or a different backup port. If the
backup port is destroyed before the primary, then the primary port is left
without a backup. (A subsequent port_set_backup call would return PORT_NULL).
Returns
KERN_SUCCESS The call succeeded.
KERN_NOT_RECEIVER
primary doesn't name receive rights in task.
KERN_INVALID_ARGUMENT
task was invalid or primary or backup do not name a valid
port.
See Also
port_deallocate
port_set_allocate
#include <mach.h>
kern_return_t port_set_allocate(task, set_name)
task_t task;
port_set_name_t *set_name; /* out */
Arguments
task The task in which the new port set is created.
set_name The task's name for the new port set.
Description
port_set_allocate causes a port set to be created for the specified task; the
resulting set's name is returned in set_name. The new port set is empty.
Returns
KERN_SUCCESS The call succeeded.
KERN_INVALID_ARGUMENT
task was invalid.
KERN_RESOURCE_SHORTAGE
The kernel ran out of memory.
See Also
port_set_deallocate
port_set_deallocate
#include <mach.h>
kern_return_t port_set_deallocate(task, set_name)
task_t task;
port_set_name_t set_name;
Arguments
task The task owning the port set to be destroyed.
set_name task's name for the doomed port set.
Description
port_set_deallocate requests that the target task's port set be destroyed.
If the port set is non-empty, any members are first removed.
Returns
KERN_SUCCESS The call succeeded.
KERN_FAILURE set_name is task's port set used for implementing the
obsolete port_enable and port_disable calls.
KERN_INVALID_ARGUMENT
task was invalid or set_name does not name a valid port set.
See Also
port_set_allocate
port_set_add
#include <mach.h>
kern_return_t port_set_add(task, set_name, port_name)
task_t task;
port_set_name_t set_name;
port_name_t port_name;
Arguments
task The task owning the port set and port right.
set_name task's name for the port set.
port_name task's name for the port.
Description
port_set_add moves the named port into the named port set. task must have
receive rights for the port.
If the port is already a member of another port set, it is removed from that
set first.
Returns
KERN_SUCCESS The call succeeded.
KERN_NOT_RECEIVER
port_name doesn't name receive rights in task.
KERN_INVALID_ARGUMENT
task was invalid or set_name does not name a valid port set
or port_name does not name a valid port.
See Also
port_set_remove
port_set_remove
#include <mach.h>
kern_return_t port_set_remove(task, port_name)
task_t task;
port_name_t port_name;
Arguments
task The task owning the receive rights and port set.
port_name task's name for the receive rights to be removed.
Description
port_set_remove removes the named port from a port set. task must have
receive rights for the port, and the port must be a member of a port set.
Returns
KERN_SUCCESS The call succeeded.
KERN_NOT_RECEIVER
port_name doesn't name receive rights in task.
KERN_NOT_IN_SET The port isn't a member of a set.
KERN_INVALID_ARGUMENT
task was invalid or port_name does not name a valid port.
See Also
port_set_add
port_set_status
#include <mach.h>
kern_return_t port_set_status(task, set_name, members, membersCnt)
task_t task;
port_set_name_t set_name;
port_name_array_t *members; /* out array */
unsigned int *membersCnt; /* out */
Arguments
task The task whose port set is queried.
set_name task's name for the port set.
members task's names for the port set's members.
membersCnt The number of port names returned.
Description
port_set_status returns the members of a port set. members is an array that
is automatically allocated when the reply message is received. The user may
wish to vm_deallocate it when the data is no longer needed.
Returns
KERN_SUCCESS The call succeeded.
KERN_INVALID_ARGUMENT
task was invalid or set_name does not name a valid port set.
See Also
port_status
port_insert
#include <mach.h>
kern_return_t port_insert_send(task, my_port, his_name)
task_t task;
port_t my_port;
port_name_t his_name;
kern_return_t port_insert_receive(task, my_port, his_name)
task_t task;
port_t my_port;
port_name_t his_name;
Arguments
task The task getting the new rights.
my_port Rights supplied by the caller.
his_name The name by which task will know the new rights.
Description
port_insert_send and port_insert_receive give a task rights with a specific
name. If task already has rights named his_name, or has some other name for
my_port, then the operation will fail. his_name can't be a distinguished value
like PORT_NULL.
port_insert_send inserts send rights, and port_insert_receive inserts receive
and ownership rights.
Returns
KERN_SUCCESS The call succeeded.
KERN_NAME_EXISTS
task already has a right named his_name.
KERN_FAILURE task already has rights to my_port.
KERN_INVALID_ARGUMENT
task was invalid or new_name was an invalid name.
Notes
There is no way to insert just receive rights or just ownership rights.
See Also
port_extract_send, port_extract_receive
port_extract
#include <mach.h>
kern_return_t port_extract_send(task, his_name, his_port)
task_t task;
port_name_t his_name;
port_t *his_port; /* out */
kern_return_t port_extract_receive(task, his_name, his_port)
task_t task;
port_name_t his_name;
port_t *his_port; /* out */
Arguments
task The task whose rights the caller takes.
his_name The name by which task knows the rights.
his_port Rights returned to the caller.
Description
port_extract_send and port_extract_receive remove task's rights for a port
and return the rights to the caller. task is left with no rights for the port.
port_extract_send extracts send rights; task can't have receive or ownership
rights for the named port. port_extract_receive extracts receive/ownership
rights, both of which task must hold.
Returns
KERN_SUCCESS The call succeeded.
KERN_INVALID_ARGUMENT
task was invalid or his_name does not name a port for which
task has the required rights.
Notes
There is no way to extract just receive rights or just ownership rights.
See Also
port_insert_send, port_insert_receive
4. Task and thread primitives
4.1. Basic terms
The MACH system separates the traditional notion of a process into two
subconcepts:
- Tasks contain the capabilities, namely the port rights, resource
limits, and address space of a running entity. Tasks perform no
computation; they are a framework for running threads.
- Threads contain the minimal processing state associated with a
computation, e.g. a program counter, a stack pointer, and a set of
registers. A thread exists within exactly one task; however, one
task may contain many threads.
Tasks are the basic unit of protection. All threads within a task have
access to all of that task's capabilities, and are thus not protected from each
other.
Threads are the basic unit of scheduling. On a multiprocessor host, multiple
threads from one task may be executing simultaneously (within the task's one
address space). A thread may be in a suspended state (prevented from running),
or in a runnable state (may be running or be scheduled to run). There is a
non-negative suspend count associated with each thread. The suspend count is
zero for runnable threads and positive for suspended threads.
Tasks may be suspended or resumed as a whole. A thread may only execute when
both it and its task are runnable. Resuming a task does not cause all
component threads to begin executing, but only those threads which are not
suspended.
Both tasks and threads are represented by ports. These ports are called the
task kernel port and the thread kernel port. These are the handles that are
used in the task and thread kernel calls to identify to the kernel which task
or thread is to be affected by the call. The two primitives task_self() and
thread_self() return the task and thread ports of the currently executing
thread. Tasks may have access to the task and thread ports of other tasks and
threads. For example, a task that creates another task or thread gets access to
the new task or thread port. Also any thread may pass access to these ports in
a message to another thread in the same or different task. Having access to a
task or thread port enables the possessor to perform kernel calls on behalf of
that task or thread. Access to a task's kernel port indirectly permits access
to all threads within that task via the task_threads call; however, access to a
thread's kernel port does not currently imply access to its task port.
In addition to their kernel ports, tasks and threads have a number of special
ports associated with them. In general these are ports that the kernel must
know about in order to communicate with the task or thread in a structured
manner.
There are three ports associated with a task in addition to its kernel port:
- The notify port, on which the task should attempt to receive
notification of such kernel events as the destruction of a port to
which it has send rights. The task has receive rights to this port
and can get its value from the primitive task_notify().
- The exception port, to which the kernel sends messages when an
exception occurs. Exceptions are synchronous interuptions to the
normal flow of program control caused by the program itself. They
include illegal memory accesses, protection violations, arithmetic
exceptions, and hardware instructions intended to support emulation,
debugging and/or error detection. Some of these exceptions are
handled transparently by the operating system but some must be
reported to the user program. A default exception port is inherited
from the parent at task creation time. This port can be changed by
the task or any one of its threads in order to take an active role in
handling exceptions.
- The bootstrap port, to which a new task can send a message that will
return any other system service ports that the task needs, for
example a port to the Network Nameserver or the Environment Manager.
Send rights to this port are inherited from the parent at task
creation. This is the one port that the kernel does not actually
use, it just makes it available to a new task.
There are two ports associated with a thread in addition to its kernel port:
- The thread reply port, which may be used for initial messages from a
parent or for early remote procedure calls. The thread_reply()
primitive returns receive rights to this port.
- The thread exception port, to which kernel sends exceptions occuring
in this thread. This port is set to PORT_NULL at thread creation and
can be set subsequently by the call thread_set_exception_port. As
long as the thread exception port is PORT_NULL the task exception
port will be used instead.
4.2. Access to Tasks: Terminology
In this and following sections, calls are described which may manipulate the
state of a task. Although some of the descriptions may refer to tasks as
performing these calls, it is in fact some thread within a task which makes any
call.
Furthermore, any thread within any task which holds access rights to that
task (i.e. task kernel port) may perform calls which take a task as an
argument. Customarily, only threads within a task will manipulate that task's
state, but this custom is not enforced by the MACH kernel. Debugger tasks are a
notable exception to this rule. Similarly, access to a thread is controlled by
access to its thread kernel port.
task_create
#include <mach.h>
kern_return_t task_create(parent_task, inherit_memory,
child_task)
task_t parent_task
boolean_t inherit_memory;
task_t *child_task; /* out */
Arguments
target_task The task from which the child's capabilities are drawn.
inherit_memory If set, the child task's address space is built from the
parent task according to its memory inheritance values;
otherwise, the child task is given an empty address space.
child_task The new task.
Description
task_create creates a new task from parent_task; the resulting task
(child_task) acquires shared or copied parts of the parent's address space (see
vm_inherit). The child task initially contains no threads.
The child task gets the four special ports created or copied for it at task
creation. The task_kernel_port is created and send rights for it are given to
the child and returned to the caller. The task_notify_port is created and
receive, ownership and send rights for it are given to the child. The caller
has no access to it. The task_bootstrap_port and the task_exception_port are
inherited from the parent task. The new task can get send rights to these
ports with the call task_get_special_port.
Returns
KERN_SUCCESS A new task has been created.
KERN_INVALID_ARGUMENT
parent_task is not a valid task port.
KERN_RESOURCE_SHORTAGE
Some critical kernel resource is unavailable.
See Also
task_terminate, task_suspend, task_resume, task_special_ports, task_threads,
thread_create, thread_resume, vm_inherit
Notes
Not implemented yet. Use fork.
task_terminate
#include <mach.h>
kern_return_t task_terminate(target_task)
task_t target_task;
Arguments
target_task The task to be destroyed.
Description
task_terminate destroys the task specified by target_task and all its
threads. All resources that are used only by this task are freed. Any port to
which this task has receive and ownership rights is destroyed.
Returns
KERN_SUCCESS The task has been killed.
KERN_INVALID_ARGUMENT
target_task is not a task.
See Also
task_create, task_suspend, task_resume, thread_terminate, thread_suspend
Notes
Not implemented yet.
task_suspend
#include <mach.h>
kern_return_t task_suspend(target_task)
task_t target_task;
Arguments
target_task The task to be suspended.
Description
Increments the task's suspend count and stops all threads in the task. As
long as the suspend count is positive newly created threads will not run. This
call does not return until all threads are suspended.
The count may become greater than one, with the effect that it will take more
than one resume call to restart the task.
Returns
KERN_SUCCESS The task has been suspended.
KERN_INVALID_ARGUMENT
target_task is not a task.
See Also
task_create, task_terminate, task_resume, task_info, thread_suspend
task_resume
#include <mach.h>
kern_return_t task_resume(target_task)
task_t target_task;
Description
Decrements the task's suspend count. If it becomes zero, all threads with
zero suspend counts in the task are resumed. The count may not become negative.
Arguments
target_task The task to be resumed.
Returns
KERN_SUCCESS The task has been resumed.
KERN_FAILURE The suspend count is already at zero.
KERN_INVALID_ARGUMENT
target_task is not a task.
See Also
task_create, task_terminate, task_suspend, task_info, thread_suspend,
thread_resume, thread_info
task_special_ports
#include <mach.h>
kern_return_t task_get_special_port(task, which_port, special_port)
task_t task;
int which_port;
port_t *special_port; /* out */
kern_return_t task_set_special_port(task, which_port, special_port)
task_t task;
int which_port;
port_t special_port;
task_t task_self()
port_t task_notify()
Arguments
task The task for which to get the port
which_port the port that is requested. Is one of TASK_NOTIFY_PORT,
TASK_BOOTSTRAP_PORT, TASK_EXCEPTION_PORT.
special_port the value of the port that is being requested or being set.
Description
get_special_port returns send rights to one of a set of special ports for the
task specified by task. In the case of the task's own task_notify_port, the
task also gets receive and ownership rights.
set_special_port sets one of a set of special ports for the task specified by
task.
task_self returns the port to which kernel calls for the currently executing
thread should be directed. Currently, task_self returns the task kernel port
which is a port for which the kernel has receive rights and which it uses to
identify a task. In the future it may be possible for one task to interpose a
port as another's task's kernel port. At that time, task_self will still return
the port to which the executing thread should direct kernel calls, but it may
no longer be a port on which the kernel has receive rights.
If one task, the controller, has send access to the kernel port of another
task, the subject task, then the controller task can perform kernel operations
for the subject task. Normally only the task itself and the task that created
it will have access to the task kernel port, but any task may pass rights to
its kernel port to any other task.
task_notify returns receive, ownership and send rights to the notify port
associated with the task to which the executing thread belongs. The notify port
is a port on which the task should receive notification of such kernel events
of the destruction of a port to which it has send rights.
The other special ports associated with a task are the bootstrap port and the
exception port. The bootstrap port is a port to which a thread may send a
message requesting other system service ports. This port is not used by the
kernel. The task's exception port is the port to which messages are sent by the
kernel when an exception occurs and the thread causing the exception has no
exception port of its own.
Within the C environment, task_self and task_notify are implemented as macros
which execute the system traps the first time and thereafter return a cached
value for the ports. Thus it is unnecessary for a programmer to cache these
variables himself and such caching may interfere with the future implementation
of port interposition.
The following macros to call task_set/get_special_port for a specific port
are defined in <mach/task_special_ports.h>: task_get_notify_port,
task_set_notify_port, task_get_exception_port, task_set_exception_port,
task_get_bootstrap_port and task_set_bootstrap_port.
Returns
KERN_SUCCESS The port was returned or set.
KERN_INVALID_ARGUMENT
task is not a task or which_port is an invalid port selector.
See Also
thread_special_ports,mach_init,task_create
Notes
The call on the bootstrap port to get system service ports has not been
implemented yet.
TASK_KERNEL_PORT may be added to the set of ports that task_set_special_port
accepts.
task_info
#include <mach.h>
/* the definition of task_info_t from mach.h - mach/task_info.h is */
typedef int *task_info_t; /* variable length array of int */
/* currently the only interpretation of info is */
struct task_basic_info {
int suspend_count; /* suspend count for task */
vm_size_t virtual_size; /* number of virtual pages */
vm_size_t resident_size; /* number of resident pages */
time_value_t user_time; /* total user run time for
terminated threads */
time_value_t system_time; /* total system run time for
terminated threads */
};
typedef struct task_basic_info *task_basic_info_t;
kern_return_t task_info(target_task, flavor, task_info, task_infoCnt)
task_t target_task;
int flavor;
task_info_t task_info; /* in and out */
unsigned int *task_infoCnt; /* in and out */
Arguments
target_task The task to be affected.
flavor The type of statistics that are wanted. Currently only
TASK_BASIC_INFO is implemented.
task_info Statistics about the task specified by target_task.
task_infoCnt Size of the info structure. Currently only
TASK_BASIC_INFO_COUNT is implemented.
Description
Returns the selected information array for a task, as specified by flavor.
task_info is an array of integers that is supplied by the caller, and filled
with specified information. task_infoCnt is supplied as the maximum number of
integers in task_info. On return, it contains the actual number of integers in
task_info.
Currently there is only one flavor of information which is defined by
TASK_BASIC_INFO. Its size is defined by TASK_BASIC_INFO_COUNT.
Returns
KERN_SUCCESS The call succeeded.
KERN_INVALID_ARGUMENT
target_task is not a task or flavor is not recognized.
MIG_ARRAY_TOO_LARGE
Returned info array is too large for task_info. task_info is
filled as much as possible. task_infoCnt is set to the
number of elements that would be returned if there were
enough room.
See Also
task_special_ports, task_threads, thread_info, thread_state
task_threads
#include <mach.h>
kern_return_t task_threads(target_task, thread_list, thread_count)
task_t target_task;
thread_array_t *thread_list; /* out, ptr to array */
int *thread_count; /* out */
Arguments
target_task The task to be affected.
thread_list The set of threads contained within target_task; no
particular ordering is guaranteed.
thread_count The number of threads in the thread_list.
Description
task_threads gets send rights to the kernel port for each thread contained in
target_task. thread_list is an array that is created as a result of this call.
The caller may wish to vm_deallocate this array when the data is no longer
needed.
Returns
KERN_SUCCESS The call succeeded.
KERN_INVALID_ARGUMENT
target_task is not a task.
See Also
thread_create, thread_terminate, thread_suspend
thread_create
#include <mach.h>
kern_return_t thread_create(parent_task, child_thread)
task_t parent_task;
thread_t *child_thread; /* out */
Description
thread_create creates a new thread within the task specified by parent_task.
The new thread has no processor state, and has a suspend count of 1. To get a