|
|
< Previous PageNext Page > |
A universal page list, or UPL, is a data structure used when
communicating with the virtual memory system. UPLs can be used to
change the behavior of pages with respect to caching, permissions,
mapping, and so on. UPLs can also be used to push data into and pull
data from VM objects. The term is also often used to refer to the
family of routines that operate on UPLs. The flags used when dealing
with UPLs are described in osfmk/mach/memory_object_types.h
.
The life cycle of a UPL looks like this:
A UPL is created based on the contents of a VM object. This UPL includes information about the pages within that object.
That UPL is modified in some way.
The changes to the UPL are either committed (pushed back to
the VM system) or aborted, with ubc_upl_commit
or ubc_upl_abort
,
respectively.
If you have a control handle for a given VM object (which
generally means that you are inside a pager), you can use vm_object_upl_request
to
get a UPL for that object. Otherwise, you must use the vm_map_get_upl
call.
In either case, you are left with a handle to the UPL.
When a pagein is requested, the pager receives a list of pages that are locked against the object, with certain pages set to not valid. The pager must either write data into those pages or must abort the transaction to prevent invalid data in the kernel. Similarly in pageout, the kernel must write the data to a backing store or abort the transaction to prevent data loss. The pager may also elect to bring additional pages into memory or throw additional pages out of memory at its discretion.
Because pagers can be used both for virtual memory and for
memory mapping of file data, when a pageout is requested, the data
may need to be freed from memory, or it may be desirable to keep
it there and simply flush the changes to disk. For this reason,
the flag UPL_CLEAN_IN_PLACE
exists
to allow a page to be flushed to disk but not removed from memory.
When a pager decides to page in or out additional pages, it
must determine which pages to move. A pager can request all of the
dirty pages by setting the RETURN_ONLY_DIRTY
flag. It
can also request all pages that are not in memory using the RETURN_ONLY_ABSENT
flag.
There is a slight problem, however. If a given page is marked
as BUSY
in the UPL, a
request for information on that page would normally block. If the
pager is doing prefetching or preflushing, this is not desirable,
since it might be blocking on itself or on some other pager that
is blocked waiting for the current transaction to complete. To avoid
such deadlock, the UPL mechanism provides the UPL_NOBLOCK
flag.
This is frequently used in the anonymous pager for requesting free
memory.
The flag QUERY_OBJECT_TYPE
can
be used to determine if an object is physically contiguous and to
get other properties of the underlying object.
The flag UPL_PRECIOUS
means
that there should be only one copy of the data. This prevents having
a copy both in memory and in the backing store. However, this breaks
the adjacency of adjacent pages in the backing store, and is thus
generally not used to avoid a performance hit.
The flag SET_INTERNAL
is
used by the BSD subsystem to cause all information about a UPL to
be contained in a single memory object so that it can be passed
around more easily. It can only be used if your code is running
in the kernel’s address space.
Since this handle can be used for multiple small transactions
(for example, when mapping a file into memory block-by-block), the
UPL API includes functions for committing and aborting changes to
only a portion of the UPL. These functions are upl_commit_range
and upl_abort_range
,
respectively.
To aid in the use of UPLs for handling multi-part transactions,
the upl_commit_range
and upl_abort_range
calls
have a flag that causes the UPL to be freed when there are no unmodified
pages in the UPL. If you use this flag, you must be very careful
not to use the UPL after all ranges have been committed or aborted.
Finally, the function vm_map_get_upl
is
frequently used in file systems. It gets the underlying VM object
associated with a given range within an address space. Since this returns
only the first object in that range, it is your responsibility to
determine whether the entire range is covered by the resulting UPL
and, if not, to make additional calls to get UPLs for other objects.
Note that while the vm_map_get_upl
call
is against an address space range, most UPL calls
are against a vm_object
.
< Previous PageNext Page > |
Last updated: 2006-11-07
|
Get information on Apple products.
Visit the Apple Store online or at retail locations. 1-800-MY-APPLE Copyright © 2007 Apple Inc. All rights reserved. | Terms of use | Privacy Notice |