1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-08 04:30:45 -08:00

First draft of land design.

Copied from Perforce
 Change: 185146
 ServerID: perforce.ravenbrook.com
This commit is contained in:
Gareth Rees 2014-04-01 23:35:23 +01:00
parent 651c2b9df0
commit 6beb2ed5f2
5 changed files with 341 additions and 173 deletions

View file

@ -19,7 +19,7 @@ SRCID(arena, "$Id$");
#define ArenaControlPool(arena) MV2Pool(&(arena)->controlPoolStruct)
#define ArenaCBSBlockPool(arena) (&(arena)->freeCBSBlockPoolStruct.poolStruct)
#define ArenaFreeLand(arena) ((Land)&(arena)->freeLandStruct)
#define ArenaFreeLand(arena) (&(arena)->freeLandStruct.landStruct)
/* Forward declarations */

View file

@ -29,50 +29,24 @@ high level communication with the client about the size of contiguous
ranges, and detection of protocol violations.
Definitions
-----------
_`.def.range`: A (contiguous) *range* of addresses is a semi-open
interval on address space.
_`.def.isolated`: A contiguous range is *isolated* with respect to
some property it has, if adjacent elements do not have that property.
Requirements
------------
_`.req.set`: Must maintain a set of addresses.
In addition to the generic land requirements (see
design.mps.land.req), the CBS must satisfy:
_`.req.fast`: Common operations must have a low amortized cost.
_`.req.add`: Must be able to add address ranges to the set.
_`.req.remove`: Must be able to remove address ranges from the set.
_`.req.size`: Must report concisely to the client when isolated
contiguous ranges of at least a certain size appear and disappear.
_`.req.iterate`: Must support the iteration of all isolated
contiguous ranges. This will not be a common operation.
_`.req.protocol`: Must detect protocol violations.
_`.req.debug`: Must support debugging of client code.
_`.req.small`: Must have a small space overhead for the storage of
typical subsets of address space and not have abysmal overhead for the
storage of any subset of address space.
_`.req.align`: Must support an alignment (the alignment of all
addresses specifying ranges) of down to ``sizeof(void *)`` without
losing memory.
Interface
---------
_`.header`: CBS is used through impl.h.cbs.
_`.land`: The interface to CBS is the generic functions for the *land*
abstract data type. See `design.mps.land <land/>`_.
External types
@ -80,147 +54,51 @@ External types
``typedef struct CBSStruct *CBS``
_`.type.cbs`: ``CBS`` is the main data structure for manipulating a
CBS. It is intended that a ``CBSStruct`` be embedded in another
structure. No convenience functions are provided for the allocation or
deallocation of the CBS.
``typedef Bool (*CBSIterateMethod)(CBS cbs, Range range, void *closureP, Size closureS)``
_`.type.cbs.iterate.method`: Type ``CBSIterateMethod`` is a callback
function that may be passed to ``CBSIterate()``. It is called for
every isolated contiguous range in address order. The function must
returns a ``Bool`` indicating whether to continue with the iteration.
_`.type.cbs`: A ``CBSStruct`` may be embedded in another structure, or
you can create it using ``LandCreate()``.
External functions
..................
``Res CBSInit(Arena arena, CBS cbs, void *owner, Align alignment, Bool fastFind, ArgList args)``
``LandClass CBSLandClassGet(void)``
_`.function.cbs.init`: ``CBSInit()`` is the function that initialises
the CBS structure. It performs allocation in the supplied arena. The
parameter ``owner`` is passed to ``MeterInit()``, an ``alignment``
indicates the alignment of ranges to be maintained. An initialised CBS
contains no ranges.
``fastFind``, if set, causes the CBS to maintain, for each subtree,
the size of the largest block in that subtree. This must be true if
any of the ``CBSFindFirst()``, ``CBSFindLast()``, or
``CBSFindLargest()`` functions are going to be used on the CBS.
``CBSInit()`` may take one keyword argument:
* ``MPS_KEY_CBS_EXTEND_BY`` (type ``Size``; default 4096) is the size
of segment that the CBS will request from the arena in which to
allocate its ``CBSBlock`` structures.
``void CBSFinish(CBS cbs)``
_`.function.cbs.finish`: ``CBSFinish()`` is the function that finishes
the CBS structure and discards any other resources associated with the
CBS.
``Res CBSInsert(Range rangeReturn, CBS cbs, Range range)``
_`.function.cbs.insert`: If any part of ``range`` is already in the
CBS, then leave it unchanged and return ``ResFAIL``. Otherwise,
attempt to insert ``range`` into the CBS. If the insertion succeeds,
then update ``rangeReturn`` to describe the contiguous isolated range
containing the inserted range (this may differ from ``range`` if there
was coalescence on either side) and return ``ResOK``. If the insertion
fails, return a result code indicating allocation failure.
_`.function.cbs.insert.fail`: Insertion of a valid range (that is, one
that does not overlap with any range in the CBS) can only fail if the
new range is isolated and the allocation of the necessary data
structure to represent it failed.
_`.function.class`: The function ``CBSLandClassGet()`` returns the CBS
class, a subclass of ``LandClass`` suitable for passing to
``LandCreate()`` or ``LandInit()``.
``Res CBSDelete(Range rangeReturn, CBS cbs, Range range)``
Keyword arguments
.................
_`.function.cbs.delete`: If any part of the range is not in the CBS,
then leave the CBS unchanged and return ``ResFAIL``. Otherwise, update
``rangeReturn`` to describe the contiguous isolated range that
contains ``range`` (this may differ from ``range`` if there are
fragments on either side) and attempt to delete the range from the
CBS. If the deletion succeeds, return ``ResOK``. If the deletion
fails, return a result code indicating allocation failure.
When initializing a CBS, ``LandCreate()`` and ``LandInit()`` take the
following optional keyword arguments:
_`.function.cbs.delete.fail`: Deletion of a valid range (that is, one
that is wholly contained in the CBS) can only fail if there are
fragments on both sides and the allocation of the necessary data
structures to represent them fails.
* ``CBSBlockPool`` (type ``Pool``) is the pool from which the CBS
block descriptors will be allocated. If omitted, a new MFS pool is
created for this purpose.
_`.function.cbs.delete.return`: ``CBSDelete()`` returns the contiguous
isolated range that contains ``range`` even if the deletion fails.
This is so that the caller can try deleting the whole block (which is
guaranteed to succeed) and managing the fragments using a fallback
strategy.
* ``MPS_KEY_CBS_EXTEND_BY`` (type ``Size``; default 4096) is passed as
the ``MPS_KEY_EXTEND_BY`` keyword argument to ``PoolCreate()`` if a
block descriptor pool is created. It specifies the size of segment
that the block descriptor pool will request from the arena.
``void CBSIterate(CBS cbs, CBSIterateMethod iterate, void *closureP, Size closureS)``
* ``MFSExtendSelf`` (type ``Bool``; default ``TRUE``) is passed to
``PoolCreate()`` if a block descriptor pool is created. If ``TRUE``,
the block descriptor pool automatically extends itself when out of
space; if ``FALSE``, the pool returns ``ResLIMIT`` in this case.
(This feature is used by the arena to bootstrap its own CBS of free
memory.)
_`.function.cbs.iterate`: ``CBSIterate()`` is the function used to
iterate all isolated contiguous ranges in a CBS. It receives a
pointer, ``Size`` closure pair to pass on to the iterator method,
and an iterator method to invoke on every range in address order. If
the iterator method returns ``FALSE``, then the iteration is
terminated.
* ``CBSFastFind`` (type ``Bool``; default ``FALSE``). If ``TRUE``,
causes the CBS to maintain, for each subtree, the size of the
largest block in that subtree. This enables the ``LandFindFirst()``,
``LandFindLast()``, and ``LandFindLargest()`` generic functions.
``Res CBSDescribe(CBS cbs, mps_lib_FILE *stream)``
_`.function.cbs.describe`: ``CBSDescribe()`` is a function that prints
a textual representation of the CBS to the given stream, indicating
the contiguous ranges in order, as well as the structure of the
underlying splay tree implementation. It is provided for debugging
purposes only.
``Bool CBSFindFirst(Range rangeReturn, Range oldRangeReturn, CBS cbs, Size size, FindDelete findDelete)``
_`.function.cbs.find.first`: Locate the first block (in address order)
within the CBS of at least the specified size, update ``rangeReturn``
to describe that range, and return ``TRUE``. If there is no such
block, it returns ``FALSE``.
In addition, optionally delete the top, bottom, or all of the found
range, depending on the ``findDelete`` argument. This saves a separate
call to ``CBSDelete()``, and uses the knowledge of exactly where we
found the range. The value of ``findDelete`` must come from this
enumeration::
enum {
FindDeleteNONE, /* don't delete after finding */
FindDeleteLOW, /* delete size bytes from low end of block */
FindDeleteHIGH, /* delete size bytes from high end of block */
FindDeleteENTIRE /* delete entire range */
};
The original contiguous isolated range in which the range was found is
returned via the ``oldRangeReturn`` argument. (If ``findDelete`` is
``FindDeleteNONE`` or ``FindDeleteENTIRE``, then this will be
identical to the range returned via the ``rangeReturn`` argument.)
``CBSFindFirst()`` requires that ``fastFind`` was true when
``CBSInit()`` was called.
``Bool CBSFindLast(Range rangeReturn, Range oldRangeReturn, CBS cbs, Size size, FindDelete findDelete)``
_`.function.cbs.find.last`: Like ``CBSFindFirst()``, except that it
finds the last block in address order.
``Bool CBSFindLargest(Range rangeReturn, Range oldRangeReturn, CBS cbs, Size size, FindDelete findDelete)``
_`.function.cbs.find.largest`: Locate the largest block within the
CBS, and if that block is at least as big as ``size``, return its
range via the ``rangeReturn`` argument, and return ``TRUE``. If there
are no blocks in the CBS at least as large as ``size``, return
``FALSE``. Pass 0 for ``size`` if you want the largest block
unconditionally.
Like ``CBSFindFirst()``, optionally delete the range (specifying
``FindDeleteLOW`` or ``FindDeleteHIGH`` has the same effect as
``FindDeleteENTIRE``). This feature requires that ``fastFind`` was
true when ``CBSInit()`` was called.
* ``CBSZoned`` (type ``Bool``; default ``FALSE``). If ``TRUE``, caused
the CBS to maintain, for each subtree, the union of the zone sets of
all ranges in that subtree. This enables the ``LandFindInZones()``
generic function.
Implementation
@ -241,19 +119,19 @@ for comparison is the base of another range.
.. _design.mps.splay: splay
_`.impl.splay.fast-find`: ``CBSFindFirst()`` and ``CBSFindLast()`` use
_`.impl.splay.fast-find`: ``cbsFindFirst()`` and ``cbsFindLast()`` use
the update/refresh facility of splay trees to store, in each
``CBSBlock``, an accurate summary of the maximum block size in the
tree rooted at the corresponding splay node. This allows rapid
location of the first or last suitable block, and very rapid failure
if there is no suitable block.
_`.impl.find-largest`: ``CBSFindLargest()`` simply finds out the size
_`.impl.find-largest`: ``cbsFindLargest()`` simply finds out the size
of the largest block in the CBS from the root of the tree, using
``SplayRoot()``, and does ``SplayFindFirst()`` for a block of that
size. This takes time proportional to the logarithm of the size of the
free list, so it's about the best you can do without maintaining a
separate priority queue, just to do ``CBSFindLargest()``.
separate priority queue, just to do ``cbsFindLargest()``.
Low memory behaviour
@ -261,10 +139,10 @@ Low memory behaviour
_`.impl.low-mem`: When the CBS tries to allocate a new ``CBSBlock``
structure for a new isolated range as a result of either
``CBSInsert()`` or ``CBSDelete()``, and there is insufficient memory
``LandInsert()`` or ``LandDelete()``, and there is insufficient memory
to allocation the ``CBSBlock`` structure, then the range is not added
to the CBS or deleted from it, and the call to ``CBSInsert()`` or
``CBSDelete()`` returns ``ResMEMORY``.
to the CBS or deleted from it, and the call to ``LandInsert()`` or
``LandDelete()`` returns ``ResMEMORY``.
The CBS block
@ -285,15 +163,8 @@ Testing
_`.test`: The following testing will be performed on this module:
_`.test.cbstest`: There is a stress test for this module in
impl.c.cbstest. This allocates a large block of memory and then
simulates the allocation and deallocation of ranges within this block
using both a ``CBS`` and a ``BT``. It makes both valid and invalid
requests, and compares the ``CBS`` response to the correct behaviour
as determined by the ``BT``. It also iterates the ranges in the
``CBS``, comparing them to the ``BT``. It also invokes the
``CBSDescribe()`` method, but makes no automatic test of the resulting
output. It does not currently test the callbacks.
_`.test.fbmtest`: A generic test for land implementations. See
design.mps.land.fbmtest.
_`.test.pool`: Several pools (currently MVT_ and MVFF_) are implemented
on top of a CBS. These pool are subject to testing in development, QA,
@ -359,6 +230,9 @@ Document History
talking about the deleted "emergency" free list allocator.
Documented ``fastFind`` argument to ``CBSInit()``.
- 2014-04-01 GDR_ Moved generic material to design.mps.land.
Documented new keyword arguments.
.. _RB: http://www.ravenbrook.com/consultants/rb/
.. _GDR: http://www.ravenbrook.com/consultants/gdr/

