home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 14 Text
/
14-Text.zip
/
machdocs.zip
/
manual2.doc
< prev
next >
Wrap
Internet Message Format
|
1993-02-26
|
65KB
From Pa.dec.com!nobody Thu Feb 25 20:15:35 1993
Return-Path: <Pa.dec.com!nobody>
Received: by ukelele.GCR.COM (Smail3.1.28.1 #1)
id m0nRtfq-0001S0a; 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 AA01560 for spj@ukelele.GCR.COM; Thu, 25 Feb 93 19:09:07 -0500
Received: by inet-gw-2.pa.dec.com; id AA28402; Thu, 25 Feb 93 16:09:11 -0800
Date: Thu, 25 Feb 93 16:09:11 -0800
Message-Id: <9302260009.AA28402@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 002 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: 64036
Status: O
new thread to run, first thread_create is called to get the new thread's
identifier,(child_thread). Then thread_set_state is called to set a processor
state, and finally thread_resume is called to get the thread scheduled to
execute.
When the thread is created send rights to its thread kernel port are given to
it and returned to the caller in child_thread. The new thread's exception port
is set to PORT_NULL.
Arguments
parent_task The task which is to contain the new thread.
child_thread The new thread.
Returns
KERN_SUCCESS A new thread has been created.
KERN_INVALID_ARGUMENT
parent_task is not a valid task.
KERN_RESOURCE_SHORTAGE
Some critical kernel resource is not available.
See Also
task_create, task_threads, thread_terminate, thread_suspend, thread_resume,
thread_special_ports, thread_set_state
thread_terminate
#include <mach.h>
kern_return_t thread_terminate(target_thread)
thread_t target_thread;
Arguments
target_thread The thread to be destroyed.
Description
thread_terminate destroys the thread specified by target_thread.
Returns
KERN_SUCCESS The thread has been killed.
KERN_INVALID_ARGUMENT
target_thread is not a thread.
See Also
task_terminate, task_threads, thread_create, thread_resume, thread_suspend
thread_suspend
#include <mach.h>
kern_return_t thread_suspend(target_thread);
thread_t target_thread;
Arguments
target_thread The thread to be suspended.
Description
Increments the thread's suspend count and prevents the thread from executing
any more user level instructions. In this context a user level instruction is
either a machine instruction executed in user mode or a system trap instruction
including page faults. Thus if a thread is currently executing within a system
trap the kernel code may continue to execute until it reaches the system return
code or it may supend within the kernel code. In either case, when the thread
is resumed the system trap will return. This could cause unpredictible results
if the user did a suspend and then altered the user state of the thread in
order to change its direction upon a resume. The call thread_abort is provided
to allow the user to abort any system call that is in progress in a predictable
way.
The suspend count may become greater than one with the effect that it will
take more than one resume call to restart the thread.
Returns
KERN_SUCCESS The thread has been suspended.
KERN_INVALID_ARGUMENT
target_thread is not a thread.
See Also
task_suspend, task_resume, thread_info, thread_state, thread_resume,
thread_terminate, thread_abort
thread_resume
#include <mach.h>
kern_return_t thread_resume(target_thread)
thread_t target_thread;
Arguments
target_thread The thread to be resumed.
Description
Decrements the threads's suspend count. If the count becomes zero the thread
is resumed. If it is still positive, the thread is left suspended. The suspend
count may not become negative.
Returns
KERN_SUCCESS The thread has been resumed.
KERN_FAILURE The suspend count is already zero.
KERN_INVALID_ARGUMENT
target_thread is not a thread.
See Also
task_suspend, task_resume thread_info, thread_create, thread_terminate,
thread_suspend
thread_abort
#include <mach.h>
kern_return_t thread_abort(target_thread)
thread_t target_thread;
Arguments
target_thread The thread to be interrupted.
Description
thread_abort aborts the kernel primitives: msg_send, msg_receive and msg_rpc
and page-faults, making the call return a code indicating that it was
interrupted. The call is interrupted whether or not the thread (or task
containing it) is currently suspended. If it is supsended, the thread receives
the interupt when it is resumed.
A thread will retry an aborted page-fault if its state is not modified before
it is resumed. Msg_send returns SEND_INTERRUPTED; msg_receive returns
RCV_INTERRUPTED; msg_rpc returns either SEND_INTERRUPTED or RCV_INTERRUPTED,
depending on which half of the RPC was interrupted.
The main reason for this primitive is to allow one thread to cleanly stop
another thread in a manner that will allow the future execution of the target
thread to be controlled in a predictable way. thread_suspend keeps the target
thread from executing any further instructions at the user level, including the
return from a system call. thread_get/set_state allows the examination or
modification of the user state of a target thread. However, if a suspended
thread was executing within a system call, it also has associated with it a
kernel state. This kernel state can not be modified by thread_set_state with
the result that when the thread is resumed the system call may return changing
the user state and possibly user memory. thread_abort aborts the kernel call
from the target thread's point of view by resetting the kernel state so that
the thread will resume execution at the system call return with the return code
value set to one of the interrupted codes. The system call itself will either
be entirely completed or entirely aborted, depending on the precise moment at
which the abort was received. Thus if the thread's user state has been changed
by thread_set_state, it will not be modified by any unexpected system call side
effects.
For example to simulate a Unix signal, the following sequence of calls may be
used:
thread_suspend Stops the thread
thread_abort Interrupts any system call in progress, setting the return value
to 'interrupted'. Since the thread is stopped, it will not return to user
code.
thread_set_state Alters thread's state to simulate a procedure call to the
signal handler
thread_resume Resumes execution at the signal handler. If the thread's stack
has been correctly set up, the thread may return to the interrupted system
call.
(of course, the code to push an extra stack frame and change the registers is
VERY machine-dependent.)
Calling thread_abort on a non-suspended thread is pretty risky, since it is
very difficult to know exactly what system trap, if any, the thread might be
executing and whether an interrupt return would cause the thread to do
something useful.
Returns
KERN_SUCCESS The thread received an interrupt
KERN_INVALID_ARGUMENT
target_thread is not a thread.
See Also
thread_info, thread_state, thread_terminate, thread_suspend
thread_special_ports
#include <mach.h>
kern_return_t thread_get_special_port(thread, which_port, special_port)
thread_t thread;
int which_port;
port_t *special_port;
kern_return_t thread_set_special_port(thread, which_port, special_port)
thread_t thread;
int which_port;
port_t special_port;
thread_t thread_self()
port_t thread_reply()
Arguments
thread The thread for which to get the port
which_port the port that is requested. Is one of THREAD_REPLY_PORT or
THREAD_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
thread specified by thread. In the case of getting the thread's own
thread_reply_port, receive and ownership rights are also given to the thread.
set_special_port sets one of a set of special ports for the thread specified
by thread.
thread_self returns the port to which kernel calls for the currently
executing thread should be directed. Currently, thread_self returns the thread
kernel port which is a port for which the kernel has receive rights and which
it uses to identify a thread. In the future it may be possible for one thread
to interpose a port as another's thread's kernel port. At that time,
thread_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 thread, the controller, has send access to the kernel port of another
thread, the subject thread, then the controller thread can perform kernel
operations for the subject thread. Normally only the thread itself and its
parent task will have access to the thread kernel port, but any thread may pass
rights to its kernel port to any other thread.
thread_reply returns receive, ownership and send rights to the reply port of
the calling thread. The reply port is a port to which the thread has receive
rights. It is used to receive any initialization messages and as a reply port
for early remote procedure calls.
The following macros to call thread_get/set_special_port for a specific port
are defined in <mach/thread_special_ports.h>: thread_get_reply_port,
thread_set_reply_port, thread_get_exception_port and thread_set_exception_port.
A thread also has access to its task's special ports.
Returns
KERN_SUCCESS The port was returned or set.
KERN_INVALID_ARGUMENT
thread is not a thread or which_port is an invalid port
selector.
See Also
task_special_ports,thread_create
Notes
THREAD_KERNEL_PORT may be added to the set of ports that
thread_set_special_port accepts.
thread_info
#include <mach.h>
/* the definition of thread_info_data_t from mach.h - mach/thread_info.h is */
typedef int *thread_info_t; /* variable length array of int */
/* only current interpretation of thread_info */
struct thread_basic_info {
time_value_t user_time; /* user run time */
time_value_t system_time; /* system run time */
int cpu_usage; /* scaled cpu usage percentage */
int base_priority; /* base scheduling priority */
int cur_priority; /* current scheduling priority */
int run_state; /* run state (see below) */
int flags; /* various flags (see below) */
int suspend_count; /* suspend count for thread */
long sleep_time; /* number of seconds that thread
has been sleeping */
};
typedef struct thread_basic_info *thread_basic_info_t;
The possible values of the run_state field are:
TH_STATE_RUNNING, thread is running normally
TH_STATE_STOPPED, thread is suspended
TH_STATE_WAITING, thread is waiting normally
TH_STATE_UNINTERRUPTIBLE, thread is in an uninterruptible wait
TH_STATE_HALTED, thread is halted at a clean point
The possible values of the flags field are:
TH_FLAGS_SWAPPED, thread is swapped out
TH_FLAGS_IDLE, thread is an idle thread
kern_return_t thread_info(target_thread, flavor, thread_info,
thread_infoCnt)
thread_t target_thread;
int flavor;
thread_info_t thread_info; /* in and out */
unsigned int *thread_infoCnt; /* in and out */
Arguments
target_thread The thread to be affected.
flavor The type of statistics that are wanted. Currently only
THREAD_BASIC_INFO is implemented.
thread_info Statistics about the thread specified by target_thread.
thread_infoCnt Size of the info structure. Currently only
THREAD_BASIC_INFO_COUNT is implemented.
Description
Returns the selected information array for a thread, as specified by flavor.
thread_info is an array of integers that is supplied by the caller and returned
filled with specified information. thread_infoCnt is supplied as the maximum
number of integers in thread_info. On return, it contains the actual number of
integers in thread_info.
Currently there is only one flavor of information which is defined by
THREAD_BASIC_INFO. Its size is defined by THREAD_BASIC_INFO_COUNT.
Returns
KERN_SUCCESS The call succeeded.
KERN_INVALID_ARGUMENT
target_thread is not a thread or flavor is not recognized.
MIG_ARRAY_TOO_LARGE
Returned info array is too large for thread_info. thread_info
is filled as much as possible. thread_infoCnt is set to the
number of elements that would have been returned if there
were enough room.
See Also
thread_special_ports, task_threads, task_info, thread_state
thread_state
#include <mach.h>
kern_return_t thread_get_state(target_thread, flavor, old_state,
old_stateCnt)
thread_t target_thread;
int flavor;
thread_state_data_t old_state; /* in and out */
unsigned int *old_stateCnt; /* in and out */
kern_return_t thread_set_state(target_thread, flavor, new_state,
new_stateCnt)
thread_t target_thread;
int flavor;
thread_state_data_t new_state;
unsigned int new_stateCnt;
Arguments
target_thread thread to get or set the state for.
flavor The type of state that is to be manipulated. Currently must
be one of the following values: VAX_THREAD_STATE,
ROMP_THREAD_STATE, SUN_THREAD_STATE_REGS,
SUN_THREAD_STATE_FPA
new_state an array of state information
old_state an array of state information
new_stateCnt the size of the state information array. Currently must be
one of the following values: VAX_THREAD_STATE_COUNT,
ROMP_THREAD_STATE_COUNT, SUN_THREAD_STATE_REGS_COUNT,
SUN_THREAD_STATE_FPA_COUNT
old_stateCnt same as new_stateCnt
Description
thread_get_state returns the state component (e.g. the machine registers) of
target_thread as specified by flavor. The old_state is an array of integers
that is provided by the caller and returned filled with the specified
information. old_stateCnt is input set to the maximum number of integers in
old_state and returned equal to the actual number of integers in old_state.
thread_set_state sets the state component (e.g. the machine registers) of
target_thread as specified by flavor. The new_state is an array of integers.
new_stateCnt is the number of elements in new_state. The entire set of
registers is reset. This will do unpredictable things if target_thread is not
suspended.
target_thread may not be thread_self for either of these calls.
The definition of the state structures can be found in
<machine/thread_status.h>
Returns
KERN_SUCCESS The state has been set or returned
MIG_ARRAY_TOO_LARGE
Returned state is too large for the new_state array.
new_state is filled in as much as possible and new_stateCnt
is set to the number of elements that would be returned if
there were enough room.
KERN_INVALID_ARGUMENT
target_thread is not a thread or is thread_self or flavor is
unrecogized for this machine.
See Also
task_info, thread_info
5. Virtual memory primitives
5.1. Basic terms
Each MACH task has a large virtual address space within which its threads
execute. A virtual address space is divided into fixed size pages. The size of
a virtual page is set at system initialization and may differ on different
machines. A virtual address space may be sparse, that is, there may be ranges
of addresses which are not allocated followed by ranges that are allocated.
A task may allocate virtual memory in its address space; physical memory will
be acquired only when necessary, and seldom-used memory may be paged to backing
storage.
A region of an address space is that memory associated with a continuous
range of addresses; that is, a start address and an end address. The MACH
kernel will extend regions to include entire virtual memory pages containing
the first and last address in a specified range. Regions consist of pages
which have different protection or inheritance characteristics.
A task may protect the virtual pages of its address space to allow/prevent
access to that memory. The current protection is used to determine the access
rights of an executing thread. In addition, a maximum protection value limits
the current protection.
A task may specify that pages of its address space be inherited by child
tasks in one of three ways: shared, copied, or absent. Inheritance may be
changed at any time; only at the time of task creation is inheritance
information used. The only way two MACH tasks can share the same physical
memory is for one of the tasks to inherit shared access to memory from a
parent. When a child task inherits memory from a parent, it gets the same
protection on that memory that its parent had.
Protection and inheritance is attached to a task's address space, not the
physical memory contained in that address space. Tasks which share memory may
specify different protection or inheritance for their shared regions.
Physical pages in an address space have paging objects associated with them.
These objects identify the backing storage to be used when a page is to be read
in as the result of a reference or written to in order to free physical memory.
A paging object is identified outside of the kernel by an unforgeable
identifier (implemented as a port which is only used for identification and not
message transmission), and inside the kernel by a data transmission port, that
will respond to get and put page calls.
In addition to memory explicitly allocated using vm_allocate, memory may
appear in a task's address space as the result of a msg_receive operation.
vm_allocate
#include <mach.h>
kern_return_t vm_allocate(target_task, address, size, anywhere)
vm_task_t target_task;
vm_address_t *address; /* in/out */
vm_size_t size;
boolean_t anywhere;
Arguments
target_task Task whose virtual address space is to be affected.
address Starting address. If the anywhere option is false, an
attempt is made to allocate virtual memory starting at this
virtual address. If this address is not at the beginning of a
virtual page, it will be rounded down to one. If there is
not enough space at this address, no memory will be
allocated. If the anywhere option is true, the input value
of this address will be ignored, and the space will be
allocated wherever it is available. In either case, the
address at which memory was actually allocated will be
returned in address.
size Number of bytes to allocate (rounded by the system in a
machine dependent way to an integral number of virtual
pages).
anywhere If true, the kernel should find and allocate any region of
the specified size, and return the address of the resulting
region in address. If false, virtual memory will be
allocated starting at address, rounded to a virtual page
boundary if there is sufficient space.
Description
vm_allocate allocates a region of virtual memory, placing it in the specified
task's address space. The physical memory is not actually allocated until the
new virtual memory is referenced. By default, the kernel rounds all addresses
down to the nearest page boundary and all memory sizes up to the nearest page
size. The global variable vm_page_size contains the page size. task_self_
returns the value of the current task port which should be used as the
target_task argument in order to allocate memory in the caller's address space.
For languages other than C, these values can be obtained by the calls
vm_statistics and task_self. Initially, the pages of allocated memory will be
protected to allow all forms of access, and will be inherited in child tasks as
a copy. Subsequent calls to vm_protection and vm_inheritance may be used to
change these properties. The allocated region is always zero-filled.
Returns
KERN_SUCCESS Memory allocated.
KERN_INVALID_ADDRESS
Illegal address specified.
KERN_NO_SPACE Not enough space left to satisfy this request
See Also
vm_deallocate, vm_inherit, vm_protect, vm_regions, vm_statistics, task_self_
vm_deallocate
#include <mach.h>
kern_return_t vm_deallocate(target_task, address, size)
vm_task_t target_task;
vm_address_t address;
vm_size_t size;
Arguments
target_task Task whose virtual memory is to be affected.
address Starting address (will be rounded down to a page boundary).
size Number of bytes to deallocate (will be rounded up to give a
page boundary).
Description
vm_deallocate relinquishes access to a region of a task's address space,
causing further access to that memory to fail. This address range will be
available for reallocation. Note, that because of the rounding to virtual page
boundaries, more than size bytes may be deallocated. Use vm_page_size or
vm_statistics to find out the current virtual page size.
This call may be used to deallocte memory that was passed to a task in a
message (via out of line data). In that case, the rounding should cause no
trouble, since the region of memory was allocated as a set of pages.
The vm_deallocate call affects only the task specified by the target_task.
Other tasks which may have access to this memory may continue to reference it.
Returns
KERN_SUCCESS Memory deallocated.
KERN_INVALID_ADDRESS
Illegal or non-allocated address specified.
See Also
vm_allocate, vm_statistics, msg_receive
vm_read
#include <mach.h>
kern_return_t vm_read(target_task, address, size, data, data_count)
vm_task_t target_task
vm_address_t address;
vm_size_t size;
pointer_t *data; /* out */
int *data_count; /* out */
Arguments
target_task Task whose memory is to be read.
address The first address to be read (must be on a page boundary).
size The number of bytes of data to be read (must be an integral
number of pages)
data The array of data copied from the given task.
data_count The size of the data array in bytes. (will be an integral
number of pages).
Description
vm_read allows one task's virtual memory to be read by another task. Note
that the data array is returned in a newly allocated region; the task reading
the data should vm_deallocate this region when it is done with the data.
Returns
KERN_SUCCESS Memory read.
KERN_INVALID_ARGUMENT
Either the address does not start on a page boundary or the
size is not an integral number of pages.
KERN_NO_SPACE There is not enough room in the callers virtual memory to
allocate space for the data to be returned.
KERN_PROTECTION_FAILURE
The address region in the target task is protected against
reading.
KERN_INVALID_ADDRESS
Illegal or non-allocated address specified, or there was not
size bytes of data following that address.
See Also
vm_read, vm_write, vm_copy, vm_deallocate
vm_write
#include <mach.h>
kern_return_t vm_write(target_task, address, data, data_count)
vm_task_t target_task;
vm_address_t address;
pointer_t data;
int data_count;
Arguments
target_task Task whose memory is to be written.
address Starting address in task to be affected (must be a page
boundary).
data An array of bytes to be written.
data_count The size of the data array (must be an integral number of
pages).
Description
vm_write allows a task's virtual memory to be written by another task. Use
vm_page_size or vm_statistics to find out the virtual page size.
Returns
KERN_SUCCESS Memory written.
KERN_INVALID_ARGUMENT
Either the address does not start on a page boundary or the
size is not an integral number of pages.
KERN_PROTECTION_FAILURE
The address region in the target task is protected against
writing.
KERN_INVALID_ADDRESS
Illegal or non_allocated address specified or there is not
data_count of allocated memory starting at address.
See Also
vm_copy, vm_protect, vm_read, vm_statistics
vm_copy
#include <mach.h>
kern_return_t vm_copy (target_task, source_address, count, dest_address)
vm_task_t target_task;
vm_address_t source_address;
vm_size_t count;
vm_address_t dest_address;
Arguments
target_task Task whose virtual memory is to be affected.
source_address Address in target_task of the start of the source range (must
be a page boundary).
count Number of bytes to copy (must be an integral number of
pages).
dest_address Address in target_task of the start of the destination range
(must be a page boundary).
Description
vm_copy causes the source memory range to be copied to the destination
address; the destination region may not overlap the source region. The
destination address range must already be allocated and writable; the source
range must be readable.
Returns
KERN_SUCCESS Memory copied.
KERN_INVALID_ARGUMENT
Either the address does not start on a page boundary or the
size is not an integral number of pages.
KERN_PROTECTION_FAILURE
Either the destination region was not not writable, or the
source region was not readable.
KERN_INVALID_ADDRESS
Illegal or non-allocated address specified or insufficient
memory allocated at one of the addresses.
See Also
vm_protect, vm_write, vm_statistics
vm_region
#include <mach.h>
kern_return_t vm_region(target_task, address, size, protection,
max_protection, inheritance, shared,
object_name, offset)
vm_task_t target_task;
vm_address_t *address; /* in/out */
vm_size_t *size; /* out */
vm_prot_t *protection; /* out */
vm_prot_t *max_protection; /* out */
vm_inherit_t *inheritance; /* out */
boolean_t *shared; /* out */
port_t *object_name; /* out */
vm_offset_t *offset; /* out */
Arguments
target_task The task for which an address space description is requested.
address The address at which to start looking for a region.
size The size (in bytes) of the located region.
protection The current protection of the region.
max_protection The maximum allowable protection for this region.
inheritance The inheritance attribute for this region.
shared Is this region shared or not.
object_name The port identifying the memory object associated with this
region. (See pager_init.)
offset The offset into the pager object that this region begins at.
Description
vm_region returns a description of the specified region of the target task's
virtual address space. vm_region begins at address and looks forward thru
memory until it comes to an allocated region. (If address is within a region,
then that region is used.) Various bits of information about the region are
returned. If address was not within a region, then address is set to the start
of the first region which follows the incoming value. In this way an entire
address space can be scanned.
Returns
KERN_SUCCESS Region located and information returned.
KERN_NO_SPACE There is no region at or above address in the specified task.
See Also
vm_allocate, vm_deallocate, vm_protect, vm_inherit
vm_protect
#include <mach.h>
kern_return_t vm_protect(target_task, address, size, set_maximum,
new_protection)
vm_task_t target_task;
vm_address_t address;
vm_size_t size;
boolean_t set_maximum;
vm_prot_t new_protection;
Arguments
target_task Task whose virtual memory is to be affected.
address Starting address (will be rounded down to a page boundary).
size Size in bytes of the region for which protection is to change
(will be rounded up to give a page boundary).
set_maximum If set, make the protection change apply to the maximum
protection associated with this address range; otherwise, the
current protection on this range is changed. If the maximum
protection is reduced below the current protection, both will
be changed to reflect the new maximum.
new_protection A new protection value for this region; a set of:
VM_PROT_READ, VM_PROT_WRITE, VM_PROT_EXECUTE.
Description
vm_protect sets the virtual memory access privileges for a range of allocated
addresses in a task's virtual address space. The protection argument describes
a combination of read, write, and execute accesses that should be permitted.
The enforcement of virtual memory protection is machine-dependent. Some
combinations of access rights may not be supported. In particular, the kernel
interface allows any of the following: write permission may imply read
permission; read permission may imply execute permission; or, execute
permission may imply read permission.
All architectures must support the following access combinations: all (read,
write, and execute) access; write-protected (read and execute) access; no
access.
For the Vax, RT/PC, and Sun3, all three of the reductions stated above apply.
That is: VM_PROT_WRITE allows read, execute and write access, VM_PROT_READ or
VM_PROT_EXECUTE allows read and execute access, but not write access.
Returns
KERN_SUCCESS Memory protected.
KERN_PROTECTION_FAILURE
An attempt was made to increase the current or maximum
protection beyond the existing maximum protection value.
KERN_INVALID_ADDRESS
Illegal or non-allocated address specified.
vm_inherit
#include <mach.h>
kern_return_t vm_inherit(target_task, address, size, new_inheritance)
vm_task_t target_task;
vm_address_t address;
vm_size_t size;
vm_inherit_t new_inheritance;
Arguments
target_task Task whose virtual memory is to be affected.
address Starting address (will be rounded down to a page boundary).
size Size in bytes of the region for which inheritance is to
change (will be rounded up to give a page boundary).
new_inheritance How this memory is to be inherited in child tasks.
Inheritance is specified by using one of these following
three values:
VM_INHERIT_SHARE
Child tasks will share this memory with this task.
VM_INHERIT_COPY Child tasks will receive a copy of this region.
VM_INHERIT_NONE This region will be absent from child tasks.
Description
vm_inherit specifies how a region of a task's address space is to be passed
to child tasks at the time of task creation. Inheritance is an attribute of
virtual pages, thus the addresses and size of memory to be set will be rounded
out to refer to whole pages.
Setting vm_inherit to VM_INHERIT_SHARE and forking a child task is the only
way two Mach tasks can share physical memory. Remember that all the theads of
a given task share all the same memory.
Returns
KERN_SUCCESS Memory protected.
KERN_INVALID_ADDRESS
Illegal address specified.
See Also
task_create, vm_regions
vm_statistics
#include <mach.h>
struct vm_statistics {
long pagesize; /* page size in bytes */
long free_count; /* # of pages free */
long active_count; /* # of pages active */
long inactive_count; /* # of pages inactive */
long wire_count; /* # of pages wired down */
long zero_fill_count; /* # of zero fill pages */
long reactivations; /* # of pages reactivated */
long pageins; /* # of pageins */
long pageouts; /* # of pageouts */
long faults; /* # of faults */
long cow_faults; /* # of copy-on-writes */
long lookups; /* object cache lookups */
long hits; /* object cache hits */
};
typedef struct vm_statistics vm_statistics_data_t;
kern_return_t vm_statistics(target_task, vm_stats)
task_t target_task;
vm_statistics_data_t *vm_stats; /* out */
Arguments
target_task Task which is requesting statistics.
vm_stats The structure that will receive the statistics.
Description
vm_statistics returns the statistics about the kernel's use of virtual memory
since the kernel was booted. pagesize can also be found as a global variable
vm_page_size which is set at task initialization and remains constant for the
life of the task.
Returns
KERN_SUCCESS
6. Ancillary primitives
mach_ports
#include <mach.h>
kern_return_t mach_ports_register(target_task,
init_port_set, init_port_array_count)
task_t target_task;
port_array_t init_port_set; /* array */
int init_port_array_count;
kern_return_t mach_ports_lookup(target_task,
init_port_set, init_port_array_count)
task_t target_task;
port_array_t *init_port_set; /* out array */
int *init_port_array_count; /* out */
Arguments
target_task Task to be affected.
init_port_set An array of system ports to be registered, or returned.
Although the array size is given as variable, the MACH kernel
will only accept a limited number of ports.
init_port_array_count
The number of ports returned in init_port_set.
Description
mach_ports_register registers an array of well-known system ports with the
kernel on behalf of a specific task. Currently the ports to be registered are:
the port to the Network Name Server, the port to the Environment Manager, and a
port to the Service server. These port values must be placed in specific slots
in the init_port_set. The slot numbers are given by the global constants
defined in mach_init.h: NAME_SERVER_SLOT, ENVIRONMENT_SLOT, and SERVICE_SLOT.
These ports may later be retrieved with mach_ports_lookup.
When a new task is created (see task_create), the child task will be given
access to these ports. Only port send rights may be registered. Furthermore,
the number of ports which may be registered is fixed and given by the global
constant MACH_PORT_SLOTS_USED. Attempts to register too many ports will fail.
It is intended that this mechanism be used only for task initialization, and
then only by runtime support modules. A parent task has three choices in
passing these system ports to a child task. Most commonly it can do nothing and
its child will inherit access to the same init_port_set that the parent has; or
a parent task may register a set of ports it wishes to have passed to all of
its children by calling mach_ports_register using its task port; or it may make
necessary modifications to the set of ports it wishes its child to see, and
then register those ports using the child's task port prior to starting the
child's thread(s). The mach_ports_lookup call which is done by mach_init in
the child task will acquire these initial ports for the child.
Tasks other than the Network Name Server and the Environment Mangager should
not need access to the Service port. The Network Name Server port is the same
for all tasks on a given machine. The Environment port is the only port likely
to have different values for different tasks.
Since the number of ports which may be registered is limited, ports other
than those used by the runtime system to initialize a task should be passed to
children either through an initial message, or through the Network Name Server
for public ports, or the Environment Manager for private ports.
Returns
KERN_SUCCESS Memory allocated.
KERN_INVALID_ARGUMENT
An attempt was made to register more ports than the current
kernel implementation allows.
See Also
mach_init, netname, env_mgr, service
host_ipc_statistics
#include <mach.h>
kern_return_t host_ipc_statistics(task, statistics)
task_t target_task;
ipc_statistics_t *statistics; /* inout */
Arguments
task Task running on the kernel whose statistics are desired.
statistics The returned statistics.
Description
host_ipc_statistics returns the statistics about MACH IPC, since the kernel
was booted. statistics is a fixed length array provided by the user. See
<kern/ipc_statistics.h> for a description of what is returned.
Returns
KERN_SUCCESS The call succeeded.
Notes
Only kernels compiled with MACH_IPCSTATS enabled support this call.
The first argument should be a host port of some kind.
The meaning of the statistics varies; not all fields are used.
7. External memory management primitives
7.1. Memory Managers
The MACH kernel allows users to provide memory managment (i.e. paging)
services outside the kernel. A server that provides such functions is called a
memory manager. There is a default memory manager that is part of the kernel
and is normally used to handle paging to both files and temporary memory
objects. Users may provide additional memory managers to handle special kinds
of objects, such as fault-tolerant objects, objects whose backing store is
across a network link, or objects whose backing store is on devices for which
the kernel does not provide drivers.
The protocol defined in this section consists of messages that the kernel
will send to memory managers and the primitives that the kernel provides for
the use of memory managers. Use of these primitives involves increased
responsibility. A memory manager is expected to respond in a timely fashion to
all the requests that the kernel makes of it, otherwise threads within the
kernel are left hanging and the client task that is attempting to reference the
memory object is also left hanging.
It is also possible for a privileged user to replace the default memory
manager. This involves increased reliability and responsibility as now all the
users of the system will be dependent on the new server.
7.1.1. Memory objects: definitions and basics
In MACH, physical memory is used as a cache of the contents of secondary
storage objects called memory objects. The virtual address space of a task is
represented as a series of mappings from contiguous virtual address ranges to
such memory objects. For each memory object the kernel keeps track of those
pages that are currently in the physical memory cache and it allows tasks
mapped to that memory to use those physical pages.
When a virtual memory request occurs that cannot be resolved through the use
of a previously cached physical page, the kernel must make a request of the
memory object for the required data. As the physical page cache becomes full,
the kernel must replace pages from the cache, writing the contents of modified
pages back to the corresponding memory objects.
When a task uses the vm_allocate call, the kernel allocates a memory object
that provides zero-filled memory on reference; this memory object is managed by
a default memory manager.
Alternatively, a task may map a specific memory object into its address space
by issuing a vm_map call. Included in this call is the memory object,
represented by a port, that is to manage the data in the allocated region. The
kernel will use the memory object port to make requests for data, or to request
that data be written back to the object. The memory manager must act as a
server for these requests. The memory manager server interface differs from
other servers only in that the kernel does not synchronously await replies.
A given memory object may be mapped into an arbitrary number of tasks, at any
addresses available in those tasks. When a vm_map call is issued, the MACH
kernel will recognize the memory object if it has been mapped before; any
physical memory pages from this memory object already cached from previous uses
may be shared by later mappings as well. A single MACH kernel keeps the
physical memory cache consistent across all uses of the same memory object at
similar page alignments on that host.
Furthermore, a single memory object may be mapped into tasks created on
different hosts (and therefore be cached by different MACH kernels). In this
case, the memory manager is responsible for maintaining any desired consistency
among the various hosts on which its data resides.
7.1.2. Initialization and termination
The memory manager must define a protocol for giving out memory object ports.
This could take the form of the memory manager registering a general service
port somewhere that clients could find and exporting an object create or object
lookup call that will return a memory object port. This is the port that is
passed to the kernel in the vm_map call.
Upon processing the first vm_map call for a given memory object, the MACH
kernel will make a memory_object_init call, providing the memory manager with
two ports: a control port, and a name port. The memory manager may use the
memory object control port to supply the kernel with data for it to cache, or
to perform other cache management functions. These requests will be covered in
the next section.
The memory object name, a port, will only be used by the kernel in the
results from a vm_region call to describe the source of data for a given
region. Since this port is not to be used for requests for data, the memory
manager may wish to provide this port to clients to identify memory which it
supplies.
The initialization call also includes the system page size for the host on
which the mapping took place. This allows the memory manager to provide data
to the kernel in whole pages, and to detect mappings at inconsistent page
alignments.
In order to indicate its readiness to accept requests, the memory manager
must respond to the initialization call by making a
memory_object_set_attributes call, asserting the readiness parameter.
Normally, when a memory object is no longer referenced by any virtual address
space, the MACH kernel will deallocate its port rights to that memory object
after sending all port rights for the control and name ports in an
memory_object_terminate call. To enhance performance, a memory manager may
allow a MACH kernel to maintain its memory cache for a memory object after all
virtual address space references to it are gone, by asserting the caching
parameter to the memory_object_set_attributes call. However, allowing caching
does not prevent the kernel from terminating an object.
In the event that a memory manager destroys a memory object port that is
currently mapped into one or more virtual address spaces, future page faults on
addresses mapped to this object (for which data is not available in the cache)
will result in a memory exception.
7.1.3. Kernel-created memory objects
As noted earlier, memory created using vm_allocate results in the creation of
a memory object; this object is created by the kernel, and is passed to the
default memory manager, using the memory_object_create call. Since the memory
object is initially zero-filled, it only contains data that has been modified.
The memory_object_create request will only be made of the default memory
manager. The default memory manager must not allow any memory object passed in
a memory_object_create call to be used in any other task, as the kernel may
make assumptions about such an object that could adversely affect external
consistency.
7.2. Kernel calls supporting memory managers
vm_map
#include <mach.h>
kern_return_t vm_map(target_task, address, size, mask, anywhere,
memory_object, offset, copy,
cur_protection, max_protection,
inheritance)
task_t target_task;
vm_offset_t *address; /* in/out */
vm_size_t size;
vm_offset_t mask;
boolean_t anywhere;
memory_object_t memory_object;
vm_offset_t offset;
boolean_t copy;
vm_prot_t cur_protection;
vm_prot_t max_protection;
vm_inherit_t inheritance;
Description
vm_map maps a region of virtual memory at the specified address, for which
data is to be supplied by the given memory object, starting at the given offset
within that object. In addition to the arguments used in vm_allocate, the
vm_map call allows the specification of an address alignment parameter, and of
the initial protection and inheritance values. [See the descriptions of
vm_allocate, vm_protect, and vm_inherit.]
If the memory object in question is not currently in use, the MACH kernel
will perform a memory_object_init call at this time. If the copy parameter is
asserted, the specified region of the memory object will be copied to this
address space; changes made to this object by other tasks will not be visible
in this mapping, and changes made in this mapping will not be visible to others
(or returned to the memory object).
The vm_map call returns once the mapping is established. Completion of the
call does not require any action on the part of the memory manager.
Warning: Only memory objects that are provided by bona fide memory managers
should be used in the vm_map call. A memory manager must implement the memory
object interface described elsewhere in this manual. If other ports are used,
a thread that accesses the mapped virtual memory may become permanently hung or
may receive a memory exception.
Arguments
target_task Task to be affected.
address Starting address. If the anywhere option is used, this
address is ignored. The address actually allocated will be
returned in address.
size Number of bytes to allocate (rounded by the system in a
machine dependent way).
mask Alignment restriction. Bits asserted in this mask must not
be asserted in the address returned.
anywhere If set, the kernel should find and allocate any region of the
specified size, and return the address of the resulting
region in address.
memory_object Port that represents the memory object: used by user tasks in
vm_map; used by the MACH kernel to make requests for data or
other management actions. If this port is
MEMORY_OBJECT_NULL, then zero-filled memory is allocated
instead.
offset An offset within a memory object, in bytes. This must be
page aligned.
copy If set, the range of the memory object should be copied to
the target task, rather than mapped read-write.
Returns
KERN_SUCCESS The object is mapped.
KERN_NO_SPACE No unused region of the task's virtual address space that
meets the address, size, and alignment criteria could be
found.
KERN_INVALID_ARGUMENT
An illegal argument was provided.
See Also
memory_object_server, vm_allocate
memory_object_set_attributes
#include <mach.h>
kern_return_t memory_object_set_attributes(memory_control,
object_ready, may_cache_object,
copy_strategy)
memory_object_control_t
memory_control;
boolean_t object_ready;
boolean_t may_cache_object;
memory_object_copy_strategy_t
copy_strategy;
Description
memory_object_set_attributes controls how the MACH kernel uses the memory
object. The kernel will only make data or unlock requests when the ready
attribute is asserted. If the caching attribute is asserted, the kernel is
permitted (and encouraged) to maintain cached data for this memory object even
after no virtual address space contains this data.
There are three possible caching strategies: MEMORY_OBJECT_COPY_NONE which
specifies that nothing special should be done when data in the object is
copied; MEMORY_OBJECT_COPY_CALL which specifies that the memory manager should
be notified via a memory_object_copy call before any part of the object is
copied; and MEMORY_OBJECT_COPY_DELAY which guarantees that the memory manager
does not externally modify the data so that the kernel can use its normal
copy-on-write algorithms. MEMORY_OBJECT_COPY_DELAY is the strategy most
commonly used.
Arguments
memory_control The port, provided by the kernel in a memory_object_init
call, to which cache management requests may be issued.
object_ready When set, the kernel may issue new data and unlock requests
on the associated memory object.
may_cache_object
If set, the kernel may keep data associated with this memory
object, even after virtual memory references to it are gone.
copy_strategy How the kernel should copy regions of the associated memory
object.
Returns
KERN_SUCCESS This routine does not receive a reply message (and
consequently has no return value), so only message
transmission errors apply.
See Also
memory_object_init, memory_object_copy, memory_object_attributes
memory_object_get_attributes
#include <mach.h>
kern_return_t memory_object_get_attributes(memory_control,
object_ready, may_cache_object,
copy_strategy)
memory_object_control_t
memory_control;
boolean_t *object_ready;
boolean_t *may_cache_object;
memory_object_copy_strategy_t
*copy_strategy;
Description
memory_object_get_attributes retrieves the current attributes associated with
the memory object.
Arguments
memory_control The port, provided by the kernel in a memory_object_init
call, to which cache management requests may be issued.
object_ready When set, the kernel may issue new data and unlock requests
on the associated memory object.
may_cache_object
If set, the kernel may keep data associated with this memory
object, even after virtual memory references to it are gone.
copy_strategy How the kernel should copy regions of the associated memory
object.
Returns
KERN_SUCCESS This routine does not receive a reply message (and
consequently has no return value), so only message
transmission errors apply.
See Also
memory_object_set_attributes, memory_object_copy
memory_object_lock_request
#include <mach.h>
kern_return_t memory_object_lock_request(memory_control,
offset, size, should_clean
should_flush, lock_value, reply_to)
memory_object_control_t
memory_control;
vm_offset_t offset;
vm_size_t size;
boolean_t should_clean;
boolean_t should_flush;
vm_prot_t lock_value;
port_t reply_to;
Description
memory_object_lock_request allows a memory manager to make cache management
requests. As specified in arguments to the call, the kernel will: clean
(i.e., write back using memory_object_data_write) any cached data which has
been modified since the last time it was written; flush (i.e., remove any uses
of) that data from memory; lock (i.e., prohibit the specified uses of) the
cached data. Locks applied to cached data are not cumulative; new lock values
override previous ones. Thus, data may also be unlocked using this primitive.
The lock values must be one or more of the following values: VM_PROT_NONE,
VM_PROT_READ, VM_PROT_WRITE, VM_PROT_EXECUTE and VM_PROT_ALL as defined in
<mach/vm_prot.h>.
Only data which is cached at the time of this call is affected. When a
running thread requires a prohibited access to cached data, the MACH kernel
will issue a memory_object_data_unlock call specifying the forms of access
required. Once all of the actions requested by this call have been completed,
the MACH kernel will issue a memory_object_lock_completed call on the specified
reply port.
Arguments
memory_control The port, provided by the kernel in a memory_object_init
call, to which cache management requests may be issued.
offset An offset within a memory object, in bytes. This must be
page aligned.
size The amount of cached data (starting at offset) to be handled,
must be an integral multiple of the memory object page size.
should_clean If set, modified data should be written back to the memory
manager.
should_flush If set, the specified cached data should be invalidated, and
all uses of that data should be revoked.
lock_value A protection value indicating those forms of access that
should not be permitted to the specified cached data.
reply_to A port on which a memory_object_lock_completed call should be
issued, or PORT_NULL if no acknowledgement is desired.
Returns
KERN_SUCCESS This routine does not receive a reply message (and
consequently has no return value), so only message
transmission errors apply.
See Also
memory_object_lock_completed, memory_object_data_unlock
memory_object_data_provided
#include <mach.h>
kern_return_t memory_object_data_provided(memory_control,
offset, data, data_count, lock_value)
memory_object_control_t
memory_control;
vm_offset_t offset;
pointer_t data;
int data_count;
vm_prot_t lock_value;
Description
memory_object_data_provided supplies the kernel with data for the specified
memory object. Ordinarily, memory managers should only provide data in reponse
to memory_object_data_request calls from the kernel. The lock_value specifies
what type of access will not be allowed to the data range. The lock values must
be one or more of the set: VM_PROT_NONE, VM_PROT_READ, VM_PROT_WRITE,
VM_PROT_EXECUTE and VM_PROT_ALL as defined in <mach/vm_prot.h>.
Arguments
memory_control The port, provided by the kernel in a memory_object_init
call, to which cache management requests may be issued.
offset An offset within a memory object, in bytes. This must be
page aligned.
data Data that is being provided to the kernel. This is a pointer
to the data.
data_count The amount of data to be provided. Must be an integral
number of memory object pages.
lock_value A protection value indicating those forms of access that
should not be permitted to the specified cached data.
Returns
KERN_SUCCESS This routine does not receive a reply message (and
consequently has no return value), so only message
transmission errors apply.
See Also
memory_object_data_request, memory_object_data_error,
memory_object_lock_request
memory_object_data_unavailable
#include <mach.h>
kern_return_t memory_object_data_unavailable(memory_control,
offset, size);
memory_object_control_t
memory_control;
vm_offset_t offset;
vm_size_t size;
Description
memory_object_data_unavailable indicates that the memory object does not have
data for the given region and that the kernel should provide the data for this
range. The memory manager may use this call in three different situations. 1)
The object was created by memory_object_create and the kernel has not yet
provided data for this range (either via a memory_object_data_initialize or a
memory_object_data_write. In this case the kernel should supply zero-filled
pages for the object. 2) The object was created by an memory_object_data_copy
and the kernel should copy this region from the original memory object. 3) The
object is a normal user-created memory object and the kernel should supply
unlocked zero-filled pages for the range.
Arguments
memory_control The port, provided by the kernel in a memory_object_init
call, to which cache management requests may be issued.
offset An offset within a memory object, in bytes. This must be
page aligned.
size The amount of cached data (starting at offset) to be handled.
This must be an integral multiple of the memory object page
size.
Returns
KERN_SUCCESS This routine does not receive a reply message (and
consequently has no return value), so only message
transmission errors apply.
See Also
memory_object_create, memory_object_data_request, memory_object_data_error
memory_object_data_error
#include <mach.h>
kern_return_t memory_object_data_error(memory_control,
offset, size, reason);
memory_object_control_t
memory_control;
vm_offset_t offset;
vm_size_t size;
kern_return_t reason;
Description
memory_object_data_error indicates that the memory manager cannot return the
data requested for the given region, specifying a reason for the error. This
is typically used when a hardware error is encountered.
Arguments
memory_control The port, provided by the kernel in a memory_object_init
call, to which cache management requests may be issued.
offset An offset within a memory object, in bytes. This must be
page aligned.
size The amount of cached data (starting at offset) to be handled.
This must be an integral multiple of the memory object page
size.
reason Could be a Unix error code for a hardware error.
Returns
KERN_SUCCESS This routine does not receive a reply message (and
consequently has no return value), so only message
transmission errors apply.
See Also
memory_object_data_request, memory_object_data_provided
Notes
The error code is currently ignored.
memory_object_destroy
#include <mach.h>
kern_return_t memory_object_destroy(memory_control, reason);
memory_object_control_t
memory_control;
kern_return_t reason;
Description
memory_object_destroy tells the kernel to shut down the memory object. As a
result of this call the kernel will no longer support paging activity or any
memory_object calls on this object, and all rights to the memory object port,
the memory control port and the memory name port will be returned to the memory
manager in a memory_object_terminate call. If the memory manager is concerned
that any modified cached data be returned to it before the object is
terminated, it should call memory_object_lock_request with should_flush set and
a lock value of VM_PROT_WRITE before making this call.
Arguments
memory_control The port, provided by the kernel in a memory_object_init
call, to which cache management requests may be issued.
reason An error code indicating when the object must be destroyed.
Returns
KERN_SUCCESS This routine does not receive a reply message (and
consequently has no return value), so only message
transmission errors apply.
See Also
memory_object_terminate, memory_object_lock_request
Notes
The error code is currently ingnored.
vm_set_default_memory_manager
#include <mach.h>
routine vm_set_default_memory_manager(host,default_manager)
task_t host;
memory_object_t default_manager; /* in/out */
Description
vm_set_default_memory_manager sets the kernel's default memory manager. It
sets the port to which newly-created temporary memory objects are delivered by
memory_object_create to the host. The old memory manager port is returned. If
default_manager is PORT_NULL then this routine just returns the current default
manager port without changing it.
Arguments
host A task port to the kernel whose default memory manager is to