mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-03-27 01:01:52 -07:00
Merged branch/2014-05-15/size into the master sources.
Copied from Perforce Change: 186540 ServerID: perforce.ravenbrook.com
This commit is contained in:
commit
49e1793f59
26 changed files with 510 additions and 211 deletions
|
|
@ -41,9 +41,21 @@ static mps_res_t make(mps_addr_t *p, mps_ap_t ap, size_t size)
|
|||
}
|
||||
|
||||
|
||||
/* check_allocated_size -- check the allocated size of the pool */
|
||||
|
||||
static void check_allocated_size(mps_pool_t pool, mps_ap_t ap, size_t allocated)
|
||||
{
|
||||
size_t total = mps_pool_total_size(pool);
|
||||
size_t free = mps_pool_free_size(pool);
|
||||
size_t ap_free = (size_t)((char *)ap->limit - (char *)ap->init);
|
||||
Insist(total - free == allocated + ap_free);
|
||||
}
|
||||
|
||||
|
||||
/* stress -- create a pool of the requested type and allocate in it */
|
||||
|
||||
static mps_res_t stress(mps_arena_t arena, mps_align_t align,
|
||||
static mps_res_t stress(mps_arena_t arena, mps_pool_debug_option_s *options,
|
||||
mps_align_t align,
|
||||
size_t (*size)(size_t i, mps_align_t align),
|
||||
const char *name, mps_class_t class, mps_arg_s args[])
|
||||
{
|
||||
|
|
@ -53,6 +65,8 @@ static mps_res_t stress(mps_arena_t arena, mps_align_t align,
|
|||
size_t i, k;
|
||||
int *ps[testSetSIZE];
|
||||
size_t ss[testSetSIZE];
|
||||
size_t allocated = 0; /* Total allocated memory */
|
||||
size_t debugOverhead = options ? 2 * alignUp(options->fence_size, align) : 0;
|
||||
|
||||
printf("stress %s\n", name);
|
||||
|
||||
|
|
@ -66,8 +80,10 @@ static mps_res_t stress(mps_arena_t arena, mps_align_t align,
|
|||
res = make((mps_addr_t *)&ps[i], ap, ss[i]);
|
||||
if (res != MPS_RES_OK)
|
||||
goto allocFail;
|
||||
allocated += ss[i] + debugOverhead;
|
||||
if (ss[i] >= sizeof(ps[i]))
|
||||
*ps[i] = 1; /* Write something, so it gets swap. */
|
||||
check_allocated_size(pool, ap, allocated);
|
||||
}
|
||||
|
||||
mps_pool_check_fenceposts(pool);
|
||||
|
|
@ -90,6 +106,8 @@ static mps_res_t stress(mps_arena_t arena, mps_align_t align,
|
|||
mps_free(pool, (mps_addr_t)ps[i], ss[i]);
|
||||
/* if (i == testSetSIZE/2) */
|
||||
/* PoolDescribe((Pool)pool, mps_lib_stdout); */
|
||||
Insist(ss[i] + debugOverhead <= allocated);
|
||||
allocated -= ss[i] + debugOverhead;
|
||||
}
|
||||
/* allocate some new objects */
|
||||
for (i=testSetSIZE/2; i<testSetSIZE; ++i) {
|
||||
|
|
@ -97,7 +115,9 @@ static mps_res_t stress(mps_arena_t arena, mps_align_t align,
|
|||
res = make((mps_addr_t *)&ps[i], ap, ss[i]);
|
||||
if (res != MPS_RES_OK)
|
||||
goto allocFail;
|
||||
allocated += ss[i] + debugOverhead;
|
||||
}
|
||||
check_allocated_size(pool, ap, allocated);
|
||||
}
|
||||
|
||||
allocFail:
|
||||
|
|
@ -145,8 +165,8 @@ static void testInArena(mps_arena_t arena, mps_pool_debug_option_s *options)
|
|||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_ARENA_HIGH, TRUE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_SLOT_HIGH, TRUE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_FIRST_FIT, TRUE);
|
||||
die(stress(arena, align, randomSizeAligned, "MVFF", mps_class_mvff(), args),
|
||||
"stress MVFF");
|
||||
die(stress(arena, NULL, align, randomSizeAligned, "MVFF",
|
||||
mps_class_mvff(), args), "stress MVFF");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
/* IWBN to test MVFFDebug, but the MPS doesn't support debugging APs, */
|
||||
|
|
@ -155,24 +175,23 @@ static void testInArena(mps_arena_t arena, mps_pool_debug_option_s *options)
|
|||
MPS_ARGS_BEGIN(args) {
|
||||
mps_align_t align = (mps_align_t)1 << (rnd() % 6);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ALIGN, align);
|
||||
die(stress(arena, align, randomSizeAligned, "MV", mps_class_mv(), args),
|
||||
"stress MV");
|
||||
die(stress(arena, NULL, align, randomSizeAligned, "MV",
|
||||
mps_class_mv(), args), "stress MV");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
mps_align_t align = (mps_align_t)1 << (rnd() % 6);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ALIGN, align);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_POOL_DEBUG_OPTIONS, options);
|
||||
die(stress(arena, align, randomSizeAligned, "MV debug",
|
||||
mps_class_mv_debug(), args),
|
||||
"stress MV debug");
|
||||
die(stress(arena, options, align, randomSizeAligned, "MV debug",
|
||||
mps_class_mv_debug(), args), "stress MV debug");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
mps_align_t align = sizeof(void *) << (rnd() % 4);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ALIGN, align);
|
||||
die(stress(arena, align, randomSizeAligned, "MVT", mps_class_mvt(), args),
|
||||
"stress MVT");
|
||||
die(stress(arena, NULL, align, randomSizeAligned, "MVT",
|
||||
mps_class_mvt(), args), "stress MVT");
|
||||
} MPS_ARGS_END(args);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ static mps_addr_t test_awl_find_dependent(mps_addr_t addr)
|
|||
static void *root[rootCOUNT];
|
||||
|
||||
static void test_trees(int mode, const char *name, mps_arena_t arena,
|
||||
mps_ap_t ap,
|
||||
mps_pool_t pool, mps_ap_t ap,
|
||||
mps_word_t (*make)(mps_word_t, mps_ap_t),
|
||||
void (*reg)(mps_word_t, mps_arena_t))
|
||||
{
|
||||
|
|
@ -158,7 +158,9 @@ static void test_trees(int mode, const char *name, mps_arena_t arena,
|
|||
|
||||
object_count = 0;
|
||||
|
||||
printf("Making some %s finalized trees of objects.\n", name);
|
||||
printf("---- Mode %s, pool class %s, %s trees ----\n",
|
||||
mode == ModePARK ? "PARK" : "POLL",
|
||||
pool->class->name, name);
|
||||
mps_arena_park(arena);
|
||||
|
||||
/* make some trees */
|
||||
|
|
@ -167,7 +169,6 @@ static void test_trees(int mode, const char *name, mps_arena_t arena,
|
|||
(*reg)((mps_word_t)root[i], arena);
|
||||
}
|
||||
|
||||
printf("Losing all pointers to the trees.\n");
|
||||
/* clean out the roots */
|
||||
for(i = 0; i < rootCOUNT; ++i) {
|
||||
root[i] = 0;
|
||||
|
|
@ -190,9 +191,15 @@ static void test_trees(int mode, const char *name, mps_arena_t arena,
|
|||
object_alloc = 0;
|
||||
while (object_alloc < 1000 && !mps_message_poll(arena))
|
||||
(void)DYLAN_INT(object_alloc++);
|
||||
printf(" Done.\n");
|
||||
break;
|
||||
}
|
||||
++ collections;
|
||||
{
|
||||
size_t live_size = (object_count - finals) * sizeof(void *) * 3;
|
||||
size_t alloc_size = mps_pool_total_size(pool) - mps_pool_free_size(pool);
|
||||
Insist(live_size <= alloc_size);
|
||||
}
|
||||
while (mps_message_poll(arena)) {
|
||||
mps_message_t message;
|
||||
mps_addr_t objaddr;
|
||||
|
|
@ -238,9 +245,9 @@ static void test_pool(int mode, mps_arena_t arena, mps_chain_t chain,
|
|||
"root_create\n");
|
||||
die(mps_ap_create(&ap, pool, mps_rank_exact()), "ap_create\n");
|
||||
|
||||
test_trees(mode, "numbered", arena, ap, make_numbered_tree,
|
||||
test_trees(mode, "numbered", arena, pool, ap, make_numbered_tree,
|
||||
register_numbered_tree);
|
||||
test_trees(mode, "indirect", arena, ap, make_indirect_tree,
|
||||
test_trees(mode, "indirect", arena, pool, ap, make_indirect_tree,
|
||||
register_indirect_tree);
|
||||
|
||||
mps_ap_destroy(ap);
|
||||
|
|
|
|||
|
|
@ -156,13 +156,12 @@ typedef const struct SrcIdStruct {
|
|||
*
|
||||
* Use these values for unused pointer, size closure arguments and
|
||||
* check them in the callback or visitor.
|
||||
*
|
||||
* We use PointerAdd rather than a cast to avoid "warning C4306: 'type
|
||||
* cast' : conversion from 'unsigned int' to 'Pointer' of greater
|
||||
* size" on platform w3i6mv.
|
||||
*
|
||||
* Ensure that they have high bits set on 64-bit platforms for maximum
|
||||
* unusability.
|
||||
*/
|
||||
#define UNUSED_POINTER PointerAdd(0, 0xB60405ED) /* PointeR UNUSED */
|
||||
#define UNUSED_SIZE ((Size)0x520405ED) /* SiZe UNUSED */
|
||||
#define UNUSED_POINTER (Pointer)((Word)~0xFFFFFFFF | (Word)0xB60405ED) /* PointeR UNUSED */
|
||||
#define UNUSED_SIZE ((Size)~0xFFFFFFFF | (Size)0x520405ED) /* SiZe UNUSED */
|
||||
|
||||
|
||||
/* PARENT -- parent structure
|
||||
|
|
|
|||
|
|
@ -224,6 +224,9 @@ extern Res PoolAddrObject(Addr *pReturn, Pool pool, Seg seg, Addr addr);
|
|||
extern void PoolWalk(Pool pool, Seg seg, FormattedObjectsStepMethod f,
|
||||
void *v, size_t s);
|
||||
extern void PoolFreeWalk(Pool pool, FreeBlockStepMethod f, void *p);
|
||||
extern Size PoolTotalSize(Pool pool);
|
||||
extern Size PoolFreeSize(Pool pool);
|
||||
|
||||
extern Res PoolTrivInit(Pool pool, ArgList arg);
|
||||
extern void PoolTrivFinish(Pool pool);
|
||||
extern Res PoolNoAlloc(Addr *pReturn, Pool pool, Size size,
|
||||
|
|
@ -277,6 +280,7 @@ extern void PoolNoWalk(Pool pool, Seg seg, FormattedObjectsStepMethod step,
|
|||
extern void PoolTrivFreeWalk(Pool pool, FreeBlockStepMethod f, void *p);
|
||||
extern PoolDebugMixin PoolNoDebugMixin(Pool pool);
|
||||
extern BufferClass PoolNoBufferClass(void);
|
||||
extern Size PoolNoSize(Pool pool);
|
||||
|
||||
#define ClassOfPool(pool) ((pool)->class)
|
||||
#define SuperclassOfPool(pool) \
|
||||
|
|
|
|||
|
|
@ -24,9 +24,20 @@
|
|||
#define testLOOPS 10
|
||||
|
||||
|
||||
/* check_allocated_size -- check the allocated size of the pool */
|
||||
|
||||
static void check_allocated_size(mps_pool_t pool, size_t allocated)
|
||||
{
|
||||
size_t total = mps_pool_total_size(pool);
|
||||
size_t free = mps_pool_free_size(pool);
|
||||
Insist(total - free == allocated);
|
||||
}
|
||||
|
||||
|
||||
/* stress -- create a pool of the requested type and allocate in it */
|
||||
|
||||
static mps_res_t stress(mps_arena_t arena, size_t (*size)(size_t i),
|
||||
static mps_res_t stress(mps_arena_t arena, mps_pool_debug_option_s *options,
|
||||
size_t (*size)(size_t i), mps_align_t align,
|
||||
const char *name, mps_class_t pool_class,
|
||||
mps_arg_s *args)
|
||||
{
|
||||
|
|
@ -35,8 +46,10 @@ static mps_res_t stress(mps_arena_t arena, size_t (*size)(size_t i),
|
|||
size_t i, k;
|
||||
int *ps[testSetSIZE];
|
||||
size_t ss[testSetSIZE];
|
||||
size_t allocated = 0; /* Total allocated memory */
|
||||
size_t debugOverhead = options ? 2 * alignUp(options->fence_size, align) : 0;
|
||||
|
||||
printf("%s\n", name);
|
||||
printf("Pool class %s, alignment %u\n", name, (unsigned)align);
|
||||
|
||||
res = mps_pool_create_k(&pool, arena, pool_class, args);
|
||||
if (res != MPS_RES_OK)
|
||||
|
|
@ -49,8 +62,10 @@ static mps_res_t stress(mps_arena_t arena, size_t (*size)(size_t i),
|
|||
res = mps_alloc((mps_addr_t *)&ps[i], pool, ss[i]);
|
||||
if (res != MPS_RES_OK)
|
||||
return res;
|
||||
allocated += alignUp(ss[i], align) + debugOverhead;
|
||||
if (ss[i] >= sizeof(ps[i]))
|
||||
*ps[i] = 1; /* Write something, so it gets swap. */
|
||||
check_allocated_size(pool, allocated);
|
||||
}
|
||||
|
||||
mps_pool_check_fenceposts(pool);
|
||||
|
|
@ -73,13 +88,17 @@ static mps_res_t stress(mps_arena_t arena, size_t (*size)(size_t i),
|
|||
mps_free(pool, (mps_addr_t)ps[i], ss[i]);
|
||||
/* if (i == testSetSIZE/2) */
|
||||
/* PoolDescribe((Pool)pool, mps_lib_stdout); */
|
||||
Insist(alignUp(ss[i], align) + debugOverhead <= allocated);
|
||||
allocated -= alignUp(ss[i], align) + debugOverhead;
|
||||
}
|
||||
/* allocate some new objects */
|
||||
for (i=testSetSIZE/2; i<testSetSIZE; ++i) {
|
||||
ss[i] = (*size)(i);
|
||||
res = mps_alloc((mps_addr_t *)&ps[i], pool, ss[i]);
|
||||
if (res != MPS_RES_OK) return res;
|
||||
allocated += alignUp(ss[i], align) + debugOverhead;
|
||||
}
|
||||
check_allocated_size(pool, allocated);
|
||||
}
|
||||
|
||||
die(PoolDescribe(pool, mps_lib_get_stdout(), 0), "PoolDescribe");
|
||||
|
|
@ -152,8 +171,8 @@ static void testInArena(mps_arena_class_t arena_class, mps_arg_s *arena_args,
|
|||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_ARENA_HIGH, TRUE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_SLOT_HIGH, TRUE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_FIRST_FIT, TRUE);
|
||||
die(stress(arena, randomSize8, "MVFF", mps_class_mvff(), args),
|
||||
"stress MVFF");
|
||||
die(stress(arena, NULL, randomSize8, align, "MVFF",
|
||||
mps_class_mvff(), args), "stress MVFF");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
|
|
@ -163,31 +182,31 @@ static void testInArena(mps_arena_class_t arena_class, mps_arg_s *arena_args,
|
|||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_SLOT_HIGH, TRUE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_FIRST_FIT, TRUE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_POOL_DEBUG_OPTIONS, options);
|
||||
die(stress(arena, randomSize8, "MVFF debug", mps_class_mvff_debug(), args),
|
||||
"stress MVFF debug");
|
||||
die(stress(arena, options, randomSize8, align, "MVFF debug",
|
||||
mps_class_mvff_debug(), args), "stress MVFF debug");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
mps_align_t align = (mps_align_t)1 << (rnd() % 6);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ALIGN, align);
|
||||
die(stress(arena, randomSize, "MV", mps_class_mv(), args),
|
||||
"stress MV");
|
||||
die(stress(arena, NULL, randomSize, align, "MV",
|
||||
mps_class_mv(), args), "stress MV");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
mps_align_t align = (mps_align_t)1 << (rnd() % 6);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ALIGN, align);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_POOL_DEBUG_OPTIONS, options);
|
||||
die(stress(arena, randomSize, "MV debug", mps_class_mv_debug(), args),
|
||||
"stress MV debug");
|
||||
die(stress(arena, options, randomSize, align, "MV debug",
|
||||
mps_class_mv_debug(), args), "stress MV debug");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
fixedSizeSize = 1 + rnd() % 64;
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MFS_UNIT_SIZE, fixedSizeSize);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_EXTEND_BY, 100000);
|
||||
die(stress(arena, fixedSize, "MFS", mps_class_mfs(), args),
|
||||
"stress MFS");
|
||||
die(stress(arena, NULL, fixedSize, MPS_PF_ALIGN, "MFS",
|
||||
mps_class_mfs(), args), "stress MFS");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
mps_arena_destroy(arena);
|
||||
|
|
|
|||
|
|
@ -81,6 +81,8 @@ typedef struct mps_class_s {
|
|||
PoolBufferClassMethod bufferClass; /* default BufferClass of pool */
|
||||
PoolDescribeMethod describe; /* describe the contents of the pool */
|
||||
PoolDebugMixinMethod debugMixin; /* find the debug mixin, if any */
|
||||
PoolSizeMethod totalSize; /* total memory allocated from arena */
|
||||
PoolSizeMethod freeSize; /* free memory (unused by client program) */
|
||||
Bool labelled; /* whether it has been EventLabelled */
|
||||
Sig sig; /* .class.end-sig */
|
||||
} PoolClassStruct;
|
||||
|
|
@ -136,6 +138,8 @@ typedef struct MFSStruct { /* MFS outer structure */
|
|||
Bool extendSelf; /* whether to allocate tracts */
|
||||
Size unitSize; /* rounded for management purposes */
|
||||
struct MFSHeaderStruct *freeList; /* head of the free list */
|
||||
Size total; /* total size allocated from arena */
|
||||
Size free; /* free space in pool */
|
||||
Tract tractList; /* the first tract */
|
||||
Sig sig; /* <design/sig/> */
|
||||
} MFSStruct;
|
||||
|
|
@ -158,7 +162,7 @@ typedef struct MVStruct { /* MV pool outer structure */
|
|||
Size extendBy; /* segment size to extend pool by */
|
||||
Size avgSize; /* client estimate of allocation size */
|
||||
Size maxSize; /* client estimate of maximum size */
|
||||
Size space; /* total free space in pool */
|
||||
Size free; /* free space in pool */
|
||||
Size lost; /* <design/poolmv/#lost> */
|
||||
RingStruct spans; /* span chain */
|
||||
Sig sig; /* <design/sig/> */
|
||||
|
|
|
|||
|
|
@ -237,6 +237,7 @@ typedef void (*PoolFreeWalkMethod)(Pool pool, FreeBlockStepMethod f, void *p);
|
|||
typedef BufferClass (*PoolBufferClassMethod)(void);
|
||||
typedef Res (*PoolDescribeMethod)(Pool pool, mps_lib_FILE *stream, Count depth);
|
||||
typedef PoolDebugMixin (*PoolDebugMixinMethod)(Pool pool);
|
||||
typedef Size (*PoolSizeMethod)(Pool pool);
|
||||
|
||||
|
||||
/* Messages
|
||||
|
|
|
|||
|
|
@ -472,6 +472,11 @@ extern mps_res_t mps_pool_create_v(mps_pool_t *, mps_arena_t,
|
|||
extern mps_res_t mps_pool_create_k(mps_pool_t *, mps_arena_t,
|
||||
mps_class_t, mps_arg_s []);
|
||||
extern void mps_pool_destroy(mps_pool_t);
|
||||
extern size_t mps_pool_total_size(mps_pool_t);
|
||||
extern size_t mps_pool_free_size(mps_pool_t);
|
||||
|
||||
|
||||
/* Chains */
|
||||
|
||||
/* .gen-param: This structure must match <code/chain.h#gen-param>. */
|
||||
typedef struct mps_gen_param_s {
|
||||
|
|
@ -483,6 +488,9 @@ extern mps_res_t mps_chain_create(mps_chain_t *, mps_arena_t,
|
|||
size_t, mps_gen_param_s *);
|
||||
extern void mps_chain_destroy(mps_chain_t);
|
||||
|
||||
|
||||
/* Manual Allocation */
|
||||
|
||||
extern mps_res_t mps_alloc(mps_addr_t *, mps_pool_t, size_t);
|
||||
extern mps_res_t mps_alloc_v(mps_addr_t *, mps_pool_t, size_t, va_list);
|
||||
extern void mps_free(mps_pool_t, mps_addr_t, size_t);
|
||||
|
|
|
|||
|
|
@ -9,8 +9,9 @@
|
|||
|
||||
#include "mps.h"
|
||||
|
||||
extern size_t mps_mv_free_size(mps_pool_t mps_pool);
|
||||
extern size_t mps_mv_size(mps_pool_t mps_pool);
|
||||
#define mps_mv_free_size mps_pool_free_size
|
||||
#define mps_mv_size mps_pool_total_size
|
||||
|
||||
extern mps_class_t mps_class_mv(void);
|
||||
extern mps_class_t mps_class_mv_debug(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,27 +1,24 @@
|
|||
/* mpscmv2.h: MEMORY POOL SYSTEM CLASS "MVT"
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* The MVT pool class used to be known as "MV2" in some places: this
|
||||
* header provides backwards compatibility for prograns that included
|
||||
* it under its old name.
|
||||
*/
|
||||
|
||||
#ifndef mpscmv2_h
|
||||
#define mpscmv2_h
|
||||
|
||||
#include "mps.h"
|
||||
|
||||
extern mps_class_t mps_class_mvt(void);
|
||||
|
||||
/* The mvt pool class supports two extensions to the pool protocol:
|
||||
size and free_size. */
|
||||
extern size_t mps_mvt_free_size(mps_pool_t mps_pool);
|
||||
extern size_t mps_mvt_size(mps_pool_t mps_pool);
|
||||
#include "mpscmvt.h"
|
||||
|
||||
#endif /* mpscmv2_h */
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -19,8 +19,9 @@ extern const struct mps_key_s _mps_key_mvff_first_fit;
|
|||
#define MPS_KEY_MVFF_FIRST_FIT (&_mps_key_mvff_first_fit)
|
||||
#define MPS_KEY_MVFF_FIRST_FIT_FIELD b
|
||||
|
||||
extern size_t mps_mvff_free_size(mps_pool_t mps_pool);
|
||||
extern size_t mps_mvff_size(mps_pool_t mps_pool);
|
||||
#define mps_mvff_free_size mps_pool_free_size
|
||||
#define mps_mvff_size mps_pool_total_size
|
||||
|
||||
extern mps_class_t mps_class_mvff(void);
|
||||
extern mps_class_t mps_class_mvff_debug(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -16,28 +16,10 @@ extern const struct mps_key_s _mps_key_mvt_frag_limit;
|
|||
#define MPS_KEY_MVT_FRAG_LIMIT (&_mps_key_mvt_frag_limit)
|
||||
#define MPS_KEY_MVT_FRAG_LIMIT_FIELD d
|
||||
|
||||
/* The mvt pool class has five extra parameters to mps_pool_create:
|
||||
* mps_res_t mps_pool_create(mps_pool_t * pool, mps_arena_t arena,
|
||||
* mps_class_t mvt_class,
|
||||
* size_t minimum_size,
|
||||
* size_t mean_size,
|
||||
* size_t maximum_size,
|
||||
* mps_count_t reserve_depth
|
||||
* mps_count_t fragmentation_limit);
|
||||
* minimum_, mean_, and maximum_size are the mimimum, mean, and
|
||||
* maximum (typical) size of objects expected to be allocated in the
|
||||
* pool. reserve_depth is a measure of the expected hysteresis of the
|
||||
* object population. fragmentation_limit is a percentage (between 0
|
||||
* and 100): if the free space managed by the pool exceeds the
|
||||
* specified percentage, the pool will resort to a "first fit"
|
||||
* allocation policy.
|
||||
*/
|
||||
extern mps_class_t mps_class_mvt(void);
|
||||
|
||||
/* The mvt pool class supports two extensions to the pool protocol:
|
||||
size and free_size. */
|
||||
extern size_t mps_mvt_free_size(mps_pool_t mps_pool);
|
||||
extern size_t mps_mvt_size(mps_pool_t mps_pool);
|
||||
#define mps_mvt_free_size mps_pool_free_size
|
||||
#define mps_mvt_size mps_pool_total_size
|
||||
|
||||
#endif /* mpscmvt_h */
|
||||
|
||||
|
|
|
|||
|
|
@ -678,6 +678,40 @@ void mps_pool_destroy(mps_pool_t pool)
|
|||
ArenaLeave(arena);
|
||||
}
|
||||
|
||||
size_t mps_pool_total_size(mps_pool_t pool)
|
||||
{
|
||||
Arena arena;
|
||||
Size size;
|
||||
|
||||
AVER(TESTT(Pool, pool));
|
||||
arena = PoolArena(pool);
|
||||
|
||||
ArenaEnter(arena);
|
||||
|
||||
size = PoolTotalSize(pool);
|
||||
|
||||
ArenaLeave(arena);
|
||||
|
||||
return (size_t)size;
|
||||
}
|
||||
|
||||
size_t mps_pool_free_size(mps_pool_t pool)
|
||||
{
|
||||
Arena arena;
|
||||
Size size;
|
||||
|
||||
AVER(TESTT(Pool, pool));
|
||||
arena = PoolArena(pool);
|
||||
|
||||
ArenaEnter(arena);
|
||||
|
||||
size = PoolFreeSize(pool);
|
||||
|
||||
ArenaLeave(arena);
|
||||
|
||||
return (size_t)size;
|
||||
}
|
||||
|
||||
|
||||
mps_res_t mps_alloc(mps_addr_t *p_o, mps_pool_t pool, size_t size)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -72,6 +72,8 @@ Bool PoolClassCheck(PoolClass class)
|
|||
CHECKL(FUNCHECK(class->bufferClass));
|
||||
CHECKL(FUNCHECK(class->describe));
|
||||
CHECKL(FUNCHECK(class->debugMixin));
|
||||
CHECKL(FUNCHECK(class->totalSize));
|
||||
CHECKL(FUNCHECK(class->freeSize));
|
||||
CHECKS(PoolClass, class);
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -518,6 +520,26 @@ void PoolFreeWalk(Pool pool, FreeBlockStepMethod f, void *p)
|
|||
}
|
||||
|
||||
|
||||
/* PoolTotalSize -- return total memory allocated from arena */
|
||||
|
||||
Size PoolTotalSize(Pool pool)
|
||||
{
|
||||
AVERT(Pool, pool);
|
||||
|
||||
return (*pool->class->totalSize)(pool);
|
||||
}
|
||||
|
||||
|
||||
/* PoolFreeSize -- return free memory (unused by client program) */
|
||||
|
||||
Size PoolFreeSize(Pool pool)
|
||||
{
|
||||
AVERT(Pool, pool);
|
||||
|
||||
return (*pool->class->freeSize)(pool);
|
||||
}
|
||||
|
||||
|
||||
/* PoolDescribe -- describe a pool */
|
||||
|
||||
Res PoolDescribe(Pool pool, mps_lib_FILE *stream, Count depth)
|
||||
|
|
|
|||
|
|
@ -145,6 +145,8 @@ DEFINE_CLASS(AbstractPoolClass, class)
|
|||
class->bufferClass = PoolNoBufferClass;
|
||||
class->describe = PoolTrivDescribe;
|
||||
class->debugMixin = PoolNoDebugMixin;
|
||||
class->totalSize = PoolNoSize;
|
||||
class->freeSize = PoolNoSize;
|
||||
class->labelled = FALSE;
|
||||
class->sig = PoolClassSig;
|
||||
}
|
||||
|
|
@ -677,6 +679,14 @@ BufferClass PoolNoBufferClass(void)
|
|||
}
|
||||
|
||||
|
||||
Size PoolNoSize(Pool pool)
|
||||
{
|
||||
AVERT(Pool, pool);
|
||||
NOTREACHED;
|
||||
return UNUSED_SIZE;
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
|
|
|
|||
|
|
@ -2272,6 +2272,50 @@ static Res AMCAddrObject(Addr *pReturn, Pool pool, Seg seg, Addr addr)
|
|||
}
|
||||
|
||||
|
||||
/* AMCTotalSize -- total memory allocated from the arena */
|
||||
|
||||
static Size AMCTotalSize(Pool pool)
|
||||
{
|
||||
AMC amc;
|
||||
Size size = 0;
|
||||
Ring node, nextNode;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
amc = PoolAMC(pool);
|
||||
AVERT(AMC, amc);
|
||||
|
||||
RING_FOR(node, &amc->genRing, nextNode) {
|
||||
amcGen gen = RING_ELT(amcGen, amcRing, node);
|
||||
AVERT(amcGen, gen);
|
||||
size += gen->pgen.totalSize;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
/* AMCFreeSize -- free memory (unused by client program) */
|
||||
|
||||
static Size AMCFreeSize(Pool pool)
|
||||
{
|
||||
AMC amc;
|
||||
Size size = 0;
|
||||
Ring node, nextNode;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
amc = PoolAMC(pool);
|
||||
AVERT(AMC, amc);
|
||||
|
||||
RING_FOR(node, &amc->genRing, nextNode) {
|
||||
amcGen gen = RING_ELT(amcGen, amcRing, node);
|
||||
AVERT(amcGen, gen);
|
||||
size += gen->pgen.freeSize;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
/* AMCDescribe -- describe the contents of the AMC pool
|
||||
*
|
||||
* See <design/poolamc/#describe>.
|
||||
|
|
@ -2367,6 +2411,8 @@ DEFINE_POOL_CLASS(AMCZPoolClass, this)
|
|||
this->addrObject = AMCAddrObject;
|
||||
this->walk = AMCWalk;
|
||||
this->bufferClass = amcBufClassGet;
|
||||
this->totalSize = AMCTotalSize;
|
||||
this->freeSize = AMCFreeSize;
|
||||
this->describe = AMCDescribe;
|
||||
AVERT(PoolClass, this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1659,6 +1659,34 @@ static void AMSFreeWalk(Pool pool, FreeBlockStepMethod f, void *p)
|
|||
}
|
||||
|
||||
|
||||
/* AMSTotalSize -- total memory allocated from the arena */
|
||||
|
||||
static Size AMSTotalSize(Pool pool)
|
||||
{
|
||||
AMS ams;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
ams = PoolAMS(pool);
|
||||
AVERT(AMS, ams);
|
||||
|
||||
return ams->pgen.totalSize;
|
||||
}
|
||||
|
||||
|
||||
/* AMSFreeSize -- free memory (unused by client program) */
|
||||
|
||||
static Size AMSFreeSize(Pool pool)
|
||||
{
|
||||
AMS ams;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
ams = PoolAMS(pool);
|
||||
AVERT(AMS, ams);
|
||||
|
||||
return ams->pgen.freeSize;
|
||||
}
|
||||
|
||||
|
||||
/* AMSDescribe -- the pool class description method
|
||||
*
|
||||
* Iterates over the segments, describing all of them.
|
||||
|
|
@ -1728,6 +1756,8 @@ DEFINE_CLASS(AMSPoolClass, this)
|
|||
this->reclaim = AMSReclaim;
|
||||
this->walk = PoolNoWalk; /* TODO: job003738 */
|
||||
this->freewalk = AMSFreeWalk;
|
||||
this->totalSize = AMSTotalSize;
|
||||
this->freeSize = AMSFreeSize;
|
||||
this->describe = AMSDescribe;
|
||||
AVERT(PoolClass, this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1282,6 +1282,34 @@ static void AWLWalk(Pool pool, Seg seg, FormattedObjectsStepMethod f,
|
|||
}
|
||||
|
||||
|
||||
/* AWLTotalSize -- total memory allocated from the arena */
|
||||
|
||||
static Size AWLTotalSize(Pool pool)
|
||||
{
|
||||
AWL awl;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
awl = PoolAWL(pool);
|
||||
AVERT(AWL, awl);
|
||||
|
||||
return awl->pgen.totalSize;
|
||||
}
|
||||
|
||||
|
||||
/* AWLFreeSize -- free memory (unused by client program) */
|
||||
|
||||
static Size AWLFreeSize(Pool pool)
|
||||
{
|
||||
AWL awl;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
awl = PoolAWL(pool);
|
||||
AVERT(AWL, awl);
|
||||
|
||||
return awl->pgen.freeSize;
|
||||
}
|
||||
|
||||
|
||||
/* AWLPoolClass -- the class definition */
|
||||
|
||||
DEFINE_POOL_CLASS(AWLPoolClass, this)
|
||||
|
|
@ -1306,6 +1334,8 @@ DEFINE_POOL_CLASS(AWLPoolClass, this)
|
|||
this->fixEmergency = AWLFix;
|
||||
this->reclaim = AWLReclaim;
|
||||
this->walk = AWLWalk;
|
||||
this->totalSize = AWLTotalSize;
|
||||
this->freeSize = AWLFreeSize;
|
||||
AVERT(PoolClass, this);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -794,6 +794,34 @@ static void LOReclaim(Pool pool, Trace trace, Seg seg)
|
|||
}
|
||||
|
||||
|
||||
/* LOTotalSize -- total memory allocated from the arena */
|
||||
|
||||
static Size LOTotalSize(Pool pool)
|
||||
{
|
||||
LO lo;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
lo = PoolPoolLO(pool);
|
||||
AVERT(LO, lo);
|
||||
|
||||
return lo->pgen.totalSize;
|
||||
}
|
||||
|
||||
|
||||
/* LOFreeSize -- free memory (unused by client program) */
|
||||
|
||||
static Size LOFreeSize(Pool pool)
|
||||
{
|
||||
LO lo;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
lo = PoolPoolLO(pool);
|
||||
AVERT(LO, lo);
|
||||
|
||||
return lo->pgen.freeSize;
|
||||
}
|
||||
|
||||
|
||||
/* LOPoolClass -- the class definition */
|
||||
|
||||
DEFINE_POOL_CLASS(LOPoolClass, this)
|
||||
|
|
@ -814,6 +842,8 @@ DEFINE_POOL_CLASS(LOPoolClass, this)
|
|||
this->fixEmergency = LOFix;
|
||||
this->reclaim = LOReclaim;
|
||||
this->walk = LOWalk;
|
||||
this->totalSize = LOTotalSize;
|
||||
this->freeSize = LOFreeSize;
|
||||
AVERT(PoolClass, this);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -116,6 +116,8 @@ static Res MFSInit(Pool pool, ArgList args)
|
|||
mfs->unitSize = unitSize;
|
||||
mfs->freeList = NULL;
|
||||
mfs->tractList = NULL;
|
||||
mfs->total = 0;
|
||||
mfs->free = 0;
|
||||
mfs->sig = MFSSig;
|
||||
|
||||
AVERT(MFS, mfs);
|
||||
|
|
@ -192,6 +194,10 @@ void MFSExtend(Pool pool, Addr base, Size size)
|
|||
TractSetP(tract, (void *)mfs->tractList);
|
||||
mfs->tractList = tract;
|
||||
|
||||
/* Update accounting */
|
||||
mfs->total += size;
|
||||
mfs->free += size;
|
||||
|
||||
/* Sew together all the new empty units in the region, working down */
|
||||
/* from the top so that they are in ascending order of address on the */
|
||||
/* free list. */
|
||||
|
|
@ -265,6 +271,8 @@ static Res MFSAlloc(Addr *pReturn, Pool pool, Size size,
|
|||
/* Detach the first free unit from the free list and return its address. */
|
||||
|
||||
mfs->freeList = f->next;
|
||||
AVER(mfs->free >= mfs->unitSize);
|
||||
mfs->free -= mfs->unitSize;
|
||||
|
||||
*pReturn = (Addr)f;
|
||||
return ResOK;
|
||||
|
|
@ -293,6 +301,35 @@ static void MFSFree(Pool pool, Addr old, Size size)
|
|||
h = (Header)old;
|
||||
h->next = mfs->freeList;
|
||||
mfs->freeList = h;
|
||||
mfs->free += mfs->unitSize;
|
||||
}
|
||||
|
||||
|
||||
/* MFSTotalSize -- total memory allocated from the arena */
|
||||
|
||||
static Size MFSTotalSize(Pool pool)
|
||||
{
|
||||
MFS mfs;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
mfs = PoolPoolMFS(pool);
|
||||
AVERT(MFS, mfs);
|
||||
|
||||
return mfs->total;
|
||||
}
|
||||
|
||||
|
||||
/* MFSFreeSize -- free memory (unused by client program) */
|
||||
|
||||
static Size MFSFreeSize(Pool pool)
|
||||
{
|
||||
MFS mfs;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
mfs = PoolPoolMFS(pool);
|
||||
AVERT(MFS, mfs);
|
||||
|
||||
return mfs->free;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -331,6 +368,8 @@ DEFINE_POOL_CLASS(MFSPoolClass, this)
|
|||
this->finish = MFSFinish;
|
||||
this->alloc = MFSAlloc;
|
||||
this->free = MFSFree;
|
||||
this->totalSize = MFSTotalSize;
|
||||
this->freeSize = MFSFreeSize;
|
||||
this->describe = MFSDescribe;
|
||||
AVERT(PoolClass, this);
|
||||
}
|
||||
|
|
@ -365,6 +404,8 @@ Bool MFSCheck(MFS mfs)
|
|||
if(mfs->tractList != NULL) {
|
||||
CHECKD_NOSIG(Tract, mfs->tractList);
|
||||
}
|
||||
CHECKL(mfs->free <= mfs->total);
|
||||
CHECKL((mfs->total - mfs->free) % mfs->unitSize == 0);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ typedef struct MVSpanStruct {
|
|||
MVBlockStruct base; /* sentinel at base of span */
|
||||
MVBlockStruct limit; /* sentinel at limit of span */
|
||||
MVBlock blocks; /* allocated blocks */
|
||||
Size space; /* total free space in span */
|
||||
Size free; /* free space in span */
|
||||
Size largest; /* .design.largest */
|
||||
Bool largestKnown; /* .design.largest */
|
||||
unsigned blockCount; /* number of blocks on chain */
|
||||
|
|
@ -160,11 +160,11 @@ static Bool MVSpanCheck(MVSpan span)
|
|||
/* The sentinels mustn't overlap. */
|
||||
CHECKL(span->base.limit <= span->limit.base);
|
||||
/* The free space can't be more than the gap between the sentinels. */
|
||||
CHECKL(span->space <= SpanInsideSentinels(span));
|
||||
CHECKL(span->free <= SpanInsideSentinels(span));
|
||||
|
||||
CHECKL(BoolCheck(span->largestKnown));
|
||||
if (span->largestKnown) { /* .design.largest */
|
||||
CHECKL(span->largest <= span->space);
|
||||
CHECKL(span->largest <= span->free);
|
||||
/* at least this much is free */
|
||||
} else {
|
||||
CHECKL(span->largest == SpanSize(span)+1);
|
||||
|
|
@ -277,7 +277,7 @@ static Res MVInit(Pool pool, ArgList args)
|
|||
mv->maxSize = maxSize;
|
||||
RingInit(&mv->spans);
|
||||
|
||||
mv->space = 0;
|
||||
mv->free = 0;
|
||||
mv->lost = 0;
|
||||
|
||||
mv->sig = MVSig;
|
||||
|
|
@ -368,7 +368,7 @@ static Bool MVSpanAlloc(Addr *addrReturn, MVSpan span, Size size,
|
|||
span->largest = SpanSize(span) + 1; /* .design.largest */
|
||||
}
|
||||
|
||||
span->space -= size;
|
||||
span->free -= size;
|
||||
*addrReturn = new;
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -484,7 +484,7 @@ static Res MVSpanFree(MVSpan span, Addr base, Addr limit, Pool blockPool)
|
|||
|
||||
AVERT(MVBlock, block);
|
||||
|
||||
span->space += AddrOffset(base, limit);
|
||||
span->free += AddrOffset(base, limit);
|
||||
|
||||
if (freeAreaSize > span->largest) { /* .design.largest */
|
||||
AVER(span->largestKnown);
|
||||
|
|
@ -528,16 +528,16 @@ static Res MVAlloc(Addr *pReturn, Pool pool, Size size,
|
|||
|
||||
size = SizeAlignUp(size, pool->alignment);
|
||||
|
||||
if(size <= mv->space) {
|
||||
if(size <= mv->free) {
|
||||
spans = &mv->spans;
|
||||
RING_FOR(node, spans, nextNode) {
|
||||
span = RING_ELT(MVSpan, spans, node);
|
||||
if((size <= span->largest) && /* .design.largest.alloc */
|
||||
(size <= span->space)) {
|
||||
(size <= span->free)) {
|
||||
Addr new;
|
||||
|
||||
if(MVSpanAlloc(&new, span, size, mvBlockPool(mv))) {
|
||||
mv->space -= size;
|
||||
mv->free -= size;
|
||||
AVER(AddrIsAligned(new, pool->alignment));
|
||||
*pReturn = new;
|
||||
return ResOK;
|
||||
|
|
@ -593,20 +593,20 @@ static Res MVAlloc(Addr *pReturn, Pool pool, Size size,
|
|||
RingInit(&span->spans);
|
||||
span->base.base = span->base.limit = base;
|
||||
span->limit.base = span->limit.limit = limit;
|
||||
span->space = AddrOffset(span->base.limit, span->limit.base);
|
||||
span->free = AddrOffset(span->base.limit, span->limit.base);
|
||||
span->limit.next = NULL;
|
||||
span->base.next = &span->limit;
|
||||
span->blocks = &span->base;
|
||||
span->blockCount = 2;
|
||||
span->base.limit = AddrAdd(span->base.limit, size);
|
||||
span->space -= size;
|
||||
span->largest = span->space;
|
||||
span->free -= size;
|
||||
span->largest = span->free;
|
||||
span->largestKnown = TRUE;
|
||||
|
||||
span->sig = MVSpanSig;
|
||||
AVERT(MVSpan, span);
|
||||
|
||||
mv->space += span->space;
|
||||
mv->free += span->free;
|
||||
RingInsert(&mv->spans, &span->spans);
|
||||
/* use RingInsert so that we examine this new span first when allocating */
|
||||
|
||||
|
|
@ -655,16 +655,16 @@ static void MVFree(Pool pool, Addr old, Size size)
|
|||
if(res != ResOK)
|
||||
mv->lost += size;
|
||||
else
|
||||
mv->space += size;
|
||||
mv->free += size;
|
||||
|
||||
/* free space should be less than total space */
|
||||
AVER(span->space <= SpanInsideSentinels(span));
|
||||
if(span->space == SpanSize(span)) { /* the whole span is free */
|
||||
AVER(span->free <= SpanInsideSentinels(span));
|
||||
if(span->free == SpanSize(span)) { /* the whole span is free */
|
||||
AVER(span->blockCount == 2);
|
||||
/* both blocks are the trivial sentinel blocks */
|
||||
AVER(span->base.limit == span->base.base);
|
||||
AVER(span->limit.limit == span->limit.base);
|
||||
mv->space -= span->space;
|
||||
mv->free -= span->free;
|
||||
ArenaFree(TractBase(span->tract), span->size, pool);
|
||||
RingRemove(&span->spans);
|
||||
RingFinish(&span->spans);
|
||||
|
|
@ -687,6 +687,51 @@ static PoolDebugMixin MVDebugMixin(Pool pool)
|
|||
}
|
||||
|
||||
|
||||
/* MVTotalSize -- total memory allocated from the arena */
|
||||
|
||||
static Size MVTotalSize(Pool pool)
|
||||
{
|
||||
MV mv;
|
||||
Size size = 0;
|
||||
Ring node, next;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
mv = PoolMV(pool);
|
||||
AVERT(MV, mv);
|
||||
|
||||
RING_FOR(node, &mv->spans, next) {
|
||||
MVSpan span = RING_ELT(MVSpan, spans, node);
|
||||
AVERT(MVSpan, span);
|
||||
size += span->size;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
/* MVFreeSize -- free memory (unused by client program) */
|
||||
|
||||
static Size MVFreeSize(Pool pool)
|
||||
{
|
||||
MV mv;
|
||||
Size size = 0;
|
||||
Ring node, next;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
mv = PoolMV(pool);
|
||||
AVERT(MV, mv);
|
||||
|
||||
RING_FOR(node, &mv->spans, next) {
|
||||
MVSpan span = RING_ELT(MVSpan, spans, node);
|
||||
AVERT(MVSpan, span);
|
||||
size += span->free;
|
||||
}
|
||||
|
||||
AVER(size == mv->free + mv->lost);
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
static Res MVDescribe(Pool pool, mps_lib_FILE *stream, Count depth)
|
||||
{
|
||||
Res res;
|
||||
|
|
@ -710,7 +755,8 @@ static Res MVDescribe(Pool pool, mps_lib_FILE *stream, Count depth)
|
|||
"extendBy $W\n", (WriteFW)mv->extendBy,
|
||||
"avgSize $W\n", (WriteFW)mv->avgSize,
|
||||
"maxSize $W\n", (WriteFW)mv->maxSize,
|
||||
"space $P\n", (WriteFP)mv->space,
|
||||
"free $W\n", (WriteFP)mv->free,
|
||||
"lost $W\n", (WriteFP)mv->lost,
|
||||
NULL);
|
||||
if(res != ResOK) return res;
|
||||
|
||||
|
|
@ -728,7 +774,7 @@ static Res MVDescribe(Pool pool, mps_lib_FILE *stream, Count depth)
|
|||
res = WriteF(stream, depth + 2,
|
||||
"span $P\n", (WriteFP)span,
|
||||
"tract $P\n", (WriteFP)span->tract,
|
||||
"space $W\n", (WriteFW)span->space,
|
||||
"free $W\n", (WriteFW)span->free,
|
||||
"blocks $U\n", (WriteFU)span->blockCount,
|
||||
"largest ",
|
||||
NULL);
|
||||
|
|
@ -794,6 +840,8 @@ DEFINE_POOL_CLASS(MVPoolClass, this)
|
|||
this->finish = MVFinish;
|
||||
this->alloc = MVAlloc;
|
||||
this->free = MVFree;
|
||||
this->totalSize = MVTotalSize;
|
||||
this->freeSize = MVFreeSize;
|
||||
this->describe = MVDescribe;
|
||||
AVERT(PoolClass, this);
|
||||
}
|
||||
|
|
@ -835,58 +883,6 @@ mps_class_t mps_class_mv_debug(void)
|
|||
}
|
||||
|
||||
|
||||
/* mps_mv_free_size -- free bytes in pool */
|
||||
|
||||
size_t mps_mv_free_size(mps_pool_t mps_pool)
|
||||
{
|
||||
Pool pool;
|
||||
MV mv;
|
||||
MVSpan span;
|
||||
Size f = 0;
|
||||
Ring spans, node = NULL, nextNode; /* gcc whinge stop */
|
||||
|
||||
pool = (Pool)mps_pool;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
mv = PoolMV(pool);
|
||||
AVERT(MV, mv);
|
||||
|
||||
spans = &mv->spans;
|
||||
RING_FOR(node, spans, nextNode) {
|
||||
span = RING_ELT(MVSpan, spans, node);
|
||||
AVERT(MVSpan, span);
|
||||
f += span->space;
|
||||
}
|
||||
|
||||
return (size_t)f;
|
||||
}
|
||||
|
||||
|
||||
size_t mps_mv_size(mps_pool_t mps_pool)
|
||||
{
|
||||
Pool pool;
|
||||
MV mv;
|
||||
MVSpan span;
|
||||
Size f = 0;
|
||||
Ring spans, node = NULL, nextNode; /* gcc whinge stop */
|
||||
|
||||
pool = (Pool)mps_pool;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
mv = PoolMV(pool);
|
||||
AVERT(MV, mv);
|
||||
|
||||
spans = &mv->spans;
|
||||
RING_FOR(node, spans, nextNode) {
|
||||
span = RING_ELT(MVSpan, spans, node);
|
||||
AVERT(MVSpan, span);
|
||||
f += span->size;
|
||||
}
|
||||
|
||||
return (size_t)f;
|
||||
}
|
||||
|
||||
|
||||
/* MVCheck -- check the consistency of an MV structure */
|
||||
|
||||
Bool MVCheck(MV mv)
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@ static Res MVTBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
static void MVTBufferEmpty(Pool pool, Buffer buffer, Addr base, Addr limit);
|
||||
static void MVTFree(Pool pool, Addr base, Size size);
|
||||
static Res MVTDescribe(Pool pool, mps_lib_FILE *stream, Count depth);
|
||||
static Size MVTTotalSize(Pool pool);
|
||||
static Size MVTFreeSize(Pool pool);
|
||||
static Res MVTSegAlloc(Seg *segReturn, MVT mvt, Size size,
|
||||
Bool withReservoirPermit);
|
||||
|
||||
|
|
@ -145,6 +147,8 @@ DEFINE_POOL_CLASS(MVTPoolClass, this)
|
|||
this->free = MVTFree;
|
||||
this->bufferFill = MVTBufferFill;
|
||||
this->bufferEmpty = MVTBufferEmpty;
|
||||
this->totalSize = MVTTotalSize;
|
||||
this->freeSize = MVTFreeSize;
|
||||
this->describe = MVTDescribe;
|
||||
AVERT(PoolClass, this);
|
||||
}
|
||||
|
|
@ -987,6 +991,34 @@ static void MVTFree(Pool pool, Addr base, Size size)
|
|||
}
|
||||
|
||||
|
||||
/* MVTTotalSize -- total memory allocated from the arena */
|
||||
|
||||
static Size MVTTotalSize(Pool pool)
|
||||
{
|
||||
MVT mvt;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
mvt = PoolMVT(pool);
|
||||
AVERT(MVT, mvt);
|
||||
|
||||
return mvt->size;
|
||||
}
|
||||
|
||||
|
||||
/* MVTFreeSize -- free memory (unused by client program) */
|
||||
|
||||
static Size MVTFreeSize(Pool pool)
|
||||
{
|
||||
MVT mvt;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
mvt = PoolMVT(pool);
|
||||
AVERT(MVT, mvt);
|
||||
|
||||
return mvt->available + mvt->unavailable;
|
||||
}
|
||||
|
||||
|
||||
/* MVTDescribe -- describe an MVT pool */
|
||||
|
||||
static Res MVTDescribe(Pool pool, mps_lib_FILE *stream, Count depth)
|
||||
|
|
@ -1088,44 +1120,6 @@ mps_class_t mps_class_mvt(void)
|
|||
}
|
||||
|
||||
|
||||
/* MPS Interface extensions --- should these be pool generics? */
|
||||
|
||||
|
||||
/* mps_mvt_size -- number of bytes committed to the pool */
|
||||
|
||||
size_t mps_mvt_size(mps_pool_t mps_pool)
|
||||
{
|
||||
Pool pool;
|
||||
MVT mvt;
|
||||
|
||||
pool = (Pool)mps_pool;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
mvt = PoolMVT(pool);
|
||||
AVERT(MVT, mvt);
|
||||
|
||||
return (size_t)mvt->size;
|
||||
}
|
||||
|
||||
|
||||
/* mps_mvt_free_size -- number of bytes comitted to the pool that are
|
||||
* available for allocation
|
||||
*/
|
||||
size_t mps_mvt_free_size(mps_pool_t mps_pool)
|
||||
{
|
||||
Pool pool;
|
||||
MVT mvt;
|
||||
|
||||
pool = (Pool)mps_pool;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
mvt = PoolMVT(pool);
|
||||
AVERT(MVT, mvt);
|
||||
|
||||
return (size_t)mvt->available;
|
||||
}
|
||||
|
||||
|
||||
/* Internal methods */
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -636,6 +636,34 @@ static PoolDebugMixin MVFFDebugMixin(Pool pool)
|
|||
}
|
||||
|
||||
|
||||
/* MVFFTotalSize -- total memory allocated from the arena */
|
||||
|
||||
static Size MVFFTotalSize(Pool pool)
|
||||
{
|
||||
MVFF mvff;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
mvff = PoolMVFF(pool);
|
||||
AVERT(MVFF, mvff);
|
||||
|
||||
return LandSize(MVFFTotalLand(mvff));
|
||||
}
|
||||
|
||||
|
||||
/* MVFFFreeSize -- free memory (unused by client program) */
|
||||
|
||||
static Size MVFFFreeSize(Pool pool)
|
||||
{
|
||||
MVFF mvff;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
mvff = PoolMVFF(pool);
|
||||
AVERT(MVFF, mvff);
|
||||
|
||||
return LandSize(MVFFFreeLand(mvff));
|
||||
}
|
||||
|
||||
|
||||
/* MVFFDescribe -- describe an MVFF pool */
|
||||
|
||||
static Res MVFFDescribe(Pool pool, mps_lib_FILE *stream, Count depth)
|
||||
|
|
@ -693,6 +721,8 @@ DEFINE_POOL_CLASS(MVFFPoolClass, this)
|
|||
this->free = MVFFFree;
|
||||
this->bufferFill = MVFFBufferFill;
|
||||
this->bufferEmpty = MVFFBufferEmpty;
|
||||
this->totalSize = MVFFTotalSize;
|
||||
this->freeSize = MVFFFreeSize;
|
||||
this->describe = MVFFDescribe;
|
||||
AVERT(PoolClass, this);
|
||||
}
|
||||
|
|
@ -732,37 +762,6 @@ mps_class_t mps_class_mvff_debug(void)
|
|||
}
|
||||
|
||||
|
||||
/* Total free bytes. See <design/poolmvff/#design.arena-enter> */
|
||||
|
||||
size_t mps_mvff_free_size(mps_pool_t mps_pool)
|
||||
{
|
||||
Pool pool;
|
||||
MVFF mvff;
|
||||
|
||||
pool = (Pool)mps_pool;
|
||||
AVERT(Pool, pool);
|
||||
mvff = PoolMVFF(pool);
|
||||
AVERT(MVFF, mvff);
|
||||
|
||||
return (size_t)LandSize(MVFFFreeLand(mvff));
|
||||
}
|
||||
|
||||
/* Total owned bytes. See <design/poolmvff/#design.arena-enter> */
|
||||
|
||||
size_t mps_mvff_size(mps_pool_t mps_pool)
|
||||
{
|
||||
Pool pool;
|
||||
MVFF mvff;
|
||||
|
||||
pool = (Pool)mps_pool;
|
||||
AVERT(Pool, pool);
|
||||
mvff = PoolMVFF(pool);
|
||||
AVERT(MVFF, mvff);
|
||||
|
||||
return (size_t)LandSize(MVFFTotalLand(mvff));
|
||||
}
|
||||
|
||||
|
||||
/* MVFFCheck -- check the consistency of an MVFF structure */
|
||||
|
||||
ATTRIBUTE_UNUSED
|
||||
|
|
|
|||
|
|
@ -24,9 +24,6 @@
|
|||
SRCID(poolsnc, "$Id$");
|
||||
|
||||
|
||||
#define SNCGen ((Serial)1) /* "generation" for SNC pools */
|
||||
|
||||
|
||||
/* SNCStruct -- structure for an SNC pool
|
||||
*
|
||||
* See design.mps.poolsnc.poolstruct.
|
||||
|
|
|
|||
|
|
@ -39,6 +39,9 @@ New features
|
|||
was considered, and a chain was collected up to, but not including,
|
||||
the lowest generation whose new size was within its capacity.)
|
||||
|
||||
#. New pool introspection functions :c:func:`mps_pool_total_size` and
|
||||
:c:func:`mps_pool_free_size`.
|
||||
|
||||
|
||||
Interface changes
|
||||
.................
|
||||
|
|
|
|||
|
|
@ -135,6 +135,31 @@ See the :ref:`pool` for a list of pool classes.
|
|||
Pool introspection
|
||||
------------------
|
||||
|
||||
.. c:function:: size_t mps_pool_total_size(mps_pool_t pool)
|
||||
|
||||
Return the total memory allocated from the arena and managed by
|
||||
the pool.
|
||||
|
||||
``pool`` is the pool.
|
||||
|
||||
The result includes memory in use by the client program, memory
|
||||
that's available for use by the client program, and memory
|
||||
that's lost to fragmentation. It does not include memory used by
|
||||
the pool's internal control structures.
|
||||
|
||||
|
||||
.. c:function:: size_t mps_pool_free_size(mps_pool_t pool)
|
||||
|
||||
Return the free memory: memory managed by the pool but not in use
|
||||
by the client program.
|
||||
|
||||
``pool`` is the pool.
|
||||
|
||||
The result includes memory that's available for use by the client
|
||||
program, and memory that's lost to fragmentation. It does not
|
||||
include memory used by the pool's internal control structures.
|
||||
|
||||
|
||||
.. c:function:: mps_bool_t mps_addr_pool(mps_pool_t *pool_o, mps_arena_t arena, mps_addr_t addr)
|
||||
|
||||
Determine the :term:`pool` to which an address belongs.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue