Ravenbrook / Projects / Memory Pool System / Master Product Sources / Product Manuals
This is the reference manual for the Memory Pool System.
This document is quite incomplete. At present it consists simply of reference descriptions of a number of MPS symbols (section 3). Many MPS symbols are not described here (see section 4 for a list). There are also no overview or protocol-oriented sections.
MPS_ARCH_AL mps_fix MPS_FIX1 MPS_FIX12 MPS_FIX2 MPS_FIX_CALL MPS_RES_LIMIT MPS_RES_MEMORY MPS_RES_PARAM MPS_RM_CONST MPS_RM_PROT mps_sac_alloc MPS_SAC_ALLOC_FAST MPS_SAC_CLASS_LIMIT mps_sac_free MPS_SAC_FREE_FAST MPS_SCAN_BEGIN MPS_SCAN_END MPS_T_WORD MPS_WORD_SHIFT MPS_WORD_WIDTH mps_addr_t mps_align_t mps_alloc mps_alloc_pattern_ramp mps_alloc_pattern_ramp_collect_all mps_amc_apply mps_ap_alloc_pattern_begin mps_ap_alloc_pattern_end mps_ap_alloc_pattern_reset mps_ap_frame_pop mps_ap_frame_push mps_arena_clamp mps_arena_class_cl mps_arena_class_t mps_arena_class_vm mps_arena_class_vmnz mps_arena_collect mps_arena_commit_limit mps_arena_commit_limit_set mps_arena_committed mps_arena_create mps_arena_create_v mps_arena_expose mps_arena_formatted_objects_walk mps_arena_park mps_arena_release mps_arena_roots_walk mps_arena_spare_commit_limit mps_arena_spare_commit_limit_set mps_arena_spare_committed mps_arena_unsafe_expose_remember_protection mps_arena_unsafe_restore_protection mps_bool_t mps_class_amc mps_class_mvff mps_class_snc mps_class_mvt mps_class_t mps_finalize mps_fmt_A_s mps_fmt_A_t mps_fmt_B_s mps_fmt_B_t mps_fmt_auto_header_s mps_fmt_class_t mps_fmt_copy_t mps_fmt_create_A mps_fmt_create_B mps_fmt_create_auto_header mps_fmt_fwd_t mps_fmt_isfwd_t mps_fmt_pad_t mps_fmt_scan_t mps_fmt_skip_t mps_fmt_t mps_formatted_objects_stepper_t mps_free mps_lib_memcmp mps_lib_memcpy mps_lib_memset mps_lib_telemetry_control mps_message_discard mps_message_finalization_ref mps_message_gc_condemned_size mps_message_gc_live_size mps_message_gc_not_condemned_size mps_message_get mps_message_poll mps_message_queue_type mps_message_t mps_message_type mps_message_type_disable mps_message_type_enable mps_message_type_finalization mps_message_type_gc mps_message_type_t mps_pool_check_fenceposts mps_pool_debug_option_s mps_rank_ambig mps_rank_exact mps_rank_t mps_rank_weak mps_reg_scan_t mps_res_t mps_root_create mps_root_create_fmt mps_root_create_reg mps_root_create_table mps_root_create_table_masked mps_root_scan_t mps_roots_stepper_t mps_sac_class_s mps_sac_create mps_sac_destroy mps_sac_flush mps_sac_t mps_stack_scan_ambig mps_telemetry_control mps_telemetry_flush mps_telemetry_intern mps_telemetry_label mps_thr_t MPS_ARCH_ALMPS_ARCH_AL is a C
preprocessor macro that indicates, if defined, that the target
processor architecture of the compilation is a member of the DEC Alpha
family. It is defined, if appropriate, by "mpstd.h".
None.
mpstd.h.
See summary.
#ifdef MPS_ARCH_AL
typedef struct RegisterFile {
unsigned long v0;
unsigned long t0, t1, t2, t3, t4, t5, t6, t7;
unsigned long s0, s1, s2, s3, s4, s5;
unsigned long fp;
unsigned long a0, a1, a2, a3, a4, a5;
unsigned long t8, t9, t10, t11;
unsigned long ra;
unsigned long t12;
unsigned long at, gp, sp, zero;
unsigned long fir;
unsigned psr;
} RegisterFile;
#endif /* MPS_ARCH_AL */
Not applicable.
MPS_PF_*,
MPS_OS_*,
MPS_BUILD_*,
MPS_ARCH_*
I'm not sure that the user ought to be using these symbols. GavinM 1997-05-01
mps_fixThe function mps_fix is the
part of the scanning protocol used to indicate references to the
MPS. It may only be called from within a scanning function.
Scanning.
mps_res_t mps_fix(mps_ss_t mps_ss, mps_addr_t *ref_io)
mps_ss the scan state argument that was passed to the
scanning function
ref_io a pointer to a reference within the object
being scanned
Returns a result code, see ERROR HANDLING.
If the reference rank of the object being scanned is not MPS_RANK_AMBIG then the reference
pointed to by ref_io may be modified by mps_fix.
mps.h
This function is the part of the scanning protocol used to indicate
references. Scanning functions apply it, or MPS_FIX12, or MPS_FIX1 and MPS_FIX2 tothe references in the object
being scanned.
It may only be called from within a scanning function. If it is
called within a MPS_SCAN_BEGIN block, MPS_FIX_CALL must be used (yes,
really).
This function does not perform any particular operation. The MPS
may call scanning functions for a number of reasons, and mps_fix may take different actions
depending on those reasons.
mps_res_t scan_array(mps_ss_t ss, mps_addr_t object, size_t length)
{
size_t i;
mps_res_t res;
mps_addr_t *array = (mps_addr_t *)object;
for(i = 0; i < length; ++i) {
res = mps_fix(ss, &array[i]);
if(res != MPS_RES_OK) return res;
}
return res;
}
The function returns MPS_RES_OK if it was successful, in
which case the scanning function should continue to scan the rest of
the object, applying mps_fix to
the remaining references. If mps_fix returns a value other than MPS_RES_OK, the scanning function must
return that value, and may return without scanning further
references. Generally, it is better if it returns as soon
as possible.
mps_ss_t,
mps_root_scan_t,
mps_fmt_scan_t,
mps_reg_scan_t,
MPS_SCAN_BEGIN,
MPS_SCAN_END,
MPS_FIX12,
MPS_FIX1,
MPS_FIX2,
MPS_FIX_CALL
MPS_FIX1The macro MPS_FIX1 is the part
of the scanning protocol used to indicate references to the MPS. It
may only be used from within MPS_SCAN_BEGIN and MPS_SCAN_END.
Format.
MPS_FIX1(mps_ss, ref)
mps_ss the scan state argument
that was passed to the scanning function
ref a reference within the object being scanned, type
mps_addr_t
Returns a truth value (type mps_bool_t) indicating whether the
reference is likely to be interesting to the MPS.
mps.h.
MPS_FIX1 and MPS_FIX2 are a trick to speed up scanning
by splitting MPS_FIX12 into two
macros. MPS_FIX1 is a fast test
to see if the reference is likely to be interesting to the MPS; if it
returns false, the scanner can proceed to the next reference. If it
returns true, the scan method must invoke MPS_FIX2, which does the actual
fixing.
This macro may only be used in code textually between MPS_SCAN_BEGIN and MPS_SCAN_END.
mps_res_t scan_array(mps_ss_t ss, Array object, size_t length)
{
size_t i;
mps_res_t res;
mps_addr_t *array = (mps_addr_t *)object;
MPS_SCAN_BEGIN(ss)
for(i = 0; i < length; ++i) {
mps_addr_t ref = array[i];
if(MPS_FIX1(ss, ref)) {
/* if(((Object*)ref)->type == ScannableType) { */
/* You can do something here, but in the end, you must call MPS_FIX2. */
res = MPS_FIX2(ss, &array[i]);
if(res != MPS_RES_OK)
return res;
/* } */
}
}
MPS_SCAN_END(ss);
return res;
}
MPS_FIX12,
MPS_FIX2,
mps_fix,
mps_ss_t,
mps_root_scan_t,
mps_fmt_scan_t,
mps_reg_scan_t,
MPS_SCAN_BEGIN,
MPS_SCAN_END,
MPS_FIX_CALL
MPS_FIX12The macro MPS_FIX12 is the
part of the scanning protocol used to indicate references to the
MPS. It may only be used from within MPS_SCAN_BEGIN and MPS_SCAN_END.
Scanning.
MPS_FIX12(mps_ss, ref_io);
mps_ss the scan state argument that was passed to the scanning function
ref_io a pointer to a reference within the object
being scanned, type mps_addr_t *
Returns a result code, see ERROR HANDLING.
If the reference rank of the object being scanned is not MPS_RANK_AMBIG then the reference
pointed to by ref_io may be modified by MPS_FIX12.
mps.h
This macro is used in the scanning protocol to indicate
references. Scanning functions apply it or mps_fix or MPS_FIX1 and MPS_FIX2 to the references in the object
being scanned.
It may only be used in code textually between MPS_SCAN_BEGIN and MPS_SCAN_END.
It is permitted for the reference (*ref_io) to point
outside the MPS arena being scanned, or to be NULL; in that case, it
is simply ignored.
This macro does not perform any particular operation. The MPS may
call scanning functions for a number of reasons, and MPS_FIX may take different actions
depending on those reasons.
mps_res_t scan_array(mps_ss_t ss, mps_addr_t object, size_t length) {
size_t i;
mps_res_t res;
mps_addr_t *array = (mps_addr_t *)object;
MPS_SCAN_BEGIN(ss)
for(i = 0; i < length; ++i) {
res = MPS_FIX(ss, &array[i]);
if(res != MPS_RES_OK)
return res;
}
MPS_SCAN_END(ss);
return res;
}
The macro returns MPS_RES_OK
if it was successful, in which case the scanning function should
continue to scan the rest of the object, fixing the remaining
references. If MPS_FIX12 returns
a value other than MPS_RES_OK,
the scanning function must return that value, and may return without
scanning further references. Generally, it is better if it returns as
soon as possible.
mps_fix,
mps_ss_t,
mps_root_scan_t,
mps_fmt_scan_t,
mps_reg_scan_t,
MPS_SCAN_BEGIN,
MPS_SCAN_END,
MPS_FIX1,
MPS_FIX2,
MPS_FIX_CALL
MPS_FIX12 is so called, as it basically performs the work of both MPS_FIX1 and MPS_FIX2.
MPS_FIX2The macro MPS_FIX2, together with MPS_FIX1, is the part of the scanning protocol used to indicate references to the MPS. It may only be used from within MPS_SCAN_BEGIN and MPS_SCAN_END.
Scanning.
MPS_FIX2(mps_ss, ref_io);
mps_ss the scan state argument
that was passed to the scanning function
ref_io a pointer to a reference within the object
being scanned, type mps_addr_t *
Returns a result code, see ERROR HANDLING.
If the reference rank of the object being scanned is not MPS_RANK_AMBIG then the reference pointed to by ref_io may be modified by MPS_FIX2.
mps.h.
MPS_FIX1 and MPS_FIX2 are a trick to speed up scanning
by splitting MPS_FIX12 into two
macros. MPS_FIX1 is a fast test
to see if the reference is likely to be interesting to the MPS; if it
returns false, the scanner can proceed to the next reference. If it
returns true, the scan method must invoke MPS_FIX2, which does the actual
fixing.
This macro may only be used in code textually between MPS_SCAN_BEGIN and MPS_SCAN_END.
This macro does not perform any particular operation. The MPS may call scanning functions for a number of reasons, and MPS_FIX2 may take different actions depending on those reasons.
mps_res_t scan_array(mps_ss_t ss, Array object, size_t length) {
size_t i;
mps_res_t res;
mps_addr_t *array = (mps_addr_t *)object;
MPS_SCAN_BEGIN(ss)
for(i = 0; i < length; ++i) {
mps_addr_t ref = array[i];
if(MPS_FIX1(ss, ref)) {
/* if(((Object*)ref)->type == ScannableType) { */
/* You can do something here, but in the end, you must call MPS_FIX2. */
res = MPS_FIX2(ss, &array[i]);
if(res != MPS_RES_OK)
return res;
/* } */
}
}
MPS_SCAN_END(ss);
return res;
}
The macro returns MPS_RES_OK
if it was successful, in which case the scanning function should
continue to scan the rest of the object, fixing the remaining
references. IfMPS_FIX2 returns a
value other than MPS_RES_OK,
the scanning function must return that value, and may return without
scanning further references. Generally, it is better if it returns as
soon as possible.
MPS_FIX12,
MPS_FIX1,
mps_fix,
mps_ss_t,
mps_root_scan_t,
mps_fmt_scan_t,
mps_reg_scan_t,
MPS_SCAN_BEGIN,
MPS_SCAN_END,
MPS_FIX_CALL
MPS_FIX_CALLMPS_FIX_CALL is used to call a scanning function from within MPS_SCAN_BEGIN and MPS_SCAN_END.
Scanning.
MPS_FIX_CALL(ss, call);
mps_ss the scan state argument that was passed to the scanning function
call an expression (containing a call to a scanning function)
None.
mps.h.
When using the MPS_SCAN_BEGIN and MPS_SCAN_END macros, you can't
directly call a separate function to do part of the scanning, because
between MPS_SCAN_BEGIN and
MPS_SCAN_END, the
scan_state parameter is in a strange state, so you
shouldn't pass it as an argument to a function. However, if you
really want to do it (say, because you have an embedded structure
shared between two scan methods), you can pass the scan state
correctly using MPS_FIX_CALL.
Note that you must receive the return value of the scanning function called, and pass it on as described in the ERROR HANDLING section.
mps_res_t foo_scan(mps_ss_t scan_state, mps_addr_t base, mps_addr_t limit)
{
Object *obj;
Object *obj_limit;
mps_res_t res;
obj_limit = limit;
MPS_SCAN_BEGIN(scan_state)
for(obj = base; obj < obj_limit; obj++) {
if(MPS_FIX12(scan_state, &obj->left) != MPS_RES_OK)
return res;
MPS_FIX_CALL(scan_state,
res = scan_data(scan_state, &obj->data));
if(res != MPS_RES_OK) return res;
if(MPS_FIX12(scan_state, &obj->right) != MPS_RES_OK)
return res;
}
MPS_SCAN_END(scan_state);
return MPS_RES_OK;
}
You must receive the return value of the function called. Like all
scanning functions, itreturns MPS_RES_OK if it was successful, in
which case the caller should continue to scan the rest of the object,
fixing the remaining references. If it returns a value other
thanMPS_RES_OK, the calling
scanning function must return that value, and may return without
scanning further references. Generally, it is better if it returns as
soon as possible.
mps_fix,
mps_ss_t,
mps_root_scan_t,
mps_fmt_scan_t,
mps_reg_scan_t,
MPS_SCAN_BEGIN,
MPS_SCAN_END,
MPS_FIX12,
MPS_FIX1,
MPS_FIX2
MPS_RES_LIMITMPS_RES_LIMIT is a result
code, indicating that an operation failed because an internal limit
was reached.
mps.h.
This result code is returned if an operation could not be completed as requested because of an internal limitation of the MPS. The precise meaning depends on the function that returned the code. Refer to the documentation of that function for details.
switch(mps_alloc(&(mps_addr_t)object, pool, size)) {
case MPS_RES_LIMIT:
bomb("The MPS has reached an internal limit");
break;
/* ... */
}
MPS_RES_MEMORYMPS_RES_MEMORY is a result code, indicating that an operation failed because it ran out of memory.
All.
mps.h
This result code is returned if an operation could not be completed because there wasn't enough memory available. You need to deallocate something or allow the garbage collector to reclaim something to free enough memory, or expand the arena (if you're using an arena for which that does not happen automatically).
Note that failing to acquire enough memory because the arena commit
limit would have been exceeded is indicated by returning MPS_RES_COMMIT_LIMIT, not
MPS_RES_MEMORY.
Note that running out of address space (as might happen in virtual
memory systems) is indicated by returning MPS_RES_RESOURCE, not MPS_RES_MEMORY.
mps_res_t,
MPS_RES_RESOURCE,
MPS_RES_COMMIT_LIMIT
MPS_RES_PARAMMPS_RES_PARAM is a result
code, indicating that an operation failed because an invalid parameter
was specified for the operation.
All.
mps.h.
This result code is returned if an operation could not be completed as requested because an invalid parameter was specified for the operation. The precise meaning depends on the function that returned the code. Refer to the documentation of that function for details.
switch( res = mps_pool_create_v(&pool, arena, class, params) ) {
case MPS_RES_PARAM:
bomb("Can't make a pool with those specifications");
break;
/* ... */
}
MPS_RM_CONSTMPS_RM_CONST is a constant used in root mode arguments to indicate constant roots.
Root.
Integral constant.
mps.h
MPS_RM_CONST is a
preprocessor macro defining a constant that can be OR'ed with other
MPS_RM_* constants, and passed as the root mode argument
to certain root creation functions (mps_root_create, mps_root_create_fmt, mps_root_create_table,
mps_root_create_table_masked,
mps_root_create_reg
).
Passing MPS_RM_CONST means
that the client program will not change the root after it is
declared. I.e., scanning the root will produce the same set of
references every time. Furthermore, for formatted and table roots, the
client program may not write to the root at all.
res = mps_root_create_table(&mmRoot,
arena,
MPS_RANK_EXACT,
MPS_RM_CONST,
(mps_addr_t)&Objects,
rootCOUNT);
mps_root_create,
mps_root_create_fmt,
mps_root_create_table,
mps_root_create_table_masked,
mps_root_create_reg
Currently ignored. -- drj 1997-12-18.
MPS_RM_PROTMPS_RM_PROT is a constant used in root mode arguments to indicate protectable roots.
Root.
Integral constant.
mps.h
MPS_RM_PROT is a
preprocessor macro defining a constant that can be OR'ed with other
MPS_RM_* contants, and passed as the root mode argument
to certain root creation functions (mps_root_create_fmt, mps_root_create_table,
mps_root_create_table_masked).
Passing MPS_RM_PROT means
that the MPS may place a hardware write barrier on any pages which any
part of the root covers. Format methods and any scanning function
(except for the one for this root) may not write data in this
root. They may read it.
You mustn't specify MPS_RM_PROT on a root allocated from
the MPS.
res = mps_root_create_table(&mmRoot,
arena,
MPS_RANK_EXACT,
MPS_RM_PROT,
(mps_addr_t)&Objects,
rootCOUNT);
mps_root_create_fmt,
mps_root_create_table,
mps_root_create_table_masked.
No page may contain parts of two or more roots with MPS_RM_PROT [how does one prevent
that?]. You mustn't specify MPS_RM_PROT if the client program or
anything other than (this instance of) the MPS is going to protect or
unprotect the relevant pages.
Future meaning: The MPS may place a hardware read and/or write
barrier on any pages which any part of the root covers. Format methods
and scanning functions (except for the one for thisroot) may not read
or write data in this root. You may specify MPS_RM_PROT on a root allocated from
the MPS, as long as it's not from a GCd pool. - drj 1997-12-18
This feature is far too technical for most of our clients: we should think about producing some guidelines on how to use it. - pekka 1998-01-27
There may be problems if the client wants the OS to access the root. Lots of OSes can't cope with writing to protected pages. So we'll need to document that caveat too. drj 1998-05-20
mps_sac_allocThis function allocates a block using the segregated allocation cache given.
Allocation cache
mps_res_t mps_sac_alloc(mps_addr_t *p_o, mps_sac_t sac, size_t size, mps_bool_t has_reservoir_permit);
p_o a pointer to a variable to hold the address of the new block
sac the segregated allocation cache
size the size of the block requested
has_reservoir_permit regulates access to the reservoir
If the return value is MPS_RES_OK, the address of a new block
is *p_o .
mps.h
This function allocates a block using the cache given. If no
suitable block exists in the cache, it will ask for more memory from
the associated pool. size does not have to be one of the
class sizes of the cache; it does not have to be aligned.
The client is responsible for synchronising the access to the cache, but if the cache decides to access the pool, the MPS will properly synchronize with any other threads that might be accessing the same pool.
has_reservoir_permit regulates whether the pool has
permission to get more memory from the reservoir to satisfy this
request.
void *p;
Foo *foo;
res = mps_sac_alloc(&p, sac, FooSIZE, is_in_panic);
if (res != MPS_RES_OK) {
printf("Failed to alloc foo!\n");
exit(1);
}
foo = p;
/* use foo */
mps_sac_free(sac, p, FooSIZE);
mps_sac_alloc returns
MPS_RES_MEMORY when it
fails to find enough memory; see the documentation for this return
code for recovery options. It returns MPS_RES_COMMIT_LIMIT if it
can't allocate without exceeding the arena commit limit; Free
something to make more space or increase the limit using mps_arena_commit_limit_set. It
returns MPS_RES_RESOURCE
if it has run out of swap space; Free something or terminate other
processes on the same machine.
MPS_SAC_ALLOC_FAST,
mps_sac_free,
MPS_SAC_FREE_FAST,
mps_sac_t,
mps_reservoir_limit_set,
mps_arena_commit_limit_set,
MPS_RES_MEMORY,
MPS_RES_COMMIT_LIMIT,
MPS_RES_RESOURCE
There's also a macro called MPS_SAC_ALLOC_FAST, that does
the same thing. The macro is faster, but generates more code and does
less checking.
The block allocated can be larger than requested. Blocks not matching any class size are allocated from the next largest class, and blocks larger than the largest class size are simply allocated at the requested size (rounded up to alignment, as usual).
Objects allocated through a segregated allocation cache should only
be freed through a segregated allocation cache with the same class
structure. Using mps_free on
them can cause memory leaks, because the size of the block might be
larger than you think. Naturally, the cache must also be attached to
the same pool.
MPS_SAC_ALLOC_FASTThis macro allocates a block using the segregated allocation cache given.
Allocation cache
MPS_SAC_ALLOC_FAST(res_o, p_o, sac, size, has_reservoir_permit)
res_o |
mps_res_t |
an lvalue to hold the result code |
p_o |
mps_addr_t |
an lvalue to hold the address of the new block |
sac |
mps_sac_t |
the segregated allocation cache |
size |
size_t |
the size of the block requested |
has_reservoir_permit |
mps_bool_t |
regulates access to the reservoir |
res_o will be set to the return code. If this is
MPS_RES_OK, the address of the
new block is in p_o.
mps.h
This macro allocates a block using the cache given. If no suitable
block exists in the cache, it will ask for more memory from the
associated pool. size does not have to be one of the
class sizes of the cache; it does not have to be aligned.
The client is responsible for synchronizing the access to the cache, but if the cache decides to access the pool, the MPS will properly synchronize with any other threads that might be accessing the same pool.
has_reservoir_permit regulates whether the pool has
permission to get more memory from the reservoir to satisfy this
request.
void *p;
Foo *foo;
mps_res_t res;
MPS_SAC_ALLOC_FAST(res, p, sac, FooSIZE, is_in_panic);
if (res != MPS_RES_OK) {
printf("Failed to alloc foo!\n");
exit(1);
}
foo = p;
/* use foo */
MPS_SAC_FREE_FAST(sac, p, FooSIZE);
MPS_SAC_ALLOC_FAST
returns MPS_RES_MEMORY when
it fails to find enough memory; see the documentation for this return
code for recovery options. It returns MPS_RES_COMMIT_LIMIT if it
can't allocate without exceeding the arena commit limit; free something
to make more space or increase the limit using mps_arena_commit_limit_set. It
returns MPS_RES_RESOURCE
if it has run out of swap space; free something or terminate other
processes on the same machine.
mps_sac_alloc,
MPS_SAC_FREE_FAST,
mps_sac_free,
mps_sac_t,
mps_reservoir_limit_set,
mps_arena_commit_limit_set,
MPS_RES_MEMORY,
MPS_RES_COMMIT_LIMIT,
MPS_RES_RESOURCE
There's also a function called mps_sac_alloc, that does the same
thing.
The block allocated can be larger than requested. Blocks not matching any class size are allocated from the next largest class, and blocks larger than the largest class size are simply allocated at the requested size (rounded up to alignment, as usual).
Objects allocated through a segregated allocation cache should only
be freed through a segregated allocation cache with the same class
structure. Using mps_free on them
can cause memory leaks or assertions, because the size of the block
might be larger than you think. Naturally, the cache must also be
attached to the same pool.
The macro doesn't evaluate has_reservoir_permit,
unless it decides to access the pool.
MPS_SAC_CLASS_LIMITMPS_SAC_CLASS_LIMIT specifies how many classes mps_sac_create is guaranteed to accept.
size_t
Allocation cache
mps.h
MPS_SAC_CLASS_LIMIT specifies a lower limit on the maximum number of classesthat can be described in a call to mps_sac_create, i.e., the MPS guarantees to acceptat least this many classes. More might be accepted -- in fact, there might not be any limit in theimplementation on the maximum number of classes, but if you specify more than this, you should beprepared to handle the error.
MPS_SAC_CLASS_LIMIT is a macro suitable for use in a constant expression, bothin a #if directive and wherever else constant expressions may be used.
mps_sac_t sac;
mps_sac_class_s classes[3] = { {8, 38, 1}, {136, 19, 3}, {512, 4, 1} };
#if (MPS_SAC_CLASS_LIMIT < 3)
# error "Too many classes!"
#endif
res = mps_sac_create(&sac, pool, 3, classes);
if (res != MPS_RES_OK) {
printf("Failed to create the allocation cache!");
exit(1);
}
If you ask for too many size classes, mps_sac_create returns MPS_RES_LIMIT; you can recover by combining some small adjacent classes.
mps_sac_freeThis function frees an object using the segregated allocation cache given.
Allocation cache
void mps_sac_free(mps_sac_t sac, mps_addr_t p, size_t size);
sac the segregated allocation cache
p a pointer to the block being freed
size the size of the block being freed
None.
mps.h
This function frees an object using the cache given. If the cache would become too full,some blocks are returned to the associated pool.
size
should be the size that wasspecified when the object was allocated (the cache knows what the real size of the block is). Theobject must have been allocated through a segregated allocation cache with the same class structure,attached to the same pool.
The client is responsible for synchronising the access to the cache, but if the cachedecides to access the pool, the MPS will properly synchronize with any other threads that might beaccessing the same pool.
void *p;
Foo *foo;
res = mps_sac_alloc(&p, sac, FooSIZE, is_in_panic);
if (res != MPS_RES_OK) {
printf("Failed to alloc foo!\n");
exit(1);
}
foo = p;
/* use foo */
mps_sac_free(sac, p, FooSIZE);
MPS_SAC_FREE_FAST,
mps_sac_alloc,
MPS_SAC_ALLOC_FAST,
mps_sac_t
Usually, you'd use the same cache to allocate and deallocate an object.
There's also a macro called MPS_SAC_FREE_FAST, that does the same thing. The macro is faster, but generates more code and does no checking.
Note that mps_sac_free does very little checking; it's optimized for speed.Double frees and other mistakes will only be detected when the cache is flushed (which can happen bydemand through mps_sac_flush or automatically), unless intervening operations have obscured symptom.
MPS_SAC_FREE_FASTMPS_SAC_FREE_FAST frees an object using the segregated allocation cache given.
Allocation cache
MPS_SAC_FREE_FAST(sac, p, size)
sac
|
mps_sac_t
|
the segregated allocation cache |
p
|
mps_addt_t
|
the address of the object to be freed |
size
|
size_t
|
the size of the object |
None.
mps.h
This macro frees an object using the cache given. If the cache would become too full, someblocks are returned to the associated pool.
size
should be the size that was specifiedwhen the object was allocated (the cache knows what the real size of the block is). The objects musthave been allocated through a segregated allocation cache with the same class structure, attachedto the same pool.
The client is responsible for synchronizing the access to the cache, but if the cachedecides to access the pool, the MPS will properly synchronize with any other threads that might beaccessing the same pool.
void *p;
Foo *foo;
mps_res_t res;
MPS_SAC_ALLOC_FAST(res, p, sac, FooSIZE, is_in_panic);
if (res != MPS_RES_OK) {
printf("Failed to alloc foo!\n");
exit(1);
}
foo = p;
/* use foo */
MPS_SAC_FREE_FAST(sac, p, FooSIZE);
mps_sac_free,
MPS_SAC_ALLOC_FAST,
mps_sac_alloc,
mps_sac_t
Usually, you'd use the same cache to allocate and deallocate an object.
There's also a function called mps_sac_free, that does the same thing. Themacro is faster, but generates more code and does no checking.
Note that MPS_SAC_FREE_FAST doesn't do any checking; it's optimized for speed. Double frees and other mistakes will only be detected when the cache is flushed (which can happen by demand through mps_sac_flush or automatically), unless intervening operations have obscured symptom.
MPS_SCAN_BEGINThe macro MPS_SCAN_BEGIN is part of the scanning protocol; together with MPS_SCAN_END, it sets up local information used by MPS_FIX*.
Scanning.
MPS_SCAN_BEGIN(ss)
ss the scan state argument that was passed to the scanning function
mps.h
This macro is used in the scanning protocol. Together with MPS_SCAN_END, it sets up local information used by the fast MPS_FIX* macros.
mps_res_t scan_array(mps_ss_t ss, mps_addr_t object, size_t length)
{
size_t i;
mps_res_t res;
mps_addr_t *array = (mps_addr_t *)object;
MPS_SCAN_BEGIN(ss)
for(i = 0; i < length; ++i) {
res = MPS_FIX12(ss, &array[i]);
if(res != MPS_RES_OK)
return res;
}
MPS_SCAN_END(ss);
return res;
}
MPS_SCAN_END,
MPS_FIX12,
MPS_FIX1,
MPS_FIX2,
MPS_FIX_CALL
Between MPS_SCAN_BEGIN and MPS_SCAN_END, you may not call another scanning functiondirectly, because the scan state parameter is in a strange state, so you shouldn't pass it as anargument to a function. However, you can pass the scan state using MPS_FIX_CALL. You also cannotnest MPS_SCAN_BEGIN textually within another MPS_SCAN_BEGIN -- MPS_SCAN_END pair.
MPS_SCAN_ENDThe macro MPS_SCAN_END is part of the scanning protocol; it terminates a blockstarted by MPS_SCAN_BEGIN.
Scanning.
MPS_SCAN_END(ss);
ss the scan state argument that was passed to the scanning function
mps.h
This macro is used in the scanning protocol. Together with MPS_SCAN_BEGIN, itsets up local information used by the fast MPS_FIX* macros. Note that MPS_SCAN_END completes the scanning, so successful termination of the scanning mustinvoke it (error branches can return without passing through).
mps_res_t scan_array(mps_ss_t ss, mps_addr_t object, size_t length) {
size_t i;
mps_res_t res;
mps_addr_t *array = (mps_addr_t *)object;
MPS_SCAN_BEGIN(ss)
for(i = 0; i < length; ++i) {
res = MPS_FIX12(ss, &array[i]);
if(res != MPS_RES_OK)
return res;
}
MPS_SCAN_END(ss);
return res;
}
MPS_SCAN_BEGIN,
MPS_FIX12,
MPS_FIX1,
MPS_FIX2,
MPS_FIX_CALL
Between MPS_SCAN_BEGIN and MPS_SCAN_END, you may not call another scanning functiondirectly, because the scan state parameter is in a strange state, so you shouldn't pass it as anargument to a function. However, you can pass the scan state using MPS_FIX_CALL.
MPS_T_WORDMPS_T_WORD an unsigned integral type that is the same size as an object pointer.
mpstd.h.
MPS_T_WORD is a preprocessor macro defined in "mpstd.h". It is the name of an unsignedintegral type that is the same size as an object pointer (so sizeof(MPS_T_WORD) == sizeof(void*)).The exact identity of the type is platform-dependent.
MPS_WORD_SHIFT,
MPS_WORD_WIDTH
MPS_WORD_SHIFTMPS_WORD_SHIFT is log base 2 of MPS_WORD_WIDTH.
Integral constant.
mpstd.h.
MPS_WORD_SHIFT is a preprocessor macro defined in "mpstd.h". It is the logarithm in base 2 of MPS_WORD_WIDTH (so 1 << MPS_WORD_SHIFT == MPS_WORD_WIDTH). The value of MPS_WORD_SHIFT is platform-dependent. Typical values are 5 and 6.
MPS_WORD_WIDTHMPS_WORD_WIDTH is the width in bits of the type MPS_T_WORD.
Integral constant.
mpstd.h.
MPS_WORD_WIDTH is a preprocessor macro defined in "mpstd.h" to be the width in bits of the type MPS_T_WORD (so MPS_WORD_WIDTH == sizeof(MPS_T_WORD) * CHAR_BIT).
This value is required for the use of the MPS C interface and the interpretation of "mps.h".It is platform-dependent. It is a power of 2; typical values are 32 and 64. It may be defined byincluding "mpstd.h" on a supported platform, or by defining it to be the width of MPS_T_WORD inbits.
#define MPS_WORD_WIDTH 32
mps_addr_tmps_addr_t is the type of addresses managed by the MPS, and also the type of references too bjects.
Allocation, allocation point, format, root, location dependency.
typedef void *mps_addr_t;
mps.h
mps_addr_t is the type of addresses managed by the MPS, and also the type of referencesto objects. It is used in the MPS C interface where the MPS needs to pass a pointer to memory thatis under the control of the MPS.
In accordance with standard C practice, the value NULL of type mps_addr_t will never beused to represent the address of an object.
{
mps_addr_t new_block;
mps_res_t res;
thingy *tp;
res = mps_pool_alloc(&new_block, pool, sizeof(thingy));
if(res != MPS_RES_OK) return res;
tp = new_block;
/* ... */
}
Not applicable.
mps_align_tmps_align_t is the type of an alignment.
Format, pool, allocation.
typedef size_t mps_align_t;
mps.h
An alignment specifies the address modulus to which all objects in an object format must bealigned. That is, if an alignment of 4 is specified, then the address of any object in that formatmodulo 4 will always be 0.
mps_align_t is a transparent type equivalent to the C type "size_t" and must be a positivepower of 2.
Some pools and allocation protocols accept an alignment as an option that can be used toensure that objects in the pool or objects allocated observe a stricter alignment than that of theobject format.
mps_align_t floatAlign = 4; mps_align_t doubleFloatAlign = 8;
mps_allocmps_alloc allocates a block of memory in a pool.
Allocation.
mps_res_t mps_alloc(mps_addr_t *p, mps_pool_t pool, size_t size, ...);
p output parameter for a pointer to the block allocated
pool the pool to allocate in
size the size of the block to allocate in bytes
... (some pools can take additional arguments)
A return code.
mps.h
mps_alloc allocates a block of memory in the given pool.
mps_res_t res;
mps_addr_t p;
res = mps_alloc(&p, pool, size);
if(res != MPS_RES_OK) {
/* p hasn't been touched in this case. */
handle error;
}
/* p now contains the result, which is the address of the new block */
/* in this case. */
mps_alloc_pattern_rampReturns a allocation pattern type indicating that allocation will follow a ramp pattern.
alloc-pattern-ramp
mps_alloc_pattern_t mps_alloc_pattern_ramp();
none
Returns the allocation pattern type for ramps.
When declaring an allocation pattern for an AP, if the calls to mps_ap_alloc_pattern_begin use ramp allocation patterns (such as the result of mps_alloc_pattern_ramp), then the MPS willtake this as an indication that most of the objects allocated after the call to mps_ap_alloc_pattern_begin are likely to be dead by the corresponding call to mps_ap_alloc_pattern_end.
This permits the client to indicate useful points for GC with minimal perturbation of the GCstrategy.
{
mps_ap_alloc_pattern_begin(ap, mps_alloc_pattern_ramp());
do_lots_of_work();
mps_ap_alloc_pattern_end(ap, mps_alloc_pattern_ramp());
}
Cannot fail.
mps_alloc_pattern_ramp_collect_all,
mps_ap_alloc_pattern_begin
mps_alloc_pattern_ramp_collect_allmps_alloc_pattern_ramp_collect_all
Returns a ramp allocation pattern type indicating that a full GC should be done.
GC, AP, ramps
mps_alloc_pattern_t mps_alloc_pattern_ramp_collect_all();
none
Returns the allocation pattern type for full collection ramps.
This yields an allocation pattern for an AP that is similar to that returned by mps_alloc_pattern_ramp, in that it declares a ramp allocation pattern, but additionally indicates tothe MPS that the next collection following the ramp should be a full GC.
This permits the client to indicate useful points for a full GC, either because most of theheap is likely to be dead, or because accurate statistics are required, with minimal perturbation ofthe GC strategy.
As usual, this allocation pattern should be used in matching mps_ap_alloc_pattern_begin and mps_ap_alloc_pattern_end pairs. It may nest with, but should not otherwise overlap with allocationpatterns of type mps_alloc_pattern_ramp. In this case, the MPS may defer the full GC until after allramp allocation patterns have ended.
{
mps_ap_alloc_pattern_begin(ap, mps_alloc_pattern_ramp_collect_all());
do_lots_of_work();
mps_ap_alloc_pattern_end(ap, mps_alloc_pattern_ramp_collect_all());
wait_for_collection_statistics_while_doing_other_allocation();
}
Cannot fail.
mps_alloc_pattern_ramp,
mps_ap_alloc_pattern_begin
mps_amc_applymps_amc_apply is used to inspect objects in an AMC pool. You may only call it when the
arena is parked (for example, after mps_arena_collect).
Arena.
extern void mps_amc_apply(mps_pool_t, void(*f)(mps_addr_t, void *, size_t), void *, size_t);
mps_pool_t the pool whose objects you want to inpect
f a supplied function
mps_addr_t the address of the object you want to inspect
*
size_t
Not applicable.
Not applicable.
mps_amc_apply is used to inspect objects in an AMC pool. You may only call it when thearena is parked (for example, after mps_arena_collect). When called, mps_amc_apply calls thesupplied function "f" once for each object in the pool, with the address of the object as its firstargument. "f" is given as its second and third arguments whatever values were given as the third andfourth arguments to mps_amc_apply. (This is intended to make it easy to pass, for example, anarray and its size as parameters.)
"f" will be called on both data and pad objects, and it is "f"'s job to distinguish, ifrequired, between the two. Note (c.f. mps_arena_collect, above) that it may be called onunreachable objects that the collector has not recycled or has not been able to recycle.
The function "f" may not allocate memory or access any automatically-managed memory exceptthe object at which it is pointed and, in the case of objects in Dylan Container Format, thatobject's wrapper.
Functions that park the arena:
mps_arena_park,
mps_arena_collect.
A more general heap walker which inspects all formatted objects in
the arena:
mps_arena_formatted_objects_walk
There is no equivalent function for other pool classes, but there is a more general heapwalker: mps_arena_formatted_objects_walk.
Does "You must call it when the arena is parked" mean that (a) parking an arena requires that you call this function, or (b) you can only call this function when the arena is in the parked state? LMB
(b). Changed "must call" to "may only call" drj 1998-08-25
mps_ap_alloc_pattern_beginIndicates the start of allocation following a particular pattern.
AP, Allocation, Alloc-pattern-ramp.
mps_res_t mps_ap_alloc_pattern_begin(mps_ap_t ap, mps_alloc_pattern_t alloc_pattern)
ap The allocation point in which the patterned allocation will occur
alloc_pattern The pattern of the allocation
Result code indicating whether start of the allocation pattern was successfully registered.
mps.h
This function is used, together with mps_ap_alloc_pattern_end, to indicate periods ofallocation in an allocation point that follow some pattern of lifetime.
The nesting/overlapping restrictions on allocation patterns may vary depending on theparticular allocation pattern type, but in general, if mps_ap_alloc_pattern_begin is used multipletimes on the same allocation point without intervening calls to mps_ap_alloc_pattern_end, the callsmatch in a stack-like way, outermost and innermost; that is, allocation patterns may nest, but nototherwise overlap.
{
res = mps_ap_alloc_pattern_begin(ap, mps_alloc_pattern_ramp());
assert(res == mps_res_ok);
do_some_work(); /* Leaves stuff lying around */
res = mps_ap_alloc_pattern_begin(ap, mps_alloc_pattern_ramp());
assert(res == mps_res_ok);
do_some_more_work(); /* Tidies up after itself */
res = mps_ap_alloc_pattern_end(ap, mps_alloc_pattern_ramp());
assert(res == mps_res_ok);
tidy_up_first_work();
res = mps_ap_alloc_pattern_end(ap, mps_alloc_pattern_ramp());
assert(res == mps_res_ok);
}
Currently doesn't fail, but may in future if certain allocation patterns are inappropriatefor that allocation point at that point in time.
mps_alloc_pattern_ramp,
mps_alloc_pattern_ramp_collect_all,
mps_ap_alloc_pattern_end,
mps_ap_alloc_pattern_reset
mps_ap_alloc_pattern_endIndicates the end of allocation following a particular pattern.
AP, Allocation, Alloc-pattern-ramp.
mps_res_t mps_ap_alloc_pattern_end(mps_ap_t ap, mps_alloc_pattern_t alloc_pattern)
ap The allocation point in which the patterned allocation occurred
alloc_pattern The pattern of the allocation
Result code indicating whether end of the allocation pattern was successfully registered.
This function is used, together with mps_ap_alloc_pattern_begin, to indicate periods of allocation in an allocation point that follow some pattern of lifetime.
{
res = mps_ap_alloc_pattern_begin(ap, mps_alloc_pattern_ramp());
assert(res == mps_res_ok);
do_some_work(); /* Leaves stuff lying around */
res = mps_ap_alloc_pattern_begin(ap, mps_alloc_pattern_ramp());
assert(res == mps_res_ok);
do_some_more_work(); /* Tidies up after itself */
res = mps_ap_alloc_pattern_end(ap, mps_alloc_pattern_ramp());
assert(res == mps_res_ok);
tidy_up_first_work();
res = mps_ap_alloc_pattern_end(ap, mps_alloc_pattern_ramp());
assert(res == mps_res_ok);
}
Will fail if there is no extant allocation pattern of that type. May fail in future ifcertain allocation patterns are inappropriate for that allocation point at that point in time.
mps_alloc_pattern_ramp,
mps_alloc_pattern_ramp_collect_all,
mps_ap_alloc_pattern_begin,
mps_ap_alloc_pattern_reset
mps_ap_alloc_pattern_resetIndicates the end of allocation pattern on an allocation point.
AP, Alloc-pattern-ramp
mps_res_t mps_ap_alloc_pattern_reset(mps_ap_t ap);
ap The allocation point in which the patterned allocation occurred
Result code indicating whether end of the allocation patterns was successfully registered.
This function may be used in place of mps_ap_alloc_pattern_end to end all extant allocationpatterns on an allocation point. It is anticipated that this may be used to recover from errorconditions.
{
res = mps_ap_alloc_pattern_begin(ap, mps_alloc_pattern_ramp());
assert(res == mps_res_ok);
do_some_work(); /* Leaves stuff lying around */
res = mps_ap_alloc_pattern_begin(ap, mps_alloc_pattern_ramp());
assert(res == mps_res_ok);
res = do_some_more_work(); /* Tidies up after itself */
if(res != mps_res_ok) {
res = mps_ap_alloc_pattern_reset(ap);
assert(res == mps_res_ok);
return;
}
res = mps_ap_alloc_pattern_end(ap, mps_alloc_pattern_ramp());
assert(res == mps_res_ok);
tidy_up_first_work();
res = mps_ap_alloc_pattern_end(ap, mps_alloc_pattern_ramp());
assert(res == mps_res_ok);
}
Cannot fail at present. May fail in future if certain allocation patterns cannot be endedfor that allocation point at that point in time.
mps_alloc_pattern_ramp,
mps_alloc_pattern_ramp_collect_all,
mps_ap_alloc_pattern_begin,
mps_ap_alloc_pattern_end
mps_ap_frame_popDeclares that a set of objects in a particular frame are dead or likely to be dead.
AP Stack Protocol
mps_res_t (mps_ap_frame_pop)(mps_ap_t /* ap */, mps_frame_t /* frame */)
mps_ap_t ap
The allocation point in which the frame was pushed.
frame
The frame.
A result code in the usual way.
This function pops the specified frame making its parent the current frame (frames areimplicitly created using the push operation, see mps_ap_frame_push). Poppinginvalidates the specified frame and all frames pushed since the specified frame. Popping the framemakes a declaration about the set of objects which were allocated in the specified frame and alsoall frames which were pushed since the specified frame. It can be used to declare a set of objectsdead or likely to be mostly dead; the exact interpretation of the declaration depends on pool classthat the allocation point is in (the same pool class that that objects are in). Typically poolclasses which are mostly manually managed will use this declaration to mean that the objects aredead and their space can be reclaimed immediately, whereas pool classes which are mostlyautomatically managed will use this declaration to mean that the objects are likely to be mostlydead (the pool class may use this declaration to alter its collection decisions). Consult the poolclass documentation for details.
In general a frame other than the current frame can be popped (all frames pushed morerecently will be invalidated as well, as described above), but a particular pool class may imposethe restriction that only the current frame may be popped. This restriction means that every pushmust have a corresponding pop. Consult the pool class documentation for details.
It is illegal to pass invalid frames to any MPS function. In particular it is not possibleto pop frames out of order (so the sequence "A = push, B = push, pop A, pop B" is illegal) or to popto the same frame twice (so the sequence "A = push, pop A, pop A" is illegal).
More comprehensive documentation is available in the protocol document (AP Stack Protocol).
<example of how to use the symbol>
<how the client program should handle errors that the symbol returns, if applicable>
mps.protocol.alloc-point.stack,
mps_ap_frame_push
None.
mps_ap_frame_pushDeclares a new frame as part of the AP stack protocol.
AP Stack Protocol
mps_res_t (mps_ap_frame_push)(mps_frame_t * /* frameReturn */, mps_ap_t /* ap */);
mps_frame_t *frameReturn The frame return parameter. A new frame (declared by this function) is stored in thislocation if this function is successful.
mps_ap_t ap The allocation point in which the new frame is declared.
A result code in the usual way. The creation of new frame objects (which is implicit in theaction of this function) can consume resources, so this function can fail because there areinsufficient resources. This function may fail if the correct protocol is not followed by theclient.
This function declares a new frame in the specified allocation point, makes that new frame achild of the current frame, changes the current frame to be the newly created frame, and returns ahandle to the frame. Frames have two important features: A single frame identifies a set of objects(those objects that are "allocated in the frame") which can be destroyed (or declared dead) in a popoperation (see mps_ap_frame_pop); They are arranged in a partially ordered sequence (this isimportant when the pop operation is used). A fuller and more useful description is found in the APstack protocol document (protocol.mps.alloc-point.stack).
[missing]
Errors can either be because the client hasn't followed the correct protocol in which casethere isn't much that we can recommend or else because some needed resource isn't available. Theusual course of actions when short of resources is recommended.
mps_ap_frame_pop,
protocol.mps.alloc-point.stack
mps_arena_clampmps_arena_clamp puts the specified arena into the clamped state.
Arena.
extern void mps_arena_clamp(mps_arena_t);
arena -- the arena to be put into the clamped state
None.
mps.h
mps_arena_clamp puts the specified arena into the clamped state. In the clamped state, no
object motion will occur and the staleness of location dependencies will not change. All references
to objects loaded while the arena is clamped will keep the same binary representation until after itis released.
In a clamped arena, incremental collection may still occur, but it will not be visible to the mutator and no new collections will begin. Space used by unreachable objects will not be recycled until the arena becomes unclamped.
mps_arena_park,
mps_arena_release
mps_arena_class_clmps_arena_class_cl returns the client arena class.
Arena.
mps_arena_class_t mps_arena_class_cl(void)
None.
Returns the client arena class.
mpsacl.h
This function is used to get hold of the client arena class, for the purpose of passing itto mps_arena_create.
mps_arena_t arena;
int main(void)
{
void *block;
mps_res_t res;
block = malloc(ARENA_SIZE);
if(block == NULL) {
printf("Not enough memory!");
exit(1);
}
res = mps_arena_create(&arena, mps_arena_class_cl(), ARENA_SIZE, block);
if(res != MPS_RES_OK) {
printf("ARENA_SIZE too small");
exit(2);
}
/* rest of program */
}
None.
A client arena gets its managed memory from the client. This memory block is passed when thearena is created. When creating a client arena, mps_arena_create takes two extraarguments:
mps_res_t mps_arena_create(mps_arena_t *mps_arena_o, mps_arena_class_t mps_arena_class_cl,size_t size, void *block)
block is the address of the memory block managed by the arena, andsize is its size in bytes. If mps_arena_create returnsMPS_RES_MEMORY, then the block was too small to hold the internal arena structures.Allocate a (much) larger one, and try again. mps_arena_create returnsMPS_RES_FAIL, if the MPS library is copy-protected by a security device, such as adongle, and a valid security device cannot be found.
mps_arena_class_t"m ps_arena_class_t " is the type of arena classes.
Arena.
typedef struct mps_arena_s *mps_arena_t;
mps_arena_class_s is an incomplete structure type used only to declare the opaque type mps_arena_class_t.
mps.h
mps_arena_class_t is the type of arena classes. It is opaque.
The definition of the client arena class in the "mpsacl.h" header:
extern mps_arena_class_t mps_arena_class_cl(void);
None.
mps_arena_class_vmmps_arena_class_vm returns the virtual memory arena class.
Arena.
mps_arena_class_t mps_arena_class_vm(void)
None.
Returns the virtual memory arena class.
mpsavm.h
This function is used to get hold of the virtual memory arena class, for the purpose of passing it to mps_arena_create. The VM arenas use the OS virtual memory interfaces toallocate memory. The chief consequence of this is that the arena can manage many more virtual addresses than it needs to commit memory to. This gives it flexibility as to where to place objects, which reduces fragmentation and helps make garbage collection more efficient.
This class is similar to mps_arena_class_vmnz but uses a more complex placement policy, which is more suited to copying garbage collection.
mps_arena_t arena;
int main(void)
{
mps_res_t res;
res = mps_arena_create(&arena, mps_arena_class_vm(), ARENA_SIZE);
if(res != MPS_RES_OK) {
printf("Not enough memory!");
exit(1);
}
/* rest of program */
}
None.
mps_arena_create,
mps_arena_class_vmnz
A virtual memory arena gets its managed memory from the operating system's virtual memoryservices. An initial address space size is passed when the arena is created. When creating a virtualmemory arena, mps_arena_create takes one extra argument:
mps_res_t mps_arena_create(mps_arena_t *arena_o,
mps_arena_class_t arena_class_vm,
size_t size)
size is the initial amount of virtual address space, in bytes, that the arenawill reserve (this space is initially reserved so that the arena can subsequently use it withoutinterference from other parts of the program, but most of it is not committed, so it don't requireany RAM or backing store). The arena may allocate more virtual address space beyond this initialreservation as and when it deems it necessary. The MPS is most efficient if you reserve an addressspace that is several times larger than your peak memory usage.
mps_arena_create returns MPS_RES_RESOURCE if it fails to reserveadequate address space to place the arena in; possibly other parts of the program are reserving toomuch virtual memory. It returns MPS_RES_MEMORY when it fails to allocate memory for theinternal arena structures; either size was far too small or you ran out of swap space.It returns MPS_RES_FAIL, if the library is copy-protected by a security device, suchas a dongle, and a valid security device cannot be found.
Virtual memory arenas are not available on the Mac platforms, other than MacOS X. You willget a linking error, if you attempt to use this function.
mps_arena_class_vmnzAn arena class like mps_arena_class_vm but with a different placement policy.
Arena.
mps_arena_class_t mps_arena_class_vmnz(void);
None.
Returns the VMNZ arena class.
mpsavm.h
Returns the VMNZ arena class (stands for Virtual Memory No Zones, if you really care.) Thisclass can be passed to mps_arena_create in order to create a VMNZ arena. The VMNZarenas use the OS virtual memory interfaces to allocate memory. The chief consequence of this isthat the arena can manage many more virtual addresses than it needs to commit memory to. This givesit flexibility as to where to place objects.
This class is similar to mps_arena_class_vm but uses a simpler placementpolicy, that makes it slightly faster.
mps_arena_t arena;
int main(void)
{
mps_res_t res;
res = mps_arena_create(&arena, mps_arena_class_vmnz(), ARENA_SIZE);
if(res != MPS_RES_OK) {
printf("Not enough memory!");
exit(1);
}
/* rest of program */
}
No errors.
mps_arena_create,
mps_arena_class_vm
This class takes an extra argument when used in mps_arena_create (see example).The extra parameter should be of type size_t. It specifies the amount of virtualaddress space, in bytes, that this arena should use. The arena will reserve this amount of virtualaddress space from the OS during initialization. It will not subsequently use any more address space(compare with mps_arena_class_vm which can grow).
mps_arena_create returns MPS_RES_RESOURCE if it fails to reserveadequate address space to place the arena in; possibly other parts of the program are reserving toomuch virtual memory. It returns MPS_RES_MEMORY when it fails to allocate memory for theinternal arena structures; either size was far too small or you ran out of swap space.It returns MPS_RES_FAIL, if the library is copy-protected by a security device, suchas a dongle, and a valid security device cannot be found.
Virtual memory arenas are not available on the Mac platforms, other than MacOS X. You willget a linking error, if you attempt to use this function.
mps_arena_collectmps_arena_collect collects the arena and puts it in the parked state.
Arena.
void mps_arena_collect(mps_arena_t arena);
arena the arena to collect
mps.h
mps_arena_collect collects the arena and puts it in the parked state. Collecting the arenaattempts to recycle as many unreachable objects as possible and reduce the size of the arena as muchas possible (though in some cases it may increase because it becomes more fragmented). If you do notwant the arena to be in the parked state, you must explicitly call mps_arena_release aftermps_arena_collect.
Note that the collector may not be able to recycle some objects (such as those near thedestination of ambiguous references) even though they are not reachable.
[missing]
No errors.
mps_arena_park,
mps_arena_release
None.
mps_arena_commit_limitReturns the current commit limit associated with the arena in bytes.
Arena
size_t mps_arena_commit_limit(mps_arena_t arena)
arena -- the arena
Returns the current commit limit as a number of bytes in a size_t
mps.h
Returns the current commit limit associated with the arena in bytes. The commit limit can bechanged using the function mps_commit_limit_set. The commit limit is used to control how much memorythe MPS can obtain from the OS. See Arena Protocol for details.
limit = mps_arena_commit_limit(arena);
No errors.
mps_arena_committed,
mps_arena_commit_limit_set
None.
mps_arena_commit_limit_setChanges the current commit limit associated with the arena.
Arena
mps_res_t mps_arena_commit_limit_set(mps_arena_t arena, size_t limit)
arena -- the arena
limit -- the new commit limit in bytes
Returns a result code.
mps.h
The commit limit of the arena is set to the limit given. The commit limit controls how muchmemory the MPS will obtain from the OS. See Arena Protocol for details. The commit limit cannot beset to a value that is lower than the number of bytes that the MPS is using. If an attempt is madeto set the commit limit to a value greater than or equal to that returned bymps_arena_committed then it will succeed. If an attempt is made to set the commit limitto a value less than that returned by mps_arena_committed then it will succeed only ifthe amount committed by the MPS can be reduced by reducing the amount of spare committed memory; insuch a case the spare committed memory will be reduced appropriately and the attempt will succeed.
do {
res = mps_arena_commit_limit_set(arena, limit - 100 * 1024);
if(res != MPS_RES_OK)
flush_caches();
} while(res != MPS_RES_OK);
Returns MPS_RES_OK when successful, and some other result code when not.
mps_arena_committed,
mps_arena_commit_limit,
mps_arena_spare_commit_limit_set
mps_arena_commit_limit_set puts a limit on all memory committed by the MPS. The"spare committed" memory can be limited separately with mps_arena_spare_commit_limit_set. Note that "spare committed" memory is subject toboth limits; there cannot be more spare committed memory than the spare commit limit, and therecan't be so much spare committed memory that there is more committed memory than the commit limit.
mps_arena_committedmps_arena_committed returns the amount of memory (backing store) in use by the arena, bothfor storing client objects and for its own data structures.
Arena.
extern size_t mps_arena_committed(mps_arena_t arena)
arena -- the arena
Returns a number of bytes (the amount of committed memory) as a size_t.
mps.h
mps_arena_committed returns the amount of memory (backing store) in use by the arena (alsoknown as "committed memory"). The value returned is a number of bytes.
Committed memory may be used both for storing client objects and for storing MPS datastructures. In addition the MPS maintains committed memory which is not being used (for either ofthe above purposes). This memory is known as "spare committed" memory (see mps_arena_spare_committed). The amount of "spare committed" memory can change atany time, in particular in will be reduced as appropriate in order meet client requests.
The reasons that the committed memory (as return by this function) might be large than thesum of the sizes of client allocated objects are:
some memory is used internally by the MPS to manage its own data structures and to recordinformation about client objects (such as free lists, page tables, colour tables, statistics, etc).
operating systems (and hardware) typically restrict programs to requesting and releasingmemory with a certain granularity (for example, pages), so extra memory is committed when thisrounding is necessary.
there might be "spare committed" memory.
The amount of committed memory is a good measure of how much virtual memory resource ("swapspace") the MPS is using from the OS.
This function may be called whether the arena is unclamped, clamped or parked, if calledwhen the arena in unclamped then the value may change after this function returns. A possible usemight be to call it just after mps_arena_collect to (over-)estimate the size of the heap.
If you want to know how much memory the MPS is using then you're probably interested in the value mps_arena_committed() - mps_arena_spare_committed().
The amount of committed memory can be limited with the function mps_arena_commit_limit.
mps_arena_collect,
mps_arena_clamp,
mps_arena_park,
mps_arena_release
-
mps_arena_createmps_arena_create is used to create an arena.
Arena.
mps_res_t mps_arena_create(mps_arena_t *mps_arena_o, mps_arena_class_t mps_arena_class, ...)
mps_arena_o pointer to a variable to store the new arena in
mps_arena_class the arena class
... initialization arguments for the arena class
Different for each arena class. See mps_arena_class_*.
If the return value is MPS_RES_OK, the new arena is in *mps_arena_o.
mps.h
mps_arena_create is used to create an arena.
mps_arena_t arena;
int main(void)
{
mps_res_t res;
res = mps_arena_create(&arena, mps_arena_class_vm(), ARENA_SIZE);
if(res != MPS_ RES_OK) {
printf("Not enough memory!");
exit(1);
}
/* rest of program */
}
mps_arena_create returns MPS_RES_FAIL, if the MPS library iscopy-protected by a security device, such as a dongle, and a valid security device cannot be found.Other error codes are specific to each arena class. See mps_arena_class_*.
mps_arena_create_v,
mps_arena_class_*,
mps_arena_destroy
mps_arena_create_vmps_arena_create_v is used to create an arena.
Arena.
mps_res_t mps_arena_create_v(mps_arena_t *mps_arena_o, mps_arena_class_t mps_arena_class, va_list args)
mps_arena_o pointer to a variable to store the new arena in
mps_arena_class the arena class
args initialization arguments for the arena class
Different for each arena class. See mps_arena_class_*.
If the return value is MPS_RES_OK, the new arena is in *mps_arena_o.
mps.h
mps_arena_create_v is used to create an arena. It is exactly the same as mps_arena_create, except that it takes the arena class initialization arguments in a va_list .
mps_arena_create_v returns MPS_RES_FAIL, if the MPS library is copy-protected by a security device, such as a dongle, and a valid security device cannot be found. Other error codes are specific to each arena class. See mps_arena_class_*.
mps_arena_create,
mps_arena_class_*,
mps_arena_destroy
mps_arena_exposemps_arena_expose ensures
that the MPS is not protecting any pages in the arena with read- or
write-memory protection barriers.
Arena, clamp, park, protection
mps_arena_expose(mps_arena);
extern void mps_arena_expose(mps_arena_t);
(mps_arena_t mps_arena)
mps_arena is an MPS arena object.
None.
mps.h
This function will ensure that the MPS is not protecting (with memory
read/write barriers) any page in the arena.
This is expected to only be useful for debugging.
The arena is left in the clamped state (see mps_arena_clamp).
Since barriers are used during a collection, calling this function has
the same effect as calling mps_arena_park; all collections are
run to completion and the arena is clamped so that no new collections
begin. The MPS also uses barriers to maintain remembered sets (an
optimisation to help avoid scanning work); calling
this function will effectively destroy the remembered sets and any
optimisation gains.
Calling this function will introduce a slow down, primarily for two reasons: any active collections will be run to completion before this function returns; the next collection will have to recompute all the remembered sets by scanning the entire heap.
The second aspect of the slow down, having the next collection recompute
the remembered sets, can be avoided by using mps_arena_unsafe_expose_remember_protection
instead of mps_arena_expose, and calling
mps_arena_unsafe_restore_protection
before calling mps_arena_release.
Those functions have unsafe aspects and place restrictions on what the
client can do (basically no exposed data can be changed).
None.
There can be no errors.
mps_arena_clamp,
mps_arena_park,
mps_arena_release,
mps_arena_unsafe_expose_remember_protection,
mps_arena_unsafe_restore_protection
mps_arena_formatted_objects_walkmps_arena_formatted_objects_walk
mps_arena_formatted_objects_walk is used to iterate over all formatted objects in the MPS heap.
None.
mps_arena_formatted_objects_walk(mps_arena, client_step_function, client_step_closure_p,client_step_closure_s);
extern void mps_arena_formatted_objects_walk(mps_arena_t, mps_formatted_objects_stepper_t, void *, size_t);
(mps_arena_t mps_arena, mps_formatted_objects_stepper_t stepper, void *p, size_t s)
mps_arena is an MPS arena object.
stepper is a client-supplied function (pointer) of
the right type (see mps_formatted_objects_stepper_t).
This function is applied to every object in all formatted pools.
This function should take the argument list (mps_addr_t object,
mps_fmt_t format,mps_pool_t pool, void *p, size_t s) and return
void.
object is the object to which the function is being
applied.
format is the format (an MPS format object)
of the object. pool is the pool in which the object
resides. p and s are copies of the
corresponding values that the client passed into mps_arena_formatted_objects_walk
originally.
p and s are passed into the function specified by the stepper argument whenever the MPS calls that function. See mps_formatted_objects_stepper_t.
None.
mps.h
mps_arena_formatted_objects_walk
is used to iterate over all formatted objects in the MPS heap. A
client-supplied function is called for every object in all formatted
pools; the object, the format, and the pool are passed to the user
supplied function, as well as user supplied closure variables.
Applies stepper function to a pool-class-specific collection of objects (that is, the pool class determines which objects in its instances get walked). Typically pool classes will arrange that all validly formatted objects are walked. During a trace this will in general be only the blackobjects, though the leaf pool class (LO), for example, will walk all objects since they are validly formatted whether they are black or white. Padding objects may be walked at the pool classes discretion, the client should handle this case.
The user supplied stepper function is called in a restricted context. It may not in general call any MPS function.
[not yet]
There are none.
mps_amc_apply (the
historical walker),
mps_formatted_objects_stepper_t
mps_arena_parkmps_arena_has_addr tests
whether an address is managed by a particular arena.
Arena.
extern mps_bool_t mps_arena_has_addr(mps_arena_t arena,
mps_addr_t addr);
arena an arena
addr an address
A boolean. Returns true if the address is managed by the arena, false otherwise.
mps.h
mps_arena_has_addr determines
whether a particular address is managed by a particular arena. An arena
manages a portion of total address space available on the hardware
architecture. No two arenas overlap so for any particular address this
function will return true for at most one arena. In general not all the
architecture addresses are managed by some arena; some addreses will not
be managed by any arena. This is what allows the MPS to cooperate with
other memory managers, shared object loaders, memory mapped file I/O,
and such like - it does not steal the whole address space.
The results from this function are true only for the instant at which the function returned. In some circumstances the results may immediately become invalidated (for example, a garbage collection may occur, the address in question may become free, the arena may choose to unmap the address and return storage to the operating system); for reliable results call this function whilst the arena is parked.
Can't fail.
mps_arena_park used to park an
arena
None.
mps_arena_parkmps_arena_park puts the specified arena into the parked state.
Arena.
extern void mps_arena_park(mps_arena_t arena);
arena the arena to park
None.
mps.h
mps_arena_park puts the specified arena into the parked state. While an arena is parked,no object motion will occur and the staleness of location dependencies will not change. Allreferences to objects loaded while the arena is parked will keep the same binary representationuntil after it is released.
Any current collection is run to completion before the arena is parked, and no newcollections will start. When an arena is in the parked state, it is necessarily not in the middle ofa collection.
Can't fail.
mps_arena_clamp,
mps_arena_release
None.
mps_arena_releasemps_arena_release puts the specified arena into the unclamped state.
Arena.
extern void mps_arena_release(mps_arena_t);
None.
mps.h
mps_arena_release puts the specified arena into the unclamped state. While an arena isunclamped, garbage collection, object motion, and other background activity can take place.
Can't fail.
mps_arena_clamp,
mps_arena_park
None.
mps_arena_roots_walkmps_arena_roots_walk is used to iterate over all roots of the MPS heap.
None.
mps_arena_roots_walk(mps_arena, client_step_function, client_step_closure_p,client_step_closure_s);
extern void mps_arena_roots_walk(mps_arena_t, mps_roots_stepper_t, void *, size_t);
(mps_arena_t mps_arena, mps_roots_stepper_t stepper, void *p, size_t s)
mps_arena in an MPS arena object.
stepper is a client-supplied function (pointer) of the right type (see mps_roots_stepper_t). This function is applied to every reference to the heap fromevery root object registered with the arena. This function should take the argument list (mps_addr_t *ref, mps_root_t root, void *p, size_t s). ref is the address of a root which references an object in the arena. root is the registered root (an MPS root object) of which ref is a single reference, p and s are copies of the corresponding values that the client passed into mps_arena_roots_walk originally.
p and s are passed into the function specified by the stepper argument whenever the MPS calls that function. See mps_roots_stepper_t
None.
mps.h
mps_arena_roots_walk is used to iterate over all roots of the MPS heap. A client-suppliedfunction is called for every root reference which points to an object in any automatically managedpools; the address of the root reference and the MPS root object are passed to the user suppliedfunction, as well as some closure variables.
May only be called when the arena is in the parked state.
Applies stepper to each reference in any roots registered with the arena and which point toobjects in automatically managed pools. If the root has rank MPS_RANK_AMBIG then the reference mightnot be to the start of an object; the client should handle this case. There is no guarantee that thereference corresponds to the actual location that holds the pointer to the object (since this mightbe a register, for example) - but the actual location will be passed if possible. This may aidanalysis of roots via a debugger.
[not yet]
There are none.
mps_arena_formatted_objects_walk
mps_arena_spare_commit_limitRetrieves the value of the spare commit limit (previously set with mps_arena_spare_commit_limit_set).
Arena.
extern size_t mps_arena_spare_commit_limit(mps_arena_t arena)
mps_arena_t arena
Specifies the arena to retrieve the spare commit limit of.
Returns, as a size_t, the value of the spare commit limit.
mps.h
Returns the current value of the spare commit limit which is the value most recently setwith mps_arena_spare_commit_limit_set. (See mps_arena_spare_commit_limit_set fordetails).
[missing]
There are no errors.
mps_arena_spare_commit_limit_set
None.
mps_arena_spare_commit_limit_setmps_arena_spare_commit_limit_set
Sets the limit of the amount of spare committed memory.
Arena.
extern void mps_arena_spare_commit_limit_set(mps_arena_t arena, size_t limit)
mps_arena_t arena
The arena to which the new limit should apply.
size_t limit
The value of the new limit (specified in bytes).
mps.h
The limit argument specifies a new "spare commit limit". The spare commit limit specifiesthe maximum amount of bytes of "spare committed" memory the MPS is allowed to have. Setting it to avalue lower than the current amount of spare committed memory would immediately cause sufficientspare committed memory to be uncommitted so as to bring the value under the limit. In particularsetting to 0 will mean that the MPS will have no "spare committed" memory.
"spare committed" memory is the term for describing memory which the arena is managing asfree memory (so not in use by any pool and not otherwise in use for obscure internal reasons) butwhich remains committed (mapped from the OS). It is used by the arena to (attempt to) avoid callingthe OS to repeatedly unmap and map areas of VM. "spare committed" memory is counted as committedmemory as counted by mps_arena_committed and restricted by mps_arena_commit_limit.
Non-VM arenas do not have this concept, but they support the two functions mps_arena_spare_commit_limit and mps_arena_spare_commit_limit_set. The functions simply get andretrieve a value but do nothing else in that case.
Initially the value is some configuration-dependent value.
The value of the limit can be retrieved with mps_arena_spare_commit_limit.
[missing]
There are no errors.
None.
mps_arena_spare_committedReturns the number of bytes of spare committed memory.
Memory
size_t mps_arena_spare_committed(mps_arena_t);
The arena to which the query applies.
Returns the number of bytes of spare committed memory.
mps.h
"Spare committed" memory is the term for describing memory which the arena is committed fromthe OS but which is free (so not in use by any pool and not otherwise in use for obscure internalreasons). It is used by the arena to (attempt to) avoid calling the OS to repeatedly uncommit andcommit areas of VM (because calling the OS to commit and uncommit memory is typically expensive)."Spare committed" memory can be used for grant client requests; if this is done when the MPS wouldotherwise have had to call the OS to commit more memory then the MPS has avoid some OS calls.
"spare committed" memory is counted as part of committed memory. The amount of committedmemory can be retrieved with mps_arena_committed (see mps_arena_committed).
The amount of "spare committed" memory can be limited by using mps_arena_spare_commit_limit_set (see mps_arena_spare_commit_limit_set ), and the valueof that limit ca