View file

@ -59,6 +59,7 @@ guide.impl.c.format_ Coding standard: conventions for the general format of C
interface-c_ The design of the Memory Pool System interface to C
io_ The design of the MPS I/O subsystem
keyword-arguments_ The design of the MPS mechanism for passing arguments by keyword.
land_ Lands (collections of address ranges)
lib_ The design of the Memory Pool System library interface
lock_ The design of the lock module
locus_ The design for the locus manager

292
mps/design/land.txt Normal file
View file

@ -0,0 +1,292 @@
.. mode: -*- rst -*-
Lands
=====
:Tag: design.mps.land
:Author: Gareth Rees
:Date: 2014-04-01
:Status: incomplete design
:Revision: $Id$
:Copyright: See section `Copyright and License`_.
Introduction
------------
_`.intro`: This is the design of the *land* abstract data type, which
represents a collection of contiguous address ranges.
_`.readership`: This document is intended for any MPS developer.
_`.source`: `design.mps.cbs <cbs/>`_, `design.mps.freelist <freelist/>`_.
_`.overview`: Collections of address ranges are used in several places
in the MPS: the arena stores a set of mapped address ranges; pools
store sets of address ranges which have been acquired from the arena
and sets of address ranges that are available for allocation. The
*land* abstract data type makes it easy to try out different
implementations with different performance characteristics and other
attributes.
_`.name`: The name is inspired by *rangeland* meaning *group of
ranges* (where *ranges* is used in the sense *grazing areas*).
Definitions
-----------
_`.def.range`: A (contiguous) *range* of addresses is a semi-open
interval on address space.
_`.def.isolated`: A contiguous range is *isolated* with respect to
some property it has, if adjacent elements do not have that property.
Requirements
------------
_`.req.set`: Must maintain a set of addresses.
_`.req.add`: Must be able to add address ranges to the set.
_`.req.remove`: Must be able to remove address ranges from the set.
_`.req.size`: Must report concisely to the client when isolated
contiguous ranges of at least a certain size appear and disappear.
_`.req.iterate`: Must support the iteration of all isolated
contiguous ranges.
_`.req.protocol`: Must detect protocol violations.
_`.req.debug`: Must support debugging of client code.
_`.req.align`: Must support an alignment (the alignment of all
addresses specifying ranges) of down to ``sizeof(void *)`` without
losing memory.
Interface
---------
Types
.....
``typedef LandStruct *Land;``
_`.type.land`: The type of a generic land instance.
``typedef Bool (*LandVisitor)(Land land, Range range, void *closureP, Size closureS);``
_`.type.visitor`: Type ``LandVisitor`` is a callback function that
may be passed to ``LandIterate()``. It is called for every isolated
contiguous range in address order. The function must return a
``Bool`` indicating whether to continue with the iteration.
Generic functions
.................
``Res LandInit(Land land, LandClass class, Arena arena, Align alignment, void *owner, ArgList args)``
_`.function.init`: ``LandInit()`` initializes the land structure for
the given class. The land will perform allocation (if necessary -- not
all land classes need to allocate) in the supplied arena. The
``alignment`` parameter is the alignment of the address ranges that
will be stored and retrieved from the land. The parameter ``owner`` is
output as a parameter to the ``LandInit`` event. The newly initialized
land contains no ranges.
``Res LandCreate(Land *landReturn, Arena arena, LandClass class, Align alignment, void *owner, ArgList args)``
_`.function.create`: ``LandCreate()`` allocates memory for a land
structure of the given class in ``arena``, and then passes all
parameters to ``LandInit()``.
``void LandDestroy(Land land)``
_`.function.destroy`: ``LandDestroy()`` calls ``LandFinish()`` to
finish the land structure, and then frees its memory.
``void LandFinish(Land land)``
_`.function.finish`: ``LandFinish()`` finishes the land structure and
discards any other resources associated with the land.
``Res LandInsert(Range rangeReturn, Land land, Range range)``
_`.function.insert`: If any part of ``range`` is already in the
land, then leave it unchanged and return ``ResFAIL``. Otherwise,
attempt to insert ``range`` into the land. If the insertion succeeds,
then update ``rangeReturn`` to describe the contiguous isolated range
containing the inserted range (this may differ from ``range`` if there
was coalescence on either side) and return ``ResOK``. If the insertion
fails, return a result code indicating allocation failure.
_`.function.insert.fail`: Insertion of a valid range (that is, one
that does not overlap with any range in the land) can only fail if the
new range is isolated and the allocation of the necessary data
structure to represent it failed.
``Res LandDelete(Range rangeReturn, Land land, Range range)``
_`.function.delete`: If any part of the range is not in the land,
then leave the land unchanged and return ``ResFAIL``. Otherwise, update
``rangeReturn`` to describe the contiguous isolated range that
contains ``range`` (this may differ from ``range`` if there are
fragments on either side) and attempt to delete the range from the
land. If the deletion succeeds, return ``ResOK``. If the deletion
fails, return a result code indicating allocation failure.
_`.function.delete.fail`: Deletion of a valid range (that is, one
that is wholly contained in the land) can only fail if there are
fragments on both sides and the allocation of the necessary data
structures to represent them fails.
_`.function.delete.return`: ``LandDelete()`` returns the contiguous
isolated range that contains ``range`` even if the deletion fails.
This is so that the caller can try deleting the whole block (which is
guaranteed to succeed) and managing the fragments using a fallback
strategy.
``void LandIterate(Land land, LandIterateMethod iterate, void *closureP, Size closureS)``
_`.function.iterate`: ``LandIterate()`` is the function used to
iterate all isolated contiguous ranges in a land. It receives a
pointer, ``Size`` closure pair to pass on to the iterator method,
and an iterator method to invoke on every range in address order. If
the iterator method returns ``FALSE``, then the iteration is
terminated.
``Bool LandFindFirst(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete)``
_`.function.find.first`: Locate the first block (in address order)
within the land of at least the specified size, update ``rangeReturn``
to describe that range, and return ``TRUE``. If there is no such
block, it returns ``FALSE``.
In addition, optionally delete the top, bottom, or all of the found
range, depending on the ``findDelete`` argument. This saves a separate
call to ``LandDelete()``, and uses the knowledge of exactly where we
found the range. The value of ``findDelete`` must come from this
enumeration::
enum {
FindDeleteNONE, /* don't delete after finding */
FindDeleteLOW, /* delete size bytes from low end of block */
FindDeleteHIGH, /* delete size bytes from high end of block */
FindDeleteENTIRE /* delete entire range */
};
The original contiguous isolated range in which the range was found is
returned via the ``oldRangeReturn`` argument. (If ``findDelete`` is
``FindDeleteNONE`` or ``FindDeleteENTIRE``, then this will be
identical to the range returned via the ``rangeReturn`` argument.)
``Bool LandFindLast(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete)``
_`.function.find.last`: Like ``LandFindFirst()``, except that it
finds the last block in address order.
``Bool LandFindLargest(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete)``
_`.function.find.largest`: Locate the largest block within the
land, and if that block is at least as big as ``size``, return its
range via the ``rangeReturn`` argument, and return ``TRUE``. If there
are no blocks in the land at least as large as ``size``, return
``FALSE``. Pass 0 for ``size`` if you want the largest block
unconditionally.
Like ``LandFindFirst()``, optionally delete the range (specifying
``FindDeleteLOW`` or ``FindDeleteHIGH`` has the same effect as
``FindDeleteENTIRE``), and return the original contiguous isolated
range in which the range was found via the ``oldRangeReturn``
argument.
``Res LandFindInZones(Range rangeReturn, Range oldRangeReturn, Land land, Size size, ZoneSet zoneSet, Bool high)``
_`.function.find.zones`: Locate a block at least as big as ``size``
that lies entirely within the ``zoneSet``, return its range via the
``rangeReturn`` argument, and return ``TRUE``. (The first such block,
if ``high`` is ``FALSE``, or the last, if ``high`` is ``TRUE``.) If
there is no such block, , return ``FALSE``.
Delete the range as for ``LandFindFirst()`` and ``LastFindLast()``
(with the effect of ``FindDeleteLOW`` if ``high`` is ``FALSE`` and the
effect of ``FindDeleteHIGH`` if ``high`` is ``TRUE``), and return the
original contiguous isolated range in which the range was found via
the ``oldRangeReturn`` argument.
``Res LandDescribe(Land land, mps_lib_FILE *stream)``
_`.function.describe`: ``LandDescribe()`` is a function that prints
a textual representation of the land to the given stream, indicating
the contiguous ranges in order, as well as the structure of the
underlying splay tree implementation. It is provided for debugging
purposes only.
Testing
-------
_`.test.fbmtest`: There is a stress test for implementations of this
interface in impl.c.fbmtest. This allocates a large block of memory
and then simulates the allocation and deallocation of ranges within
this block using both a ``Land`` and a ``BT``. It makes both valid and
invalid requests, and compares the ``Land`` response to the correct
behaviour as determined by the ``BT``. It iterates the ranges in the
``Land``, comparing them to the ``BT``. It invokes the
``LandDescribe()`` generic function, but makes no automatic test of
the resulting output.
Document History
----------------
- 2014-04-01 GDR_ Created based on `design.mps.cbs <cbs/>`_.
.. _GDR: http://www.ravenbrook.com/consultants/gdr/
Copyright and License
---------------------
Copyright © 2014 Ravenbrook Limited. All rights reserved.
<http://www.ravenbrook.com/>. This is an open source license. Contact
Ravenbrook for commercial licensing options.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
#. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
#. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
#. Redistributions in any form must be accompanied by information on how
to obtain complete source code for this software and any
accompanying software that uses this software. The source code must
either be included in the distribution or be available for no more than
the cost of distribution plus a nominal fee, and must be freely
redistributable under reasonable conditions. For an executable file,
complete source code means the source code for all modules it contains.
It does not include source code for modules or files that typically
accompany the major components of the operating system on which the
executable file runs.
**This software is provided by the copyright holders and contributors
"as is" and any express or implied warranties, including, but not
limited to, the implied warranties of merchantability, fitness for a
particular purpose, or non-infringement, are disclaimed. In no event
shall the copyright holders and contributors be liable for any direct,
indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or
services; loss of use, data, or profits; or business interruption)
however caused and on any theory of liability, whether in contract,
strict liability, or tort (including negligence or otherwise) arising in
any way out of the use of this software, even if advised of the
possibility of such damage.**

View file

@ -14,6 +14,7 @@ Design
guide.hex.trans
guide.impl.c.format
keyword-arguments
land
range
ring
sig