mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-04-30 02:02:38 -07:00
Integrate changes from global graphics.
Copied from Perforce Change: 30250 ServerID: perforce.ravenbrook.com
This commit is contained in:
parent
63e5f52915
commit
6a1a360814
103 changed files with 2821 additions and 1423 deletions
|
|
@ -1,12 +0,0 @@
|
|||
/* impl.c.action: STRATEGIC ACTION
|
||||
*
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "mpm.h"
|
||||
|
||||
SRCID(action, "$Id$");
|
||||
|
||||
|
||||
/* All contents obsolete. */
|
||||
132
mps/code/amcss.c
132
mps/code/amcss.c
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (C) 2002 Global Graphics Software.
|
||||
*/
|
||||
|
||||
#include "fmtdy.h"
|
||||
|
|
@ -18,10 +19,12 @@
|
|||
#include <string.h>
|
||||
|
||||
|
||||
/* These values have been tuned to cause one top-generation collection. */
|
||||
/* These values have been tuned in the hope of getting one dynamic collection. */
|
||||
#define testArenaSIZE ((size_t)1000*1024)
|
||||
#define gen1SIZE ((size_t)150)
|
||||
#define gen2SIZE ((size_t)170)
|
||||
#define avLEN 3
|
||||
#define exactRootsCOUNT 200
|
||||
#define exactRootsCOUNT 180
|
||||
#define ambigRootsCOUNT 50
|
||||
#define genCOUNT 2
|
||||
#define collectionsCOUNT 37
|
||||
|
|
@ -31,42 +34,51 @@
|
|||
/* testChain -- generation parameters for the test */
|
||||
|
||||
static mps_gen_param_s testChain[genCOUNT] = {
|
||||
{ 150, 0.85 }, { 170, 0.45 } };
|
||||
{ gen1SIZE, 0.85 }, { gen2SIZE, 0.45 } };
|
||||
|
||||
|
||||
/* objNULL needs to be odd so that it's ignored in exactRoots. */
|
||||
#define objNULL ((mps_addr_t)0xDECEA5ED)
|
||||
|
||||
|
||||
static mps_pool_t pool;
|
||||
static mps_ap_t ap;
|
||||
static mps_addr_t exactRoots[exactRootsCOUNT];
|
||||
static mps_addr_t ambigRoots[ambigRootsCOUNT];
|
||||
|
||||
|
||||
static void enable(mps_arena_t arena)
|
||||
{
|
||||
mps_message_type_enable(arena, mps_message_type_gc());
|
||||
}
|
||||
/* report - report statistics from any terminated GCs */
|
||||
|
||||
static void report(mps_arena_t arena)
|
||||
{
|
||||
mps_message_t message;
|
||||
mps_message_t message;
|
||||
static int nCollections = 0;
|
||||
|
||||
while (mps_message_get(&message, arena, mps_message_type_gc())) {
|
||||
size_t live, condemned, not_condemned;
|
||||
|
||||
while (mps_message_get(&message, arena, mps_message_type_gc())) {
|
||||
size_t live, condemned, not_condemned;
|
||||
live = mps_message_gc_live_size(arena, message);
|
||||
condemned = mps_message_gc_condemned_size(arena, message);
|
||||
not_condemned = mps_message_gc_not_condemned_size(arena, message);
|
||||
|
||||
live = mps_message_gc_live_size(arena, message);
|
||||
condemned = mps_message_gc_condemned_size(arena, message);
|
||||
not_condemned = mps_message_gc_not_condemned_size(arena, message);
|
||||
printf("\nCollection %d finished:\n", ++nCollections);
|
||||
printf("live %lu\n", (unsigned long)live);
|
||||
printf("condemned %lu\n", (unsigned long)condemned);
|
||||
printf("not_condemned %lu\n", (unsigned long)not_condemned);
|
||||
|
||||
mps_message_discard(arena, message);
|
||||
mps_message_discard(arena, message);
|
||||
|
||||
printf("live %lu\n", (unsigned long)live);
|
||||
printf("condemned %lu\n", (unsigned long)condemned);
|
||||
printf("not_condemned %lu\n", (unsigned long)not_condemned);
|
||||
}
|
||||
if (condemned > (gen1SIZE + gen2SIZE + (size_t)128) * 1024)
|
||||
/* When condemned size is larger than could happen in a gen 2
|
||||
* collection (discounting ramps, natch), guess that was a dynamic
|
||||
* collection, and reset the commit limit, so it doesn't run out. */
|
||||
die(mps_arena_commit_limit_set(arena, 2 * testArenaSIZE), "set limit");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* make -- create one new object */
|
||||
|
||||
static mps_addr_t make(void)
|
||||
{
|
||||
size_t length = rnd() % (2*avLEN);
|
||||
|
|
@ -76,10 +88,10 @@ static mps_addr_t make(void)
|
|||
|
||||
do {
|
||||
MPS_RESERVE_BLOCK(res, p, ap, size);
|
||||
if(res)
|
||||
if (res)
|
||||
die(res, "MPS_RESERVE_BLOCK");
|
||||
res = dylan_init(p, size, exactRoots, exactRootsCOUNT);
|
||||
if(res)
|
||||
if (res)
|
||||
die(res, "dylan_init");
|
||||
} while(!mps_commit(ap, p, size));
|
||||
|
||||
|
|
@ -87,6 +99,8 @@ static mps_addr_t make(void)
|
|||
}
|
||||
|
||||
|
||||
/* test_stepper -- stepping function for walk */
|
||||
|
||||
static void test_stepper(mps_addr_t object, mps_fmt_t fmt, mps_pool_t pol,
|
||||
void *p, size_t s)
|
||||
{
|
||||
|
|
@ -126,7 +140,7 @@ static void *test(void *arg, size_t s)
|
|||
for(i = 0; i < exactRootsCOUNT; ++i)
|
||||
exactRoots[i] = objNULL;
|
||||
for(i = 0; i < ambigRootsCOUNT; ++i)
|
||||
ambigRoots[i] = (mps_addr_t)rnd();
|
||||
ambigRoots[i] = rnd_addr();
|
||||
|
||||
die(mps_root_create_table_masked(&exactRoot, arena,
|
||||
MPS_RANK_EXACT, (mps_rm_t)0,
|
||||
|
|
@ -143,74 +157,81 @@ static void *test(void *arg, size_t s)
|
|||
|
||||
collections = 0;
|
||||
rampSwitch = rampSIZE;
|
||||
mps_ap_alloc_pattern_begin(ap, ramp);
|
||||
mps_ap_alloc_pattern_begin(busy_ap, ramp);
|
||||
die(mps_ap_alloc_pattern_begin(ap, ramp), "pattern begin (ap)");
|
||||
die(mps_ap_alloc_pattern_begin(busy_ap, ramp), "pattern begin (busy_ap)");
|
||||
ramping = 1;
|
||||
objs = 0;
|
||||
while(collections < collectionsCOUNT) {
|
||||
while (collections < collectionsCOUNT) {
|
||||
unsigned long c;
|
||||
size_t r;
|
||||
size_t hitRatio;
|
||||
|
||||
c = mps_collections(arena);
|
||||
|
||||
if(collections != c) {
|
||||
if (collections != c) {
|
||||
collections = c;
|
||||
printf("\nCollection %lu, %lu objects.\n",
|
||||
c, objs);
|
||||
do {
|
||||
mps_addr_t p = (mps_addr_t)rnd();
|
||||
if (mps_arena_has_addr(arena, p)) {
|
||||
printf("0x%08x is in arena\n", (int)p);
|
||||
break;
|
||||
}
|
||||
} while(1);
|
||||
printf("\nCollection %lu started, %lu objects.\n", c, objs);
|
||||
|
||||
/* test mps_arena_has_addr */
|
||||
hitRatio = ((size_t)-1 / mps_arena_committed(arena));
|
||||
/* That's roughly how often a random addr should hit the arena. */
|
||||
for (i = 0; i < 4 * hitRatio ; i++) {
|
||||
mps_addr_t p = rnd_addr();
|
||||
if (mps_arena_has_addr(arena, p)) {
|
||||
printf("%p is in the arena\n", p);
|
||||
}
|
||||
}
|
||||
|
||||
report(arena);
|
||||
for(r = 0; r < exactRootsCOUNT; ++r)
|
||||
cdie(exactRoots[r] == objNULL ||
|
||||
(dylan_check(exactRoots[r]) &&
|
||||
mps_arena_has_addr(arena, exactRoots[r])),
|
||||
for (i = 0; i < exactRootsCOUNT; ++i)
|
||||
cdie(exactRoots[i] == objNULL
|
||||
|| (dylan_check(exactRoots[i])
|
||||
&& mps_arena_has_addr(arena, exactRoots[i])),
|
||||
"all roots check");
|
||||
cdie(!mps_arena_has_addr(arena, NULL),
|
||||
"NULL in arena");
|
||||
|
||||
if(collections == collectionsCOUNT / 2) {
|
||||
if (collections == collectionsCOUNT / 2) {
|
||||
unsigned long object_count = 0;
|
||||
mps_arena_park(arena);
|
||||
mps_arena_formatted_objects_walk(arena, test_stepper, &object_count, 0);
|
||||
mps_arena_release(arena);
|
||||
printf("stepped on %lu objects.\n", object_count);
|
||||
}
|
||||
if(collections == rampSwitch) {
|
||||
if (collections == rampSwitch) {
|
||||
int begin_ramp = !ramping
|
||||
|| /* Every other time, switch back immediately. */ (collections & 1);
|
||||
|
||||
rampSwitch += rampSIZE;
|
||||
if(ramping) {
|
||||
mps_ap_alloc_pattern_end(ap, ramp);
|
||||
mps_ap_alloc_pattern_end(busy_ap, ramp);
|
||||
if (ramping) {
|
||||
die(mps_ap_alloc_pattern_end(ap, ramp), "pattern end (ap)");
|
||||
die(mps_ap_alloc_pattern_end(busy_ap, ramp), "pattern end (busy_ap)");
|
||||
ramping = 0;
|
||||
/* kill half of the roots */
|
||||
for(i = 0; i < exactRootsCOUNT; i += 2) {
|
||||
if(exactRoots[i] != objNULL) {
|
||||
if (exactRoots[i] != objNULL) {
|
||||
cdie(dylan_check(exactRoots[i]), "ramp kill check");
|
||||
exactRoots[i] = objNULL;
|
||||
}
|
||||
}
|
||||
/* Every other time, switch back immediately. */
|
||||
if(collections & 1) ramping = 0;
|
||||
}
|
||||
if(!ramping) {
|
||||
mps_ap_alloc_pattern_begin(ap, ramp);
|
||||
mps_ap_alloc_pattern_begin(busy_ap, ramp);
|
||||
if (begin_ramp) {
|
||||
die(mps_ap_alloc_pattern_begin(ap, ramp),
|
||||
"pattern rebegin (ap)");
|
||||
die(mps_ap_alloc_pattern_begin(busy_ap, ramp),
|
||||
"pattern rebegin (busy_ap)");
|
||||
ramping = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r = (size_t)rnd();
|
||||
if(r & 1) {
|
||||
if (r & 1) {
|
||||
i = (r >> 1) % exactRootsCOUNT;
|
||||
if(exactRoots[i] != objNULL)
|
||||
if (exactRoots[i] != objNULL)
|
||||
cdie(dylan_check(exactRoots[i]), "dying root check");
|
||||
exactRoots[i] = make();
|
||||
if(exactRoots[(exactRootsCOUNT-1) - i] != objNULL)
|
||||
if (exactRoots[(exactRootsCOUNT-1) - i] != objNULL)
|
||||
dylan_write(exactRoots[(exactRootsCOUNT-1) - i],
|
||||
exactRoots, exactRootsCOUNT);
|
||||
} else {
|
||||
|
|
@ -220,10 +241,11 @@ static void *test(void *arg, size_t s)
|
|||
ambigRoots[i] = (mps_addr_t)((char *)(ambigRoots[i/2]) + 1);
|
||||
}
|
||||
|
||||
if(r % initTestFREQ == 0)
|
||||
if (r % initTestFREQ == 0)
|
||||
*(int*)busy_init = -1; /* check that the buffer is still there */
|
||||
|
||||
if(objs % 1024 == 0) {
|
||||
if (objs % 1024 == 0) {
|
||||
report(arena);
|
||||
putchar('.');
|
||||
fflush(stdout);
|
||||
}
|
||||
|
|
@ -253,7 +275,7 @@ int main(int argc, char **argv)
|
|||
|
||||
die(mps_arena_create(&arena, mps_arena_class_vm(), 2*testArenaSIZE),
|
||||
"arena_create");
|
||||
enable(arena);
|
||||
mps_message_type_enable(arena, mps_message_type_gc());
|
||||
die(mps_arena_commit_limit_set(arena, testArenaSIZE), "set limit");
|
||||
die(mps_thread_reg(&thread, arena), "thread_reg");
|
||||
mps_tramp(&r, test, arena, 0);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (c) 2002 Global Graphics Software.
|
||||
*/
|
||||
|
||||
#include "fmthe.h"
|
||||
|
|
@ -18,8 +19,12 @@
|
|||
#include <string.h>
|
||||
|
||||
|
||||
/* These values have been tuned to cause one top-generation collection. */
|
||||
#define testArenaSIZE ((size_t)1400*1024)
|
||||
/* These values have been tuned in the hope of getting one dynamic collection. */
|
||||
#define headerFACTOR ((float)(20 + headerSIZE) / 20)
|
||||
/* headerFACTOR measures how much larger objects are compared to fmtdy. */
|
||||
#define testArenaSIZE ((size_t)(1000*headerFACTOR)*1024)
|
||||
#define gen1SIZE ((size_t)150*headerFACTOR)
|
||||
#define gen2SIZE ((size_t)170*headerFACTOR)
|
||||
#define avLEN 3
|
||||
#define exactRootsCOUNT 200
|
||||
#define ambigRootsCOUNT 50
|
||||
|
|
@ -32,7 +37,7 @@
|
|||
/* testChain -- generation parameters for the test */
|
||||
|
||||
static mps_gen_param_s testChain[genCOUNT] = {
|
||||
{ 210, 0.85 }, { 248, 0.45 } };
|
||||
{ gen1SIZE, 0.85 }, { gen2SIZE, 0.45 } };
|
||||
|
||||
|
||||
/* objNULL needs to be odd so that it's ignored in exactRoots. */
|
||||
|
|
@ -68,6 +73,36 @@ static mps_addr_t make(void)
|
|||
}
|
||||
|
||||
|
||||
/* report - report statistics from any terminated GCs */
|
||||
|
||||
static void report(mps_arena_t arena)
|
||||
{
|
||||
mps_message_t message;
|
||||
static int nCollections = 0;
|
||||
|
||||
while (mps_message_get(&message, arena, mps_message_type_gc())) {
|
||||
size_t live, condemned, not_condemned;
|
||||
|
||||
live = mps_message_gc_live_size(arena, message);
|
||||
condemned = mps_message_gc_condemned_size(arena, message);
|
||||
not_condemned = mps_message_gc_not_condemned_size(arena, message);
|
||||
|
||||
printf("\nCollection %d finished:\n", ++nCollections);
|
||||
printf("live %lu\n", (unsigned long)live);
|
||||
printf("condemned %lu\n", (unsigned long)condemned);
|
||||
printf("not_condemned %lu\n", (unsigned long)not_condemned);
|
||||
|
||||
mps_message_discard(arena, message);
|
||||
|
||||
if (condemned > (gen1SIZE + gen2SIZE + (size_t)128) * 1024)
|
||||
/* When condemned size is larger than could happen in a gen 2
|
||||
* collection (discounting ramps, natch), guess that was a dynamic
|
||||
* collection, and reset the commit limit, so it doesn't run out. */
|
||||
die(mps_arena_commit_limit_set(arena, 2 * testArenaSIZE), "set limit");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* test -- the body of the test */
|
||||
|
||||
static void *test(void *arg, size_t s)
|
||||
|
|
@ -98,7 +133,7 @@ static void *test(void *arg, size_t s)
|
|||
for(i = 0; i < exactRootsCOUNT; ++i)
|
||||
exactRoots[i] = objNULL;
|
||||
for(i = 0; i < ambigRootsCOUNT; ++i)
|
||||
ambigRoots[i] = (mps_addr_t)rnd();
|
||||
ambigRoots[i] = rnd_addr();
|
||||
|
||||
die(mps_root_create_table_masked(&exactRoot, arena,
|
||||
MPS_RANK_EXACT, (mps_rm_t)0,
|
||||
|
|
@ -119,11 +154,11 @@ static void *test(void *arg, size_t s)
|
|||
|
||||
collections = 0;
|
||||
rampSwitch = rampSIZE;
|
||||
mps_ap_alloc_pattern_begin(ap, ramp);
|
||||
mps_ap_alloc_pattern_begin(busy_ap, ramp);
|
||||
die(mps_ap_alloc_pattern_begin(ap, ramp), "pattern begin (ap)");
|
||||
die(mps_ap_alloc_pattern_begin(busy_ap, ramp), "pattern begin (busy_ap)");
|
||||
ramping = 1;
|
||||
objs = 0;
|
||||
while(collections < collectionsCOUNT) {
|
||||
while (collections < collectionsCOUNT) {
|
||||
unsigned long c;
|
||||
size_t r;
|
||||
|
||||
|
|
@ -132,15 +167,20 @@ static void *test(void *arg, size_t s)
|
|||
if (collections != c) {
|
||||
collections = c;
|
||||
printf("\nCollection %lu, %lu objects.\n", c, objs);
|
||||
for(r = 0; r < exactRootsCOUNT; ++r) {
|
||||
report(arena);
|
||||
for (r = 0; r < exactRootsCOUNT; ++r) {
|
||||
if (exactRoots[r] != objNULL)
|
||||
die(HeaderFormatCheck(exactRoots[r]), "wrapper check");
|
||||
}
|
||||
if (collections == rampSwitch) {
|
||||
int begin_ramp = !ramping
|
||||
|| /* Every other time, switch back immediately. */ (collections & 1);
|
||||
|
||||
rampSwitch += rampSIZE;
|
||||
if (ramping) {
|
||||
mps_ap_alloc_pattern_end(ap, ramp);
|
||||
mps_ap_alloc_pattern_end(busy_ap, ramp);
|
||||
die(mps_ap_alloc_pattern_end(ap, ramp), "pattern end (ap)");
|
||||
die(mps_ap_alloc_pattern_end(busy_ap, ramp), "pattern end (busy_ap)");
|
||||
ramping = 0;
|
||||
/* kill half of the roots */
|
||||
for(i = 0; i < exactRootsCOUNT; i += 2) {
|
||||
if (exactRoots[i] != objNULL) {
|
||||
|
|
@ -148,12 +188,12 @@ static void *test(void *arg, size_t s)
|
|||
exactRoots[i] = objNULL;
|
||||
}
|
||||
}
|
||||
/* Every other time, switch back immediately. */
|
||||
if (collections & 1) ramping = 0;
|
||||
}
|
||||
if (!ramping) {
|
||||
mps_ap_alloc_pattern_begin(ap, ramp);
|
||||
mps_ap_alloc_pattern_begin(busy_ap, ramp);
|
||||
if (begin_ramp) {
|
||||
die(mps_ap_alloc_pattern_begin(ap, ramp),
|
||||
"pattern rebegin (ap)");
|
||||
die(mps_ap_alloc_pattern_begin(busy_ap, ramp),
|
||||
"pattern rebegin (busy_ap)");
|
||||
ramping = 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -187,6 +227,7 @@ static void *test(void *arg, size_t s)
|
|||
*(int*)busy_init = -1; /* check that the buffer is still there */
|
||||
|
||||
if (objs % 1024 == 0) {
|
||||
report(arena);
|
||||
putchar('.');
|
||||
fflush(stdout);
|
||||
}
|
||||
|
|
@ -218,6 +259,7 @@ int main(int argc, char **argv)
|
|||
|
||||
die(mps_arena_create(&arena, mps_arena_class_vm(), 3*testArenaSIZE),
|
||||
"arena_create\n");
|
||||
mps_message_type_enable(arena, mps_message_type_gc());
|
||||
die(mps_arena_commit_limit_set(arena, testArenaSIZE), "set limit");
|
||||
die(mps_thread_reg(&thread, arena), "thread_reg");
|
||||
mps_tramp(&r, test, arena, 0);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (c) 2002 Global Graphics Software.
|
||||
*
|
||||
* .posix: This is Posix only.
|
||||
*/
|
||||
|
|
@ -12,21 +13,18 @@
|
|||
#include "testlib.h"
|
||||
#include "mpscamc.h"
|
||||
#include "mpsavm.h"
|
||||
#include "mpstd.h"
|
||||
#ifdef MPS_OS_W3
|
||||
#include "mpsw3.h"
|
||||
#endif
|
||||
#include "mps.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
/* These values have been tuned to cause one top-generation collection. */
|
||||
/* These values have been tuned in the hope of getting one dynamic collection. */
|
||||
#define testArenaSIZE ((size_t)1000*1024)
|
||||
#define gen1SIZE ((size_t)150)
|
||||
#define gen2SIZE ((size_t)170)
|
||||
#define avLEN 3
|
||||
#define exactRootsCOUNT 200
|
||||
#define exactRootsCOUNT 180
|
||||
#define ambigRootsCOUNT 50
|
||||
#define genCOUNT 2
|
||||
#define collectionsCOUNT 37
|
||||
|
|
@ -36,7 +34,7 @@
|
|||
/* testChain -- generation parameters for the test */
|
||||
|
||||
static mps_gen_param_s testChain[genCOUNT] = {
|
||||
{ 150, 0.85 }, { 170, 0.45 } };
|
||||
{ gen1SIZE, 0.85 }, { gen2SIZE, 0.45 } };
|
||||
|
||||
|
||||
/* objNULL needs to be odd so that it's ignored in exactRoots. */
|
||||
|
|
@ -54,6 +52,38 @@ mps_root_t exactRoot, ambigRoot;
|
|||
unsigned long objs = 0;
|
||||
|
||||
|
||||
/* report - report statistics from any terminated GCs */
|
||||
|
||||
static void report(mps_arena_t arena)
|
||||
{
|
||||
mps_message_t message;
|
||||
static int nCollections = 0;
|
||||
|
||||
while (mps_message_get(&message, arena, mps_message_type_gc())) {
|
||||
size_t live, condemned, not_condemned;
|
||||
|
||||
live = mps_message_gc_live_size(arena, message);
|
||||
condemned = mps_message_gc_condemned_size(arena, message);
|
||||
not_condemned = mps_message_gc_not_condemned_size(arena, message);
|
||||
|
||||
printf("\nCollection %d finished:\n", ++nCollections);
|
||||
printf("live %lu\n", (unsigned long)live);
|
||||
printf("condemned %lu\n", (unsigned long)condemned);
|
||||
printf("not_condemned %lu\n", (unsigned long)not_condemned);
|
||||
|
||||
mps_message_discard(arena, message);
|
||||
|
||||
if (condemned > (gen1SIZE + gen2SIZE + (size_t)128) * 1024)
|
||||
/* When condemned size is larger than could happen in a gen 2
|
||||
* collection (discounting ramps, natch), guess that was a dynamic
|
||||
* collection, and reset the commit limit, so it doesn't run out. */
|
||||
die(mps_arena_commit_limit_set(arena, 2 * testArenaSIZE), "set limit");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* make -- create one new object */
|
||||
|
||||
static mps_addr_t make(mps_ap_t ap)
|
||||
{
|
||||
size_t length = rnd() % (2*avLEN);
|
||||
|
|
@ -74,11 +104,14 @@ static mps_addr_t make(mps_ap_t ap)
|
|||
}
|
||||
|
||||
|
||||
static void test_stepper(mps_addr_t object, void *p, size_t s)
|
||||
/* test_stepper -- stepping function for walk */
|
||||
|
||||
static void test_stepper(mps_addr_t object, mps_fmt_t fmt, mps_pool_t pol,
|
||||
void *p, size_t s)
|
||||
{
|
||||
(*(unsigned long *)p)++;
|
||||
testlib_unused(object); testlib_unused(fmt); testlib_unused(pol);
|
||||
testlib_unused(s);
|
||||
testlib_unused(object);
|
||||
(*(unsigned long *)p)++;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -97,7 +130,7 @@ static void init(void)
|
|||
for(i = 0; i < exactRootsCOUNT; ++i)
|
||||
exactRoots[i] = objNULL;
|
||||
for(i = 0; i < ambigRootsCOUNT; ++i)
|
||||
ambigRoots[i] = (mps_addr_t)rnd();
|
||||
ambigRoots[i] = rnd_addr();
|
||||
|
||||
die(mps_root_create_table_masked(&exactRoot, arena,
|
||||
MPS_RANK_EXACT, (mps_rm_t)0,
|
||||
|
|
@ -171,10 +204,10 @@ static void *test(void *arg, size_t s)
|
|||
|
||||
collections = 0;
|
||||
rampSwitch = rampSIZE;
|
||||
mps_ap_alloc_pattern_begin(ap, ramp);
|
||||
mps_ap_alloc_pattern_begin(busy_ap, ramp);
|
||||
die(mps_ap_alloc_pattern_begin(ap, ramp), "pattern begin (ap)");
|
||||
die(mps_ap_alloc_pattern_begin(busy_ap, ramp), "pattern begin (busy_ap)");
|
||||
ramping = 1;
|
||||
while(collections < collectionsCOUNT) {
|
||||
while (collections < collectionsCOUNT) {
|
||||
unsigned long c;
|
||||
size_t r;
|
||||
|
||||
|
|
@ -182,23 +215,29 @@ static void *test(void *arg, size_t s)
|
|||
|
||||
if (collections != c) {
|
||||
collections = c;
|
||||
printf("\nCollection %lu, %lu objects.\n",
|
||||
c, objs);
|
||||
for(r = 0; r < exactRootsCOUNT; ++r)
|
||||
cdie(exactRoots[r] == objNULL || dylan_check(exactRoots[r]),
|
||||
printf("\nCollection %lu started, %lu objects.\n", c, objs);
|
||||
report(arena);
|
||||
|
||||
for (i = 0; i < exactRootsCOUNT; ++i)
|
||||
cdie(exactRoots[i] == objNULL || dylan_check(exactRoots[i]),
|
||||
"all roots check");
|
||||
|
||||
if (collections == collectionsCOUNT / 2) {
|
||||
unsigned long object_count = 0;
|
||||
mps_arena_park(arena);
|
||||
mps_amc_apply(pool, test_stepper, &object_count, 0);
|
||||
mps_arena_formatted_objects_walk(arena, test_stepper, &object_count, 0);
|
||||
mps_arena_release(arena);
|
||||
printf("mps_amc_apply stepped on %lu objects.\n", object_count);
|
||||
printf("stepped on %lu objects.\n", object_count);
|
||||
}
|
||||
if (collections == rampSwitch) {
|
||||
int begin_ramp = !ramping
|
||||
|| /* Every other time, switch back immediately. */ (collections & 1);
|
||||
|
||||
rampSwitch += rampSIZE;
|
||||
if (ramping) {
|
||||
mps_ap_alloc_pattern_end(ap, ramp);
|
||||
mps_ap_alloc_pattern_end(busy_ap, ramp);
|
||||
die(mps_ap_alloc_pattern_end(ap, ramp), "pattern end (ap)");
|
||||
die(mps_ap_alloc_pattern_end(busy_ap, ramp), "pattern end (busy_ap)");
|
||||
ramping = 0;
|
||||
/* kill half of the roots */
|
||||
for(i = 0; i < exactRootsCOUNT; i += 2) {
|
||||
if (exactRoots[i] != objNULL) {
|
||||
|
|
@ -206,12 +245,12 @@ static void *test(void *arg, size_t s)
|
|||
exactRoots[i] = objNULL;
|
||||
}
|
||||
}
|
||||
/* Every other time, switch back immediately. */
|
||||
if (collections & 1) ramping = 0;
|
||||
}
|
||||
if (!ramping) {
|
||||
mps_ap_alloc_pattern_begin(ap, ramp);
|
||||
mps_ap_alloc_pattern_begin(busy_ap, ramp);
|
||||
if (begin_ramp) {
|
||||
die(mps_ap_alloc_pattern_begin(ap, ramp),
|
||||
"pattern rebegin (ap)");
|
||||
die(mps_ap_alloc_pattern_begin(busy_ap, ramp),
|
||||
"pattern rebegin (busy_ap)");
|
||||
ramping = 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -223,6 +262,7 @@ static void *test(void *arg, size_t s)
|
|||
*(int*)busy_init = -1; /* check that the buffer is still there */
|
||||
|
||||
if (objs % 1024 == 0) {
|
||||
report(arena);
|
||||
putchar('.');
|
||||
fflush(stdout);
|
||||
}
|
||||
|
|
@ -278,6 +318,7 @@ int main(int argc, char **argv)
|
|||
|
||||
die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE),
|
||||
"arena_create");
|
||||
mps_message_type_enable(arena, mps_message_type_gc());
|
||||
init();
|
||||
die(mps_thread_reg(&thread, arena), "thread_reg");
|
||||
pthread_create(&pthread1, NULL, fooey, (void *)&childIsFinished);
|
||||
|
|
@ -290,6 +331,7 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
finish();
|
||||
report(arena);
|
||||
mps_arena_destroy(arena);
|
||||
|
||||
fflush(stdout); /* synchronize */
|
||||
|
|
|
|||
107
mps/code/amsss.c
107
mps/code/amsss.c
|
|
@ -2,11 +2,11 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (c) 2002 Global Graphics Software.
|
||||
*
|
||||
* .design: Adapted from amcss.c, but not counting collections, just
|
||||
* total size of objects allocated (because epoch doesn't increment
|
||||
* when AMS is collected).
|
||||
*/
|
||||
* total size of objects allocated (because epoch doesn't increment when
|
||||
* AMS is collected). */
|
||||
|
||||
#include "fmtdy.h"
|
||||
#include "fmtdytst.h"
|
||||
|
|
@ -32,17 +32,20 @@
|
|||
/* objNULL needs to be odd so that it's ignored in exactRoots. */
|
||||
#define objNULL ((mps_addr_t)0xDECEA5ED)
|
||||
#define testArenaSIZE ((size_t)16<<20)
|
||||
#define initTestFREQ 6000
|
||||
#define initTestFREQ 3000
|
||||
#define splatTestFREQ 6000
|
||||
static mps_gen_param_s testChain[1] = { { 160, 0.90 } };
|
||||
|
||||
|
||||
static mps_pool_t pool;
|
||||
static mps_arena_t arena;
|
||||
static mps_ap_t ap;
|
||||
static mps_addr_t exactRoots[exactRootsCOUNT];
|
||||
static mps_addr_t ambigRoots[ambigRootsCOUNT];
|
||||
static size_t totalSize = 0;
|
||||
|
||||
|
||||
/* make -- object allocation and init */
|
||||
|
||||
static mps_addr_t make(void)
|
||||
{
|
||||
size_t length = rnd() % 20, size = (length+2) * sizeof(mps_word_t);
|
||||
|
|
@ -51,10 +54,10 @@ static mps_addr_t make(void)
|
|||
|
||||
do {
|
||||
MPS_RESERVE_BLOCK(res, p, ap, size);
|
||||
if(res)
|
||||
if (res)
|
||||
die(res, "MPS_RESERVE_BLOCK");
|
||||
res = dylan_init(p, size, exactRoots, exactRootsCOUNT);
|
||||
if(res)
|
||||
if (res)
|
||||
die(res, "dylan_init");
|
||||
} while(!mps_commit(ap, p, size));
|
||||
|
||||
|
|
@ -63,49 +66,48 @@ static mps_addr_t make(void)
|
|||
}
|
||||
|
||||
|
||||
static void *test(void *arg, size_t s)
|
||||
/* test -- the actual stress test */
|
||||
|
||||
static mps_pool_debug_option_s freecheckOptions =
|
||||
{ NULL, 0, (void *)"Dead", 4 };
|
||||
|
||||
static void *test(void *arg, size_t haveAmbigous)
|
||||
{
|
||||
mps_arena_t arena;
|
||||
mps_fmt_t format;
|
||||
mps_chain_t chain;
|
||||
mps_pool_t pool;
|
||||
mps_root_t exactRoot, ambigRoot;
|
||||
size_t lastStep = 0, i, r;
|
||||
unsigned long objs;
|
||||
mps_ap_t busy_ap;
|
||||
mps_addr_t busy_init;
|
||||
|
||||
arena = (mps_arena_t)arg;
|
||||
(void)s; /* unused */
|
||||
|
||||
die(mps_fmt_create_A(&format, arena, dylan_fmt_A()), "fmt_create");
|
||||
die(mps_chain_create(&chain, arena, 1, testChain), "chain_create");
|
||||
die(mps_pool_create(&pool, arena, mps_class_ams(), format, chain),
|
||||
"pool_create(ams)");
|
||||
pool = (mps_pool_t)arg;
|
||||
|
||||
die(mps_ap_create(&ap, pool, MPS_RANK_EXACT), "BufferCreate");
|
||||
die(mps_ap_create(&busy_ap, pool, MPS_RANK_EXACT), "BufferCreate 2");
|
||||
|
||||
for(i = 0; i < exactRootsCOUNT; ++i)
|
||||
exactRoots[i] = objNULL;
|
||||
for(i = 0; i < ambigRootsCOUNT; ++i)
|
||||
ambigRoots[i] = (mps_addr_t)rnd();
|
||||
if (haveAmbigous)
|
||||
for(i = 0; i < ambigRootsCOUNT; ++i)
|
||||
ambigRoots[i] = rnd_addr();
|
||||
|
||||
die(mps_root_create_table_masked(&exactRoot, arena,
|
||||
MPS_RANK_EXACT, (mps_rm_t)0,
|
||||
&exactRoots[0], exactRootsCOUNT,
|
||||
(mps_word_t)1),
|
||||
"root_create_table(exact)");
|
||||
die(mps_root_create_table(&ambigRoot, arena,
|
||||
MPS_RANK_AMBIG, (mps_rm_t)0,
|
||||
&ambigRoots[0], ambigRootsCOUNT),
|
||||
"root_create_table(ambig)");
|
||||
if (haveAmbigous)
|
||||
die(mps_root_create_table(&ambigRoot, arena,
|
||||
MPS_RANK_AMBIG, (mps_rm_t)0,
|
||||
&ambigRoots[0], ambigRootsCOUNT),
|
||||
"root_create_table(ambig)");
|
||||
|
||||
/* create an ap, and leave it busy */
|
||||
die(mps_reserve(&busy_init, busy_ap, 64), "mps_reserve busy");
|
||||
|
||||
objs = 0;
|
||||
objs = 0; totalSize = 0;
|
||||
while(totalSize < totalSizeMAX) {
|
||||
if(totalSize > lastStep + totalSizeSTEP) {
|
||||
if (totalSize > lastStep + totalSizeSTEP) {
|
||||
lastStep = totalSize;
|
||||
printf("\nSize %lu bytes, %lu objects.\n",
|
||||
(unsigned long)totalSize, objs);
|
||||
|
|
@ -116,12 +118,12 @@ static void *test(void *arg, size_t s)
|
|||
}
|
||||
|
||||
r = (size_t)rnd();
|
||||
if(r & 1) {
|
||||
if (!haveAmbigous || (r & 1)) {
|
||||
i = (r >> 1) % exactRootsCOUNT;
|
||||
if(exactRoots[i] != objNULL)
|
||||
if (exactRoots[i] != objNULL)
|
||||
cdie(dylan_check(exactRoots[i]), "dying root check");
|
||||
exactRoots[i] = make();
|
||||
if(exactRoots[(exactRootsCOUNT-1) - i] != objNULL)
|
||||
if (exactRoots[(exactRootsCOUNT-1) - i] != objNULL)
|
||||
dylan_write(exactRoots[(exactRootsCOUNT-1) - i],
|
||||
exactRoots, exactRootsCOUNT);
|
||||
} else {
|
||||
|
|
@ -131,9 +133,12 @@ static void *test(void *arg, size_t s)
|
|||
ambigRoots[i] = (mps_addr_t)((char *)(ambigRoots[i/2]) + 1);
|
||||
}
|
||||
|
||||
if(rnd() % initTestFREQ == 0)
|
||||
if (rnd() % initTestFREQ == 0)
|
||||
*(int*)busy_init = -1; /* check that the buffer is still there */
|
||||
|
||||
if (rnd() % splatTestFREQ == 0)
|
||||
mps_pool_check_free_space(pool);
|
||||
|
||||
++objs;
|
||||
if (objs % 256 == 0) {
|
||||
printf(".");
|
||||
|
|
@ -145,10 +150,8 @@ static void *test(void *arg, size_t s)
|
|||
mps_ap_destroy(busy_ap);
|
||||
mps_ap_destroy(ap);
|
||||
mps_root_destroy(exactRoot);
|
||||
mps_root_destroy(ambigRoot);
|
||||
mps_pool_destroy(pool);
|
||||
mps_chain_destroy(chain);
|
||||
mps_fmt_destroy(format);
|
||||
if (haveAmbigous)
|
||||
mps_root_destroy(ambigRoot);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -156,8 +159,10 @@ static void *test(void *arg, size_t s)
|
|||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
mps_arena_t arena;
|
||||
mps_thr_t thread;
|
||||
mps_fmt_t format;
|
||||
mps_chain_t chain;
|
||||
mps_pool_t pool;
|
||||
void *r;
|
||||
|
||||
randomize(argc, argv);
|
||||
|
|
@ -165,7 +170,37 @@ int main(int argc, char **argv)
|
|||
die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE),
|
||||
"arena_create");
|
||||
die(mps_thread_reg(&thread, arena), "thread_reg");
|
||||
mps_tramp(&r, test, arena, 0);
|
||||
die(mps_fmt_create_A(&format, arena, dylan_fmt_A()), "fmt_create");
|
||||
die(mps_chain_create(&chain, arena, 1, testChain), "chain_create");
|
||||
|
||||
printf("\nAMS Debug\n");
|
||||
die(mps_pool_create(&pool, arena, mps_class_ams_debug(), &freecheckOptions,
|
||||
format, chain, FALSE),
|
||||
"pool_create(ams_debug,share)");
|
||||
mps_tramp(&r, test, pool, 0);
|
||||
mps_pool_destroy(pool);
|
||||
|
||||
printf("\nAMS Debug\n");
|
||||
die(mps_pool_create(&pool, arena, mps_class_ams_debug(), &freecheckOptions,
|
||||
format, chain, TRUE),
|
||||
"pool_create(ams_debug,ambig)");
|
||||
mps_tramp(&r, test, pool, 1);
|
||||
mps_pool_destroy(pool);
|
||||
|
||||
printf("\nAMS\n");
|
||||
die(mps_pool_create(&pool, arena, mps_class_ams(), format, chain, TRUE),
|
||||
"pool_create(ams,ambig)");
|
||||
mps_tramp(&r, test, pool, 1);
|
||||
mps_pool_destroy(pool);
|
||||
|
||||
printf("\nAMS\n");
|
||||
die(mps_pool_create(&pool, arena, mps_class_ams(), format, chain, FALSE),
|
||||
"pool_create(ams,share)");
|
||||
mps_tramp(&r, test, pool, 0);
|
||||
mps_pool_destroy(pool);
|
||||
|
||||
mps_chain_destroy(chain);
|
||||
mps_fmt_destroy(format);
|
||||
mps_thread_dereg(thread);
|
||||
mps_arena_destroy(arena);
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ static mps_addr_t make(void)
|
|||
res = dylan_init(userP, size, exactRoots, exactRootsCOUNT);
|
||||
if(res)
|
||||
die(res, "dylan_init");
|
||||
((int*)p)[0] = realTYPE;
|
||||
((int*)p)[0] = realHeader;
|
||||
((int*)p)[1] = 0xED0ED;
|
||||
} while(!mps_commit(ap, p, size + headerSIZE));
|
||||
|
||||
|
|
@ -80,8 +80,8 @@ static void *test(void *arg, size_t s)
|
|||
|
||||
die(EnsureHeaderFormat(&format, arena), "make header format");
|
||||
die(mps_chain_create(&chain, arena, 1, testChain), "chain_create");
|
||||
die(mps_pool_create(&pool, arena, mps_class_ams(), format, chain),
|
||||
"pool_create(ams)");
|
||||
die(mps_pool_create(&pool, arena, mps_class_ams(), format, chain,
|
||||
TRUE), "pool_create(ams)");
|
||||
|
||||
die(mps_ap_create(&ap, pool, MPS_RANK_EXACT), "BufferCreate");
|
||||
die(mps_ap_create(&busy_ap, pool, MPS_RANK_EXACT), "BufferCreate 2");
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (C) 2002 Global Graphics Software.
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -21,6 +22,8 @@
|
|||
#define testLOOPS 10
|
||||
|
||||
|
||||
/* make -- allocate one object */
|
||||
|
||||
static mps_res_t make(mps_addr_t *p, mps_ap_t ap, size_t size)
|
||||
{
|
||||
mps_res_t res;
|
||||
|
|
@ -35,8 +38,10 @@ static mps_res_t make(mps_addr_t *p, mps_ap_t ap, size_t size)
|
|||
}
|
||||
|
||||
|
||||
static mps_res_t stress(mps_class_t class, mps_arena_t arena,
|
||||
size_t (*size)(int i), ...)
|
||||
/* stress -- create a pool of the requested type and allocate in it */
|
||||
|
||||
static mps_res_t stress(mps_class_t class, size_t (*size)(int i),
|
||||
mps_arena_t arena, ...)
|
||||
{
|
||||
mps_res_t res = MPS_RES_OK;
|
||||
mps_pool_t pool;
|
||||
|
|
@ -46,7 +51,7 @@ static mps_res_t stress(mps_class_t class, mps_arena_t arena,
|
|||
int *ps[testSetSIZE];
|
||||
size_t ss[testSetSIZE];
|
||||
|
||||
va_start(arg, size);
|
||||
va_start(arg, arena);
|
||||
res = mps_pool_create_v(&pool, arena, class, arg);
|
||||
va_end(arg);
|
||||
if (res != MPS_RES_OK)
|
||||
|
|
@ -107,6 +112,9 @@ allocFail:
|
|||
|
||||
#define alignUp(w, a) (((w) + (a) - 1) & ~((size_t)(a) - 1))
|
||||
|
||||
|
||||
/* randomSize8 -- produce sizes both latge and small, 8-byte aligned */
|
||||
|
||||
static size_t randomSize8(int i)
|
||||
{
|
||||
size_t maxSize = 2 * 160 * 0x2000;
|
||||
|
|
@ -115,24 +123,32 @@ static size_t randomSize8(int i)
|
|||
}
|
||||
|
||||
|
||||
static mps_pool_debug_option_s debugOptions = { (void *)"postpost", 8 };
|
||||
/* testInArena -- test all the pool classes in the given arena */
|
||||
|
||||
static void testInArena(mps_arena_t arena)
|
||||
static mps_pool_debug_option_s bothOptions =
|
||||
{ (void *)"postpost", 8, (void *)"DEAD", 4 };
|
||||
|
||||
static mps_pool_debug_option_s fenceOptions =
|
||||
{ (void *)"\0XXX ''\"\"'' XXX\0", 16, NULL, 0 };
|
||||
|
||||
static void testInArena(mps_arena_t arena, mps_pool_debug_option_s *options)
|
||||
{
|
||||
mps_res_t res;
|
||||
|
||||
/* IWBN to test MVFFDebug, but the MPS doesn't support debugging APs, */
|
||||
/* yet (MV Debug works here, because it fakes it through PoolAlloc). */
|
||||
printf("MVFF\n\n");
|
||||
res = stress(mps_class_mvff(), arena, randomSize8,
|
||||
res = stress(mps_class_mvff(), randomSize8, arena,
|
||||
(size_t)65536, (size_t)32, (size_t)4, TRUE, TRUE, TRUE);
|
||||
if (res == MPS_RES_COMMIT_LIMIT) return;
|
||||
die(res, "stress MVFF");
|
||||
printf("MV debug\n\n");
|
||||
res = stress(mps_class_mv_debug(), arena, randomSize8,
|
||||
&debugOptions, (size_t)65536, (size_t)32, (size_t)65536);
|
||||
res = stress(mps_class_mv_debug(), randomSize8, arena,
|
||||
options, (size_t)65536, (size_t)32, (size_t)65536);
|
||||
if (res == MPS_RES_COMMIT_LIMIT) return;
|
||||
die(res, "stress MV debug");
|
||||
printf("MV\n\n");
|
||||
res = stress(mps_class_mv(), arena, randomSize8,
|
||||
res = stress(mps_class_mv(), randomSize8, arena,
|
||||
(size_t)65536, (size_t)32, (size_t)65536);
|
||||
if (res == MPS_RES_COMMIT_LIMIT) return;
|
||||
die(res, "stress MV");
|
||||
|
|
@ -147,13 +163,13 @@ int main(int argc, char **argv)
|
|||
|
||||
die(mps_arena_create(&arena, mps_arena_class_vm(), 2*testArenaSIZE),
|
||||
"mps_arena_create");
|
||||
mps_arena_commit_limit_set(arena, testArenaSIZE);
|
||||
testInArena(arena);
|
||||
die(mps_arena_commit_limit_set(arena, testArenaSIZE), "commit limit");
|
||||
testInArena(arena, &fenceOptions);
|
||||
mps_arena_destroy(arena);
|
||||
|
||||
die(mps_arena_create(&arena, mps_arena_class_vmnz(), 2*testArenaSIZE),
|
||||
"mps_arena_create");
|
||||
testInArena(arena);
|
||||
testInArena(arena, &bothOptions);
|
||||
mps_arena_destroy(arena);
|
||||
|
||||
fflush(stdout); /* synchronize */
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ SRCID(arena, "$Id$");
|
|||
|
||||
/* ArenaControlPool -- get the control pool */
|
||||
|
||||
#define ArenaControlPool(arena) MVPool(&(arena)->controlPoolStruct)
|
||||
#define ArenaControlPool(arena) MV2Pool(&(arena)->controlPoolStruct)
|
||||
|
||||
|
||||
/* ArenaTrivDescribe -- produce trivial description of an arena */
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "boot.h"
|
||||
#include "tract.h"
|
||||
#include "bt.h"
|
||||
#include "mpm.h"
|
||||
#include "mpsacl.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "boot.h"
|
||||
#include "tract.h"
|
||||
#include "bt.h"
|
||||
#include "mpm.h"
|
||||
#include "mpsavm.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,32 +0,0 @@
|
|||
/* impl.c.arenavmx: STUBS FOR ARENAVM
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
*
|
||||
* .purpose: This file is not properly part of the MPS. It is a
|
||||
* convenience file for EP-Core who do _not_ wish to get a link error,
|
||||
* when they link to a VM arena function on a platform where it isn't
|
||||
* supported (see req.epcore.link.no-error).
|
||||
*
|
||||
* .stub: This file provides stub functions for the VM arena class
|
||||
* functions. Calling any of them causes a run-time assertion.
|
||||
*/
|
||||
|
||||
|
||||
#include "mpm.h"
|
||||
#include "mpsavm.h"
|
||||
|
||||
SRCID(arenavmx, "$Id$");
|
||||
|
||||
|
||||
mps_arena_class_t mps_arena_class_vm(void)
|
||||
{
|
||||
NOTREACHED;
|
||||
return (mps_arena_class_t)NULL;
|
||||
}
|
||||
|
||||
mps_arena_class_t mps_arena_class_vmnz(void)
|
||||
{
|
||||
NOTREACHED;
|
||||
return (mps_arena_class_t)NULL;
|
||||
}
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
/* impl.c.assert: ASSERTION IMPLEMENTATION
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
*
|
||||
* This source provides the AssertFail function which is
|
||||
* invoked by the assertion macros (see impl.h.assert).
|
||||
* It also provides for user-installed assertion failure handlers.
|
||||
*/
|
||||
|
||||
#include "check.h"
|
||||
#include "mpm.h"
|
||||
|
||||
SRCID(assert, "$Id$");
|
||||
|
||||
|
||||
/* CheckLevel -- Control check level
|
||||
*
|
||||
* This controls the behaviour of Check methods unless MPS_HOT_RED
|
||||
* is defined, when it is effectively stuck at "CheckNONE".
|
||||
*/
|
||||
|
||||
unsigned CheckLevel = CheckSHALLOW;
|
||||
|
||||
|
||||
static void AssertLib(const char *cond, const char *id,
|
||||
const char *file, unsigned line)
|
||||
{
|
||||
WriteF(mps_lib_stderr,
|
||||
"\n"
|
||||
"MPS ASSERTION FAILURE\n"
|
||||
"\n"
|
||||
"Id: $S\n", id,
|
||||
"File: $S\n", file,
|
||||
"Line: $U\n", (WriteFU)line,
|
||||
"Condition: $S\n", cond,
|
||||
"\n",
|
||||
NULL);
|
||||
|
||||
mps_lib_abort();
|
||||
}
|
||||
|
||||
|
||||
static AssertHandler handler = &AssertLib;
|
||||
|
||||
|
||||
AssertHandler AssertDefault(void)
|
||||
{
|
||||
return &AssertLib;
|
||||
}
|
||||
|
||||
|
||||
AssertHandler AssertInstall(AssertHandler new)
|
||||
{
|
||||
AssertHandler prev = handler;
|
||||
handler = new;
|
||||
return prev;
|
||||
}
|
||||
|
||||
|
||||
/* AssertFail -- fail an assertion
|
||||
*
|
||||
* This function is called when an ASSERT macro fails a test. It
|
||||
* calls the installed assertion handler, if it is not NULL. If
|
||||
* handler returns the progam continues.
|
||||
*/
|
||||
void AssertFail1(const char *s)
|
||||
{
|
||||
if (handler != NULL)
|
||||
(*handler)(s, "", "", 0);
|
||||
}
|
||||
|
|
@ -12,9 +12,11 @@
|
|||
* .design: see design.mps.bt
|
||||
*/
|
||||
|
||||
#include "bt.h"
|
||||
#include "config.h"
|
||||
#include "check.h"
|
||||
#include "mpm.h"
|
||||
|
||||
|
||||
SRCID(bt, "$Id$");
|
||||
|
||||
|
||||
|
|
@ -999,3 +1001,18 @@ void BTCopyOffsetRange(BT fromBT, BT toBT,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* BTCountResRange -- count number of reset bits in a range */
|
||||
|
||||
Count BTCountResRange(BT bt, Index base, Index limit)
|
||||
{
|
||||
Count c = 0;
|
||||
Index bit;
|
||||
|
||||
AVER(BTCheck(bt));
|
||||
AVER(base < limit);
|
||||
|
||||
for (bit = base; bit < limit; ++bit)
|
||||
if (!BTGet(bt, bit)) ++c;
|
||||
return c;
|
||||
}
|
||||
|
|
|
|||
75
mps/code/bt.h
Normal file
75
mps/code/bt.h
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/* impl.h.bt: Bit Table Interface
|
||||
*
|
||||
* $Id: bt.h,v 1.2 2002/02/01 13:52:04 pekka Exp $
|
||||
* $HopeName: MMsrc!bt.h(trunk.2) $
|
||||
* Copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* .source: design.mps.bt. */
|
||||
|
||||
#ifndef bt_h
|
||||
#define bt_h
|
||||
|
||||
#include "mpmtypes.h"
|
||||
|
||||
|
||||
/* design.mps.bt.if.size */
|
||||
extern size_t (BTSize)(unsigned long length);
|
||||
#define BTSize(n) (((n) + MPS_WORD_WIDTH-1) / MPS_WORD_WIDTH * sizeof(Word))
|
||||
|
||||
|
||||
/* design.mps.bt.if.get */
|
||||
extern Bool (BTGet)(BT bt, Index index);
|
||||
#define BTGet(a, i) \
|
||||
((Bool)(((a)[((i) >> MPS_WORD_SHIFT)] \
|
||||
>> ((i) & ~((Word)-1 << MPS_WORD_SHIFT))) \
|
||||
& (Word)1))
|
||||
|
||||
/* design.mps.bt.if.set */
|
||||
extern void (BTSet)(BT bt, Index index);
|
||||
#define BTSet(a, i) \
|
||||
BEGIN \
|
||||
(a)[((i)>>MPS_WORD_SHIFT)] |= (Word)1<<((i)&~((Word)-1<<MPS_WORD_SHIFT)); \
|
||||
END
|
||||
|
||||
/* design.mps.bt.if.res */
|
||||
extern void (BTRes)(BT bt, Index index);
|
||||
#define BTRes(a, i) \
|
||||
BEGIN \
|
||||
(a)[((i)>>MPS_WORD_SHIFT)] &= \
|
||||
~((Word)1 << ((i) & ~((Word)-1<<MPS_WORD_SHIFT))); \
|
||||
END
|
||||
|
||||
|
||||
extern Res BTCreate(BT *btReturn, Arena arena, Count length);
|
||||
extern void BTDestroy(BT bt, Arena arena, Count length);
|
||||
|
||||
extern void BTSetRange(BT bt, Index base, Index limit);
|
||||
extern Bool BTIsSetRange(BT bt, Index base, Index limit);
|
||||
extern void BTResRange(BT bt, Index base, Index limit);
|
||||
extern Bool BTIsResRange(BT bt, Index base, Index limit);
|
||||
|
||||
extern Bool BTFindShortResRange(Index *baseReturn, Index *limitReturn,
|
||||
BT bt, Index searchBase, Index searchLimit,
|
||||
unsigned long length);
|
||||
extern Bool BTFindShortResRangeHigh(Index *baseReturn, Index *limitReturn,
|
||||
BT bt, Index searchBase, Index searchLimit,
|
||||
unsigned long length);
|
||||
extern Bool BTFindLongResRange(Index *baseReturn, Index *limitReturn,
|
||||
BT bt, Index searchBase, Index searchLimit,
|
||||
unsigned long length);
|
||||
extern Bool BTFindLongResRangeHigh(Index *baseReturn, Index *limitReturn,
|
||||
BT bt, Index searchBase, Index searchLimit,
|
||||
unsigned long length);
|
||||
|
||||
extern Bool BTRangesSame(BT BTx, BT BTy, Index base, Index limit);
|
||||
|
||||
extern void BTCopyInvertRange(BT fromBT, BT toBT, Index base, Index limit);
|
||||
extern void BTCopyRange(BT fromBT, BT toBT, Index base, Index limit);
|
||||
extern void BTCopyOffsetRange(BT fromBT, BT toBT,
|
||||
Index fromBase, Index fromLimit,
|
||||
Index toBase, Index toLimit);
|
||||
|
||||
extern Count BTCountResRange(BT bt, Index base, Index limit);
|
||||
|
||||
|
||||
#endif /* bt_h */
|
||||
|
|
@ -18,7 +18,6 @@ struct itimerspec; /* stop complaints from time.h */
|
|||
#endif
|
||||
#include <time.h>
|
||||
|
||||
|
||||
SRCID(bttest, "$Id$");
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@
|
|||
#include "poolmfs.h"
|
||||
#include "mpm.h"
|
||||
|
||||
|
||||
SRCID(cbs, "$Id$");
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* .aver: This header defines a family of AVER and NOTREACHED macros.
|
||||
* These macros should be used to instrument and annotate code with
|
||||
|
|
@ -12,7 +13,7 @@
|
|||
* a comment.
|
||||
*
|
||||
* .disable: When assertions are disabled, AVER expands to something
|
||||
* which evaluates the condition but discards the result. Compilers
|
||||
* which contains the condition but discards the result. Compilers
|
||||
* will throw the code away, but check its syntax.
|
||||
*
|
||||
* .trans.level-check: CheckLevel itself is not checked anywhere.
|
||||
|
|
@ -26,7 +27,7 @@
|
|||
#include "mpslib.h"
|
||||
|
||||
|
||||
/* CheckLevel -- Control check method behaviour; see impl.c.assert */
|
||||
/* CheckLevel -- Control check method behaviour */
|
||||
|
||||
extern unsigned CheckLevel;
|
||||
|
||||
|
|
@ -39,86 +40,73 @@ enum {
|
|||
|
||||
/* AVER, AVERT -- MPM assertions
|
||||
*
|
||||
* AVER and AVERT are used to assert conditions within the MPM.
|
||||
* In white-hot varieties, all assertions compile away to nothing.
|
||||
* AVER and AVERT are used to assert conditions in the code.
|
||||
*/
|
||||
|
||||
#if defined(MPS_HOT_WHITE)
|
||||
#if defined(CHECK_NONE)
|
||||
|
||||
#define AVER(cond) DISCARD(cond)
|
||||
#define AVERT(type, val) DISCARD(type ## Check(val))
|
||||
#define AVER_CRITICAL(cond) DISCARD(cond)
|
||||
#define AVERT_CRITICAL(type, val) DISCARD(type ## Check(val))
|
||||
|
||||
#elif defined(MPS_HOT_RED)
|
||||
#elif defined(CHECK)
|
||||
|
||||
#define AVER(cond) ASSERT(cond, #cond)
|
||||
#define AVERT(type, val) ASSERT(type ## Check(val), \
|
||||
"TypeCheck " #type ": " #val)
|
||||
#define AVER_CRITICAL(cond) DISCARD(cond)
|
||||
#define AVERT_CRITICAL(type, val) DISCARD(type ## Check(val))
|
||||
|
||||
#elif defined(MPS_COOL)
|
||||
|
||||
#define AVER(cond) ASSERT(cond, #cond)
|
||||
#define AVERT(type, val) ASSERT(type ## Check(val), \
|
||||
"TypeCheck " #type ": " #val)
|
||||
#define AVER_CRITICAL(cond) ASSERT(cond, #cond)
|
||||
#define AVERT_CRITICAL(type, val) ASSERT(type ## Check(val), \
|
||||
"TypeCheck " #type ": " #val)
|
||||
"TypeCheck " #type ": " #val)
|
||||
#define AVER_CRITICAL(cond) \
|
||||
BEGIN \
|
||||
if (CheckLevel != CheckNONE) ASSERT(cond, #cond); \
|
||||
END
|
||||
#define AVERT_CRITICAL(type, val) \
|
||||
BEGIN \
|
||||
if (CheckLevel != CheckNONE) \
|
||||
ASSERT(type ## Check(val), "TypeCheck " #type ": " #val); \
|
||||
END
|
||||
|
||||
#else
|
||||
|
||||
#error "No heat defined."
|
||||
#error "No checking defined."
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* AssertHandler -- the assert handler */
|
||||
|
||||
typedef void (*AssertHandler)(const char *cond, const char *id,
|
||||
const char *file, unsigned line);
|
||||
extern AssertHandler AssertInstall(AssertHandler handler);
|
||||
extern AssertHandler AssertDefault(void);
|
||||
|
||||
|
||||
/* internals for actually asserting */
|
||||
|
||||
extern void AssertFail1(const char *s);
|
||||
|
||||
#define ASSERT(cond, condstring) \
|
||||
BEGIN \
|
||||
if(cond) NOOP; else \
|
||||
AssertFail1(condstring "\n" __FILE__ "\n" STR(__LINE__)); \
|
||||
if (cond) NOOP; else \
|
||||
mps_lib_assert_fail(condstring "\n" __FILE__ "\n" STR(__LINE__)); \
|
||||
END
|
||||
|
||||
|
||||
/* NOTREACHED -- control should never reach this statement */
|
||||
|
||||
#if defined(MPS_HOT_WHITE)
|
||||
|
||||
#define NOTREACHED NOOP
|
||||
|
||||
#else
|
||||
#if defined(CHECK)
|
||||
|
||||
#define NOTREACHED \
|
||||
BEGIN \
|
||||
AssertFail1("unreachable statement" "\n" __FILE__ "\n" STR(__LINE__)); \
|
||||
mps_lib_assert_fail("unreachable code" "\n" __FILE__ "\n" STR(__LINE__)); \
|
||||
END
|
||||
|
||||
#else
|
||||
|
||||
#define NOTREACHED NOOP
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* CHECKT -- check type simply
|
||||
*
|
||||
* Must be thread safe. See design.mps.interface.c.thread-safety
|
||||
* Must be thread-safe. See design.mps.interface.c.thread-safety
|
||||
* and design.mps.interface.c.check.space.
|
||||
*/
|
||||
|
||||
#define CHECKT(type, val) ((val) != NULL && (val)->sig == type ## Sig)
|
||||
|
||||
|
||||
#if defined(MPS_HOT_WHITE)
|
||||
#if defined(CHECK_NONE)
|
||||
|
||||
|
||||
#define CHECKS(type, val) DISCARD(CHECKT(type, val))
|
||||
|
|
@ -129,26 +117,14 @@ extern void AssertFail1(const char *s);
|
|||
#define CHECKU_NOSIG(type, val) DISCARD((val) != NULL)
|
||||
|
||||
|
||||
#elif defined(MPS_HOT_RED)
|
||||
|
||||
|
||||
#define CHECKS(type, val) ASSERT(CHECKT(type, val), \
|
||||
"SigCheck " #type ": " #val)
|
||||
|
||||
#define CHECKL(cond) DISCARD(cond)
|
||||
#define CHECKD(type, val) DISCARD(CHECKT(type, val))
|
||||
#define CHECKD_NOSIG(type, val) DISCARD((val) != NULL)
|
||||
#define CHECKU(type, val) DISCARD(CHECKT(type, val))
|
||||
#define CHECKU_NOSIG(type, val) DISCARD((val) != NULL)
|
||||
|
||||
|
||||
#elif defined(MPS_COOL)
|
||||
#else
|
||||
|
||||
|
||||
/* CHECKS -- Check Signature */
|
||||
|
||||
#define CHECKS(type, val) ASSERT(CHECKT(type, val), \
|
||||
"SigCheck " #type ": " #val)
|
||||
"SigCheck " #type ": " #val)
|
||||
|
||||
|
||||
/* CHECKL -- Check Local Invariant
|
||||
*
|
||||
|
|
@ -243,10 +219,6 @@ extern void AssertFail1(const char *s);
|
|||
END
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#error "No heat defined."
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -99,15 +99,9 @@ ifdef TARGET
|
|||
ifeq ($(TARGET),mmsw.a)
|
||||
CFLAGSTARGET = -DCONFIG_PROD_EPCORE
|
||||
else
|
||||
ifeq ($(TARGET),epvmss)
|
||||
CFLAGSTARGET = -DCONFIG_PROD_EPCORE
|
||||
else
|
||||
ifeq ($(TARGET),replaysw)
|
||||
CFLAGSTARGET = -DCONFIG_PROD_EPCORE
|
||||
else
|
||||
ifeq ($(TARGET),epdss)
|
||||
CFLAGSTARGET = -DCONFIG_PROD_EPCORE
|
||||
else
|
||||
ifeq ($(TARGET),mmdw.a)
|
||||
CFLAGSTARGET = -DCONFIG_PROD_DYLAN
|
||||
else
|
||||
|
|
@ -120,8 +114,6 @@ endif
|
|||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# These flags are included in all compilations.
|
||||
CFLAGSCOMMON = $(PFMDEFS) $(CFLAGSTARGET) $(CFLAGSCOMPILER)
|
||||
|
|
@ -184,7 +176,7 @@ ARFLAGS=rc$(ARFLAGSPFM)
|
|||
# platforms.
|
||||
|
||||
AMC = poolamc.c
|
||||
AMS = poolams.c
|
||||
AMS = poolams.c poolamsi.c
|
||||
AWL = poolawl.c
|
||||
LO = poollo.c
|
||||
SNC = poolsnc.c
|
||||
|
|
@ -200,16 +192,16 @@ EVENTPROC = eventcnv.c eventpro.c table.c
|
|||
MPMCOMMON = mpsi.c mpm.c arenavm.c arenacl.c arena.c global.c locus.c \
|
||||
tract.c walk.c reserv.c protocol.c pool.c poolabs.c \
|
||||
trace.c root.c seg.c format.c buffer.c ref.c bt.c ring.c \
|
||||
shield.c ld.c event.c action.c sac.c message.c assert.c \
|
||||
poolmrg.c poolmfs.c poolmv.c dbgpool.c \
|
||||
shield.c ld.c event.c sac.c message.c \
|
||||
poolmrg.c poolmfs.c poolmv.c dbgpool.c dbgpooli.c \
|
||||
boot.c meter.c splay.c cbs.c version.c
|
||||
MPM = $(MPMCOMMON) $(MPMPF)
|
||||
SWCOMMON = mpsi.c mpm.c arenavm.c arenacl.c arena.c global.c locus.c \
|
||||
tract.c walk.c reserv.c protocol.c pool.c poolabs.c \
|
||||
trace.c root.c seg.c format.c buffer.c ref.c bt.c ring.c \
|
||||
shield.c ld.c event.c action.c sac.c message.c assert.c \
|
||||
poolmrg.c poolmfs.c poolmv.c dbgpool.c \
|
||||
poolepdl.c poolepvm.c poolams.c poolmvff.c \
|
||||
shield.c ld.c event.c sac.c message.c \
|
||||
poolmrg.c poolmfs.c poolmv.c dbgpool.c dbgpooli \
|
||||
poolams.c poolamsi.c poolmvff.c \
|
||||
boot.c meter.c splay.c cbs.c version.c mpsioan.c
|
||||
SW = $(SWCOMMON) $(SWPF)
|
||||
|
||||
|
|
@ -246,9 +238,6 @@ ifdef TARGET
|
|||
ifeq ($(TARGET),mmsw.a)
|
||||
SWDEP = $(SW:%.c=$(PFM)/$(VARIETY)/%.d)
|
||||
else
|
||||
ifeq ($(TARGET),epvmss)
|
||||
SWDEP = $(SW:%.c=$(PFM)/$(VARIETY)/%.d)
|
||||
else
|
||||
ifeq ($(TARGET),depend)
|
||||
SWDEP = $(SW:%.c=$(PFM)/$(VARIETY)/%.d)
|
||||
else
|
||||
|
|
@ -256,7 +245,6 @@ SWDEP =
|
|||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
TESTLIBOBJ = $(TESTLIB:%.c=$(PFM)/$(VARIETY)/%.o)
|
||||
TESTLIBDEP = $(TESTLIB:%.c=$(PFM)/$(VARIETY)/%.d)
|
||||
|
|
@ -284,7 +272,7 @@ all: mpmss sacss amcss amcsshe amsss amssshe segsmss awlut awluthe \
|
|||
abqtest cbstest btcv mv2test messtest steptest \
|
||||
eventcnv mps.a
|
||||
|
||||
swall: mmsw.a epvmss replaysw epdss
|
||||
swall: mmsw.a replaysw
|
||||
|
||||
# Runs the automatic tests that are built with CONFIG_PROD_MPS
|
||||
# These tests are run overnight (see design.buildsys.overnight).
|
||||
|
|
@ -295,11 +283,6 @@ testrun: mpmss apss sacss amcss amcsshe amsss amssshe segsmss awlut awluthe \
|
|||
abqtest cbstest btcv messtest steptest
|
||||
$(^:%=date && $(PFM)/$(VARIETY)/% &&) true
|
||||
|
||||
# Runs the automatic tests that are built with CONFIG_PROD_EPCORE
|
||||
testrunep: epvmss epdss
|
||||
$(^:%=date && $(PFM)/$(VARIETY)/% &&) true
|
||||
|
||||
|
||||
# These convenience targets allow one to type "make foo" to build target
|
||||
# foo in selected varieties (or none, for the latter rule).
|
||||
#
|
||||
|
|
@ -307,7 +290,7 @@ testrunep: epvmss epdss
|
|||
|
||||
mpmss sacss amcss amcssth amcsshe amsss amssshe segsmss awlut awlutth \
|
||||
awluthe mpsicv lockcov poolncv locv qs apss \
|
||||
finalcv arenacv bttest teletest epvmss epdss \
|
||||
finalcv arenacv bttest teletest \
|
||||
abqtest cbstest btcv mv2test \
|
||||
messtest steptest \
|
||||
eventcnv replay replaysw \
|
||||
|
|
@ -367,7 +350,7 @@ $(PFM)/$(VARIETY)/locv: $(PFM)/$(VARIETY)/locv.o \
|
|||
$(MPMOBJ) $(LOOBJ) $(TESTLIBOBJ)
|
||||
|
||||
$(PFM)/$(VARIETY)/mpmss: $(PFM)/$(VARIETY)/mpmss.o \
|
||||
$(MPMOBJ) $(TESTLIBOBJ)
|
||||
$(MPMOBJ) $(MVFFOBJ) $(TESTLIBOBJ)
|
||||
|
||||
$(PFM)/$(VARIETY)/apss: $(PFM)/$(VARIETY)/apss.o \
|
||||
$(MPMOBJ) $(MVFFOBJ) $(TESTLIBOBJ)
|
||||
|
|
@ -405,12 +388,6 @@ $(PFM)/$(VARIETY)/amssshe: $(PFM)/$(VARIETY)/amssshe.o \
|
|||
$(PFM)/$(VARIETY)/segsmss: $(PFM)/$(VARIETY)/segsmss.o \
|
||||
$(FMTDYTSTOBJ) $(MPMOBJ) $(AMSOBJ) $(TESTLIBOBJ)
|
||||
|
||||
$(PFM)/$(VARIETY)/epvmss: $(PFM)/$(VARIETY)/epvmss.o \
|
||||
$(FMTPSOBJ) $(SWOBJ) $(TESTLIBOBJ) $(PLINTHOBJ)
|
||||
|
||||
$(PFM)/$(VARIETY)/epdss: $(PFM)/$(VARIETY)/epdss.o \
|
||||
$(SWOBJ) $(TESTLIBOBJ) $(PLINTHOBJ)
|
||||
|
||||
$(PFM)/$(VARIETY)/awlut: $(PFM)/$(VARIETY)/awlut.o \
|
||||
$(FMTDYTSTOBJ) $(MPMOBJ) $(LOOBJ) $(AWLOBJ) $(TESTLIBOBJ)
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ all: mpmss.exe amcss.exe amsss.exe amssshe.exe segsmss.exe awlut.exe awluthe.exe
|
|||
locbwcss.exe locusss.exe \
|
||||
eventcnv.exe
|
||||
|
||||
swall: mmsw.lib epvmss.exe replaysw.exe
|
||||
swall: mmsw.lib replaysw.exe
|
||||
|
||||
|
||||
# Convenience targets
|
||||
|
|
@ -31,7 +31,7 @@ swall: mmsw.lib epvmss.exe replaysw.exe
|
|||
|
||||
mpmss.exe amcss.exe amcsshe.exe amsss.exe amssshe.exe segsmss.exe awlut.exe awluthe.exe dwstress.exe \
|
||||
mpsicv.exe lockutw3.exe lockcov.exe poolncv.exe locv.exe qs.exe apss.exe \
|
||||
finalcv.exe arenacv.exe bttest.exe teletest.exe protcv.exe epvmss.exe \
|
||||
finalcv.exe arenacv.exe bttest.exe teletest.exe protcv.exe \
|
||||
abqtest.exe cbstest.exe btcv.exe mv2test.exe messtest.exe steptest.exe \
|
||||
locbwcss.exe locusss.exe \
|
||||
replay.exe replaysw.exe eventcnv.exe \
|
||||
|
|
@ -162,10 +162,6 @@ $(PFM)\$(VARIETY)\locbwcss.exe: $(PFM)\$(VARIETY)\locbwcss.obj \
|
|||
$(PFM)\$(VARIETY)\dwstress.exe: $(PFM)\$(VARIETY)\dwstress.obj \
|
||||
$(DWOBJ) $(MPMOBJ) $(PLINTHOBJ) $(AMCOBJ)
|
||||
|
||||
$(PFM)\$(VARIETY)\epvmss.exe: $(PFM)\$(VARIETY)\epvmss.obj \
|
||||
$(PFM)\$(VARIETY)\fmtpstst.obj \
|
||||
$(SWOBJ) $(TESTLIBOBJ) $(PLINTHOBJ) $(EVENTOBJ)
|
||||
|
||||
$(PFM)\$(VARIETY)\awlut.exe: $(PFM)\$(VARIETY)\awlut.obj \
|
||||
$(DWTESTOBJ) \
|
||||
$(MPMOBJ) $(PLINTHOBJ) $(TESTLIBOBJ) $(LOOBJ) $(AWLOBJ)
|
||||
|
|
|
|||
|
|
@ -2,15 +2,13 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (c) 2002 Global Graphics Software.
|
||||
*
|
||||
* PURPOSE
|
||||
*
|
||||
* This module translates from high-level symbols defined by the
|
||||
* external build system (gnumake, nmake, etc.) into specific sets
|
||||
* of features used by MPS modules. For example, the build system
|
||||
* will defined one of the CONFIG_VAR_* symbols to indicate which
|
||||
* variety it is building, this file translates that into a certain
|
||||
* level of checking, and a certain level of telemetry.
|
||||
* of features used by MPS modules.
|
||||
*
|
||||
* DESIGN
|
||||
*
|
||||
|
|
@ -21,65 +19,38 @@
|
|||
#define config_h
|
||||
|
||||
|
||||
/* Variety Configuration
|
||||
*
|
||||
* Convert CONFIG_VAR_* defined on compiler command line into
|
||||
* internal configuration parameters. See design.mps.config.var
|
||||
* and design.mps.variety.macro. Note that MPS_HOT is subclassed
|
||||
* into MPS_HOT_RED and MPS_HOT_WHITE; this distinction should
|
||||
* be rarely used.
|
||||
*/
|
||||
/* Variety Configuration */
|
||||
|
||||
#if defined(CONFIG_VAR_HI) /* Hot, Internal; variety.hi */
|
||||
#define MPS_VARIETY_STRING "hi"
|
||||
#define MPS_HOT
|
||||
#define MPS_HOT_RED
|
||||
#define EVENT_NONE
|
||||
#elif defined(CONFIG_VAR_CI) /* Cool, Internal; variety.ci */
|
||||
#define MPS_VARIETY_STRING "ci"
|
||||
#define MPS_COOL
|
||||
#define EVENT_NONE
|
||||
#elif defined(CONFIG_VAR_TI) /* Telemetry, Internal; variety.ti */
|
||||
#define MPS_VARIETY_STRING "ti"
|
||||
#define MPS_COOL
|
||||
#define EVENT
|
||||
#elif defined(CONFIG_VAR_HE) /* Hot, External; variety.he */
|
||||
#define MPS_VARIETY_STRING "he"
|
||||
#define MPS_HOT
|
||||
#define MPS_HOT_RED
|
||||
#define EVENT_NONE
|
||||
#elif defined(CONFIG_VAR_CE) /* Cool, External; variety.ce */
|
||||
#define MPS_VARIETY_STRING "ce"
|
||||
#define MPS_COOL
|
||||
#define EVENT_NONE
|
||||
#elif defined(CONFIG_VAR_WI) /* White hot, Internal; variety.wi */
|
||||
#define MPS_VARIETY_STRING "wi"
|
||||
#define MPS_HOT
|
||||
#define MPS_HOT_WHITE
|
||||
#define EVENT_NONE
|
||||
#elif defined(CONFIG_VAR_WE) /* White hot, External; variety.we */
|
||||
#define MPS_VARIETY_STRING "we"
|
||||
#define MPS_HOT
|
||||
#define MPS_HOT_WHITE
|
||||
#define EVENT_NONE
|
||||
#elif defined(CONFIG_VAR_II) /* Ice, Internal; variety.ii */
|
||||
#define MPS_VARIETY_STRING "ii"
|
||||
#define MPS_HOT
|
||||
#define MPS_HOT_RED
|
||||
#define EVENT
|
||||
|
||||
#if defined(CONFIG_ASSERT)
|
||||
#define CHECK
|
||||
#define MPS_ASSERT_STRING "asserted"
|
||||
#else
|
||||
#error "No target variety configured."
|
||||
#define CHECK_NONE
|
||||
#define MPS_ASSERT_STRING "nonasserted"
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(EVENT)
|
||||
#if defined(CONFIG_LOG)
|
||||
#define EVENT
|
||||
#define MPS_LOG_STRING "logging"
|
||||
#else
|
||||
#define EVENT_NONE
|
||||
#define MPS_LOG_STRING "nonlogging"
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(CONFIG_DEBUG)
|
||||
#define DIAGNOSTICS
|
||||
#elif defined(EVENT_NONE)
|
||||
#define DIAGNOSTICS_NONE
|
||||
#define MPS_DEBUG_STRING "debug"
|
||||
#else
|
||||
#error "Events not configured."
|
||||
#define DIAGNOSTICS_NONE
|
||||
#define MPS_DEBUG_STRING "nondebug"
|
||||
#endif
|
||||
|
||||
#define MPS_VARIETY_STRING \
|
||||
MPS_ASSERT_STRING "." MPS_LOG_STRING "." MPS_DEBUG_STRING
|
||||
|
||||
|
||||
/* Platform Configuration */
|
||||
|
||||
|
|
@ -125,12 +96,11 @@
|
|||
#endif /* MPS_ARCH_PP */
|
||||
|
||||
|
||||
/* In white-hot versions, absolutely no checking is done. This leads to
|
||||
* many spurious warnings because parameters are suddenly unused, etc.
|
||||
* We aren't interested in these.
|
||||
/* Non-checking varieties give many spurious warnings because parameters
|
||||
* are suddenly unused, etc. We aren't interested in these
|
||||
*/
|
||||
|
||||
#if defined(MPS_HOT_WHITE)
|
||||
#if defined(CHECK_NONE)
|
||||
|
||||
/* "unreferenced formal parameter" */
|
||||
#pragma warning(disable: 4100)
|
||||
|
|
@ -138,7 +108,7 @@
|
|||
/* "unreferenced local function has been removed" */
|
||||
#pragma warning(disable: 4505)
|
||||
|
||||
#endif /* MPS_HOT_WHITE */
|
||||
#endif /* CHECK_NONE */
|
||||
|
||||
#endif /* MPS_BUILD_MV */
|
||||
|
||||
|
|
@ -240,7 +210,7 @@
|
|||
* create a dependence on an external library.
|
||||
*/
|
||||
|
||||
#if defined(MPS_PF_W3I3MV) && defined(MPS_HOT)
|
||||
#if defined(MPS_PF_W3I3MV)
|
||||
/* MSVC on Intel inlines mem* when optimizing */
|
||||
#define mps_lib_memset memset
|
||||
#define mps_lib_memcpy memcpy
|
||||
|
|
@ -264,6 +234,7 @@
|
|||
#define THREAD_SINGLE
|
||||
#define PROTECTION_NONE
|
||||
#define DONGLE_NONE
|
||||
#define CHECK_DEFAULT CheckNONE /* CheckSHALLOW is too slow for SW */
|
||||
|
||||
#elif defined(CONFIG_PROD_DYLAN)
|
||||
#define MPS_PROD_STRING "dylan"
|
||||
|
|
@ -277,6 +248,7 @@
|
|||
#define THREAD_MULTI
|
||||
#define PROTECTION
|
||||
#define DONGLE_NONE
|
||||
#define CHECK_DEFAULT CheckSHALLOW
|
||||
|
||||
#elif defined(CONFIG_PROD_CONFIGURA)
|
||||
#define MPS_PROD_STRING "configura"
|
||||
|
|
@ -293,6 +265,7 @@
|
|||
#define THREAD_MULTI
|
||||
#define PROTECTION
|
||||
#define DONGLE_NONE
|
||||
#define CHECK_DEFAULT CheckSHALLOW
|
||||
|
||||
#else
|
||||
#error "No target product configured."
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* .source: design.mps.object-debug
|
||||
*/
|
||||
|
|
@ -9,9 +10,7 @@
|
|||
#include "dbgpool.h"
|
||||
#include "poolmfs.h"
|
||||
#include "splay.h"
|
||||
#include "mpslib.h"
|
||||
#include "mpm.h"
|
||||
#include "mps.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
SRCID(dbgpool, "$Id$");
|
||||
|
|
@ -34,8 +33,7 @@ typedef tagStruct *Tag;
|
|||
|
||||
/* tag init methods: copying the user-supplied data into the tag */
|
||||
|
||||
#define TagInitMethodCheck(f) \
|
||||
((f) != NULL) /* that's the best we can do */
|
||||
#define TagInitMethodCheck(f) FUNCHECK(f)
|
||||
|
||||
static void TagTrivInit(void* tag, va_list args)
|
||||
{
|
||||
|
|
@ -68,12 +66,16 @@ Bool PoolDebugMixinCheck(PoolDebugMixin debug)
|
|||
{
|
||||
/* Nothing to check about fenceTemplate */
|
||||
/* Nothing to check about fenceSize */
|
||||
CHECKL(TagInitMethodCheck(debug->tagInit));
|
||||
/* Nothing to check about tagSize */
|
||||
CHECKD(Pool, debug->tagPool);
|
||||
CHECKL(CHECKTYPE(Addr, void*)); /* tagPool relies on this */
|
||||
/* Nothing to check about missingTags */
|
||||
CHECKL(SplayTreeCheck(&debug->index));
|
||||
/* Nothing to check about freeTemplate */
|
||||
/* Nothing to check about freeSize */
|
||||
if (debug->tagInit != NULL) {
|
||||
CHECKL(TagInitMethodCheck(debug->tagInit));
|
||||
/* Nothing to check about tagSize */
|
||||
CHECKD(Pool, debug->tagPool);
|
||||
CHECKL(CHECKTYPE(Addr, void*)); /* tagPool relies on this */
|
||||
/* Nothing to check about missingTags */
|
||||
CHECKL(SplayTreeCheck(&debug->index));
|
||||
}
|
||||
UNUSED(debug); /* see impl.c.mpm.check.unused */
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -102,6 +104,10 @@ static Bool PoolDebugOptionsCheck(PoolDebugOptions opt)
|
|||
CHECKL(opt->fenceTemplate != NULL);
|
||||
/* Nothing to check about fenceSize */
|
||||
}
|
||||
if (opt->freeSize != 0) {
|
||||
CHECKL(opt->freeTemplate != NULL);
|
||||
/* Nothing to check about freeSize */
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -150,7 +156,20 @@ static Res DebugPoolInit(Pool pool, va_list args)
|
|||
}
|
||||
debug->fenceTemplate = options->fenceTemplate;
|
||||
}
|
||||
|
||||
|
||||
/* free-checking init */
|
||||
/* @@@@ This parses a user argument, options, so it should really */
|
||||
/* go through the MPS interface. The template needs to be copied */
|
||||
/* into Addr memory, to avoid breaking design.mps.type.addr.use. */
|
||||
debug->freeSize = options->freeSize;
|
||||
if (debug->freeSize != 0) {
|
||||
if (PoolAlignment(pool) % debug->freeSize != 0) {
|
||||
res = ResPARAM;
|
||||
goto alignFail;
|
||||
}
|
||||
debug->freeTemplate = options->freeTemplate;
|
||||
}
|
||||
|
||||
/* tag init */
|
||||
debug->tagInit = tagInit;
|
||||
if (debug->tagInit != NULL) {
|
||||
|
|
@ -195,7 +214,119 @@ static void DebugPoolFinish(Pool pool)
|
|||
}
|
||||
|
||||
|
||||
/* FenceAlloc -- allocation wrapper for fenceposts
|
||||
/* freeSplat -- splat free block with splat pattern
|
||||
*
|
||||
* If base is in a segment, the whole block has to be in it.
|
||||
*/
|
||||
|
||||
static void freeSplat(PoolDebugMixin debug, Pool pool, Addr base, Addr limit)
|
||||
{
|
||||
Addr p, next;
|
||||
Size freeSize = debug->freeSize;
|
||||
Arena arena;
|
||||
Seg seg;
|
||||
Bool inSeg;
|
||||
|
||||
AVER(base < limit);
|
||||
|
||||
/* If the block is in a segment, make sure any shield is up. */
|
||||
arena = PoolArena(pool);
|
||||
inSeg = SegOfAddr(&seg, arena, base);
|
||||
if (inSeg) {
|
||||
AVER(limit <= SegLimit(seg));
|
||||
ShieldExpose(arena, seg);
|
||||
}
|
||||
/* Write as many copies of the template as fit in the block. */
|
||||
for (p = base, next = AddrAdd(p, freeSize);
|
||||
next <= limit && p < next /* watch out for overflow in next */;
|
||||
p = next, next = AddrAdd(next, freeSize))
|
||||
(void)AddrCopy(p, debug->freeTemplate, freeSize);
|
||||
/* Fill the tail of the block with a partial copy of the template. */
|
||||
if (next > limit || next < p)
|
||||
(void)AddrCopy(p, debug->freeTemplate, AddrOffset(p, limit));
|
||||
if (inSeg) {
|
||||
ShieldCover(arena, seg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* freeCheck -- check free block for splat pattern */
|
||||
|
||||
static Bool freeCheck(PoolDebugMixin debug, Pool pool, Addr base, Addr limit)
|
||||
{
|
||||
Addr p, next;
|
||||
Size freeSize = debug->freeSize;
|
||||
Res res;
|
||||
Arena arena;
|
||||
Seg seg;
|
||||
Bool inSeg;
|
||||
|
||||
AVER(base < limit);
|
||||
|
||||
/* If the block is in a segment, make sure any shield is up. */
|
||||
arena = PoolArena(pool);
|
||||
inSeg = SegOfAddr(&seg, arena, base);
|
||||
if (inSeg) {
|
||||
AVER(limit <= SegLimit(seg));
|
||||
ShieldExpose(arena, seg);
|
||||
}
|
||||
/* Compare this to the AddrCopys in freeSplat. */
|
||||
/* Check the complete copies of the template in the block. */
|
||||
for (p = base, next = AddrAdd(p, freeSize);
|
||||
next <= limit && p < next /* watch out for overflow in next */;
|
||||
p = next, next = AddrAdd(next, freeSize))
|
||||
if (AddrComp(p, debug->freeTemplate, freeSize) != 0) {
|
||||
res = FALSE; goto done;
|
||||
}
|
||||
/* Check the partial copy of the template at the tail of the block. */
|
||||
if (next > limit || next < p)
|
||||
if (AddrComp(p, debug->freeTemplate, AddrOffset(p, limit)) != 0) {
|
||||
res = FALSE; goto done;
|
||||
}
|
||||
res = TRUE;
|
||||
|
||||
done:
|
||||
if (inSeg) {
|
||||
ShieldCover(arena, seg);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* freeCheckAlloc -- allocation wrapper for free-checking */
|
||||
|
||||
static Res freeCheckAlloc(Addr *aReturn, PoolDebugMixin debug, Pool pool,
|
||||
Size size, Bool withReservoir)
|
||||
{
|
||||
Res res;
|
||||
Addr new;
|
||||
|
||||
AVER(aReturn != NULL);
|
||||
|
||||
res = SuperclassOfPool(pool)->alloc(&new, pool, size, withReservoir);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
if (debug->freeSize != 0)
|
||||
ASSERT(freeCheck(debug, pool, new, AddrAdd(new, size)),
|
||||
"free space corrupted on alloc");
|
||||
|
||||
*aReturn = new;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* freeCheckFree -- freeing wrapper for free-checking */
|
||||
|
||||
static void freeCheckFree(PoolDebugMixin debug,
|
||||
Pool pool, Addr old, Size size)
|
||||
{
|
||||
if (debug->freeSize != 0)
|
||||
freeSplat(debug, pool, old, AddrAdd(old, size));
|
||||
SuperclassOfPool(pool)->free(pool, old, size);
|
||||
}
|
||||
|
||||
|
||||
/* fenceAlloc -- allocation wrapper for fenceposts
|
||||
*
|
||||
* Allocates an object, adding fenceposts on both sides. Layout:
|
||||
*
|
||||
|
|
@ -211,7 +342,7 @@ static void DebugPoolFinish(Pool pool)
|
|||
* the template is larger).
|
||||
*/
|
||||
|
||||
static Res FenceAlloc(Addr *aReturn, PoolDebugMixin debug, Pool pool,
|
||||
static Res fenceAlloc(Addr *aReturn, PoolDebugMixin debug, Pool pool,
|
||||
Size size, Bool withReservoir)
|
||||
{
|
||||
Res res;
|
||||
|
|
@ -219,37 +350,31 @@ static Res FenceAlloc(Addr *aReturn, PoolDebugMixin debug, Pool pool,
|
|||
Size alignedSize;
|
||||
|
||||
AVER(aReturn != NULL);
|
||||
AVERT(PoolDebugMixin, debug);
|
||||
AVERT(Pool, pool);
|
||||
AVER(size > 0);
|
||||
AVERT(Bool, withReservoir);
|
||||
|
||||
alignedSize = SizeAlignUp(size, PoolAlignment(pool));
|
||||
res = SuperclassOfPool(pool)->alloc(&new, pool,
|
||||
alignedSize + 2*debug->fenceSize,
|
||||
withReservoir);
|
||||
res = freeCheckAlloc(&new, debug, pool, alignedSize + 2*debug->fenceSize,
|
||||
withReservoir);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
clientNew = AddrAdd(new, debug->fenceSize);
|
||||
/* @@@@ shields? */
|
||||
/* start fencepost */
|
||||
AddrCopy(new, debug->fenceTemplate, debug->fenceSize);
|
||||
(void)AddrCopy(new, debug->fenceTemplate, debug->fenceSize);
|
||||
/* alignment slop */
|
||||
AddrCopy(AddrAdd(clientNew, size),
|
||||
debug->fenceTemplate, alignedSize - size);
|
||||
(void)AddrCopy(AddrAdd(clientNew, size),
|
||||
debug->fenceTemplate, alignedSize - size);
|
||||
/* end fencepost */
|
||||
AddrCopy(AddrAdd(clientNew, alignedSize),
|
||||
debug->fenceTemplate, debug->fenceSize);
|
||||
(void)AddrCopy(AddrAdd(clientNew, alignedSize),
|
||||
debug->fenceTemplate, debug->fenceSize);
|
||||
|
||||
*aReturn = clientNew;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* FenceCheck -- check fences of an object */
|
||||
/* fenceCheck -- check fences of an object */
|
||||
|
||||
static Bool FenceCheck(PoolDebugMixin debug, Pool pool,
|
||||
Addr obj, Size size)
|
||||
static Bool fenceCheck(PoolDebugMixin debug, Pool pool, Addr obj, Size size)
|
||||
{
|
||||
Size alignedSize;
|
||||
|
||||
|
|
@ -258,7 +383,8 @@ static Bool FenceCheck(PoolDebugMixin debug, Pool pool,
|
|||
/* Can't check obj */
|
||||
|
||||
alignedSize = SizeAlignUp(size, PoolAlignment(pool));
|
||||
/* Compare this to the memcpy's in FenceAlloc */
|
||||
/* @@@@ shields? */
|
||||
/* Compare this to the AddrCopys in fenceAlloc */
|
||||
return (AddrComp(AddrSub(obj, debug->fenceSize), debug->fenceTemplate,
|
||||
debug->fenceSize) == 0
|
||||
&& AddrComp(AddrAdd(obj, size), debug->fenceTemplate,
|
||||
|
|
@ -268,38 +394,30 @@ static Bool FenceCheck(PoolDebugMixin debug, Pool pool,
|
|||
}
|
||||
|
||||
|
||||
/* FenceFree -- freeing wrapper for fenceposts */
|
||||
/* fenceFree -- freeing wrapper for fenceposts */
|
||||
|
||||
static void FenceFree(PoolDebugMixin debug,
|
||||
static void fenceFree(PoolDebugMixin debug,
|
||||
Pool pool, Addr old, Size size)
|
||||
{
|
||||
Size alignedSize;
|
||||
|
||||
AVERT(PoolDebugMixin, debug);
|
||||
AVERT(Pool, pool);
|
||||
/* Can't check old */
|
||||
AVER(size > 0);
|
||||
|
||||
ASSERT(FenceCheck(debug, pool, old, size), "fencepost check on free");
|
||||
ASSERT(fenceCheck(debug, pool, old, size), "fencepost check on free");
|
||||
|
||||
alignedSize = SizeAlignUp(size, PoolAlignment(pool));
|
||||
SuperclassOfPool(pool)->free(pool, AddrSub(old, debug->fenceSize),
|
||||
alignedSize + 2*debug->fenceSize);
|
||||
freeCheckFree(debug, pool, AddrSub(old, debug->fenceSize),
|
||||
alignedSize + 2*debug->fenceSize);
|
||||
}
|
||||
|
||||
|
||||
/* TagAlloc -- allocation wrapper for tagged pools */
|
||||
/* tagAlloc -- allocation wrapper for tagged pools */
|
||||
|
||||
static Res TagAlloc(PoolDebugMixin debug,
|
||||
static Res tagAlloc(PoolDebugMixin debug,
|
||||
Pool pool, Addr new, Size size, Bool withReservoir)
|
||||
{
|
||||
Tag tag;
|
||||
Res res;
|
||||
|
||||
AVERT(PoolDebugMixin, debug);
|
||||
AVERT(Pool, pool);
|
||||
AVER(size > 0);
|
||||
|
||||
UNUSED(pool);
|
||||
res = PoolAlloc((Addr*)&tag, debug->tagPool, debug->tagSize, FALSE);
|
||||
if (res != ResOK) {
|
||||
if (withReservoir) { /* design.mps.object-debug.out-of-space */
|
||||
|
|
@ -318,9 +436,9 @@ static Res TagAlloc(PoolDebugMixin debug,
|
|||
}
|
||||
|
||||
|
||||
/* TagFree -- deallocation wrapper for tagged pools */
|
||||
/* tagFree -- deallocation wrapper for tagged pools */
|
||||
|
||||
static void TagFree(PoolDebugMixin debug, Pool pool, Addr old, Size size)
|
||||
static void tagFree(PoolDebugMixin debug, Pool pool, Addr old, Size size)
|
||||
{
|
||||
SplayNode node;
|
||||
Tag tag;
|
||||
|
|
@ -351,7 +469,7 @@ static void TagFree(PoolDebugMixin debug, Pool pool, Addr old, Size size)
|
|||
*/
|
||||
|
||||
static Res DebugPoolAlloc(Addr *aReturn,
|
||||
Pool pool, Size size, Bool withReservoir)
|
||||
Pool pool, Size size, Bool withReservoir)
|
||||
{
|
||||
Res res;
|
||||
Addr new;
|
||||
|
|
@ -365,19 +483,24 @@ static Res DebugPoolAlloc(Addr *aReturn,
|
|||
debug = DebugPoolDebugMixin(pool);
|
||||
AVER(debug != NULL);
|
||||
AVERT(PoolDebugMixin, debug);
|
||||
res = FenceAlloc(&new, debug, pool, size, withReservoir);
|
||||
if (debug->fenceSize != 0)
|
||||
res = fenceAlloc(&new, debug, pool, size, withReservoir);
|
||||
else
|
||||
res = freeCheckAlloc(&new, debug, pool, size, withReservoir);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
/* Allocate object first, so it fits even when the tag doesn't. */
|
||||
res = TagAlloc(debug, pool, new, size, withReservoir);
|
||||
if (res != ResOK)
|
||||
goto tagFail;
|
||||
if (debug->tagInit != NULL) {
|
||||
res = tagAlloc(debug, pool, new, size, withReservoir);
|
||||
if (res != ResOK)
|
||||
goto tagFail;
|
||||
}
|
||||
|
||||
*aReturn = new;
|
||||
return res;
|
||||
|
||||
tagFail:
|
||||
FenceFree(debug, pool, new, size);
|
||||
fenceFree(debug, pool, new, size);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -395,13 +518,18 @@ static void DebugPoolFree(Pool pool, Addr old, Size size)
|
|||
debug = DebugPoolDebugMixin(pool);
|
||||
AVER(debug != NULL);
|
||||
AVERT(PoolDebugMixin, debug);
|
||||
FenceFree(debug, pool, old, size);
|
||||
|
||||
if (debug->fenceSize != 0)
|
||||
fenceFree(debug, pool, old, size);
|
||||
else
|
||||
freeCheckFree(debug, pool, old, size);
|
||||
/* Free the object first, to get fences checked before tag. */
|
||||
TagFree(debug, pool, old, size);
|
||||
if (debug->tagInit != NULL)
|
||||
tagFree(debug, pool, old, size);
|
||||
}
|
||||
|
||||
|
||||
/* TagWalk -- walk all object in the pool using tags */
|
||||
/* TagWalk -- walk all objects in the pool using tags */
|
||||
|
||||
typedef void (*ObjectsStepMethod)(Addr addr, Size size, Format fmt,
|
||||
Pool pool, void *tagData, void *p);
|
||||
|
|
@ -434,21 +562,21 @@ static void TagWalk(Pool pool, ObjectsStepMethod step, void *p)
|
|||
}
|
||||
|
||||
|
||||
/* FenceCheckingStep -- step function for DebugPoolCheckFences */
|
||||
/* fenceCheckingStep -- step function for DebugPoolCheckFences */
|
||||
|
||||
static void FenceCheckingStep(Addr addr, Size size, Format fmt,
|
||||
static void fenceCheckingStep(Addr addr, Size size, Format fmt,
|
||||
Pool pool, void *tagData, void *p)
|
||||
{
|
||||
/* no need to check arguments checked in the caller */
|
||||
UNUSED(fmt); UNUSED(tagData);
|
||||
ASSERT(FenceCheck((PoolDebugMixin)p, pool, addr, size),
|
||||
ASSERT(fenceCheck((PoolDebugMixin)p, pool, addr, size),
|
||||
"fencepost check requested by client");
|
||||
}
|
||||
|
||||
|
||||
/* DebugPoolCheckFences -- check all the fenceposts in the pool */
|
||||
|
||||
static void DebugPoolCheckFences(Pool pool)
|
||||
void DebugPoolCheckFences(Pool pool)
|
||||
{
|
||||
PoolDebugMixin debug;
|
||||
|
||||
|
|
@ -458,7 +586,74 @@ static void DebugPoolCheckFences(Pool pool)
|
|||
return;
|
||||
AVERT(PoolDebugMixin, debug);
|
||||
|
||||
TagWalk(pool, FenceCheckingStep, (void *)debug);
|
||||
if (debug->fenceSize != 0)
|
||||
TagWalk(pool, fenceCheckingStep, (void *)debug);
|
||||
}
|
||||
|
||||
|
||||
/* DebugPoolFreeSplat -- if in a free-checking debug pool, splat free block */
|
||||
|
||||
void DebugPoolFreeSplat(Pool pool, Addr base, Addr limit)
|
||||
{
|
||||
PoolDebugMixin debug;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
AVER(PoolHasAddr(pool, base));
|
||||
AVER(PoolHasAddr(pool, AddrSub(limit, 1)));
|
||||
|
||||
debug = DebugPoolDebugMixin(pool);
|
||||
if (debug != NULL) {
|
||||
AVERT(PoolDebugMixin, debug);
|
||||
if (debug->freeSize != 0)
|
||||
freeSplat(debug, pool, base, limit);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* DebugPoolFreeCheck -- if in a free-checking debug pool, check free block */
|
||||
|
||||
void DebugPoolFreeCheck(Pool pool, Addr base, Addr limit)
|
||||
{
|
||||
PoolDebugMixin debug;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
AVER(PoolHasAddr(pool, base));
|
||||
AVER(PoolHasAddr(pool, AddrSub(limit, 1)));
|
||||
|
||||
debug = DebugPoolDebugMixin(pool);
|
||||
if (debug != NULL) {
|
||||
AVERT(PoolDebugMixin, debug);
|
||||
if (debug->freeSize != 0)
|
||||
ASSERT(freeCheck(debug, pool, base, limit),
|
||||
"free space corrupted on release");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* freeCheckingStep -- step function for DebugPoolCheckFreeSpace */
|
||||
|
||||
static void freeCheckingStep(Addr base, Addr limit, Pool pool, void *p)
|
||||
{
|
||||
/* no need to check arguments checked in the caller */
|
||||
ASSERT(freeCheck((PoolDebugMixin)p, pool, base, limit),
|
||||
"free space corrupted on client check");
|
||||
}
|
||||
|
||||
|
||||
/* DebugPoolCheckFreeSpace -- check free space in the pool for overwrites */
|
||||
|
||||
void DebugPoolCheckFreeSpace(Pool pool)
|
||||
{
|
||||
PoolDebugMixin debug;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
debug = DebugPoolDebugMixin(pool);
|
||||
if (debug == NULL)
|
||||
return;
|
||||
AVERT(PoolDebugMixin, debug);
|
||||
|
||||
if (debug->freeSize != 0)
|
||||
PoolFreeWalk(pool, freeCheckingStep, (void *)debug);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -472,23 +667,3 @@ void PoolClassMixInDebug(PoolClass class)
|
|||
class->alloc = DebugPoolAlloc;
|
||||
class->free = DebugPoolFree;
|
||||
}
|
||||
|
||||
|
||||
/* mps_pool_check_fenceposts -- check all the fenceposts in the pool */
|
||||
|
||||
void mps_pool_check_fenceposts(mps_pool_t mps_pool)
|
||||
{
|
||||
Pool pool = (Pool)mps_pool;
|
||||
Arena arena;
|
||||
|
||||
/* CHECKT not AVERT, see design.mps.interface.c.check.space */
|
||||
AVER(CHECKT(Pool, pool));
|
||||
arena = PoolArena(pool);
|
||||
|
||||
ArenaEnter(arena);
|
||||
|
||||
AVERT(Pool, pool);
|
||||
DebugPoolCheckFences(pool);
|
||||
|
||||
ArenaLeave(arena);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (C) 2002 Global Graphics Software.
|
||||
*/
|
||||
|
||||
#ifndef dbgpool_h
|
||||
|
|
@ -25,6 +26,8 @@ typedef void (*TagInitMethod)(void* tag, va_list args);
|
|||
typedef struct PoolDebugOptionsStruct {
|
||||
void* fenceTemplate;
|
||||
Size fenceSize;
|
||||
void* freeTemplate;
|
||||
Size freeSize;
|
||||
/* TagInitMethod tagInit; */
|
||||
/* Size tagSize; */
|
||||
} PoolDebugOptionsStruct;
|
||||
|
|
@ -40,6 +43,8 @@ typedef struct PoolDebugMixinStruct {
|
|||
Sig sig;
|
||||
Addr fenceTemplate;
|
||||
Size fenceSize;
|
||||
Addr freeTemplate;
|
||||
Size freeSize;
|
||||
TagInitMethod tagInit;
|
||||
Size tagSize;
|
||||
Pool tagPool;
|
||||
|
|
@ -50,8 +55,13 @@ typedef struct PoolDebugMixinStruct {
|
|||
|
||||
extern Bool PoolDebugMixinCheck(PoolDebugMixin dbg);
|
||||
|
||||
|
||||
extern void PoolClassMixInDebug(PoolClass class);
|
||||
|
||||
extern void DebugPoolCheckFences(Pool pool);
|
||||
extern void DebugPoolCheckFreeSpace(Pool pool);
|
||||
|
||||
extern void DebugPoolFreeSplat(Pool pool, Addr base, Addr limit);
|
||||
extern void DebugPoolFreeCheck(Pool pool, Addr base, Addr limit);
|
||||
|
||||
|
||||
#endif /* dbgpool_h */
|
||||
|
|
|
|||
54
mps/code/dbgpooli.c
Normal file
54
mps/code/dbgpooli.c
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/* impl.c.dbgpooli: POOL DEBUG MIXIN C INTERFACE
|
||||
*
|
||||
* $Id: dbgpooli.c,v 1.3 2002/02/01 14:27:26 pekka Exp $
|
||||
* $HopeName: MMsrc!dbgpooli.c(trunk.3) $
|
||||
* Copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* .source: design.mps.object-debug
|
||||
*/
|
||||
|
||||
#include "dbgpool.h"
|
||||
#include "mps.h"
|
||||
#include "mpm.h"
|
||||
|
||||
SRCID(dbgpooli, "$Id: dbgpooli.c,v 1.3 2002/02/01 14:27:26 pekka Exp $");
|
||||
|
||||
|
||||
/* mps_pool_check_fenceposts -- check all the fenceposts in the pool */
|
||||
|
||||
void mps_pool_check_fenceposts(mps_pool_t mps_pool)
|
||||
{
|
||||
Pool pool = (Pool)mps_pool;
|
||||
Arena arena;
|
||||
|
||||
/* CHECKT not AVERT, see design.mps.interface.c.check.space */
|
||||
AVER(CHECKT(Pool, pool));
|
||||
arena = PoolArena(pool);
|
||||
|
||||
ArenaEnter(arena);
|
||||
|
||||
AVERT(Pool, pool);
|
||||
DebugPoolCheckFences(pool);
|
||||
|
||||
ArenaLeave(arena);
|
||||
}
|
||||
|
||||
|
||||
/* mps_pool_check_free_space -- check free space in the pool for overwrites */
|
||||
|
||||
void mps_pool_check_free_space(mps_pool_t mps_pool)
|
||||
{
|
||||
Pool pool = (Pool)mps_pool;
|
||||
Arena arena;
|
||||
|
||||
/* CHECKT not AVERT, see design.mps.interface.c.check.space */
|
||||
AVER(CHECKT(Pool, pool));
|
||||
arena = PoolArena(pool);
|
||||
|
||||
ArenaEnter(arena);
|
||||
|
||||
AVERT(Pool, pool);
|
||||
DebugPoolCheckFreeSpace(pool);
|
||||
|
||||
ArenaLeave(arena);
|
||||
}
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
/* impl.c.eventcnv: Simple event log converter
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
/* impl.h.eventgen -- Automatic event header
|
||||
*
|
||||
* $Id$
|
||||
* $HopeName$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
*
|
||||
* DO NOT EDIT THIS FILE!
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* DESIGN
|
||||
*
|
||||
|
|
@ -32,7 +33,10 @@
|
|||
|
||||
#define testArenaSIZE ((size_t)16<<20)
|
||||
#define rootCOUNT 20
|
||||
#define churnFACTOR 30
|
||||
#define churnFACTOR 10
|
||||
#define finalizationRATE 6
|
||||
#define gcINTERVAL ((size_t)150 * 1024)
|
||||
#define collectionCOUNT 3
|
||||
#define slotSIZE (3*sizeof(mps_word_t))
|
||||
#define genCOUNT 2
|
||||
|
||||
|
|
@ -65,17 +69,25 @@ static void churn(mps_ap_t ap)
|
|||
mps_addr_t p;
|
||||
mps_res_t e;
|
||||
|
||||
for(i = 0; i < churnFACTOR; ++i) {
|
||||
for (i = 0; i < churnFACTOR; ++i) {
|
||||
do {
|
||||
MPS_RESERVE_BLOCK(e, p, ap, 4096);
|
||||
die(e, "MPS_RESERVE_BLOCK");
|
||||
die(dylan_init(p, 4096, root, 1), "dylan_init");
|
||||
} while(!mps_commit(ap, p, 4096));
|
||||
} while (!mps_commit(ap, p, 4096));
|
||||
}
|
||||
p = NULL;
|
||||
}
|
||||
|
||||
|
||||
enum {
|
||||
rootSTATE,
|
||||
deadSTATE,
|
||||
finalizableSTATE,
|
||||
finalizedSTATE
|
||||
};
|
||||
|
||||
|
||||
static void *test(void *arg, size_t s)
|
||||
{
|
||||
int i; /* index */
|
||||
|
|
@ -85,8 +97,12 @@ static void *test(void *arg, size_t s)
|
|||
mps_pool_t amc;
|
||||
mps_res_t e;
|
||||
mps_root_t mps_root[2];
|
||||
int state[rootCOUNT];
|
||||
mps_arena_t arena;
|
||||
void *p = NULL;
|
||||
#ifdef CONFIG_PROD_EPCORE
|
||||
size_t gcThreshold;
|
||||
#endif
|
||||
mps_message_t message;
|
||||
|
||||
arena = (mps_arena_t)arg;
|
||||
|
|
@ -105,30 +121,48 @@ static void *test(void *arg, size_t s)
|
|||
die(mps_ap_create(&ap, amc, MPS_RANK_EXACT), "ap_create\n");
|
||||
|
||||
/* design.mps.poolmrg.test.promise.ut.alloc */
|
||||
for(i = 0; i < rootCOUNT; ++i) {
|
||||
for (i = 0; i < rootCOUNT; ++i) {
|
||||
do {
|
||||
MPS_RESERVE_BLOCK(e, p, ap, slotSIZE);
|
||||
die(e, "MPS_RES_OK");
|
||||
die(dylan_init(p, slotSIZE, root, 1), "dylan_init");
|
||||
} while(!mps_commit(ap, p, slotSIZE));
|
||||
} while (!mps_commit(ap, p, slotSIZE));
|
||||
((mps_word_t *)p)[2] = dylan_int(i);
|
||||
die(mps_finalize(arena, &p), "finalize\n");
|
||||
root[i] = p;
|
||||
root[i] = p; state[i] = rootSTATE;
|
||||
}
|
||||
p = NULL;
|
||||
|
||||
/* design.mps.poolmrg.test.promise.ut.drop */
|
||||
for(i = 0; i < rootCOUNT; ++i) {
|
||||
if (rnd() % 2 == 0)
|
||||
root[i] = NULL;
|
||||
}
|
||||
|
||||
mps_message_type_enable(arena, mps_message_type_finalization());
|
||||
|
||||
#ifdef CONFIG_PROD_EPCORE
|
||||
gcThreshold = mps_arena_committed(arena) + gcINTERVAL;
|
||||
#endif
|
||||
/* design.mps.poolmrg.test.promise.ut.churn */
|
||||
while(mps_collections(arena) < 3) {
|
||||
while (mps_collections(arena) < collectionCOUNT) {
|
||||
churn(ap);
|
||||
while(mps_message_poll(arena)) {
|
||||
/* design.mps.poolmrg.test.promise.ut.drop */
|
||||
for (i = 0; i < rootCOUNT; ++i) {
|
||||
if (root[i] != NULL && state[i] == rootSTATE) {
|
||||
if (rnd() % finalizationRATE == 0) {
|
||||
/* definalize some of them */
|
||||
if (rnd() % 2 == 0) {
|
||||
die(mps_definalize(arena, &root[i]), "definalize\n");
|
||||
state[i] = deadSTATE;
|
||||
} else {
|
||||
state[i] = finalizableSTATE;
|
||||
}
|
||||
root[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef CONFIG_PROD_EPCORE
|
||||
if (mps_arena_committed(arena) > gcThreshold) {
|
||||
die(mps_arena_collect(arena), "collect");
|
||||
gcThreshold = mps_arena_committed(arena) + gcINTERVAL;
|
||||
}
|
||||
#endif
|
||||
while (mps_message_poll(arena)) {
|
||||
mps_word_t *obj;
|
||||
mps_word_t objind;
|
||||
mps_addr_t objaddr;
|
||||
|
|
@ -141,8 +175,12 @@ static void *test(void *arg, size_t s)
|
|||
objind = dylan_int_int(obj[2]);
|
||||
printf("Finalizing: object %lu at %p\n", objind, objaddr);
|
||||
/* design.mps.poolmrg.test.promise.ut.final.check */
|
||||
cdie(root[objind] == NULL, "died");
|
||||
root[objind] = objaddr;
|
||||
cdie(root[objind] == NULL, "finalized live");
|
||||
cdie(state[objind] == finalizableSTATE, "finalized dead");
|
||||
state[objind] = finalizedSTATE;
|
||||
/* sometimes resurrect */
|
||||
if (rnd() % 2 == 0)
|
||||
root[objind] = objaddr;
|
||||
mps_message_discard(arena, message);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
/* impl.c.fmtdy: DYLAN OBJECT FORMAT IMPLEMENTATION
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (c) 2002 Global Graphics Software.
|
||||
*
|
||||
* .readership: MPS developers, Dylan developers
|
||||
*
|
||||
|
|
@ -56,29 +57,14 @@
|
|||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef MPS_PF_SUS8LC
|
||||
/* .hack.stderr: builder.lc (LCC) uses Sun's header files. Sun's
|
||||
* assert.h is broken, as it assumes it can use stderr. We have to
|
||||
* fix it by supplying stderr.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
#define notreached() assert(0)
|
||||
#define unused(param) ((void)param)
|
||||
|
||||
#ifdef MPS_BUILD_MV
|
||||
|
||||
/* MSVC 2.0 generates a warning for unused(). */
|
||||
#ifdef _MSC_VER
|
||||
#if _MSC_VER < 1000
|
||||
#pragma warning(disable: 4705)
|
||||
#endif
|
||||
#else /* _MSC_VER */
|
||||
#error "Expected _MSC_VER to be defined for builder.mv"
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
/* MPS_END causes "constant conditional" warnings. */
|
||||
#pragma warning(disable: 4127)
|
||||
|
|
@ -87,11 +73,15 @@
|
|||
/* has been removed". */
|
||||
#pragma warning(disable: 4514)
|
||||
|
||||
#endif /* MPS_BUILD_MV */
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
|
||||
#define ALIGN sizeof(mps_word_t)
|
||||
|
||||
#define MPS_WORD_WIDTH (sizeof(mps_word_t) * CHAR_BIT)
|
||||
#define MPS_WORD_SHIFT (MPS_WORD_WIDTH == 64 ? 6 : 5)
|
||||
/* MPS_WORD_SHIFT is a bit hacky, but good enough for tests. */
|
||||
|
||||
#ifdef FMTDY_COUNTING
|
||||
#define FMTDY_COUNT(x) x
|
||||
#define FMTDY_FL_LIMIT 16
|
||||
|
|
@ -198,7 +188,7 @@ int dylan_wrapper_check(mps_word_t *w)
|
|||
assert(ff == 2 || t == 0);
|
||||
|
||||
/* The number of patterns is (fixed fields+31)/32. */
|
||||
assert(ff != 2 || t == ((fl + MPS_WORD_WIDTH - 1) >> MPS_WORD_SHIFT));
|
||||
assert(ff != 2 || t == ((fl + MPS_WORD_WIDTH - 1) / MPS_WORD_WIDTH));
|
||||
|
||||
/* The patterns are random bits, so we can't check them. However, */
|
||||
/* the left-over bits in the last pattern should be zero. */
|
||||
|
|
@ -361,12 +351,14 @@ static mps_res_t dylan_scan_pat(mps_ss_t mps_ss,
|
|||
return MPS_RES_OK;
|
||||
}
|
||||
|
||||
|
||||
#define NONWORD_LENGTH(_vt, _es) \
|
||||
((_es) < MPS_WORD_SHIFT ? \
|
||||
((_vt) + (1 << (MPS_WORD_SHIFT - (_es))) - 1) >> \
|
||||
(MPS_WORD_SHIFT - (_es)) : \
|
||||
(_vt) << ((_es) - MPS_WORD_SHIFT))
|
||||
|
||||
|
||||
extern mps_res_t dylan_scan1(mps_ss_t mps_ss, mps_addr_t *object_io)
|
||||
{
|
||||
mps_addr_t *p; /* cursor in object */
|
||||
|
|
@ -408,7 +400,8 @@ extern mps_res_t dylan_scan1(mps_ss_t mps_ss, mps_addr_t *object_io)
|
|||
return MPS_RES_OK;
|
||||
}
|
||||
|
||||
mps_fix(mps_ss, p); /* fix the wrapper */
|
||||
res = mps_fix(mps_ss, p); /* fix the wrapper */
|
||||
if ( res != MPS_RES_OK ) return res;
|
||||
w = (mps_word_t *)p[0]; /* wrapper is header word */
|
||||
assert(dylan_wrapper_check(w));
|
||||
|
||||
|
|
@ -563,7 +556,8 @@ extern mps_res_t dylan_scan1_weak(mps_ss_t mps_ss, mps_addr_t *object_io)
|
|||
/* object should not be forwarded (as there is no forwarding method) */
|
||||
assert((h & 3) == 0);
|
||||
|
||||
mps_fix(mps_ss, p);
|
||||
res = mps_fix(mps_ss, p);
|
||||
if ( res != MPS_RES_OK ) return res;
|
||||
|
||||
/* w points to wrapper */
|
||||
w = (mps_word_t *)p[0];
|
||||
|
|
@ -688,7 +682,7 @@ static void dylan_copy(mps_addr_t old, mps_addr_t new)
|
|||
assert(dylan_wrapper_check(*(mps_word_t **)old));
|
||||
/* .improve.memcpy: Can do better here as we know that new and old
|
||||
* will be aligned (to MPS_PF_ALIGN) */
|
||||
memcpy(new, old, length);
|
||||
(void)memcpy(new, old, length);
|
||||
}
|
||||
|
||||
static mps_addr_t dylan_isfwd(mps_addr_t object)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (c) 2002 Global Graphics Software.
|
||||
*
|
||||
* Uses impl.c.fmtdy for the actual Dylan format, and just adds
|
||||
* a thin layer to handle the object headers themselves.
|
||||
|
|
@ -15,17 +16,6 @@
|
|||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "mpstd.h"
|
||||
#ifdef MPS_PF_SUS8LC
|
||||
/* .hack.stderr: builder.lc (LCC) uses Sun's header files. Sun's
|
||||
* assert.h is broken, as it assumes it can use stderr. We have to
|
||||
* fix it by supplying stderr.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
/* Better include ossu.h as well, in case we use other stuff from stdio.h. */
|
||||
#include "ossu.h"
|
||||
#endif
|
||||
|
||||
#include "testlib.h"
|
||||
|
||||
|
||||
|
|
@ -99,10 +89,6 @@ static mps_addr_t dylan_header_skip(mps_addr_t object)
|
|||
{
|
||||
mps_addr_t *p; /* cursor in object */
|
||||
int header;
|
||||
|
||||
p = (mps_addr_t *)object;
|
||||
assert(p != NULL);
|
||||
|
||||
header = *(int*)((char*)object - headerSIZE);
|
||||
switch(headerType(header)) {
|
||||
case realTYPE:
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (C) 2002 Global Graphics Software.
|
||||
*/
|
||||
|
||||
#ifndef fmthe_h
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (c) 2002 Global Graphics Software.
|
||||
*
|
||||
* DESIGN
|
||||
*
|
||||
|
|
@ -27,7 +28,8 @@ Bool FormatCheck(Format format)
|
|||
CHECKL(AlignCheck(format->alignment));
|
||||
/* @@@@ alignment should be less than maximum allowed */
|
||||
CHECKL(FUNCHECK(format->scan));
|
||||
CHECKL(FUNCHECK(format->skip));
|
||||
CHECKL(format->variety == FormatVarietyFixed
|
||||
? format->skip == NULL : FUNCHECK(format->skip));
|
||||
CHECKL(FUNCHECK(format->move));
|
||||
CHECKL(FUNCHECK(format->isMoved));
|
||||
/* Ignore unused copy field. */
|
||||
|
|
@ -82,13 +84,13 @@ Res FormatCreate(Format *formatReturn, Arena arena,
|
|||
format->isMoved = isMoved;
|
||||
format->copy = copy;
|
||||
format->pad = pad;
|
||||
if(class == NULL) {
|
||||
if (class == NULL) {
|
||||
format->class = &FormatDefaultClass;
|
||||
} else {
|
||||
AVER(variety == FormatVarietyB);
|
||||
format->class = class;
|
||||
}
|
||||
if(headerSize != 0) {
|
||||
if (headerSize != 0) {
|
||||
AVER(variety == FormatVarietyAutoHeader);
|
||||
format->headerSize = headerSize;
|
||||
} else {
|
||||
|
|
@ -108,6 +110,8 @@ Res FormatCreate(Format *formatReturn, Arena arena,
|
|||
}
|
||||
|
||||
|
||||
/* FormatDestroy -- destroy a format */
|
||||
|
||||
void FormatDestroy(Format format)
|
||||
{
|
||||
AVERT(Format, format);
|
||||
|
|
@ -122,7 +126,10 @@ void FormatDestroy(Format format)
|
|||
}
|
||||
|
||||
|
||||
/* Must be thread safe. See design.mps.interface.c.thread-safety. */
|
||||
/* FormatArena -- find the arena of a format
|
||||
*
|
||||
* Must be thread-safe. See design.mps.interface.c.thread-safety. */
|
||||
|
||||
Arena FormatArena(Format format)
|
||||
{
|
||||
/* Can't AVER format as that would not be thread-safe */
|
||||
|
|
@ -131,6 +138,8 @@ Arena FormatArena(Format format)
|
|||
}
|
||||
|
||||
|
||||
/* FormatDescribe -- describe a format */
|
||||
|
||||
Res FormatDescribe(Format format, mps_lib_FILE *stream)
|
||||
{
|
||||
Res res;
|
||||
|
|
@ -148,7 +157,7 @@ Res FormatDescribe(Format format, mps_lib_FILE *stream)
|
|||
" pad $F\n", (WriteFF)format->pad,
|
||||
"} Format $P ($U)\n", (WriteFP)format, (WriteFU)format->serial,
|
||||
NULL);
|
||||
if(res != ResOK) return res;
|
||||
if (res != ResOK) return res;
|
||||
|
||||
return ResOK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,37 +0,0 @@
|
|||
@rem impl.bat.gathconf: GATHERING A RELEASE FOR CONFIGURA
|
||||
@rem
|
||||
@rem $Id$
|
||||
@rem Copyright (c) 2001 Ravenbrook Limited.
|
||||
|
||||
rmdir /s w3i3mv
|
||||
nmake /f w3i3mv.nmk VARIETY=we mps_conf.lib mpsplan.lib
|
||||
nmake /f w3i3mv.nmk VARIETY=wi mps_conf.lib mpsplan.lib
|
||||
nmake /f w3i3mv.nmk VARIETY=ce mps_conf.lib mpsplan.lib
|
||||
nmake /f w3i3mv.nmk VARIETY=ci mps_conf.lib mpsplan.lib
|
||||
mkdir release
|
||||
mkdir release\include
|
||||
mkdir release\lib
|
||||
mkdir release\lib\w3i3
|
||||
mkdir release\lib\w3i3\release
|
||||
mkdir release\lib\w3i3\debug
|
||||
mkdir release\src
|
||||
copy mps.h release\include
|
||||
copy mpsavm.h release\include
|
||||
copy mpsacl.h release\include
|
||||
copy mpscamc.h release\include
|
||||
copy mpscams.h release\include
|
||||
copy mpsclo.h release\include
|
||||
copy mpscmv.h release\include
|
||||
copy mpscmvff.h release\include
|
||||
copy mpscsnc.h release\include
|
||||
copy mpsio.h release\include
|
||||
copy mpslib.h release\include
|
||||
copy mpstd.h release\include
|
||||
copy mpsw3.h release\include
|
||||
copy mpswin.h release\include
|
||||
copy w3i3mv\we\mps_conf.lib release\lib\w3i3\release
|
||||
copy w3i3mv\ce\mps_conf.lib release\lib\w3i3\debug
|
||||
copy w3i3mv\we\mpsplan.lib release\lib\w3i3\release
|
||||
copy w3i3mv\ce\mpsplan.lib release\lib\w3i3\debug
|
||||
copy mpsliban.c release\src
|
||||
copy mpsioan.c release\src
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* .sources: See design.mps.arena. design.mps.thread-safety is relevant
|
||||
* to the functions ArenaEnter and ArenaLeave in this file.
|
||||
|
|
@ -20,13 +21,12 @@
|
|||
* functions should be in some other module, they just ended up here by
|
||||
* confusion over naming. */
|
||||
|
||||
#include "dongle.h"
|
||||
#include "bt.h"
|
||||
#include "poolmrg.h"
|
||||
#include "mps.h" /* finalization */
|
||||
#include "poolmv.h"
|
||||
#include "mpm.h"
|
||||
|
||||
|
||||
SRCID(global, "$Id$");
|
||||
|
||||
|
||||
|
|
@ -217,9 +217,6 @@ Res GlobalsInit(Globals arenaGlobals)
|
|||
/* so check static consistency here. */
|
||||
AVER(MPMCheck());
|
||||
|
||||
if (!DongleTestFull())
|
||||
return ResFAIL;
|
||||
|
||||
arenaClaimRingLock();
|
||||
/* Ensure static things are initialized. */
|
||||
if (!arenaRingInit) {
|
||||
|
|
@ -542,12 +539,6 @@ void ArenaPoll(Globals globals)
|
|||
|
||||
AVERT(Globals, globals);
|
||||
|
||||
if (!DONGLE_TEST_QUICK()) {
|
||||
/* Cripple it by deleting the control pool. */
|
||||
GlobalsArena(globals)->poolReady = FALSE; /* suppress check */
|
||||
PoolFinish(ArenaControlPool(GlobalsArena(globals)));
|
||||
return;
|
||||
}
|
||||
if (globals->clamped)
|
||||
return;
|
||||
size = globals->fillMutatorSize;
|
||||
|
|
@ -589,7 +580,7 @@ Res ArenaFinalize(Arena arena, Ref obj)
|
|||
Res res;
|
||||
|
||||
AVERT(Arena, arena);
|
||||
/* Could consider checking that Ref is valid. */
|
||||
AVER(ArenaHasAddr(arena, (Addr)obj));
|
||||
|
||||
if (!arena->isFinalPool) {
|
||||
Pool pool;
|
||||
|
|
@ -600,9 +591,27 @@ Res ArenaFinalize(Arena arena, Ref obj)
|
|||
arena->finalPool = pool;
|
||||
arena->isFinalPool = TRUE;
|
||||
}
|
||||
AVER(arena->isFinalPool);
|
||||
|
||||
res = MRGRegister(arena->finalPool, (Ref)obj);
|
||||
res = MRGRegister(arena->finalPool, obj);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* ArenaDefinalize -- removes one finalization registration of an object
|
||||
*
|
||||
* See design.mps.finalize. */
|
||||
|
||||
Res ArenaDefinalize(Arena arena, Ref obj)
|
||||
{
|
||||
Res res;
|
||||
|
||||
AVERT(Arena, arena);
|
||||
AVER(ArenaHasAddr(arena, (Addr)obj));
|
||||
|
||||
if (!arena->isFinalPool) {
|
||||
return ResFAIL;
|
||||
}
|
||||
res = MRGDeregister(arena->finalPool, obj);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
MSVCNT 5_0
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
MSVCNT 5_0
|
||||
MSTOOLS Aug96US9
|
||||
MSMASM 6.11
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
#!/bin/sh
|
||||
# impl.sh.hqbuild
|
||||
#
|
||||
# $Id$
|
||||
# Copyright (c) 2001 Ravenbrook Limited.
|
||||
#
|
||||
# Build script for SWIG autobuild system.
|
||||
# The SWIG autobuild system expects to execute this file passing it
|
||||
# an argument.
|
||||
#
|
||||
# We specify that the argument will be the platform code to make life
|
||||
# easy for us
|
||||
|
||||
case $# in
|
||||
1) ;;
|
||||
*) echo 1>&2 'Wrong number of arguments to hqbuild.
|
||||
Exactly one argument expected'; exit 1;;
|
||||
esac
|
||||
|
||||
gnumake -r -f "$1.gmk"
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
@REM impl.bat.hqbuild: setup for SWIG autobuild system
|
||||
@REM $Id$
|
||||
@REM Copyright (c) 2001 Ravenbrook Limited.
|
||||
@REM Called by SWIG autobuild system
|
||||
@
|
||||
@REM we expect whatcom to have set MSVCNT and possibly MSMASM and MSTOOLS
|
||||
IF NOT %MSMASM%X == X SET PATH=%MSMASM%\bin;%PATH%
|
||||
SET PATH=%MSVCNT%\..\sharedide\bin\ide;%MSVCNT%\..\sharedide\bin;%MSVCNT%\bin;%PATH%
|
||||
SET INCLUDE=%MSVCNT%\include;%MSVCNT%\mfc\include;%INCLUDE%
|
||||
SET LIB=%MSVCNT%\lib;%MSVCNT%\mfc\lib;%LIB%
|
||||
@REM First argument is expected to be platform code, rest we pass on
|
||||
nmake /f %1.nmk %2 %3 %4 %5 %6 %7 %8 %9
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
/* impl.h.lo
|
||||
/* impl.h.lo: LEAF OBJECT POOL CLASS INTERFACE
|
||||
*
|
||||
* LEAF OBJECT POOL CLASS
|
||||
*
|
||||
|
|
@ -29,7 +29,6 @@
|
|||
*
|
||||
* Space and time performance will degrade when fragmentation
|
||||
* increases.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef lo_h
|
||||
|
|
|
|||
206
mps/code/locbwcss.c
Normal file
206
mps/code/locbwcss.c
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
/* impl.c.locbwcss: LOCUS BACKWARDS COMPATIBILITY STRESS TEST
|
||||
*
|
||||
* $Id: locbwcss.c,v 1.4 2002/05/10 11:11:39 pekka Exp $
|
||||
* $HopeName: MMsrc!locbwcss.c(trunk.4) $
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
*/
|
||||
|
||||
#include "mpscmvff.h"
|
||||
#include "mpslib.h"
|
||||
#include "mpsavm.h"
|
||||
#include "testlib.h"
|
||||
#include "mps.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
/* some constants */
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#define iterationCount 30 /* number of iterations */
|
||||
#define allocsPerIteration 8 /* number of allocs each iteration */
|
||||
#define chunkSize ((size_t)65536) /* our allocation chunk size */
|
||||
|
||||
#define testArenaSIZE \
|
||||
((size_t)(chunkSize * iterationCount * allocsPerIteration * 3))
|
||||
|
||||
|
||||
#define AddressOffset(b, l) \
|
||||
((size_t)((char *)(l) - (char *)(b)))
|
||||
|
||||
|
||||
/* PoolStat -- maintain data about contiguous allocations */
|
||||
|
||||
typedef struct PoolStatStruct *PoolStat;
|
||||
|
||||
typedef struct PoolStatStruct {
|
||||
mps_pool_t pool; /* the pool being measured */
|
||||
size_t objSize; /* size of each allocation */
|
||||
mps_addr_t min; /* lowest address lock allocated to the pool */
|
||||
mps_addr_t max; /* highest address lock allocated to the pool */
|
||||
int ncCount; /* count of non-contiguous allocations */
|
||||
int aCount; /* count of allocations */
|
||||
int fCount; /* count of frees */
|
||||
} PoolStatStruct;
|
||||
|
||||
|
||||
|
||||
static mps_addr_t allocObject(mps_pool_t pool, size_t size)
|
||||
{
|
||||
mps_addr_t addr;
|
||||
die(mps_alloc(&addr, pool, size),
|
||||
"Allocate Object");
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
||||
static void recordNewObjectStat(PoolStat stat, mps_addr_t obj)
|
||||
{
|
||||
stat->aCount++;
|
||||
if (obj < stat->min) {
|
||||
if (AddressOffset(obj, stat->min) > stat->objSize) {
|
||||
stat->ncCount++;
|
||||
}
|
||||
stat->min = obj;
|
||||
} else if (obj > stat->max) {
|
||||
if (AddressOffset(stat->max, obj) > stat->objSize) {
|
||||
stat->ncCount++;
|
||||
}
|
||||
stat->max = obj;
|
||||
}
|
||||
}
|
||||
|
||||
static void recordFreedObjectStat(PoolStat stat)
|
||||
{
|
||||
stat->fCount++;
|
||||
}
|
||||
|
||||
|
||||
static void poolStatInit(PoolStat stat, mps_pool_t pool, size_t objSize)
|
||||
{
|
||||
mps_addr_t s1, s2, s3;
|
||||
|
||||
stat->pool = pool;
|
||||
stat->objSize = objSize;
|
||||
stat->ncCount = 0;
|
||||
stat->aCount = 0;
|
||||
stat->fCount = 0;
|
||||
|
||||
/* allocate 3 half-size sentinel objects, freeing the middle one */
|
||||
/* to leave a bit of space for the control pool */
|
||||
s1 = allocObject(pool, objSize / 2);
|
||||
stat->min = s1;
|
||||
stat->max = s1;
|
||||
stat->aCount++;
|
||||
|
||||
s2 = allocObject(pool, objSize / 2);
|
||||
recordNewObjectStat(stat, s2);
|
||||
s3 = allocObject(pool, objSize / 2);
|
||||
recordNewObjectStat(stat, s3);
|
||||
|
||||
mps_free(pool, s2, objSize / 2);
|
||||
recordFreedObjectStat(stat);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void allocMultiple(PoolStat stat)
|
||||
{
|
||||
mps_addr_t objects[allocsPerIteration];
|
||||
int i;
|
||||
|
||||
/* allocate a few objects, and record stats for them */
|
||||
for (i = 0; i < allocsPerIteration; i++) {
|
||||
mps_addr_t obj = allocObject(stat->pool, stat->objSize);
|
||||
recordNewObjectStat(stat, obj);
|
||||
objects[i] = obj;
|
||||
}
|
||||
|
||||
/* free one of the objects, to make the test more interesting */
|
||||
i = rnd() % allocsPerIteration;
|
||||
mps_free(stat->pool, objects[i], stat->objSize);
|
||||
recordFreedObjectStat(stat);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* reportResults - print a report on a PoolStat */
|
||||
|
||||
static void reportResults(PoolStat stat, char *name)
|
||||
{
|
||||
printf("\nResults for ");
|
||||
printf(name);
|
||||
printf("\n");
|
||||
printf(" Allocated %lu objects\n", (unsigned long)stat->aCount);
|
||||
printf(" Freed %lu objects\n", (unsigned long)stat->fCount);
|
||||
printf(" There were %lu non-contiguous allocations\n",
|
||||
(unsigned long)stat->ncCount);
|
||||
printf(" Address range from %p to %p\n",
|
||||
(void *)stat->min, (void *)stat->max);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
static void testInArena(mps_arena_t arena)
|
||||
{
|
||||
mps_pool_t lopool, hipool;
|
||||
PoolStatStruct lostruct; /* stats about lopool */
|
||||
PoolStatStruct histruct; /* stats about lopool */
|
||||
PoolStat lostat = &lostruct;
|
||||
PoolStat histat = &histruct;
|
||||
int i;
|
||||
|
||||
die(mps_pool_create(&hipool, arena, mps_class_mvff(),
|
||||
chunkSize, chunkSize, 1024,
|
||||
TRUE, TRUE, TRUE),
|
||||
"Create HI MFFV");
|
||||
|
||||
die(mps_pool_create(&lopool, arena, mps_class_mvff(),
|
||||
chunkSize, chunkSize, 1024,
|
||||
FALSE, FALSE, TRUE),
|
||||
"Create LO MFFV");
|
||||
|
||||
poolStatInit(lostat, lopool, chunkSize);
|
||||
poolStatInit(histat, hipool, chunkSize);
|
||||
|
||||
/* iterate, allocating objects */
|
||||
for (i=0; i<iterationCount; ++i) {
|
||||
allocMultiple(lostat);
|
||||
allocMultiple(histat);
|
||||
}
|
||||
|
||||
/* report results */
|
||||
reportResults(lostat, "the low MVFF pool");
|
||||
reportResults(histat, "the high MVFF pool");
|
||||
|
||||
if (lostat->max > histat->min) {
|
||||
printf("\nFOUND PROBLEM - low range overlaps high\n");
|
||||
} else if (lostat->ncCount != 0 || histat->ncCount != 0) {
|
||||
printf("\nFOUND POSSIBLE PROBLEM - some non-contiguous allocations\n");
|
||||
} else {
|
||||
printf("\nNo problems detected.\n");
|
||||
}
|
||||
|
||||
mps_pool_destroy(hipool);
|
||||
mps_pool_destroy(lopool);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
mps_arena_t arena;
|
||||
|
||||
randomize(argc, argv);
|
||||
|
||||
die(mps_arena_create(&arena, mps_arena_class_vmnz(), testArenaSIZE),
|
||||
"mps_arena_create");
|
||||
|
||||
testInArena(arena);
|
||||
|
||||
mps_arena_destroy(arena);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -15,7 +15,6 @@
|
|||
#include "mpstd.h"
|
||||
#include <float.h> /* for DBL_MAX */
|
||||
|
||||
|
||||
SRCID(locus, "$Id$");
|
||||
|
||||
|
||||
|
|
@ -45,7 +44,7 @@ SegPref SegPrefDefault(void)
|
|||
|
||||
/* SegPrefExpress -- express a segment preference */
|
||||
|
||||
Res SegPrefExpress(SegPref pref, SegPrefKind kind, void *p)
|
||||
void SegPrefExpress(SegPref pref, SegPrefKind kind, void *p)
|
||||
{
|
||||
AVERT(SegPref, pref);
|
||||
AVER(pref != &segPrefDefault);
|
||||
|
|
@ -82,13 +81,9 @@ Res SegPrefExpress(SegPref pref, SegPrefKind kind, void *p)
|
|||
/* See design.mps.pref. */
|
||||
break;
|
||||
}
|
||||
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
||||
#if 1
|
||||
|
||||
/* GenDescCheck -- check a GenDesc */
|
||||
|
||||
static Bool GenDescCheck(GenDesc gen)
|
||||
|
|
@ -473,9 +468,6 @@ void LocusFinish(Arena arena)
|
|||
Bool LocusCheck(Arena arena)
|
||||
{
|
||||
/* Can't check arena, because this is part of ArenaCheck. */
|
||||
GenDescCheck(&arena->topGen);
|
||||
CHECKL(GenDescCheck(&arena->topGen));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
248
mps/code/locusss.c
Normal file
248
mps/code/locusss.c
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
/* impl.c.locusss: LOCUS STRESS TEST
|
||||
*
|
||||
* $Id: locusss.c,v 1.4 2002/05/10 11:00:15 pekka Exp $
|
||||
* $HopeName: MMsrc!locusss.c(trunk.4) $
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
*/
|
||||
|
||||
#include "mpscmvff.h"
|
||||
#include "mpscmv.h"
|
||||
#include "mpslib.h"
|
||||
#include "mpsavm.h"
|
||||
#include "testlib.h"
|
||||
#include "mps.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
/* some constants */
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#define iterationCount 30 /* number of iterations */
|
||||
#define contigAllocs 8 /* number of allocs each iteration */
|
||||
#define chunkSize ((size_t)65536) /* our allocation chunk size */
|
||||
|
||||
#define smallArenaSize \
|
||||
((size_t)(chunkSize * iterationCount * contigAllocs * 2))
|
||||
|
||||
|
||||
#define AddressOffset(b, l) \
|
||||
((size_t)((char *)(l) - (char *)(b)))
|
||||
|
||||
|
||||
/* PoolStat -- maintain data about contiguous allocations */
|
||||
|
||||
typedef struct PoolStatStruct *PoolStat;
|
||||
|
||||
typedef struct PoolStatStruct {
|
||||
mps_pool_t pool; /* the pool being measured */
|
||||
size_t objSize; /* size of each allocation */
|
||||
mps_addr_t min; /* lowest address lock allocated to the pool */
|
||||
mps_addr_t max; /* highest address lock allocated to the pool */
|
||||
int ncCount; /* count of non-contiguous allocations */
|
||||
int aCount; /* count of allocations */
|
||||
int fCount; /* count of frees */
|
||||
} PoolStatStruct;
|
||||
|
||||
|
||||
|
||||
static mps_addr_t allocObject(mps_pool_t pool, size_t size)
|
||||
{
|
||||
mps_addr_t addr;
|
||||
die(mps_alloc(&addr, pool, size),
|
||||
"Allocate Object");
|
||||
return addr;
|
||||
}
|
||||
|
||||
static void recordNewObjectStat(PoolStat stat, mps_addr_t obj)
|
||||
{
|
||||
stat->aCount++;
|
||||
if (obj < stat->min) {
|
||||
if (AddressOffset(obj, stat->min) > stat->objSize) {
|
||||
stat->ncCount++;
|
||||
}
|
||||
stat->min = obj;
|
||||
} else if (obj > stat->max) {
|
||||
if (AddressOffset(stat->max, obj) > stat->objSize) {
|
||||
stat->ncCount++;
|
||||
}
|
||||
stat->max = obj;
|
||||
}
|
||||
}
|
||||
|
||||
static void recordFreedObjectStat(PoolStat stat)
|
||||
{
|
||||
stat->fCount++;
|
||||
}
|
||||
|
||||
|
||||
static void poolStatInit(PoolStat stat, mps_pool_t pool, size_t objSize)
|
||||
{
|
||||
mps_addr_t s1, s2, s3;
|
||||
|
||||
stat->pool = pool;
|
||||
stat->objSize = objSize;
|
||||
stat->ncCount = 0;
|
||||
stat->aCount = 0;
|
||||
stat->fCount = 0;
|
||||
|
||||
/* allocate 3 half-size sentinel objects, freeing the middle one */
|
||||
/* to leave a bit of space for the control pool */
|
||||
s1 = allocObject(pool, objSize / 2);
|
||||
stat->min = s1;
|
||||
stat->max = s1;
|
||||
stat->aCount++;
|
||||
|
||||
s2 = allocObject(pool, objSize / 2);
|
||||
recordNewObjectStat(stat, s2);
|
||||
s3 = allocObject(pool, objSize / 2);
|
||||
recordNewObjectStat(stat, s3);
|
||||
|
||||
mps_free(pool, s2, objSize / 2);
|
||||
recordFreedObjectStat(stat);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static mps_res_t allocMultiple(PoolStat stat)
|
||||
{
|
||||
mps_addr_t objects[contigAllocs];
|
||||
int i;
|
||||
|
||||
/* allocate a few objects, and record stats for them */
|
||||
for (i = 0; i < contigAllocs; i++) {
|
||||
mps_addr_t obj;
|
||||
mps_res_t res = mps_alloc(&obj, stat->pool, stat->objSize);
|
||||
if (res != MPS_RES_OK)
|
||||
return res;
|
||||
recordNewObjectStat(stat, obj);
|
||||
objects[i] = obj;
|
||||
}
|
||||
|
||||
/* free one of the objects, to make the test more interesting */
|
||||
i = rnd() % contigAllocs;
|
||||
mps_free(stat->pool, objects[i], stat->objSize);
|
||||
recordFreedObjectStat(stat);
|
||||
|
||||
return MPS_RES_OK;
|
||||
}
|
||||
|
||||
|
||||
/* reportResults - print a report on a PoolStat */
|
||||
|
||||
static void reportResults(PoolStat stat, char *name)
|
||||
{
|
||||
printf("\nResults for ");
|
||||
printf(name);
|
||||
printf("\n");
|
||||
printf(" Allocated %lu objects\n", (unsigned long)stat->aCount);
|
||||
printf(" Freed %lu objects\n", (unsigned long)stat->fCount);
|
||||
printf(" There were %lu non-contiguous allocations\n",
|
||||
(unsigned long)stat->ncCount);
|
||||
printf(" Address range from %p to %p\n", stat->min, stat->max);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
static void testInArena(mps_arena_t arena,
|
||||
mps_bool_t failcase,
|
||||
mps_bool_t usefulFailcase)
|
||||
{
|
||||
mps_pool_t lopool, hipool, temppool;
|
||||
PoolStatStruct lostruct; /* stats about lopool */
|
||||
PoolStatStruct histruct; /* stats about lopool */
|
||||
PoolStatStruct tempstruct; /* stats about temppool */
|
||||
PoolStat lostat = &lostruct;
|
||||
PoolStat histat = &histruct;
|
||||
PoolStat tempstat = &tempstruct;
|
||||
int i;
|
||||
|
||||
die(mps_pool_create(&hipool, arena, mps_class_mvff(),
|
||||
chunkSize, chunkSize, 1024,
|
||||
TRUE, TRUE, TRUE),
|
||||
"Create HI MFFV");
|
||||
|
||||
die(mps_pool_create(&lopool, arena, mps_class_mvff(),
|
||||
chunkSize, chunkSize, 1024,
|
||||
FALSE, FALSE, TRUE),
|
||||
"Create LO MFFV");
|
||||
|
||||
die(mps_pool_create(&temppool, arena, mps_class_mv(),
|
||||
chunkSize, chunkSize, chunkSize),
|
||||
"Create TEMP");
|
||||
|
||||
if(failcase) {
|
||||
if(usefulFailcase) {
|
||||
/* describe a useful failure case */
|
||||
} else {
|
||||
/* describe a misleading failure case */
|
||||
}
|
||||
}
|
||||
|
||||
poolStatInit(lostat, lopool, chunkSize);
|
||||
poolStatInit(histat, hipool, chunkSize);
|
||||
poolStatInit(tempstat, temppool, chunkSize);
|
||||
|
||||
/* iterate, allocating objects */
|
||||
for (i=0; i<iterationCount; ++i) {
|
||||
mps_res_t res;
|
||||
res = allocMultiple(lostat);
|
||||
if (res != MPS_RES_OK)
|
||||
break;
|
||||
res = allocMultiple(histat);
|
||||
if (res != MPS_RES_OK)
|
||||
break;
|
||||
res = allocMultiple(tempstat);
|
||||
if (res != MPS_RES_OK)
|
||||
break;
|
||||
}
|
||||
|
||||
/* report results */
|
||||
reportResults(lostat, "the low MVFF pool");
|
||||
reportResults(histat, "the high MVFF pool");
|
||||
reportResults(tempstat, "the temp pool");
|
||||
|
||||
mps_pool_destroy(hipool);
|
||||
mps_pool_destroy(lopool);
|
||||
mps_pool_destroy(temppool);
|
||||
|
||||
}
|
||||
|
||||
static void runArenaTest(size_t size,
|
||||
mps_bool_t failcase,
|
||||
mps_bool_t usefulFailcase)
|
||||
{
|
||||
mps_arena_t arena;
|
||||
|
||||
die(mps_arena_create(&arena, mps_arena_class_vmnz(), size),
|
||||
"mps_arena_create");
|
||||
|
||||
die(mps_arena_commit_limit_set(arena, size - chunkSize),
|
||||
"mps_arena_commit_limit_set");
|
||||
|
||||
testInArena(arena, failcase, usefulFailcase);
|
||||
|
||||
mps_arena_destroy(arena);
|
||||
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
randomize(argc, argv);
|
||||
|
||||
printf("\nRunning test with no information about peak usage.\n");
|
||||
runArenaTest(smallArenaSize, FALSE, FALSE);
|
||||
/*
|
||||
printf("\nRunning test with useful information about peak usage.\n");
|
||||
runArenaTest(smallArenaSize, TRUE, TRUE);
|
||||
printf("\nRunning test with misleading information about peak usage.\n");
|
||||
runArenaTest(smallArenaSize, TRUE, FALSE);
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
291
mps/code/makefile.jam
Normal file
291
mps/code/makefile.jam
Normal file
|
|
@ -0,0 +1,291 @@
|
|||
#
|
||||
# Makefile for CORE RIP MPS subsystem
|
||||
#
|
||||
# $HopeName: SWmps!make:makefile.jam(trunk.11) $
|
||||
#
|
||||
|
||||
# Variant details come before compilation rules
|
||||
|
||||
RequiresVariant warning_level : high ;
|
||||
# RequiresVariant warnings_are_fatal ;
|
||||
|
||||
|
||||
# generic_MPS turns off SW-specific configuration; Non_generic_MPS
|
||||
# means SW. We do it this way round so that SW is the default. You
|
||||
# never want to build a generic_MPS variant of SW, only of MPS tests.
|
||||
ImplementsVariant generic_MPS ;
|
||||
|
||||
|
||||
# Determine which MPS platform code matches this target.
|
||||
local MPSOS ; local MPSPF ;
|
||||
switch $(TargetOS) {
|
||||
case win_32 :
|
||||
MPSOS = w3 ;
|
||||
switch $(TargetArch) {
|
||||
case pentium : MPSPF = w3i3mv ;
|
||||
case alpha : MPSPF = w3almv ;
|
||||
case ppc : MPSPF = w3ppmv ;
|
||||
}
|
||||
case irix_5 : MPSOS = i5 ; MPSPF = i5m2cc ;
|
||||
case irix_6 : MPSOS = ia ; MPSPF = iam4cc ;
|
||||
|
||||
case linux_2 : MPSOS = li ; MPSPF = lii4gc ;
|
||||
|
||||
case solaris : MPSOS = so ; MPSPF = sos8gc ;
|
||||
|
||||
case macos_8 : MPSOS = s7 ; MPSPF = s7ppac ;
|
||||
case macos_x : MPSOS = xc ; MPSPF = xcppgc ;
|
||||
}
|
||||
if ! $(MPSPF) {
|
||||
Error Cannot determine MPS platform for target $(TargetOS)-$(TargetArch) ;
|
||||
}
|
||||
|
||||
|
||||
# Set MPS configuration
|
||||
|
||||
AddToVar Inherited Local : C-Defines : CONFIG_PF_$(MPSPF:U) ;
|
||||
|
||||
AddToVar Inherited Local : C-Defines : CONFIG_PROD_EPCORE
|
||||
: Variant Non_generic_MPS ;
|
||||
AddToVar Inherited Local : C-Defines : CONFIG_PROD_MPS
|
||||
: Variant generic_MPS ;
|
||||
AddToVar Inherited Local : Suffix : mps : Variant generic_MPS ;
|
||||
|
||||
AddToVar Inherited Local : C-Defines : CONFIG_ASSERT : Build ASSERT ;
|
||||
AddToVar Inherited Local : C-Defines : CONFIG_DEBUG : Build DEBUG ;
|
||||
|
||||
|
||||
# Compilation rules
|
||||
|
||||
|
||||
DependsOn all : mps ;
|
||||
|
||||
# C-IncludeExportDirectories
|
||||
# : .. ;
|
||||
|
||||
|
||||
AddToVar Local : VariantMPSsources
|
||||
: prmcan.c protsw.c ssan.c than.c
|
||||
mpsioan.c poolepdl.c poolepvm.c
|
||||
: Variant Non_generic_MPS ;
|
||||
|
||||
switch $(MPSPF) {
|
||||
case w3i3mv :
|
||||
AddToVar Local : VariantMPSsources
|
||||
: lockw3.c prmci3w3.c proti3.c protw3.c spi3.c ssw3i3.c thw3i3.c
|
||||
mpsiw3.c
|
||||
: Variant generic_MPS ;
|
||||
AddToVar Local : VariantMPSsources : vmw3.c ;
|
||||
case w3ppmv :
|
||||
AddToVar Local : VariantMPSsources
|
||||
: lockw3.c prmcan.c protw3.c span.c ssan.c than.c
|
||||
mpsiw3.c
|
||||
: Variant generic_MPS ;
|
||||
AddToVar Local : VariantMPSsources : vmw3.c ;
|
||||
case w3almv :
|
||||
AddToVar Local : VariantMPSsources
|
||||
: lockw3.c prmcan.c protw3.c span.c ssan.c than.c
|
||||
mpsiw3.c
|
||||
: Variant generic_MPS ;
|
||||
AddToVar Local : VariantMPSsources : vmw3.c ;
|
||||
case sos8gc :
|
||||
AddToVar Local : VariantMPSsources
|
||||
: lockan.c prmcan.c protso.c span.c sssus8.c than.c
|
||||
: Variant generic_MPS ;
|
||||
AddToVar Local : VariantMPSsources : vmso.c ;
|
||||
case iam4cc :
|
||||
AddToVar Local : VariantMPSsources
|
||||
: lockan.c prmcan.c protan.c span.c ssan.c than.c
|
||||
: Variant generic_MPS ;
|
||||
AddToVar Local : VariantMPSsources : vmi5.c ;
|
||||
case lii4gc :
|
||||
AddToVar Local : VariantMPSsources
|
||||
: lockli.c prmci3li.c protli.c protlii3.c proti3.c pthrdext.c
|
||||
span.c sslii3.c thlii4.c
|
||||
: Variant generic_MPS ;
|
||||
AddToVar Local : VariantMPSsources : vmli.c ;
|
||||
AddToVar Local Inherited : C-Defines : _REENTRANT : Variant generic_MPS ;
|
||||
case s7ppac :
|
||||
AddToVar Local : VariantMPSsources
|
||||
: lockan.c prmcan.c protan.c span.c ssan.c than.c
|
||||
: Variant generic_MPS ;
|
||||
AddToVar Local : VariantMPSsources : vman.c ;
|
||||
case xcppgc :
|
||||
AddToVar Local : VariantMPSsources
|
||||
: lockan.c prmcan.c protan.c span.c ssan.c than.c
|
||||
: Variant generic_MPS ;
|
||||
AddToVar Local : VariantMPSsources : vmxc.c ;
|
||||
case * :
|
||||
Error Undefined MPS platform ;
|
||||
}
|
||||
|
||||
Library mps :
|
||||
$(VariantMPSsources)
|
||||
arena.c
|
||||
arenacl.c
|
||||
arenavm.c
|
||||
boot.c
|
||||
bt.c
|
||||
buffer.c
|
||||
cbs.c
|
||||
dbgpool.c
|
||||
dbgpooli.c
|
||||
event.c
|
||||
format.c
|
||||
global.c
|
||||
ld.c
|
||||
locus.c
|
||||
message.c
|
||||
meter.c
|
||||
mpm.c
|
||||
mpsi.c
|
||||
pool.c
|
||||
poolabs.c
|
||||
poolamc.c
|
||||
poolams.c
|
||||
poolamsi.c
|
||||
poolawl.c
|
||||
poollo.c
|
||||
poolmfs.c
|
||||
poolmrg.c
|
||||
poolmv.c
|
||||
poolmvff.c
|
||||
poolsnc.c
|
||||
protocol.c
|
||||
ref.c
|
||||
reserv.c
|
||||
ring.c
|
||||
root.c
|
||||
sac.c
|
||||
seg.c
|
||||
shield.c
|
||||
splay.c
|
||||
trace.c
|
||||
tract.c
|
||||
version.c
|
||||
walk.c
|
||||
;
|
||||
|
||||
|
||||
# Auxiliary tools
|
||||
|
||||
AddToVar Local : VariantPlinthSources : mpsioan.c : Variant generic_MPS ;
|
||||
Library plinth :
|
||||
$(VariantPlinthSources)
|
||||
mpsliban.c
|
||||
;
|
||||
|
||||
Executable eventcnv : eventcnv.c eventpro.c table.c ;
|
||||
|
||||
Executable replay
|
||||
: replay.c eventrep.c eventpro.c table.c mpsliban.c fmtpstst.c ;
|
||||
C-LinkWithLibraries replay : mps testlib ;
|
||||
|
||||
|
||||
# Test files
|
||||
|
||||
# testrun is the target for building and running all tests.
|
||||
FloatingDepends testrun ;
|
||||
# testrun1 is an intermediate target required by a bug in GenericTarget.
|
||||
DependsOn testrun : testrun1 ;
|
||||
local testTarget ; MakeGristed testTarget : testrun : $(CurrentPath) ;
|
||||
local testTarget1 ; MakeGristed testTarget1 : testrun1 : $(CurrentPath) ;
|
||||
NOTFILE $(testTarget) $(testTarget1) ;
|
||||
ALWAYS $(testTarget) $(testTarget1) ;
|
||||
|
||||
rule TestExecutable {
|
||||
# TestExecutable executable : additional_sources : variant_for_testrun ;
|
||||
Executable $(1) : $(1).c $(2).c ;
|
||||
if $(MPSPF) in sos8gc {
|
||||
# We'd like to do
|
||||
# C-Exec-Linker_Libraries on $(1) += -lm ;
|
||||
# but for some reason, it doesn't work. As long as there's nothing
|
||||
# in this file after the TestExecutables, this AddToVar is harmless.
|
||||
AddToVar Local : C-Exec-Linker_Libraries : -lm ;
|
||||
}
|
||||
C-LinkWithLibraries $(1) :
|
||||
mps
|
||||
plinth
|
||||
testlib
|
||||
;
|
||||
# Parse the variant by using AddToVar.
|
||||
AddToVar Local : runTest : yes : Variant $(3) ;
|
||||
if $(runTest) = yes {
|
||||
GenericTarget testrun1 : $(1:S=$(C-Exec-Suffix)) :
|
||||
# There must be a space after $>, or GenericTarget won't replace it.
|
||||
echo ...TESTING $> ...$(NewLine)
|
||||
$> ;
|
||||
}
|
||||
ReplaceVar Local : runTest : : Variant $(3) ;
|
||||
}
|
||||
|
||||
Library testlib :
|
||||
testlib.c
|
||||
;
|
||||
|
||||
TestExecutable abqtest : : mv2_broken ;
|
||||
TestExecutable amcss : fmtdy fmtdytst : generic_MPS ;
|
||||
TestExecutable amcsshe : fmthe : generic_MPS ;
|
||||
TestExecutable amcssth : fmtdy fmtdytst : pthreads ;
|
||||
TestExecutable amsss : fmtdy fmtdytst : generic_MPS ;
|
||||
TestExecutable apss ;
|
||||
TestExecutable arenacv ;
|
||||
TestExecutable btcv ;
|
||||
TestExecutable bttest : : interactive_test ;
|
||||
TestExecutable cbstest ;
|
||||
TestExecutable epdss : : Non_generic_MPS ;
|
||||
TestExecutable epvmss : fmtpstst : Non_generic_MPS ;
|
||||
TestExecutable finalcv : fmtdy fmtdytst ;
|
||||
TestExecutable locbwcss ;
|
||||
TestExecutable lockcov ;
|
||||
TestExecutable lockutw3 : : Windows ;
|
||||
TestExecutable locusss ;
|
||||
TestExecutable locv ;
|
||||
TestExecutable messtest ;
|
||||
TestExecutable mpmss ;
|
||||
TestExecutable mpsicv : fmtdy fmtdytst ;
|
||||
TestExecutable mv2test : poolmv2 abq : mv2_broken ;
|
||||
TestExecutable poolncv : pooln ;
|
||||
TestExecutable qs : : generic_MPS ;
|
||||
TestExecutable sacss ;
|
||||
TestExecutable segsmss : fmtdy fmtdytst : generic_MPS ;
|
||||
TestExecutable teletest : : interactive_test ;
|
||||
|
||||
|
||||
# $Log: make:makefile.jam,v $
|
||||
# Revision 1.11 2002/05/21 13:22:47 pekka
|
||||
# Remove assert.c (change.mps.epcore.chub.160200)
|
||||
#
|
||||
# Revision 1.10 2002/05/09 17:50:03 pekka
|
||||
# Add testrun
|
||||
#
|
||||
# Revision 1.9 2002/02/15 19:14:04 pekka
|
||||
# Remove .s file on Solaris
|
||||
#
|
||||
# Revision 1.8 2002/02/12 14:45:00 pekka
|
||||
# [Bug #24034]
|
||||
# On Solaris, you have add -lm
|
||||
#
|
||||
# Revision 1.7 2002/02/07 17:13:52 pekka
|
||||
# [Bug #24034]
|
||||
# clean up
|
||||
#
|
||||
# Revision 1.6 2002/01/09 17:11:45 pekka
|
||||
# Add poolamsi.c
|
||||
#
|
||||
# Revision 1.5 2002/01/04 17:25:06 pekka
|
||||
# Add dbgpooli.c
|
||||
#
|
||||
# Revision 1.4 2002/01/02 19:50:04 pekka
|
||||
# Clarify comment on generic_MPS; add some more tests
|
||||
#
|
||||
# Revision 1.3 2001/12/21 14:34:43 pekka
|
||||
# Add missing Linux stuff
|
||||
#
|
||||
# Revision 1.2 2001/12/18 21:08:32 pekka
|
||||
# Warnings can't be fatal yet
|
||||
#
|
||||
# Revision 1.1 2001/12/18 21:03:44 pekka
|
||||
# new unit
|
||||
# New makefile for building MPS with Jam Doughtnut
|
||||
#
|
||||
|
|
@ -14,6 +14,7 @@
|
|||
* "real work" goes on in the modules that provide the actual messages.
|
||||
*/
|
||||
|
||||
#include "bt.h"
|
||||
#include "mpm.h"
|
||||
|
||||
SRCID(message, "$Id$");
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (C) 2001 Global Graphics Software.
|
||||
*
|
||||
* Small general things which are useful for C but aren't part of the
|
||||
* memory manager itself. The only reason that this file exists is
|
||||
|
|
@ -22,25 +23,6 @@ enum {
|
|||
};
|
||||
|
||||
|
||||
/* offsetof -- offset of field within structure
|
||||
*
|
||||
* .hack.offsetof: On platform.sus8lc the offsetof macro is not defined
|
||||
* (because LCC does not bother fixing up SunOS's broken header files).
|
||||
* We define it here using normal C constructs. This hack is only
|
||||
* required on platform.sus8lc and no other platforms. See
|
||||
* change.mps.tracer2.170226
|
||||
*/
|
||||
|
||||
#ifdef MPS_PF_SUS8LC
|
||||
#ifdef offsetof
|
||||
#error "offsetof was unexpectedly already defined on platform SUS8LC"
|
||||
#else
|
||||
#define offsetof(type, field) ((size_t)(((char *)&((type *)0)->field) \
|
||||
- (char *)0))
|
||||
#endif /* offsetof */
|
||||
#endif /* MPS_PF_SUS8LC */
|
||||
|
||||
|
||||
/* SrcId -- source identification
|
||||
*
|
||||
* Every C source file should start with a SRCID declaration to
|
||||
|
|
@ -157,11 +139,15 @@ typedef const struct SrcIdStruct {
|
|||
* Given a pointer to a field of a structure this returns a pointer to
|
||||
* the main structure. PARENT(foo_t, x, foo->x) == foo.
|
||||
*
|
||||
* This macro is thread-safe. design.mps.misc.parent.thread-safe
|
||||
* This macro is thread-safe, see design.mps.misc.parent.thread-safe.
|
||||
*
|
||||
* That intermediate (void *) is required to stop some compilers complaining
|
||||
* about alignment of 'type *' being greater than that of 'char *'. Which
|
||||
* is true, but not a bug, since p really is a pointer into a 'type' struct.
|
||||
*/
|
||||
|
||||
#define PARENT(type, field, p) \
|
||||
((type *)((char *)(p) - offsetof(type, field)))
|
||||
((type *)(void *)((char *)(p) - offsetof(type, field)))
|
||||
|
||||
|
||||
/* Bit Sets -- sets of integers in [0,N-1].
|
||||
|
|
|
|||
|
|
@ -8,16 +8,27 @@
|
|||
*
|
||||
* .sources: design.mps.writef */
|
||||
|
||||
#include "check.h"
|
||||
#include "mpm.h"
|
||||
#include <stdarg.h>
|
||||
/* Get some floating constants for WriteDouble */
|
||||
#include <float.h>
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
SRCID(mpm, "$Id$");
|
||||
|
||||
|
||||
#if defined(CHECK)
|
||||
|
||||
|
||||
/* CheckLevel -- Control check level
|
||||
*
|
||||
* This controls the behaviour of Check methods (see impl.h.check).
|
||||
*/
|
||||
|
||||
unsigned CheckLevel = CHECK_DEFAULT;
|
||||
|
||||
|
||||
/* MPMCheck -- test MPM assumptions */
|
||||
|
||||
Bool MPMCheck(void)
|
||||
|
|
@ -112,6 +123,9 @@ Bool AlignCheck(Align align)
|
|||
}
|
||||
|
||||
|
||||
#endif /* defined(CHECK) */
|
||||
|
||||
|
||||
/* WordIsAligned -- test whether a word is aligned */
|
||||
|
||||
Bool (WordIsAligned)(Word word, Align align)
|
||||
|
|
@ -446,7 +460,8 @@ Res WriteF(mps_lib_FILE *stream, ...)
|
|||
|
||||
case 'F': { /* function */
|
||||
WriteFF f = va_arg(args, WriteFF);
|
||||
Byte *b = (Byte *)&f;
|
||||
WriteFF *fp = &f; /* dodge to placate splint */
|
||||
Byte *b = *((Byte **)&fp);
|
||||
for(i=0; i < sizeof(WriteFF); i++) {
|
||||
res = WriteWord(stream, (Word)(b[i]), 16,
|
||||
(CHAR_BIT + 3) / 4);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* .trans.bufferinit: The Buffer data structure has an Init field and
|
||||
* an Init method, there's a name clash. We resolve this by calling the
|
||||
|
|
@ -156,61 +157,6 @@ extern size_t StringLength(const char *s);
|
|||
extern char *MPSVersion(void);
|
||||
|
||||
|
||||
/* Bit Table Interface -- see design.mps.bt.if.* for doc */
|
||||
|
||||
/* design.mps.bt.if.size */
|
||||
extern size_t (BTSize)(unsigned long length);
|
||||
#define BTSize(n) (((n) + MPS_WORD_WIDTH-1) / MPS_WORD_WIDTH * sizeof(Word))
|
||||
|
||||
|
||||
/* design.mps.bt.if.get */
|
||||
extern Bool (BTGet)(BT bt, Index index);
|
||||
#define BTGet(a, i) \
|
||||
((Bool)(((a)[((i) >> MPS_WORD_SHIFT)] \
|
||||
>> ((i) & ~((Word)-1 << MPS_WORD_SHIFT))) \
|
||||
& (Word)1))
|
||||
|
||||
/* design.mps.bt.if.set */
|
||||
extern void (BTSet)(BT bt, Index index);
|
||||
#define BTSet(a, i) \
|
||||
BEGIN \
|
||||
(a)[((i)>>MPS_WORD_SHIFT)] |= (Word)1<<((i)&~((Word)-1<<MPS_WORD_SHIFT)); \
|
||||
END
|
||||
|
||||
/* design.mps.bt.if.res */
|
||||
extern void (BTRes)(BT bt, Index index);
|
||||
#define BTRes(a, i) \
|
||||
BEGIN \
|
||||
(a)[((i)>>MPS_WORD_SHIFT)] &= \
|
||||
~((Word)1 << ((i) & ~((Word)-1<<MPS_WORD_SHIFT))); \
|
||||
END
|
||||
|
||||
extern Res BTCreate(BT *btReturn, Arena arena, Count length);
|
||||
extern void BTDestroy(BT bt, Arena arena, Count length);
|
||||
extern void BTSetRange(BT bt, Index base, Index limit);
|
||||
extern Bool BTIsSetRange(BT bt, Index base, Index limit);
|
||||
extern void BTResRange(BT bt, Index base, Index limit);
|
||||
extern Bool BTIsResRange(BT bt, Index base, Index limit);
|
||||
extern Bool BTFindShortResRange(Index *baseReturn, Index *limitReturn,
|
||||
BT bt, Index searchBase, Index searchLimit,
|
||||
unsigned long length);
|
||||
extern Bool BTFindShortResRangeHigh(Index *baseReturn, Index *limitReturn,
|
||||
BT bt, Index searchBase, Index searchLimit,
|
||||
unsigned long length);
|
||||
extern Bool BTFindLongResRange(Index *baseReturn, Index *limitReturn,
|
||||
BT bt, Index searchBase, Index searchLimit,
|
||||
unsigned long length);
|
||||
extern Bool BTFindLongResRangeHigh(Index *baseReturn, Index *limitReturn,
|
||||
BT bt, Index searchBase, Index searchLimit,
|
||||
unsigned long length);
|
||||
extern Bool BTRangesSame(BT BTx, BT BTy, Index base, Index limit);
|
||||
extern void BTCopyInvertRange(BT fromBT, BT toBT, Index base, Index limit);
|
||||
extern void BTCopyRange(BT fromBT, BT toBT, Index base, Index limit);
|
||||
extern void BTCopyOffsetRange(BT fromBT, BT toBT,
|
||||
Index fromBase, Index fromLimit,
|
||||
Index toBase, Index toLimit);
|
||||
|
||||
|
||||
/* Pool Interface -- see impl.c.pool */
|
||||
|
||||
extern Res PoolInit(Pool pool, Arena arena, PoolClass class, ...);
|
||||
|
|
@ -253,6 +199,7 @@ extern void PoolFixEmergency(Pool pool, ScanState ss, Seg seg, Addr *refIO);
|
|||
extern void PoolReclaim(Pool pool, Trace trace, Seg seg);
|
||||
extern void PoolWalk(Pool pool, Seg seg, FormattedObjectsStepMethod f,
|
||||
void *v, unsigned long s);
|
||||
extern void PoolFreeWalk(Pool pool, FreeBlockStepMethod f, void *p);
|
||||
extern Res PoolTrivInit(Pool pool, va_list arg);
|
||||
extern void PoolTrivFinish(Pool pool);
|
||||
extern Res PoolNoAlloc(Addr *pReturn, Pool pool, Size size,
|
||||
|
|
@ -300,6 +247,7 @@ extern Res PoolTrivFramePop(Pool pool, Buffer buf, AllocFrame frame);
|
|||
extern void PoolNoFramePopPending(Pool pool, Buffer buf, AllocFrame frame);
|
||||
extern void PoolNoWalk(Pool pool, Seg seg, FormattedObjectsStepMethod step,
|
||||
void *p, unsigned long s);
|
||||
extern void PoolNoFreeWalk(Pool pool, FreeBlockStepMethod f, void *p);
|
||||
extern PoolDebugMixin PoolNoDebugMixin(Pool pool);
|
||||
extern BufferClass PoolNoBufferClass(void);
|
||||
|
||||
|
|
@ -584,6 +532,7 @@ extern Size ArenaAvail(Arena arena);
|
|||
extern Res ArenaExtend(Arena, Addr base, Size size);
|
||||
|
||||
extern Res ArenaFinalize(Arena arena, Ref obj);
|
||||
extern Res ArenaDefinalize(Arena arena, Ref obj);
|
||||
|
||||
extern Bool ArenaIsReservedAddr(Arena arena, Addr addr);
|
||||
|
||||
|
|
@ -611,7 +560,7 @@ extern Res ArenaNoExtend(Arena arena, Addr base, Size size);
|
|||
|
||||
extern Bool SegPrefCheck(SegPref pref);
|
||||
extern SegPref SegPrefDefault(void);
|
||||
extern Res SegPrefExpress(SegPref pref, SegPrefKind kind, void *p);
|
||||
extern void SegPrefExpress(SegPref pref, SegPrefKind kind, void *p);
|
||||
|
||||
extern void LocusInit(Arena arena);
|
||||
extern void LocusFinish(Arena arena);
|
||||
|
|
|
|||
|
|
@ -2,9 +2,11 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (C) 2002 Global Graphics Software.
|
||||
*/
|
||||
|
||||
#include "mpscmv.h"
|
||||
#include "mpscmvff.h"
|
||||
#include "mpslib.h"
|
||||
#include "mpsavm.h"
|
||||
#include "testlib.h"
|
||||
|
|
@ -23,8 +25,10 @@ extern mps_class_t PoolClassMFS(void);
|
|||
#define testLOOPS 10
|
||||
|
||||
|
||||
static mps_res_t stress(mps_class_t class, mps_arena_t arena,
|
||||
size_t (*size)(int i), ...)
|
||||
/* stress -- create a pool of the requested type and allocate in it */
|
||||
|
||||
static mps_res_t stress(mps_class_t class, size_t (*size)(int i),
|
||||
mps_arena_t arena, ...)
|
||||
{
|
||||
mps_res_t res;
|
||||
mps_pool_t pool;
|
||||
|
|
@ -33,7 +37,7 @@ static mps_res_t stress(mps_class_t class, mps_arena_t arena,
|
|||
int *ps[testSetSIZE];
|
||||
size_t ss[testSetSIZE];
|
||||
|
||||
va_start(arg, size);
|
||||
va_start(arg, arena);
|
||||
res = mps_pool_create_v(&pool, arena, class, arg);
|
||||
va_end(arg);
|
||||
if (res != MPS_RES_OK)
|
||||
|
|
@ -87,6 +91,10 @@ static mps_res_t stress(mps_class_t class, mps_arena_t arena,
|
|||
|
||||
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
#define alignUp(w, a) (((w) + (a) - 1) & ~((size_t)(a) - 1))
|
||||
|
||||
|
||||
/* randomSize -- produce sizes both latge and small */
|
||||
|
||||
static size_t randomSize(int i)
|
||||
{
|
||||
|
|
@ -98,6 +106,18 @@ static size_t randomSize(int i)
|
|||
}
|
||||
|
||||
|
||||
/* randomSize8 -- produce sizes both latge and small, 8-byte aligned */
|
||||
|
||||
static size_t randomSize8(int i)
|
||||
{
|
||||
size_t maxSize = 2 * 160 * 0x2000;
|
||||
/* Reduce by a factor of 2 every 10 cycles. Total allocation about 40 MB. */
|
||||
return alignUp(rnd() % max((maxSize >> (i / 10)), 2) + 1, 8);
|
||||
}
|
||||
|
||||
|
||||
/* fixedSize -- produce always the same size */
|
||||
|
||||
static size_t fixedSizeSize = 0;
|
||||
|
||||
static size_t fixedSize(int i)
|
||||
|
|
@ -107,23 +127,35 @@ static size_t fixedSize(int i)
|
|||
}
|
||||
|
||||
|
||||
static mps_pool_debug_option_s debugOptions = { (void *)"postpost", 8 };
|
||||
/* testInArena -- test all the pool classes in the given arena */
|
||||
|
||||
static int testInArena(mps_arena_t arena)
|
||||
static mps_pool_debug_option_s bothOptions =
|
||||
{ (void *)"postpost", 8, (void *)"DEAD", 4 };
|
||||
|
||||
static mps_pool_debug_option_s fenceOptions =
|
||||
{ (void *)"\0XXX ''\"\"'' XXX\0", 16, NULL, 0 };
|
||||
|
||||
static int testInArena(mps_arena_t arena, mps_pool_debug_option_s *options)
|
||||
{
|
||||
/* IWBN to test MVFFDebug, but the MPS doesn't support debugging */
|
||||
/* cross-segment allocation (possibly MVFF ought not to). */
|
||||
printf("MVFF\n");
|
||||
die(stress(mps_class_mvff(), randomSize8, arena,
|
||||
(size_t)65536, (size_t)32, (size_t)4, TRUE, TRUE, TRUE),
|
||||
"stress MVFF");
|
||||
printf("MV debug\n");
|
||||
die(stress(mps_class_mv_debug(), arena, randomSize,
|
||||
&debugOptions, (size_t)65536, (size_t)32, (size_t)65536),
|
||||
die(stress(mps_class_mv_debug(), randomSize, arena,
|
||||
options, (size_t)65536, (size_t)32, (size_t)65536),
|
||||
"stress MV debug");
|
||||
|
||||
printf("MFS\n");
|
||||
fixedSizeSize = 13;
|
||||
die(stress(PoolClassMFS(),
|
||||
arena, fixedSize, (size_t)100000, fixedSizeSize),
|
||||
fixedSize, arena, (size_t)100000, fixedSizeSize),
|
||||
"stress MFS");
|
||||
|
||||
printf("MV\n");
|
||||
die(stress(mps_class_mv(), arena, randomSize,
|
||||
die(stress(mps_class_mv(), randomSize, arena,
|
||||
(size_t)65536, (size_t)32, (size_t)65536),
|
||||
"stress MV");
|
||||
|
||||
|
|
@ -139,12 +171,12 @@ int main(int argc, char **argv)
|
|||
|
||||
die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE),
|
||||
"mps_arena_create");
|
||||
testInArena(arena);
|
||||
testInArena(arena, &bothOptions);
|
||||
mps_arena_destroy(arena);
|
||||
|
||||
die(mps_arena_create(&arena, mps_arena_class_vm(), smallArenaSIZE),
|
||||
"mps_arena_create");
|
||||
testInArena(arena);
|
||||
testInArena(arena, &fenceOptions);
|
||||
mps_arena_destroy(arena);
|
||||
|
||||
fflush(stdout); /* synchronize */
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (C) 2001 Global Graphics Software.
|
||||
*
|
||||
* .design: This header file crosses module boundaries. The relevant
|
||||
* design a module's structures should be found in that module's design
|
||||
|
|
@ -71,6 +72,7 @@ typedef struct PoolClassStruct {
|
|||
PoolFramePopMethod framePop; /* pop an allocation frame */
|
||||
PoolFramePopPendingMethod framePopPending; /* notify pending pop */
|
||||
PoolWalkMethod walk; /* walk over a segment */
|
||||
PoolFreeWalkMethod freewalk; /* walk over free blocks */
|
||||
PoolBufferClassMethod bufferClass; /* default BufferClass of pool */
|
||||
PoolDescribeMethod describe; /* describe the contents of the pool */
|
||||
PoolDebugMixinMethod debugMixin; /* find the debug mixin, if any */
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (c) 2001 Global Graphics Software.
|
||||
*
|
||||
* .design: design.mps.type
|
||||
*
|
||||
|
|
@ -137,8 +138,12 @@ typedef Res (*TraceFixMethod)(ScanState ss, Ref *refIO);
|
|||
/* Heap Walker */
|
||||
|
||||
/* This type is used by the PoolClass method Walk */
|
||||
typedef void (*FormattedObjectsStepMethod)(Addr, Format, Pool,
|
||||
void *, Size);
|
||||
typedef void (*FormattedObjectsStepMethod)(Addr obj, Format fmt, Pool pool,
|
||||
void *v, unsigned long s);
|
||||
|
||||
/* This type is used by the PoolClass method Walk */
|
||||
typedef void (*FreeBlockStepMethod)(Addr base, Addr limit, Pool pool, void *p);
|
||||
|
||||
|
||||
/* Seg*Method -- see design.mps.seg */
|
||||
|
||||
|
|
@ -212,7 +217,8 @@ typedef void (*PoolFramePopPendingMethod)(Pool pool, Buffer buf,
|
|||
AllocFrame frame);
|
||||
typedef void (*PoolWalkMethod)(Pool pool, Seg seg,
|
||||
FormattedObjectsStepMethod f,
|
||||
void *p, unsigned long s);
|
||||
void *v, unsigned long s);
|
||||
typedef void (*PoolFreeWalkMethod)(Pool pool, FreeBlockStepMethod f, void *p);
|
||||
typedef BufferClass (*PoolBufferClassMethod)(void);
|
||||
typedef Res (*PoolDescribeMethod)(Pool pool, mps_lib_FILE *stream);
|
||||
typedef PoolDebugMixin (*PoolDebugMixinMethod)(Pool pool);
|
||||
|
|
@ -294,10 +300,11 @@ typedef Res (*RootScanRegMethod)(ScanState ss, Thread thread, void *p, size_t s)
|
|||
|
||||
/* Format varieties */
|
||||
enum {
|
||||
FormatVarietyA = 1,
|
||||
FormatVarietyB,
|
||||
FormatVarietyAutoHeader,
|
||||
FormatVarietyLIMIT
|
||||
FormatVarietyA = 1,
|
||||
FormatVarietyB,
|
||||
FormatVarietyAutoHeader,
|
||||
FormatVarietyFixed,
|
||||
FormatVarietyLIMIT
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (c) 2002 Global Graphics Software.
|
||||
*
|
||||
* .readership: customers, MPS developers.
|
||||
* .sources: design.mps.interface.c.
|
||||
|
|
@ -10,7 +11,6 @@
|
|||
#ifndef mps_h
|
||||
#define mps_h
|
||||
|
||||
#include "mpstd.h" /* detect platform */
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <limits.h>
|
||||
|
|
@ -39,7 +39,7 @@ typedef struct mps_frame_s
|
|||
|
||||
/* Concrete Types */
|
||||
|
||||
typedef MPS_T_WORD mps_word_t; /* machine word (target dep.) */
|
||||
typedef unsigned long mps_word_t; /* pointer-sized word */
|
||||
typedef int mps_bool_t; /* boolean (int) */
|
||||
typedef int mps_res_t; /* result code (int) */
|
||||
typedef unsigned mps_shift_t; /* shift amount (unsigned int) */
|
||||
|
|
@ -133,11 +133,13 @@ typedef struct mps_sac_s {
|
|||
} mps_sac_s;
|
||||
|
||||
/* .sacc: Keep in sync with impl.h.sac. */
|
||||
typedef struct mps_sac_classes_s {
|
||||
typedef struct mps_sac_class_s {
|
||||
size_t mps_block_size;
|
||||
size_t mps_cached_count;
|
||||
unsigned mps_frequency;
|
||||
} mps_sac_classes_s;
|
||||
} mps_sac_class_s;
|
||||
|
||||
#define mps_sac_classes_s mps_sac_class_s
|
||||
|
||||
|
||||
/* Location Dependency */
|
||||
|
|
@ -210,6 +212,15 @@ typedef struct mps_fmt_auto_header_s {
|
|||
} mps_fmt_auto_header_s;
|
||||
|
||||
|
||||
typedef struct mps_fmt_fixed_s {
|
||||
mps_align_t align;
|
||||
mps_fmt_scan_t scan;
|
||||
mps_fmt_fwd_t fwd;
|
||||
mps_fmt_isfwd_t isfwd;
|
||||
mps_fmt_pad_t pad;
|
||||
} mps_fmt_fixed_s;
|
||||
|
||||
|
||||
/* Internal Definitions */
|
||||
|
||||
#define MPS_BEGIN do {
|
||||
|
|
@ -222,15 +233,6 @@ typedef struct mps_fmt_auto_header_s {
|
|||
*/
|
||||
|
||||
|
||||
/* Assertion Handling */
|
||||
|
||||
typedef void (*mps_assert_t)(const char *, const char *, const char *,
|
||||
unsigned);
|
||||
|
||||
extern mps_assert_t mps_assert_install(mps_assert_t);
|
||||
extern mps_assert_t mps_assert_default(void);
|
||||
|
||||
|
||||
/* arenas */
|
||||
|
||||
extern void mps_arena_clamp(mps_arena_t);
|
||||
|
|
@ -278,6 +280,8 @@ extern mps_res_t mps_fmt_create_B(mps_fmt_t *, mps_arena_t,
|
|||
mps_fmt_B_s *);
|
||||
extern mps_res_t mps_fmt_create_auto_header(mps_fmt_t *, mps_arena_t,
|
||||
mps_fmt_auto_header_s *);
|
||||
extern mps_res_t mps_fmt_create_fixed(mps_fmt_t *, mps_arena_t,
|
||||
mps_fmt_fixed_s *);
|
||||
extern void mps_fmt_destroy(mps_fmt_t);
|
||||
|
||||
|
||||
|
|
@ -481,22 +485,8 @@ extern mps_res_t mps_stack_scan_ambig(mps_ss_t, mps_thr_t,
|
|||
/* Protection Trampoline and Thread Registration */
|
||||
|
||||
typedef void *(*mps_tramp_t)(void *, size_t);
|
||||
|
||||
extern void (mps_tramp)(void **, mps_tramp_t, void *, size_t);
|
||||
|
||||
#ifndef mps_tramp /* If a platform-specific version hasn't been defined */
|
||||
|
||||
#define mps_tramp(r_o, f, p, s) \
|
||||
MPS_BEGIN \
|
||||
void **_r_o = (r_o); \
|
||||
mps_tramp_t _f = (f); \
|
||||
void *_p = (p); \
|
||||
size_t _s = (s); \
|
||||
*_r_o = (*_f)(_p, _s); \
|
||||
MPS_END
|
||||
|
||||
#endif
|
||||
|
||||
extern mps_res_t mps_thread_reg(mps_thr_t *, mps_arena_t);
|
||||
extern void mps_thread_dereg(mps_thr_t);
|
||||
|
||||
|
|
@ -542,7 +532,7 @@ extern size_t mps_message_gc_not_condemned_size(mps_arena_t,
|
|||
/* Finalization */
|
||||
|
||||
extern mps_res_t mps_finalize(mps_arena_t, mps_addr_t *);
|
||||
extern void mps_definalize(mps_arena_t, mps_addr_t *);
|
||||
extern mps_res_t mps_definalize(mps_arena_t, mps_addr_t *);
|
||||
|
||||
|
||||
/* Telemetry */
|
||||
|
|
@ -573,15 +563,18 @@ extern void mps_arena_roots_walk(mps_arena_t,
|
|||
void *, size_t);
|
||||
|
||||
|
||||
/* Fenceposting */
|
||||
/* Allocation debug options */
|
||||
|
||||
|
||||
typedef struct mps_pool_debug_option_s {
|
||||
void* fence_template;
|
||||
size_t fence_size;
|
||||
void* free_template;
|
||||
size_t free_size;
|
||||
} mps_pool_debug_option_s;
|
||||
|
||||
extern void mps_pool_check_fenceposts(mps_pool_t);
|
||||
extern void mps_pool_check_free_space(mps_pool_t);
|
||||
|
||||
|
||||
/* Scanner Support */
|
||||
|
|
@ -598,7 +591,8 @@ extern mps_res_t mps_fix(mps_ss_t, mps_addr_t *);
|
|||
{
|
||||
|
||||
#define MPS_FIX1(ss, ref) \
|
||||
(_mps_wt = 1uL<<((mps_word_t)(ref)>>_mps_w0&(MPS_WORD_WIDTH-1)), \
|
||||
(_mps_wt = 1uL << ((mps_word_t)(ref) >> _mps_w0 \
|
||||
& (sizeof(mps_word_t) * CHAR_BIT - 1)), \
|
||||
_mps_w2 |= _mps_wt, \
|
||||
_mps_w1 & _mps_wt)
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (C) 2002 Global Graphics Software.
|
||||
*/
|
||||
|
||||
#ifndef mpscams_h
|
||||
|
|
@ -10,5 +11,6 @@
|
|||
#include "mps.h"
|
||||
|
||||
extern mps_class_t mps_class_ams(void);
|
||||
extern mps_class_t mps_class_ams_debug(void);
|
||||
|
||||
#endif /* mpscams_h */
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (c) 2002 Global Graphics Software.
|
||||
*
|
||||
* .purpose: This code bridges between the MPS interface to C,
|
||||
* impl.h.mps, and the internal MPM interfaces, as defined by
|
||||
|
|
@ -186,18 +187,6 @@ mps_rank_t mps_rank_weak(void)
|
|||
}
|
||||
|
||||
|
||||
mps_assert_t mps_assert_install(mps_assert_t handler)
|
||||
{
|
||||
AVER(handler != NULL);
|
||||
return AssertInstall(handler);
|
||||
}
|
||||
|
||||
mps_assert_t mps_assert_default(void)
|
||||
{
|
||||
return AssertDefault();
|
||||
}
|
||||
|
||||
|
||||
mps_res_t mps_arena_extend(mps_arena_t mps_arena,
|
||||
mps_addr_t base, size_t size)
|
||||
{
|
||||
|
|
@ -442,6 +431,7 @@ void mps_space_destroy(mps_space_t mps_space)
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* mps_arena_has_addr -- is this address managed by this arena? */
|
||||
|
||||
mps_bool_t mps_arena_has_addr(mps_arena_t mps_arena, mps_addr_t p)
|
||||
|
|
@ -554,7 +544,7 @@ mps_res_t mps_fmt_create_auto_header(mps_fmt_t *mps_fmt_o,
|
|||
(FormatSkipMethod)mps_fmt->skip,
|
||||
(FormatMoveMethod)mps_fmt->fwd,
|
||||
(FormatIsMovedMethod)mps_fmt->isfwd,
|
||||
(FormatCopyMethod)NULL,
|
||||
NULL,
|
||||
(FormatPadMethod)mps_fmt->pad,
|
||||
NULL,
|
||||
(Size)mps_fmt->mps_headerSize);
|
||||
|
|
@ -567,6 +557,41 @@ mps_res_t mps_fmt_create_auto_header(mps_fmt_t *mps_fmt_o,
|
|||
}
|
||||
|
||||
|
||||
/* mps_fmt_create_fixed -- create an object format of variant fixed */
|
||||
|
||||
mps_res_t mps_fmt_create_fixed(mps_fmt_t *mps_fmt_o,
|
||||
mps_arena_t mps_arena,
|
||||
mps_fmt_fixed_s *mps_fmt_fixed)
|
||||
{
|
||||
Arena arena = (Arena)mps_arena;
|
||||
Format format;
|
||||
Res res;
|
||||
|
||||
ArenaEnter(arena);
|
||||
|
||||
AVER(mps_fmt_fixed != NULL);
|
||||
|
||||
res = FormatCreate(&format,
|
||||
arena,
|
||||
(Align)mps_fmt_fixed->align,
|
||||
FormatVarietyFixed,
|
||||
(FormatScanMethod)mps_fmt_fixed->scan,
|
||||
NULL,
|
||||
(FormatMoveMethod)mps_fmt_fixed->fwd,
|
||||
(FormatIsMovedMethod)mps_fmt_fixed->isfwd,
|
||||
NULL,
|
||||
(FormatPadMethod)mps_fmt_fixed->pad,
|
||||
NULL,
|
||||
(Size)0);
|
||||
|
||||
ArenaLeave(arena);
|
||||
|
||||
if (res != ResOK) return res;
|
||||
*mps_fmt_o = (mps_fmt_t)format;
|
||||
return MPS_RES_OK;
|
||||
}
|
||||
|
||||
|
||||
/* mps_fmt_destroy -- destroy a format object */
|
||||
|
||||
void mps_fmt_destroy(mps_fmt_t mps_fmt)
|
||||
|
|
@ -1462,7 +1487,7 @@ mps_word_t mps_collections(mps_arena_t mps_arena)
|
|||
}
|
||||
|
||||
|
||||
/* mps_finalize -- register for finalize */
|
||||
/* mps_finalize -- register for finalization */
|
||||
|
||||
mps_res_t mps_finalize(mps_arena_t mps_arena, mps_addr_t *refref)
|
||||
{
|
||||
|
|
@ -1479,11 +1504,22 @@ mps_res_t mps_finalize(mps_arena_t mps_arena, mps_addr_t *refref)
|
|||
return res;
|
||||
}
|
||||
|
||||
void mps_definalize(mps_arena_t arena, mps_addr_t *refref)
|
||||
|
||||
/* mps_definalize -- deregister for finalization */
|
||||
|
||||
mps_res_t mps_definalize(mps_arena_t mps_arena, mps_addr_t *refref)
|
||||
{
|
||||
/* Not yet implemented */
|
||||
UNUSED(arena); UNUSED(refref);
|
||||
NOTREACHED;
|
||||
Res res;
|
||||
Addr object;
|
||||
Arena arena = (Arena)mps_arena;
|
||||
|
||||
ArenaEnter(arena);
|
||||
|
||||
object = (Addr)ArenaPeek(arena, (Addr)refref);
|
||||
res = ArenaDefinalize(arena, object);
|
||||
|
||||
ArenaLeave(arena);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (c) 2002 Global Graphics Software.
|
||||
*/
|
||||
|
||||
#include "testlib.h"
|
||||
|
|
@ -10,11 +11,13 @@
|
|||
#include "mpscmv.h"
|
||||
#include "fmtdy.h"
|
||||
#include "fmtdytst.h"
|
||||
#include "mpstd.h"
|
||||
#ifdef MPS_OS_W3
|
||||
#include "mpsw3.h"
|
||||
#endif
|
||||
#include "mps.h"
|
||||
#if !defined(CONFIG_PROD_EPCORE)
|
||||
# include "mpstd.h"
|
||||
# ifdef MPS_OS_W3
|
||||
# include "mpsw3.h"
|
||||
# endif
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <math.h>
|
||||
|
|
@ -229,12 +232,12 @@ static void arena_commit_test(mps_arena_t arena)
|
|||
die(mps_pool_create(&pool, arena, mps_class_mv(), 0x1000, 1024, 16384),
|
||||
"commit pool create");
|
||||
limit = mps_arena_commit_limit(arena);
|
||||
mps_arena_commit_limit_set(arena, committed);
|
||||
die(mps_arena_commit_limit_set(arena, committed), "commit_limit_set before");
|
||||
do {
|
||||
res = mps_alloc(&p, pool, FILLER_OBJECT_SIZE);
|
||||
} while (res == MPS_RES_OK);
|
||||
die_expect(res, MPS_RES_COMMIT_LIMIT, "Commit limit allocation");
|
||||
mps_arena_commit_limit_set(arena, limit);
|
||||
die(mps_arena_commit_limit_set(arena, limit), "commit_limit_set after");
|
||||
res = mps_alloc(&p, pool, FILLER_OBJECT_SIZE);
|
||||
die_expect(res, MPS_RES_OK, "Allocation failed after raising commit_limit");
|
||||
mps_pool_destroy(pool);
|
||||
|
|
@ -280,6 +283,8 @@ static void *test(void *arg, size_t s)
|
|||
mps_addr_t obj;
|
||||
mps_ld_s ld;
|
||||
mps_alloc_pattern_t ramp = mps_alloc_pattern_ramp();
|
||||
size_t rampCount = 0;
|
||||
mps_res_t res;
|
||||
|
||||
arena = (mps_arena_t)arg;
|
||||
testlib_unused(s);
|
||||
|
|
@ -358,9 +363,20 @@ static void *test(void *arg, size_t s)
|
|||
|
||||
if (rnd() % patternFREQ == 0)
|
||||
switch(rnd() % 4) {
|
||||
case 0: case 1: mps_ap_alloc_pattern_begin(ap, ramp); break;
|
||||
case 2: mps_ap_alloc_pattern_end(ap, ramp); break;
|
||||
case 3: mps_ap_alloc_pattern_reset(ap); break;
|
||||
case 0: case 1: {
|
||||
die(mps_ap_alloc_pattern_begin(ap, ramp), "alloc_pattern_begin");
|
||||
++rampCount;
|
||||
} break;
|
||||
case 2: {
|
||||
res = mps_ap_alloc_pattern_end(ap, ramp);
|
||||
cdie(rampCount > 0 ? res == MPS_RES_OK : res == MPS_RES_FAIL,
|
||||
"alloc_pattern_end");
|
||||
if (rampCount > 0) --rampCount;
|
||||
} break;
|
||||
case 3: {
|
||||
die(mps_ap_alloc_pattern_reset(ap), "alloc_pattern_reset");
|
||||
rampCount = 0;
|
||||
} break;
|
||||
}
|
||||
|
||||
if (rnd() & 1)
|
||||
|
|
@ -377,7 +393,7 @@ static void *test(void *arg, size_t s)
|
|||
reservoir_test(arena);
|
||||
alignmentTest(arena);
|
||||
|
||||
mps_arena_collect(arena);
|
||||
die(mps_arena_collect(arena), "collect");
|
||||
|
||||
mps_free(mv, alloced_obj, 32);
|
||||
alloc_v_test(mv);
|
||||
|
|
@ -402,26 +418,31 @@ int main(int argc, char **argv)
|
|||
{
|
||||
mps_arena_t arena;
|
||||
mps_thr_t thread;
|
||||
#if !defined(CONFIG_PROD_EPCORE) && !defined(CONFIG_PF_XCPPGC)
|
||||
mps_root_t reg_root;
|
||||
#endif
|
||||
void *r;
|
||||
void *marker = ▮
|
||||
|
||||
randomize(argc, argv);
|
||||
|
||||
(void)mps_assert_install(mps_assert_default());
|
||||
die(mps_arena_create(&arena, mps_arena_class_vm(), TEST_ARENA_SIZE),
|
||||
"arena_create");
|
||||
die(mps_thread_reg(&thread, arena), "thread_reg");
|
||||
|
||||
#if !defined(CONFIG_PROD_EPCORE) && !defined(CONFIG_PF_XCPPGC)
|
||||
die(mps_root_create_reg(®_root, arena,
|
||||
MPS_RANK_AMBIG, (mps_rm_t)0,
|
||||
thread, &mps_stack_scan_ambig,
|
||||
marker, (size_t)0),
|
||||
"root_create_reg");
|
||||
#endif
|
||||
|
||||
(mps_tramp)(&r, test, arena, 0); /* non-inlined trampoline */
|
||||
mps_tramp(&r, test, arena, 0);
|
||||
#if !defined(CONFIG_PROD_EPCORE) && !defined(CONFIG_PF_XCPPGC)
|
||||
mps_root_destroy(reg_root);
|
||||
#endif
|
||||
mps_thread_dereg(thread);
|
||||
mps_arena_destroy(arena);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* impl.c.mpsint:
|
||||
/* impl.c.mpsiw3: WIN32 MEMORY POOL SYSTEM INTERFACE LAYER EXTRAS
|
||||
*
|
||||
* WIN32 MEMORY POOL SYSTEM INTERFACE LAYER EXTRAS
|
||||
*
|
||||
|
|
@ -12,9 +12,10 @@
|
|||
|
||||
#include "mpswin.h"
|
||||
|
||||
SRCID(mpsint, "$Id$");
|
||||
SRCID(mpsiw3, "$Id$");
|
||||
|
||||
/* This is defined in protnt.c */
|
||||
|
||||
/* This is defined in protw3.c */
|
||||
extern LONG ProtSEHfilter(LPEXCEPTION_POINTERS info);
|
||||
|
||||
LONG mps_SEH_filter(LPEXCEPTION_POINTERS info,
|
||||
|
|
|
|||
|
|
@ -29,9 +29,7 @@ extern mps_lib_FILE *mps_lib_get_stdout(void);
|
|||
extern int mps_lib_fputc(int, mps_lib_FILE *);
|
||||
extern int mps_lib_fputs(const char *, mps_lib_FILE *);
|
||||
|
||||
|
||||
extern void mps_lib_abort(void);
|
||||
|
||||
extern void mps_lib_assert_fail(const char *);
|
||||
|
||||
extern void *(mps_lib_memset)(void *, int, size_t);
|
||||
extern void *(mps_lib_memcpy)(void *, const void *, size_t);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (c) 2002 Global Graphics Software.
|
||||
*
|
||||
* .purpose: The purpose of this code is
|
||||
* 1. to connect the MPS Library Interface to the ANSI C libraries,
|
||||
|
|
@ -78,8 +79,11 @@ int mps_lib_fputs(const char *s, mps_lib_FILE *stream)
|
|||
}
|
||||
|
||||
|
||||
void mps_lib_abort(void)
|
||||
void mps_lib_assert_fail(const char *message)
|
||||
{
|
||||
fflush(stdout); /* synchronize */
|
||||
fprintf(stderr, "\nMPS ASSERTION FAILURE: %s\n", message);
|
||||
fflush(stderr); /* make sure the message is output */
|
||||
abort();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (C) 2001 Global Graphics Software.
|
||||
*
|
||||
* Detect the target platform using predefined preprocessor symbols
|
||||
* defined by the build environment. The symbols are derived from the
|
||||
|
|
@ -24,8 +25,9 @@
|
|||
* them. Alignment from testing.
|
||||
*/
|
||||
|
||||
#if defined(__sgi) && defined(__unix) && defined(__mips) \
|
||||
&& defined(_SYSTYPE_SVR4) && (_MIPS_FPSET == 16)
|
||||
#if defined(CONFIG_PF_I5M2CC) \
|
||||
|| defined(__sgi) && defined(__unix) && defined(__mips) \
|
||||
&& defined(_SYSTYPE_SVR4) && (_MIPS_FPSET == 16)
|
||||
#define MPS_PF_I5M2CC
|
||||
#define MPS_PF_STRING "i5m2cc"
|
||||
#define MPS_OS_I5
|
||||
|
|
@ -38,8 +40,9 @@
|
|||
|
||||
/* See above. Alignment from testing. */
|
||||
|
||||
#elif defined(__sgi) && defined(__unix) && defined(__mips) \
|
||||
&& defined(_SYSTYPE_SVR4) && defined(_ABIN32)
|
||||
#elif defined(CONFIG_PF_IAM4CC) \
|
||||
|| defined(__sgi) && defined(__unix) && defined(__mips) \
|
||||
&& defined(_SYSTYPE_SVR4) && defined(_ABIN32)
|
||||
#define MPS_PF_IAM4CC
|
||||
#define MPS_PF_STRING "iam4cc"
|
||||
#define MPS_OS_IA
|
||||
|
|
@ -52,7 +55,8 @@
|
|||
|
||||
/* winnt.h from MS VC 2.0 */
|
||||
|
||||
#elif defined(_MSC_VER) && defined(_WIN32) && defined(_M_ALPHA)
|
||||
#elif defined(CONFIG_PF_W3ALMV) \
|
||||
|| defined(_MSC_VER) && defined(_WIN32) && defined(_M_ALPHA)
|
||||
#define MPS_PF_W3ALMV
|
||||
#define MPS_PF_STRING "w3almv"
|
||||
#define MPS_OS_W3
|
||||
|
|
@ -65,7 +69,8 @@
|
|||
|
||||
/* winnt.h from MS VC 2.0 */
|
||||
|
||||
#elif defined(_MSC_VER) && defined(_WIN32) && defined(_M_PPC)
|
||||
#elif defined(CONFIG_PF_W3PPMV) \
|
||||
|| defined(_MSC_VER) && defined(_WIN32) && defined(_M_PPC)
|
||||
#define MPS_PF_W3PPMV
|
||||
#define MPS_PF_STRING "w3ppmv"
|
||||
#define MPS_OS_W3
|
||||
|
|
@ -83,7 +88,8 @@
|
|||
* VC malloc is 16!
|
||||
*/
|
||||
|
||||
#elif defined(_MSC_VER) && defined(_WIN32) && defined(_M_IX86)
|
||||
#elif defined(CONFIG_PF_W3I3MV) \
|
||||
|| defined(_MSC_VER) && defined(_WIN32) && defined(_M_IX86)
|
||||
#define MPS_PF_W3I3MV
|
||||
#define MPS_PF_STRING "w3i3mv"
|
||||
#define MPS_OS_W3
|
||||
|
|
@ -98,7 +104,8 @@
|
|||
* a way to determine the OS -- we assume MacOS 7.
|
||||
*/
|
||||
|
||||
#elif defined(__MWERKS__) && __MC68K__ == 1
|
||||
#elif defined(CONFIG_PF_S760MW) \
|
||||
|| (defined(__MWERKS__) && __MC68K__ == 1)
|
||||
#define MPS_PF_S760MW
|
||||
#define MPS_PF_STRING "s760mw"
|
||||
#define MPS_OS_S7
|
||||
|
|
@ -113,7 +120,8 @@
|
|||
* a way to determine the OS -- we assume MacOS 7.
|
||||
*/
|
||||
|
||||
#elif defined(__MWERKS__) && __POWERPC__ == 1
|
||||
#elif defined(CONFIG_PF_S7PPMW) \
|
||||
|| defined(__MWERKS__) && __POWERPC__ == 1
|
||||
#define MPS_PF_S7PPMW
|
||||
#define MPS_PF_STRING "s7ppmw"
|
||||
#define MPS_OS_S7
|
||||
|
|
@ -130,7 +138,8 @@
|
|||
* which lets us determine the system version.
|
||||
*/
|
||||
|
||||
#elif defined(m68k) && (defined (applec) || defined(__SC__))
|
||||
#elif defined(CONFIG_PF_S760AC) \
|
||||
|| defined(m68k) && (defined (applec) || defined(__SC__))
|
||||
#define MPS_PF_S760AC
|
||||
#define MPS_PF_STRING "s760ac"
|
||||
#define MPS_OS_S7
|
||||
|
|
@ -147,7 +156,8 @@
|
|||
* which lets us determine the system version.
|
||||
*/
|
||||
|
||||
#elif defined(__PPCC__) || (defined(__MRC__) && defined(__POWERPC))
|
||||
#elif defined(CONFIG_PF_S7PPAC) \
|
||||
|| defined(__PPCC__) || (defined(__MRC__) && defined(__POWERPC))
|
||||
#define MPS_PF_S7PPAC
|
||||
#define MPS_PF_STRING "s7ppac"
|
||||
#define MPS_OS_S7
|
||||
|
|
@ -163,7 +173,9 @@
|
|||
* ools/Preprocessor/Preprocessor.[ef].html>
|
||||
*/
|
||||
|
||||
#elif defined(__APPLE__) && defined(__ppc__) && defined(__MACH__) && defined(__GNUC__)
|
||||
#elif defined(CONFIG_PF_XCPPGC) \
|
||||
|| defined(__APPLE__) && defined(__ppc__) && defined(__MACH__) \
|
||||
&& defined(__GNUC__)
|
||||
#define MPS_PF_XCPPGC
|
||||
#define MPS_PF_STRING "xcppgc"
|
||||
#define MPS_OS_XC
|
||||
|
|
@ -176,8 +188,9 @@
|
|||
|
||||
/* GCC 2.5.8, gcc -E -dM, (__SVR4 indicates Solaris) */
|
||||
|
||||
#elif defined(__sun__) && defined(__sparc__) && defined(__GNUC__) \
|
||||
&& !defined(__svr4__)
|
||||
#elif defined(CONFIG_PF_SUS8GC) \
|
||||
|| defined(__sun__) && defined(__sparc__) && defined(__GNUC__) \
|
||||
&& !defined(__svr4__)
|
||||
#define MPS_PF_SUS8GC
|
||||
#define MPS_PF_STRING "sus8gc"
|
||||
#define MPS_OS_SU
|
||||
|
|
@ -190,8 +203,9 @@
|
|||
|
||||
/* LCC 3.4 (ish), man page */
|
||||
|
||||
#elif defined(sun) && defined(sparc) && defined(__LCC__) \
|
||||
&& !defined(__svr4__)
|
||||
#elif defined(CONFIG_PF_SUS8LC) \
|
||||
|| defined(sun) && defined(sparc) && defined(__LCC__) \
|
||||
&& !defined(__svr4__)
|
||||
#define MPS_PF_SUS8LC
|
||||
#define MPS_PF_STRING "sus8lc"
|
||||
#define MPS_OS_SU
|
||||
|
|
@ -204,8 +218,9 @@
|
|||
|
||||
/* GCC 2.5.8, gcc -E -dM */
|
||||
|
||||
#elif defined(__sun__) && defined(__sparc__) && defined(__GNUC__) \
|
||||
&& defined(__svr4__)
|
||||
#elif defined(CONFIG_PF_SOS8GC) \
|
||||
|| defined(__sun__) && defined(__sparc__) && defined(__GNUC__) \
|
||||
&& defined(__svr4__)
|
||||
#define MPS_PF_SOS8GC
|
||||
#define MPS_PF_STRING "sos8gc"
|
||||
#define MPS_OS_SO
|
||||
|
|
@ -221,9 +236,9 @@
|
|||
* macros for that.
|
||||
*/
|
||||
|
||||
#elif defined(__sun) && defined(__SUNPRO_C) && defined(__SVR4) \
|
||||
&& defined(__sparc)
|
||||
|
||||
#elif defined(CONFIG_PF_SOS9SC) \
|
||||
|| defined(__sun) && defined(__SUNPRO_C) && defined(__SVR4) \
|
||||
&& defined(__sparc)
|
||||
#define MPS_PF_SOS9SC
|
||||
#define MPS_PF_STRING "sos9sc"
|
||||
#define MPS_OS_SO
|
||||
|
|
@ -236,7 +251,8 @@
|
|||
|
||||
/* GCC 2.6.3, gcc -E -dM */
|
||||
|
||||
#elif defined(__osf__) && defined(__alpha__) && defined(__GNUC__)
|
||||
#elif defined(CONFIG_PF_O1ALGC) \
|
||||
|| defined(__osf__) && defined(__alpha__) && defined(__GNUC__)
|
||||
#define MPS_PF_O1ALGC
|
||||
#define MPS_PF_STRING "o1algc"
|
||||
#define MPS_OS_O1
|
||||
|
|
@ -250,7 +266,8 @@
|
|||
|
||||
/* From the cc(1) man page */
|
||||
|
||||
#elif defined(__osf__) && defined(__alpha) && defined(__DECC)
|
||||
#elif defined(CONFIG_PF_O1ALCC) \
|
||||
|| defined(__osf__) && defined(__alpha) && defined(__DECC)
|
||||
#define MPS_PF_O1ALCC
|
||||
#define MPS_PF_STRING "o1alcc"
|
||||
#define MPS_OS_O1
|
||||
|
|
@ -267,7 +284,8 @@
|
|||
* all 4.
|
||||
*/
|
||||
|
||||
#elif defined(__linux__) && defined(__i386__) && defined(__GNUC__)
|
||||
#elif defined(CONFIG_PF_LII4GC) \
|
||||
|| defined(__linux__) && defined(__i386__) && defined(__GNUC__)
|
||||
#define MPS_PF_LII4GC
|
||||
#define MPS_PF_STRING "lii4gc"
|
||||
#define MPS_OS_LI
|
||||
|
|
@ -280,7 +298,8 @@
|
|||
|
||||
/* GCC 2.7.2, gcc -E -dM */
|
||||
|
||||
#elif defined(__linux__) && defined(__PPC__) && defined(__GNUC__)
|
||||
#elif defined(CONFIG_PF_LIPPGC) \
|
||||
|| defined(__linux__) && defined(__PPC__) && defined(__GNUC__)
|
||||
#define MPS_PF_LIPPGC
|
||||
#define MPS_PF_STRING "lippgc"
|
||||
#define MPS_OS_LI
|
||||
|
|
@ -294,7 +313,8 @@
|
|||
/* GCC 2.95.3, gcc -E -dM
|
||||
*/
|
||||
|
||||
#elif defined(__FreeBSD__) && defined (__i386__) && defined (__GNUC__)
|
||||
#elif defined(CONFIG_PF_FRI4GC) \
|
||||
|| defined(__FreeBSD__) && defined (__i386__) && defined (__GNUC__)
|
||||
#define MPS_PF_FRI4GC
|
||||
#define MPS_PF_STRING "fri4gc"
|
||||
#define MPS_OS_FR
|
||||
|
|
|
|||
|
|
@ -11,15 +11,13 @@
|
|||
#define mpsw3_h
|
||||
|
||||
#include "mps.h" /* needed for mps_tramp_t */
|
||||
#include "mpswin.h" /* needed for SEH filter */
|
||||
#include <windows.h> /* needed for SEH filter */
|
||||
|
||||
|
||||
extern LONG mps_SEH_filter(LPEXCEPTION_POINTERS, void **, size_t *);
|
||||
extern void mps_SEH_handler(void *, size_t);
|
||||
|
||||
|
||||
#undef mps_tramp /* Override generic version */
|
||||
|
||||
#define mps_tramp(r_o, f, p, s) \
|
||||
MPS_BEGIN \
|
||||
void **_r_o = (r_o); \
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (C) 2001 Global Graphics Software.
|
||||
*
|
||||
* DESIGN
|
||||
*
|
||||
|
|
@ -51,10 +52,13 @@ Bool PoolClassCheck(PoolClass class)
|
|||
CHECKL(FUNCHECK(class->free));
|
||||
CHECKL(FUNCHECK(class->bufferFill));
|
||||
CHECKL(FUNCHECK(class->bufferEmpty));
|
||||
CHECKL(FUNCHECK(class->access));
|
||||
CHECKL(FUNCHECK(class->whiten));
|
||||
CHECKL(FUNCHECK(class->grey));
|
||||
CHECKL(FUNCHECK(class->blacken));
|
||||
CHECKL(FUNCHECK(class->scan));
|
||||
CHECKL(FUNCHECK(class->fix));
|
||||
CHECKL(FUNCHECK(class->fixEmergency));
|
||||
CHECKL(FUNCHECK(class->reclaim));
|
||||
CHECKL(FUNCHECK(class->rampBegin));
|
||||
CHECKL(FUNCHECK(class->rampEnd));
|
||||
|
|
@ -62,7 +66,10 @@ Bool PoolClassCheck(PoolClass class)
|
|||
CHECKL(FUNCHECK(class->framePop));
|
||||
CHECKL(FUNCHECK(class->framePopPending));
|
||||
CHECKL(FUNCHECK(class->walk));
|
||||
CHECKL(FUNCHECK(class->freewalk));
|
||||
CHECKL(FUNCHECK(class->bufferClass));
|
||||
CHECKL(FUNCHECK(class->describe));
|
||||
CHECKL(FUNCHECK(class->debugMixin));
|
||||
CHECKS(PoolClass, class);
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -452,7 +459,7 @@ void PoolReclaim(Pool pool, Trace trace, Seg seg)
|
|||
}
|
||||
|
||||
|
||||
/* PoolWalk -- walk objects in this pool */
|
||||
/* PoolWalk -- walk objects in this segment */
|
||||
|
||||
void PoolWalk(Pool pool, Seg seg, FormattedObjectsStepMethod f,
|
||||
void *p, Size s)
|
||||
|
|
@ -466,6 +473,21 @@ void PoolWalk(Pool pool, Seg seg, FormattedObjectsStepMethod f,
|
|||
}
|
||||
|
||||
|
||||
/* PoolFreeWalk -- walk free blocks in this pool
|
||||
*
|
||||
* PoolFreeWalk is not required to find all free blocks.
|
||||
*/
|
||||
|
||||
void PoolFreeWalk(Pool pool, FreeBlockStepMethod f, void *p)
|
||||
{
|
||||
AVERT(Pool, pool);
|
||||
AVER(FUNCHECK(f));
|
||||
/* p is arbitrary, hence can't be checked. */
|
||||
|
||||
(*pool->class->freewalk)(pool, f, p);
|
||||
}
|
||||
|
||||
|
||||
/* PoolDescribe -- describe a pool */
|
||||
|
||||
Res PoolDescribe(Pool pool, mps_lib_FILE *stream)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* PURPOSE
|
||||
*
|
||||
|
|
@ -141,6 +142,7 @@ DEFINE_CLASS(AbstractPoolClass, class)
|
|||
class->framePop = PoolNoFramePop;
|
||||
class->framePopPending = PoolNoFramePopPending;
|
||||
class->walk = PoolNoWalk;
|
||||
class->freewalk = PoolNoFreeWalk;
|
||||
class->bufferClass = PoolNoBufferClass;
|
||||
class->describe = PoolTrivDescribe;
|
||||
class->debugMixin = PoolNoDebugMixin;
|
||||
|
|
@ -620,6 +622,18 @@ void PoolNoWalk(Pool pool, Seg seg,
|
|||
}
|
||||
|
||||
|
||||
void PoolNoFreeWalk(Pool pool, FreeBlockStepMethod f, void *p)
|
||||
{
|
||||
AVERT(Pool, pool);
|
||||
AVER(FUNCHECK(f));
|
||||
/* p is arbitrary, hence can't be checked */
|
||||
UNUSED(p);
|
||||
|
||||
/* FreeWalk doesn't have be perfect, so just pretend you didn't find any. */
|
||||
NOOP;
|
||||
}
|
||||
|
||||
|
||||
BufferClass PoolNoBufferClass(void)
|
||||
{
|
||||
NOTREACHED;
|
||||
|
|
|
|||
|
|
@ -2,12 +2,14 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* .sources: design.mps.poolamc.
|
||||
*/
|
||||
|
||||
#include "mpscamc.h"
|
||||
#include "chain.h"
|
||||
#include "bt.h"
|
||||
#include "mpm.h"
|
||||
|
||||
SRCID(poolamc, "$Id$");
|
||||
|
|
@ -1694,14 +1696,7 @@ static void amcReclaimNailed(Pool pool, Trace trace, Seg seg)
|
|||
arena = PoolArena(pool);
|
||||
AVERT(Arena, arena);
|
||||
|
||||
if (!amcSegHasNailboard(seg)) {
|
||||
/* We didn't keep a mark table, so preserve everything. */
|
||||
/* We can't do anything about preservedInPlaceCount. */
|
||||
trace->preservedInPlaceSize += SegSize(seg);
|
||||
goto adjustColour;
|
||||
}
|
||||
|
||||
/* see design.mps.poolamc.Nailboard.limitations for improvements */
|
||||
/* see design.mps.poolamc.nailboard.limitations for improvements */
|
||||
headerSize = format->headerSize;
|
||||
ShieldExpose(arena, seg);
|
||||
p = AddrAdd(SegBase(seg), headerSize);
|
||||
|
|
@ -1715,7 +1710,11 @@ static void amcReclaimNailed(Pool pool, Trace trace, Seg seg)
|
|||
Size length;
|
||||
q = (*format->skip)(p);
|
||||
length = AddrOffset(p, q);
|
||||
if (!amcNailGetMark(seg, p)) {
|
||||
if (amcSegHasNailboard(seg)
|
||||
? !amcNailGetMark(seg, p)
|
||||
/* If there's no mark table, retain all that hasn't been forwarded. In
|
||||
* this case, preservedInPlace* become somewhat overstated. */
|
||||
: (*format->isMoved)(p) != NULL) {
|
||||
(*format->pad)(AddrSub(p, headerSize), length);
|
||||
bytesReclaimed += length;
|
||||
} else {
|
||||
|
|
@ -1729,7 +1728,6 @@ static void amcReclaimNailed(Pool pool, Trace trace, Seg seg)
|
|||
AVER(p == limit);
|
||||
ShieldCover(arena, seg);
|
||||
|
||||
adjustColour:
|
||||
SegSetNailed(seg, TraceSetDel(SegNailed(seg), trace));
|
||||
SegSetWhite(seg, TraceSetDel(SegWhite(seg), trace));
|
||||
if (SegNailed(seg) == TraceSetEMPTY && amcSegHasNailboard(seg)) {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (c) 2002 Global Graphics Software.
|
||||
*
|
||||
*
|
||||
* .design: See design.mps.poolams.
|
||||
*
|
||||
|
|
@ -13,8 +15,8 @@
|
|||
* (as opposed to being constructed by the caller).
|
||||
*/
|
||||
|
||||
#include "mpscams.h"
|
||||
#include "poolams.h"
|
||||
#include "dbgpool.h"
|
||||
#include "mpm.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
|
|
@ -25,6 +27,21 @@ SRCID(poolams, "$Id$");
|
|||
#define AMSSegSig ((Sig)0x519A3559) /* SIGnature AMS SeG */
|
||||
|
||||
|
||||
/* AMSDebugStruct -- structure for a debug subclass */
|
||||
|
||||
typedef struct AMSDebugStruct {
|
||||
AMSStruct amsStruct; /* AMS structure */
|
||||
PoolDebugMixinStruct debug; /* debug mixin */
|
||||
} AMSDebugStruct;
|
||||
|
||||
typedef struct AMSDebugStruct *AMSDebug;
|
||||
|
||||
|
||||
#define AMS2AMSDebug(ams) PARENT(AMSDebugStruct, amsStruct, ams)
|
||||
#define AMSDebug2AMS(amsd) (&((amsd)->amsStruct))
|
||||
|
||||
|
||||
|
||||
/* AMSSegCheck -- check an AMS segment */
|
||||
|
||||
Bool AMSSegCheck(AMSSeg amsseg)
|
||||
|
|
@ -34,18 +51,26 @@ Bool AMSSegCheck(AMSSeg amsseg)
|
|||
CHECKL(GCSegCheck(&amsseg->gcSegStruct));
|
||||
CHECKU(AMS, amsseg->ams);
|
||||
CHECKL(AMS2Pool(amsseg->ams) == SegPool(seg));
|
||||
CHECKL(RingCheck(&amsseg->segRing));
|
||||
CHECKD_NOSIG(Ring, &amsseg->segRing);
|
||||
|
||||
CHECKL(amsseg->grains == AMSGrains(amsseg->ams, SegSize(seg)));
|
||||
CHECKL(amsseg->grains > 0);
|
||||
CHECKL(amsseg->grains >= amsseg->free + amsseg->newAlloc);
|
||||
|
||||
if (SegWhite(seg) != TraceSetEMPTY)
|
||||
CHECKL(BoolCheck(amsseg->allocTableInUse));
|
||||
if (!amsseg->allocTableInUse)
|
||||
CHECKL(amsseg->firstFree <= amsseg->grains);
|
||||
CHECKL(amsseg->allocTable != NULL);
|
||||
|
||||
if (SegWhite(seg) != TraceSetEMPTY) {
|
||||
/* design.mps.poolams.colour.single */
|
||||
CHECKL(TraceSetIsSingle(SegWhite(seg)));
|
||||
CHECKL(amsseg->colourTablesInUse);
|
||||
}
|
||||
|
||||
CHECKL(BoolCheck(amsseg->marksChanged));
|
||||
CHECKL(amsseg->allocTable != NULL);
|
||||
CHECKL(BoolCheck(amsseg->ambiguousFixes));
|
||||
CHECKL(BoolCheck(amsseg->colourTablesInUse));
|
||||
CHECKL(amsseg->nongreyTable != NULL);
|
||||
CHECKL(amsseg->nonwhiteTable != NULL);
|
||||
|
||||
|
|
@ -53,9 +78,69 @@ Bool AMSSegCheck(AMSSeg amsseg)
|
|||
}
|
||||
|
||||
|
||||
/* AMSSegFreeWalk -- walk the free space in a segment */
|
||||
|
||||
void AMSSegFreeWalk(AMSSeg amsseg, FreeBlockStepMethod f, void *p)
|
||||
{
|
||||
Pool pool;
|
||||
Seg seg;
|
||||
|
||||
AVERT(AMSSeg, amsseg);
|
||||
pool = SegPool(AMSSeg2Seg(amsseg));
|
||||
seg = AMSSeg2Seg(amsseg);
|
||||
|
||||
if (amsseg->free == 0)
|
||||
return;
|
||||
if (amsseg->allocTableInUse) {
|
||||
Index base, limit, next;
|
||||
|
||||
next = 0;
|
||||
while (next < amsseg->grains) {
|
||||
Bool found = BTFindLongResRange(&base, &limit, amsseg->allocTable,
|
||||
next, amsseg->grains, 1);
|
||||
if (!found) break;
|
||||
(*f)(AMS_INDEX_ADDR(seg, base), AMS_INDEX_ADDR(seg, limit), pool, p);
|
||||
next = limit + 1;
|
||||
}
|
||||
} else {
|
||||
if ( amsseg->firstFree < amsseg->grains )
|
||||
(*f)(AMS_INDEX_ADDR(seg, amsseg->firstFree), SegLimit(seg), pool, p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* AMSSegFreeCheck -- check the free space in a segment */
|
||||
|
||||
static void amsFreeBlockCheckStep(Addr base, Addr limit, Pool pool, void *p)
|
||||
{
|
||||
UNUSED(p);
|
||||
DebugPoolFreeCheck(pool, base, limit);
|
||||
}
|
||||
|
||||
void AMSSegFreeCheck(AMSSeg amsseg)
|
||||
{
|
||||
Pool pool;
|
||||
PoolDebugMixin debug;
|
||||
|
||||
AVERT(AMSSeg, amsseg);
|
||||
|
||||
if (amsseg->free == 0)
|
||||
return;
|
||||
|
||||
/* If it's not a debug class, don't bother walking. */
|
||||
pool = SegPool(AMSSeg2Seg(amsseg));
|
||||
AVERT(Pool, pool);
|
||||
debug = ((pool)->class->debugMixin)(pool);
|
||||
if (debug == NULL)
|
||||
return;
|
||||
|
||||
AMSSegFreeWalk(amsseg, amsFreeBlockCheckStep, NULL);
|
||||
}
|
||||
|
||||
|
||||
/* amsCreateTables -- create the tables for an AMS seg */
|
||||
|
||||
static Res amsCreateTables(BT *allocReturn,
|
||||
static Res amsCreateTables(AMS ams, BT *allocReturn,
|
||||
BT *nongreyReturn, BT *nonwhiteReturn,
|
||||
Arena arena, Count length)
|
||||
{
|
||||
|
|
@ -74,9 +159,13 @@ static Res amsCreateTables(BT *allocReturn,
|
|||
res = BTCreate(&nongreyTable, arena, length);
|
||||
if (res != ResOK)
|
||||
goto failGrey;
|
||||
res = BTCreate(&nonwhiteTable, arena, length);
|
||||
if (res != ResOK)
|
||||
goto failWhite;
|
||||
if (ams->shareAllocTable)
|
||||
nonwhiteTable = allocTable;
|
||||
else {
|
||||
res = BTCreate(&nonwhiteTable, arena, length);
|
||||
if (res != ResOK)
|
||||
goto failWhite;
|
||||
}
|
||||
|
||||
*allocReturn = allocTable;
|
||||
*nongreyReturn = nongreyTable;
|
||||
|
|
@ -94,7 +183,7 @@ failAlloc:
|
|||
|
||||
/* amsDestroyTables -- destroy the tables for an AMS seg */
|
||||
|
||||
static void amsDestroyTables(BT allocTable,
|
||||
static void amsDestroyTables(AMS ams, BT allocTable,
|
||||
BT nongreyTable, BT nonwhiteTable,
|
||||
Arena arena, Count length)
|
||||
{
|
||||
|
|
@ -104,7 +193,8 @@ static void amsDestroyTables(BT allocTable,
|
|||
AVERT(Arena, arena);
|
||||
AVER(length > 0);
|
||||
|
||||
BTDestroy(nonwhiteTable, arena, length);
|
||||
if (!ams->shareAllocTable)
|
||||
BTDestroy(nonwhiteTable, arena, length);
|
||||
BTDestroy(nongreyTable, arena, length);
|
||||
BTDestroy(allocTable, arena, length);
|
||||
}
|
||||
|
|
@ -142,7 +232,7 @@ static Res AMSSegInit(Seg seg, Pool pool, Addr base, Size size,
|
|||
amsseg->marksChanged = FALSE; /* design.mps.poolams.marked.unused */
|
||||
amsseg->ambiguousFixes = FALSE;
|
||||
|
||||
res = amsCreateTables(&amsseg->allocTable,
|
||||
res = amsCreateTables(ams, &amsseg->allocTable,
|
||||
&amsseg->nongreyTable, &amsseg->nonwhiteTable,
|
||||
arena, amsseg->grains);
|
||||
if (res != ResOK)
|
||||
|
|
@ -189,7 +279,7 @@ static void AMSSegFinish(Seg seg)
|
|||
AVER(SegBuffer(seg) == NULL);
|
||||
|
||||
/* keep the destructions in step with AMSSegInit failure cases */
|
||||
amsDestroyTables(amsseg->allocTable, amsseg->nongreyTable,
|
||||
amsDestroyTables(ams, amsseg->allocTable, amsseg->nongreyTable,
|
||||
amsseg->nonwhiteTable, arena, amsseg->grains);
|
||||
|
||||
RingRemove(&amsseg->segRing);
|
||||
|
|
@ -259,7 +349,7 @@ static Res AMSSegMerge(Seg seg, Seg segHi,
|
|||
AVER(!amssegHi->marksChanged);
|
||||
|
||||
/* .alloc-early */
|
||||
res = amsCreateTables(&allocTable, &nongreyTable, &nonwhiteTable,
|
||||
res = amsCreateTables(ams, &allocTable, &nongreyTable, &nonwhiteTable,
|
||||
arena, allGrains);
|
||||
if (res != ResOK)
|
||||
goto failCreateTables;
|
||||
|
|
@ -283,9 +373,10 @@ static Res AMSSegMerge(Seg seg, Seg segHi,
|
|||
amsseg->table = (table); \
|
||||
END
|
||||
|
||||
MERGE_TABLES(nonwhiteTable, BTSetRange);
|
||||
MERGE_TABLES(nongreyTable, BTSetRange);
|
||||
MERGE_TABLES(allocTable, BTResRange);
|
||||
MERGE_TABLES(nongreyTable, BTSetRange);
|
||||
if (!ams->shareAllocTable)
|
||||
MERGE_TABLES(nonwhiteTable, BTSetRange);
|
||||
|
||||
amsseg->grains = allGrains;
|
||||
amsseg->free = amsseg->free + amssegHi->free;
|
||||
|
|
@ -300,7 +391,7 @@ static Res AMSSegMerge(Seg seg, Seg segHi,
|
|||
return ResOK;
|
||||
|
||||
failSuper:
|
||||
amsDestroyTables(allocTable, nongreyTable, nonwhiteTable,
|
||||
amsDestroyTables(ams, allocTable, nongreyTable, nonwhiteTable,
|
||||
arena, allGrains);
|
||||
failCreateTables:
|
||||
AVERT(AMSSeg, amsseg);
|
||||
|
|
@ -346,11 +437,11 @@ static Res AMSSegSplit(Seg seg, Seg segHi,
|
|||
}
|
||||
|
||||
/* .alloc-early */
|
||||
res = amsCreateTables(&allocTableLo, &nongreyTableLo, &nonwhiteTableLo,
|
||||
res = amsCreateTables(ams, &allocTableLo, &nongreyTableLo, &nonwhiteTableLo,
|
||||
arena, loGrains);
|
||||
if (res != ResOK)
|
||||
goto failCreateTablesLo;
|
||||
res = amsCreateTables(&allocTableHi, &nongreyTableHi, &nonwhiteTableHi,
|
||||
res = amsCreateTables(ams, &allocTableHi, &nongreyTableHi, &nonwhiteTableHi,
|
||||
arena, hiGrains);
|
||||
if (res != ResOK)
|
||||
goto failCreateTablesHi;
|
||||
|
|
@ -403,10 +494,10 @@ static Res AMSSegSplit(Seg seg, Seg segHi,
|
|||
return ResOK;
|
||||
|
||||
failSuper:
|
||||
amsDestroyTables(allocTableHi, nongreyTableHi, nonwhiteTableHi,
|
||||
amsDestroyTables(ams, allocTableHi, nongreyTableHi, nonwhiteTableHi,
|
||||
arena, hiGrains);
|
||||
failCreateTablesHi:
|
||||
amsDestroyTables(allocTableLo, nongreyTableLo, nonwhiteTableLo,
|
||||
amsDestroyTables(ams, allocTableLo, nongreyTableLo, nonwhiteTableLo,
|
||||
arena, loGrains);
|
||||
failCreateTablesLo:
|
||||
AVERT(AMSSeg, amsseg);
|
||||
|
|
@ -481,11 +572,11 @@ static Res AMSSegDescribe(Seg seg, mps_lib_FILE *stream)
|
|||
|
||||
if (AMS_ALLOCED(seg, i)) {
|
||||
if (amsseg->colourTablesInUse) {
|
||||
if (AMSIsInvalidColor(seg, i))
|
||||
if (AMS_IS_INVALID_COLOUR(seg, i))
|
||||
c = '!';
|
||||
else if (AMSIsWhite(seg, i))
|
||||
else if (AMS_IS_WHITE(seg, i))
|
||||
c = '-';
|
||||
else if (AMSIsGrey(seg, i))
|
||||
else if (AMS_IS_GREY(seg, i))
|
||||
c = '+';
|
||||
else /* must be black */
|
||||
c = '*';
|
||||
|
|
@ -599,14 +690,15 @@ static Res AMSSegCreate(Seg *segReturn, Pool pool, Size size,
|
|||
if (res != ResOK)
|
||||
goto failSeg;
|
||||
}
|
||||
PoolGenUpdateZones(&ams->pgen, seg);
|
||||
|
||||
PoolGenUpdateZones(&ams->pgen, seg);
|
||||
/* see design.mps.seg.field.rankset */
|
||||
if (rankSet != RankSetEMPTY) {
|
||||
SegSetRankAndSummary(seg, rankSet, RefSetUNIV);
|
||||
} else {
|
||||
SegSetRankAndSummary(seg, rankSet, RefSetEMPTY);
|
||||
}
|
||||
DebugPoolFreeSplat(pool, SegBase(seg), SegLimit(seg));
|
||||
|
||||
AVERT(AMSSeg, Seg2AMSSeg(seg));
|
||||
|
||||
|
|
@ -629,14 +721,12 @@ static void AMSSegsDestroy(AMS ams)
|
|||
RING_FOR(node, ring, next) {
|
||||
Seg seg = SegOfPoolRing(node);
|
||||
AVER(Seg2AMSSeg(seg)->ams == ams);
|
||||
AMSSegFreeCheck(Seg2AMSSeg(seg));
|
||||
SegFree(seg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static Res AMSIterate(Seg seg, AMSObjectFunction f, void *closure);
|
||||
|
||||
|
||||
/* AMSInit -- the pool class initialization method
|
||||
*
|
||||
* Takes one additional argument: the format of the objects
|
||||
|
|
@ -647,12 +737,16 @@ static Res AMSInit(Pool pool, va_list args)
|
|||
Res res;
|
||||
Format format;
|
||||
Chain chain;
|
||||
Bool supportAmbiguous;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
|
||||
format = va_arg(args, Format);
|
||||
chain = va_arg(args, Chain);
|
||||
res = AMSInitInternal(Pool2AMS(pool), format, chain);
|
||||
supportAmbiguous = va_arg(args, Bool);
|
||||
/* .ambiguous.noshare: If the pool is required to support ambiguous */
|
||||
/* references, the alloc and white tables cannot be shared. */
|
||||
res = AMSInitInternal(Pool2AMS(pool), format, chain, !supportAmbiguous);
|
||||
if (res == ResOK) {
|
||||
EVENT_PPP(PoolInitAMS, pool, PoolArena(pool), format);
|
||||
}
|
||||
|
|
@ -662,7 +756,7 @@ static Res AMSInit(Pool pool, va_list args)
|
|||
|
||||
/* AMSInitInternal -- initialize an AMS pool, given the format and the chain */
|
||||
|
||||
Res AMSInitInternal(AMS ams, Format format, Chain chain)
|
||||
Res AMSInitInternal(AMS ams, Format format, Chain chain, Bool shareAllocTable)
|
||||
{
|
||||
Pool pool;
|
||||
Res res;
|
||||
|
|
@ -684,10 +778,11 @@ Res AMSInitInternal(AMS ams, Format format, Chain chain)
|
|||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
ams->shareAllocTable = shareAllocTable;
|
||||
|
||||
RingInit(&ams->segRing);
|
||||
|
||||
/* The next five might be overridden by a subclass. */
|
||||
ams->iterate = AMSIterate; /* should be done using a format variant */
|
||||
/* The next four might be overridden by a subclass. */
|
||||
ams->segSize = AMSSegSizePolicy;
|
||||
ams->allocRing = AMSPoolRing;
|
||||
ams->segsDestroy = AMSSegsDestroy;
|
||||
|
|
@ -725,8 +820,7 @@ void AMSFinish(Pool pool)
|
|||
/* amsSegAlloc -- try to allocate an area in the given segment
|
||||
*
|
||||
* Tries to find an area of at least the given size. If successful,
|
||||
* makes that area black, if necessary, and returns its base and limit
|
||||
* grain indices.
|
||||
* returns its base and limit grain indices.
|
||||
*/
|
||||
static Bool amsSegAlloc(Index *baseReturn, Index *limitReturn,
|
||||
Seg seg, Size size)
|
||||
|
|
@ -766,6 +860,9 @@ static Bool amsSegAlloc(Index *baseReturn, Index *limitReturn,
|
|||
amsseg->firstFree = limit;
|
||||
}
|
||||
|
||||
/* We don't place buffers on white segments, so no need to adjust colour. */
|
||||
AVER(!amsseg->colourTablesInUse);
|
||||
|
||||
amsseg->free -= limit - base;
|
||||
amsseg->newAlloc += limit - base;
|
||||
*baseReturn = base;
|
||||
|
|
@ -779,15 +876,16 @@ static Bool amsSegAlloc(Index *baseReturn, Index *limitReturn,
|
|||
* Iterates over the segments looking for space. See
|
||||
* design.mps.poolams.fill.
|
||||
*/
|
||||
Res AMSBufferFill(Addr *baseReturn, Addr *limitReturn,
|
||||
Pool pool, Buffer buffer, Size size,
|
||||
Bool withReservoirPermit)
|
||||
static Res AMSBufferFill(Addr *baseReturn, Addr *limitReturn,
|
||||
Pool pool, Buffer buffer, Size size,
|
||||
Bool withReservoirPermit)
|
||||
{
|
||||
Res res;
|
||||
AMS ams;
|
||||
Seg seg;
|
||||
Ring node, ring, nextNode; /* for iterating over the segments */
|
||||
Index base, limit;
|
||||
Addr baseAddr, limitAddr;
|
||||
RankSet rankSet;
|
||||
Bool b; /* the return value of amsSegAlloc */
|
||||
SegPrefStruct segPrefStruct;
|
||||
|
|
@ -816,7 +914,9 @@ Res AMSBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
if (amsseg->free >= AMSGrains(ams, size)) {
|
||||
seg = AMSSeg2Seg(amsseg);
|
||||
|
||||
if (SegRankSet(seg) == rankSet && SegBuffer(seg) == NULL) {
|
||||
if (SegRankSet(seg) == rankSet && SegBuffer(seg) == NULL
|
||||
/* Can't use a white or grey segment, see d.m.p.fill.colour. */
|
||||
&& SegWhite(seg) == TraceSetEMPTY && SegGrey(seg) == TraceSetEMPTY) {
|
||||
b = amsSegAlloc(&base, &limit, seg, size);
|
||||
if (b)
|
||||
goto found;
|
||||
|
|
@ -824,7 +924,7 @@ Res AMSBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
}
|
||||
}
|
||||
|
||||
/* no segment has enough room; make a new segment */
|
||||
/* No suitable segment found; make a new one. */
|
||||
segPrefStruct = *SegPrefDefault();
|
||||
SegPrefExpress(&segPrefStruct, SegPrefCollected, NULL);
|
||||
res = AMSSegCreate(&seg, pool, size, &segPrefStruct, rankSet,
|
||||
|
|
@ -835,13 +935,13 @@ Res AMSBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
|
||||
found:
|
||||
AVER(b);
|
||||
allocatedSize = AddrOffset(AMS_INDEX_ADDR(seg, base),
|
||||
AMS_INDEX_ADDR(seg, limit));
|
||||
baseAddr = AMS_INDEX_ADDR(seg, base); limitAddr = AMS_INDEX_ADDR(seg, limit);
|
||||
DebugPoolFreeCheck(pool, baseAddr, limitAddr);
|
||||
allocatedSize = AddrOffset(baseAddr, limitAddr);
|
||||
ams->pgen.totalSize += allocatedSize;
|
||||
ams->pgen.newSize += allocatedSize;
|
||||
|
||||
*baseReturn = AMS_INDEX_ADDR(seg, base);
|
||||
*limitReturn = AMS_INDEX_ADDR(seg, limit);
|
||||
*baseReturn = baseAddr; *limitReturn = limitAddr;
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
|
@ -851,7 +951,7 @@ found:
|
|||
* Frees the unused part of the buffer. The colour of the area doesn't
|
||||
* need to be changed. See design.mps.poolams.empty.
|
||||
*/
|
||||
void AMSBufferEmpty(Pool pool, Buffer buffer, Addr init, Addr limit)
|
||||
static void AMSBufferEmpty(Pool pool, Buffer buffer, Addr init, Addr limit)
|
||||
{
|
||||
AMS ams;
|
||||
Index initIndex, limitIndex;
|
||||
|
|
@ -876,6 +976,9 @@ void AMSBufferEmpty(Pool pool, Buffer buffer, Addr init, Addr limit)
|
|||
if (init == limit)
|
||||
return;
|
||||
|
||||
/* Tripped allocations might have scribbled on it, need to splat again. */
|
||||
DebugPoolFreeSplat(pool, init, limit);
|
||||
|
||||
initIndex = AMS_ADDR_INDEX(seg, init);
|
||||
limitIndex = AMS_ADDR_INDEX(seg, limit);
|
||||
|
||||
|
|
@ -896,6 +999,10 @@ void AMSBufferEmpty(Pool pool, Buffer buffer, Addr init, Addr limit)
|
|||
BTResRange(amsseg->allocTable, initIndex, limitIndex);
|
||||
}
|
||||
}
|
||||
|
||||
if (amsseg->colourTablesInUse)
|
||||
AMS_RANGE_WHITEN(seg, initIndex, limitIndex);
|
||||
|
||||
amsseg->free += limitIndex - initIndex;
|
||||
/* The unused portion of the buffer must be new, since it's not condemned. */
|
||||
AVER(amsseg->newAlloc >= limitIndex - initIndex);
|
||||
|
|
@ -907,8 +1014,6 @@ void AMSBufferEmpty(Pool pool, Buffer buffer, Addr init, Addr limit)
|
|||
|
||||
|
||||
/* amsRangeCondemn -- Condemn a part of an AMS segment
|
||||
*
|
||||
* I.e., alloc -> white, free -> black.
|
||||
* Allow calling it with base = limit, to simplify the callers.
|
||||
*/
|
||||
static void amsRangeCondemn(Seg seg, Index base, Index limit)
|
||||
|
|
@ -919,25 +1024,14 @@ static void amsRangeCondemn(Seg seg, Index base, Index limit)
|
|||
AVER(base < limit);
|
||||
AVER(limit <= amsseg->grains);
|
||||
|
||||
if (amsseg->allocTableInUse) {
|
||||
BTSetRange(amsseg->nongreyTable, base, limit);
|
||||
BTCopyInvertRange(amsseg->allocTable, amsseg->nonwhiteTable,
|
||||
base, limit);
|
||||
} else {
|
||||
if (base < amsseg->firstFree) {
|
||||
AMSRangeWhiten(seg, base, amsseg->firstFree);
|
||||
}
|
||||
if (amsseg->firstFree < limit) {
|
||||
AMSRangeBlacken(seg, amsseg->firstFree, limit);
|
||||
}
|
||||
}
|
||||
AMS_RANGE_WHITEN(seg, base, limit);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* AMSWhiten -- the pool class segment condemning method */
|
||||
/* AMSCondemn -- the pool class segment condemning method */
|
||||
|
||||
Res AMSWhiten(Pool pool, Trace trace, Seg seg)
|
||||
static Res AMSCondemn(Pool pool, Trace trace, Seg seg)
|
||||
{
|
||||
AMS ams;
|
||||
AMSSeg amsseg;
|
||||
|
|
@ -959,6 +1053,28 @@ Res AMSWhiten(Pool pool, Trace trace, Seg seg)
|
|||
AVER(!amsseg->colourTablesInUse);
|
||||
|
||||
amsseg->colourTablesInUse = TRUE;
|
||||
|
||||
/* Init allocTable, if necessary. */
|
||||
if (!amsseg->allocTableInUse) {
|
||||
if (0 < amsseg->firstFree)
|
||||
BTSetRange(amsseg->allocTable, 0, amsseg->firstFree);
|
||||
if (amsseg->firstFree < amsseg->grains)
|
||||
BTResRange(amsseg->allocTable, amsseg->firstFree, amsseg->grains);
|
||||
}
|
||||
|
||||
/* Start using allocTable as the white table, if so configured. */
|
||||
if (ams->shareAllocTable) {
|
||||
if (amsseg->allocTableInUse) {
|
||||
/* During the collection, it can't use allocTable for AMS_ALLOCED, so */
|
||||
/* make it use firstFree. */
|
||||
amsseg->allocTableInUse = FALSE;
|
||||
/* Could find a better value for firstFree, but probably not worth it. */
|
||||
amsseg->firstFree = amsseg->grains;
|
||||
}
|
||||
} else { /* Otherwise, use it as alloc table. */
|
||||
amsseg->allocTableInUse = TRUE;
|
||||
}
|
||||
|
||||
buffer = SegBuffer(seg);
|
||||
if (buffer != NULL) { /* design.mps.poolams.condemn.buffer */
|
||||
Index scanLimitIndex, limitIndex;
|
||||
|
|
@ -967,7 +1083,7 @@ Res AMSWhiten(Pool pool, Trace trace, Seg seg)
|
|||
|
||||
amsRangeCondemn(seg, 0, scanLimitIndex);
|
||||
if (scanLimitIndex < limitIndex)
|
||||
AMSRangeBlacken(seg, scanLimitIndex, limitIndex);
|
||||
AMS_RANGE_BLACKEN(seg, scanLimitIndex, limitIndex);
|
||||
amsRangeCondemn(seg, limitIndex, amsseg->grains);
|
||||
/* We didn't condemn the buffer, subtract it from the count. */
|
||||
uncondemned = limitIndex - scanLimitIndex;
|
||||
|
|
@ -989,14 +1105,26 @@ Res AMSWhiten(Pool pool, Trace trace, Seg seg)
|
|||
}
|
||||
|
||||
|
||||
/* AMSObjectFunction is the type of the method that an */
|
||||
/* amsIterate applies to each object in a segment. */
|
||||
typedef Res (*AMSObjectFunction)(
|
||||
/* the segment */ Seg seg,
|
||||
/* the object grain index */ Index i,
|
||||
/* the address of the object */Addr p,
|
||||
/* " " after the object */Addr next,
|
||||
/* the iteration closure */ void *closure);
|
||||
|
||||
/* AMSIterate -- applies a function to each object in a segment
|
||||
#define AMSObjectFunctionCheck(f) \
|
||||
((f) != NULL) /* that's the best we can do */
|
||||
|
||||
|
||||
/* amsIterate -- applies a function to each object in a segment
|
||||
*
|
||||
* AMSIterate(seg, f, closure) applies f to all the
|
||||
* objects in the segment. It skips the buffer, if any (from
|
||||
* BufferScanLimit to BufferLimit).
|
||||
*/
|
||||
static Res AMSIterate(Seg seg, AMSObjectFunction f, void *closure)
|
||||
* amsIterate(seg, f, closure) applies f to all the objects in the
|
||||
* segment. It skips the buffer, if any (from BufferScanLimit to
|
||||
* BufferLimit). */
|
||||
|
||||
static Res amsIterate(Seg seg, AMSObjectFunction f, void *closure)
|
||||
{
|
||||
Res res;
|
||||
AMS ams;
|
||||
|
|
@ -1019,13 +1147,17 @@ static Res AMSIterate(Seg seg, AMSObjectFunction f, void *closure)
|
|||
AVERT(Format, format);
|
||||
alignment = PoolAlignment(AMS2Pool(ams));
|
||||
|
||||
/* If we're using the alloc table as a white table, we can't use it to */
|
||||
/* determine where there are objects. */
|
||||
AVER(!(ams->shareAllocTable && amsseg->colourTablesInUse));
|
||||
|
||||
p = SegBase(seg);
|
||||
limit = SegLimit(seg);
|
||||
buffer = SegBuffer(seg);
|
||||
|
||||
while (p < limit) { /* loop over the objects in the segment */
|
||||
if (buffer != NULL
|
||||
&& p == BufferScanLimit(buffer) && p != BufferLimit(buffer)) {
|
||||
&& p == BufferScanLimit(buffer) && p != BufferLimit(buffer)) {
|
||||
/* skip buffer */
|
||||
next = BufferLimit(buffer);
|
||||
AVER(AddrIsAligned(next, alignment));
|
||||
|
|
@ -1036,10 +1168,26 @@ static Res AMSIterate(Seg seg, AMSObjectFunction f, void *closure)
|
|||
|
||||
i = AMS_ADDR_INDEX(seg, p);
|
||||
if (!AMS_ALLOCED(seg, i)) { /* no object here */
|
||||
next = AddrAdd(p, alignment); /* @@@@ this could be improved */
|
||||
if (amsseg->allocTableInUse) {
|
||||
Index dummy, nextIndex;
|
||||
Bool more;
|
||||
|
||||
/* Find out how large the free block is. */
|
||||
more = BTFindLongResRange(&dummy, &nextIndex, amsseg->allocTable,
|
||||
i, amsseg->grains, 1);
|
||||
AVER(more && dummy == i);
|
||||
next = AMS_INDEX_ADDR(seg, nextIndex);
|
||||
} else {
|
||||
/* If there's no allocTable, this is the free block at the end. */
|
||||
next = limit;
|
||||
}
|
||||
} else { /* there is an object here */
|
||||
next = (*format->skip)(AddrAdd(p, format->headerSize));
|
||||
next = AddrSub(next, format->headerSize);
|
||||
if (format->skip != NULL) {
|
||||
next = (*format->skip)(AddrAdd(p, format->headerSize));
|
||||
next = AddrSub(next, format->headerSize);
|
||||
} else {
|
||||
next = AddrAdd(p, alignment);
|
||||
}
|
||||
AVER(AddrIsAligned(next, alignment));
|
||||
res = (*f)(seg, i, p, next, closure);
|
||||
if (res != ResOK)
|
||||
|
|
@ -1056,8 +1204,7 @@ static Res AMSIterate(Seg seg, AMSObjectFunction f, void *closure)
|
|||
|
||||
/* amsScanObject -- scan a single object
|
||||
*
|
||||
* This is the object function passed to AMSIterate by AMSScan.
|
||||
*/
|
||||
* This is the object function passed to amsIterate by AMSScan. */
|
||||
|
||||
struct amsScanClosureStruct {
|
||||
ScanState ss;
|
||||
|
|
@ -1074,12 +1221,12 @@ static Res amsScanObject(Seg seg, Index i, Addr p, Addr next, void *clos)
|
|||
Res res;
|
||||
|
||||
amsseg = Seg2AMSSeg(seg);
|
||||
/* seg & amsseg have already been checked, in AMSIterate. */
|
||||
/* seg & amsseg have already been checked, in amsIterate. */
|
||||
AVER(i < amsseg->grains);
|
||||
AVER(p != 0);
|
||||
AVER(p < next);
|
||||
AVER(clos != NULL);
|
||||
closure = clos;
|
||||
closure = (amsScanClosure)clos;
|
||||
AVERT(ScanState, closure->ss);
|
||||
AVER(BoolCheck(closure->scanAllObjects));
|
||||
|
||||
|
|
@ -1087,7 +1234,7 @@ static Res amsScanObject(Seg seg, Index i, Addr p, Addr next, void *clos)
|
|||
AVERT(Format, format);
|
||||
|
||||
/* @@@@ This isn't quite right for multiple traces. */
|
||||
if (closure->scanAllObjects || AMSIsGrey(seg, i)) {
|
||||
if (closure->scanAllObjects || AMS_IS_GREY(seg, i)) {
|
||||
res = (*format->scan)(closure->ss,
|
||||
AddrAdd(p, format->headerSize),
|
||||
AddrAdd(next, format->headerSize));
|
||||
|
|
@ -1096,10 +1243,10 @@ static Res amsScanObject(Seg seg, Index i, Addr p, Addr next, void *clos)
|
|||
closure->ss->scannedSize += AddrOffset(p, next);
|
||||
if (!closure->scanAllObjects) {
|
||||
Index j = AMS_ADDR_INDEX(seg, next);
|
||||
AVER(!AMSIsInvalidColor(seg, i));
|
||||
AMSGreyBlacken(seg, i);
|
||||
AVER(!AMS_IS_INVALID_COLOUR(seg, i));
|
||||
AMS_GREY_BLACKEN(seg, i);
|
||||
if (i+1 < j)
|
||||
AMSRangeWhiteBlacken(seg, i+1, j);
|
||||
AMS_RANGE_WHITE_BLACKEN(seg, i+1, j);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1141,7 +1288,7 @@ Res AMSScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg)
|
|||
/* @@@@ This isn't quite right for multiple traces. */
|
||||
if (closureStruct.scanAllObjects) {
|
||||
/* The whole seg (except the buffer) is grey for some trace. */
|
||||
res = (ams->iterate)(seg, amsScanObject, &closureStruct);
|
||||
res = amsIterate(seg, amsScanObject, &closureStruct);
|
||||
if (res != ResOK) {
|
||||
*totalReturn = FALSE;
|
||||
return res;
|
||||
|
|
@ -1157,7 +1304,7 @@ Res AMSScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg)
|
|||
amsseg->marksChanged = FALSE; /* design.mps.poolams.marked.scan */
|
||||
/* design.mps.poolams.ambiguous.middle */
|
||||
if (amsseg->ambiguousFixes) {
|
||||
res = (ams->iterate)(seg, amsScanObject, &closureStruct);
|
||||
res = amsIterate(seg, amsScanObject, &closureStruct);
|
||||
if (res != ResOK) {
|
||||
/* design.mps.poolams.marked.scan.fail */
|
||||
amsseg->marksChanged = TRUE;
|
||||
|
|
@ -1170,13 +1317,17 @@ Res AMSScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg)
|
|||
|
||||
while(j < amsseg->grains
|
||||
&& AMSFindGrey(&i, &j, seg, j, amsseg->grains)) {
|
||||
Addr clientP, clientNext;
|
||||
AVER(!AMSIsInvalidColor(seg, i));
|
||||
Addr clientP, clientNext;
|
||||
AVER(!AMS_IS_INVALID_COLOUR(seg, i));
|
||||
p = AMS_INDEX_ADDR(seg, i);
|
||||
clientP = AddrAdd(p, format->headerSize);
|
||||
clientNext = (*format->skip)(clientP);
|
||||
next = AddrSub(clientNext, format->headerSize);
|
||||
AVER(AddrIsAligned(next, alignment));
|
||||
if (format->skip != NULL) {
|
||||
clientNext = (*format->skip)(clientP);
|
||||
next = AddrSub(clientNext, format->headerSize);
|
||||
} else {
|
||||
clientNext = AddrAdd(clientP, alignment);
|
||||
next = AddrAdd(p, alignment);
|
||||
}
|
||||
j = AMS_ADDR_INDEX(seg, next);
|
||||
res = (*format->scan)(ss, clientP, clientNext);
|
||||
if (res != ResOK) {
|
||||
|
|
@ -1185,10 +1336,13 @@ Res AMSScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg)
|
|||
*totalReturn = FALSE;
|
||||
return res;
|
||||
}
|
||||
/* Check that there haven't been any ambiguous fixes during the */
|
||||
/* scan, because AMSFindGrey won't work otherwise. */
|
||||
AVER_CRITICAL(!amsseg->ambiguousFixes);
|
||||
ss->scannedSize += AddrOffset(p, next);
|
||||
AMSGreyBlacken(seg, i);
|
||||
AMS_GREY_BLACKEN(seg, i);
|
||||
if (i+1 < j)
|
||||
AMSRangeWhiteBlacken(seg, i+1, j);
|
||||
AMS_RANGE_WHITE_BLACKEN(seg, i+1, j);
|
||||
}
|
||||
}
|
||||
} while(amsseg->marksChanged);
|
||||
|
|
@ -1201,7 +1355,7 @@ Res AMSScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg)
|
|||
|
||||
/* AMSFix -- the pool class fixing method */
|
||||
|
||||
Res AMSFix(Pool pool, ScanState ss, Seg seg, Ref *refIO)
|
||||
static Res AMSFix(Pool pool, ScanState ss, Seg seg, Ref *refIO)
|
||||
{
|
||||
AMSSeg amsseg;
|
||||
Index i; /* the index of the fixed grain */
|
||||
|
|
@ -1238,12 +1392,16 @@ Res AMSFix(Pool pool, ScanState ss, Seg seg, Ref *refIO)
|
|||
}
|
||||
|
||||
i = AMS_ADDR_INDEX(seg, base);
|
||||
AVER_CRITICAL(!AMSIsInvalidColor(seg, i));
|
||||
AVER_CRITICAL(!AMS_IS_INVALID_COLOUR(seg, i));
|
||||
|
||||
ss->wasMarked = TRUE;
|
||||
|
||||
switch (ss->rank) {
|
||||
case RankAMBIG:
|
||||
if (Pool2AMS(pool)->shareAllocTable)
|
||||
/* In this state, the pool doesn't support ambiguous references (see */
|
||||
/* .ambiguous.noshare), so this is not a reference. */
|
||||
break;
|
||||
/* not a real pointer if not aligned or not allocated */
|
||||
if (!AddrIsAligned(base, PoolAlignment(pool))
|
||||
|| !AMS_ALLOCED(seg, i)) {
|
||||
|
|
@ -1256,7 +1414,7 @@ Res AMSFix(Pool pool, ScanState ss, Seg seg, Ref *refIO)
|
|||
case RankWEAK:
|
||||
AVER_CRITICAL(AddrIsAligned(base, PoolAlignment(pool)));
|
||||
AVER_CRITICAL(AMS_ALLOCED(seg, i));
|
||||
if (AMSIsWhite(seg, i)) {
|
||||
if (AMS_IS_WHITE(seg, i)) {
|
||||
ss->wasMarked = FALSE;
|
||||
if (ss->rank == RankWEAK) { /* then splat the reference */
|
||||
*refIO = (Ref)0;
|
||||
|
|
@ -1272,9 +1430,9 @@ Res AMSFix(Pool pool, ScanState ss, Seg seg, Ref *refIO)
|
|||
next = AddrSub(clientNext, format->headerSize);
|
||||
/* Part of the object might be grey, because of ambiguous */
|
||||
/* fixes, but that's OK, because scan will ignore that. */
|
||||
AMSRangeWhiteBlacken(seg, i, AMS_ADDR_INDEX(seg, next));
|
||||
AMS_RANGE_WHITE_BLACKEN(seg, i, AMS_ADDR_INDEX(seg, next));
|
||||
} else { /* turn it grey */
|
||||
AMSWhiteGreyen(seg, i);
|
||||
AMS_WHITE_GREYEN(seg, i);
|
||||
SegSetGrey(seg, TraceSetUnion(SegGrey(seg), ss->traces));
|
||||
/* mark it for scanning - design.mps.poolams.marked.fix */
|
||||
amsseg->marksChanged = TRUE;
|
||||
|
|
@ -1294,7 +1452,7 @@ Res AMSFix(Pool pool, ScanState ss, Seg seg, Ref *refIO)
|
|||
*
|
||||
* Turn all grey objects black.
|
||||
*/
|
||||
void AMSBlacken(Pool pool, TraceSet traceSet, Seg seg)
|
||||
static void AMSBlacken(Pool pool, TraceSet traceSet, Seg seg)
|
||||
{
|
||||
AMS ams;
|
||||
|
||||
|
|
@ -1304,7 +1462,7 @@ void AMSBlacken(Pool pool, TraceSet traceSet, Seg seg)
|
|||
AVERT(TraceSet, traceSet);
|
||||
AVERT(Seg, seg);
|
||||
|
||||
/* If it's white for any trace, remove the greyness from tables. */
|
||||
/* If it's white for any of these traces, remove the greyness from tables. */
|
||||
if (TraceSetInter(traceSet, SegWhite(seg)) != TraceSetEMPTY) {
|
||||
AMSSeg amsseg = Seg2AMSSeg(seg);
|
||||
AVERT(AMSSeg, amsseg);
|
||||
|
|
@ -1318,61 +1476,64 @@ void AMSBlacken(Pool pool, TraceSet traceSet, Seg seg)
|
|||
|
||||
/* AMSReclaim -- the pool class reclamation method */
|
||||
|
||||
void AMSReclaim(Pool pool, Trace trace, Seg seg)
|
||||
static void AMSReclaim(Pool pool, Trace trace, Seg seg)
|
||||
{
|
||||
AMS ams;
|
||||
AMSSeg amsseg;
|
||||
Format format;
|
||||
Align alignment;
|
||||
Count reclaimed = 0;
|
||||
Index i, j = 0;
|
||||
Addr p, next;
|
||||
Count nowFree, grains;
|
||||
Size reclaimedSize;
|
||||
PoolDebugMixin debug;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
ams = Pool2AMS(pool);
|
||||
AVERT(AMS, ams);
|
||||
AVERT(Trace, trace);
|
||||
AVERT(Seg, seg);
|
||||
|
||||
amsseg = Seg2AMSSeg(seg);
|
||||
/* It's a white seg, so it must have colour tables. */
|
||||
AVER(amsseg->colourTablesInUse);
|
||||
AVER(!amsseg->marksChanged); /* there must be nothing grey */
|
||||
format = pool->format;
|
||||
AVERT(Format, format);
|
||||
alignment = PoolAlignment(AMS2Pool(ams));
|
||||
grains = amsseg->grains;
|
||||
|
||||
/* Start using allocTable */
|
||||
if (!amsseg->allocTableInUse) {
|
||||
amsseg->allocTableInUse = TRUE;
|
||||
if (0 < amsseg->firstFree)
|
||||
BTSetRange(amsseg->allocTable, 0, amsseg->firstFree);
|
||||
if (amsseg->firstFree < amsseg->grains)
|
||||
BTResRange(amsseg->allocTable, amsseg->firstFree, amsseg->grains);
|
||||
/* Loop over all white blocks and splat them, if it's a debug class. */
|
||||
debug = ((pool)->class->debugMixin)(pool);
|
||||
if (debug != NULL) {
|
||||
Index i, j = 0;
|
||||
|
||||
while(j < grains && AMS_FIND_WHITE_RANGE(&i, &j, seg, j, grains)) {
|
||||
AVER(!AMS_IS_INVALID_COLOUR(seg, i));
|
||||
DebugPoolFreeSplat(pool, AMS_INDEX_ADDR(seg, i), AMS_INDEX_ADDR(seg, j));
|
||||
++j; /* we know next grain is not white */
|
||||
}
|
||||
}
|
||||
|
||||
/* Loop over all white objects and free them */
|
||||
while(j < amsseg->grains
|
||||
&& AMSFindWhite(&i, &j, seg, j, amsseg->grains)) {
|
||||
Addr clientP, clientNext;
|
||||
AVER(!AMSIsInvalidColor(seg, i));
|
||||
p = AMS_INDEX_ADDR(seg, i);
|
||||
clientP = AddrAdd(p, format->headerSize);
|
||||
clientNext = (*format->skip)(clientP);
|
||||
next = AddrSub(clientNext, format->headerSize);
|
||||
AVER(AddrIsAligned(next, alignment));
|
||||
j = AMS_ADDR_INDEX(seg, next);
|
||||
BTResRange(amsseg->allocTable, i, j);
|
||||
reclaimed += j - i;
|
||||
nowFree = BTCountResRange(amsseg->nonwhiteTable, 0, grains);
|
||||
|
||||
/* If the free space is all after firstFree, keep on using firstFree. */
|
||||
/* It could have a more complicated condition, but not worth the trouble. */
|
||||
if (!amsseg->allocTableInUse && amsseg->firstFree + nowFree == grains) {
|
||||
AVER(amsseg->firstFree == grains
|
||||
|| BTIsResRange(amsseg->nonwhiteTable,
|
||||
amsseg->firstFree, grains));
|
||||
} else {
|
||||
if (ams->shareAllocTable) {
|
||||
/* Stop using allocTable as the white table. */
|
||||
amsseg->allocTableInUse = TRUE;
|
||||
} else {
|
||||
AVER(amsseg->allocTableInUse);
|
||||
BTCopyRange(amsseg->nonwhiteTable, amsseg->allocTable, 0, grains);
|
||||
}
|
||||
}
|
||||
|
||||
amsseg->free += reclaimed;
|
||||
trace->reclaimSize += reclaimed << ams->grainShift;
|
||||
ams->pgen.totalSize -= reclaimed << ams->grainShift;
|
||||
reclaimedSize = (nowFree - amsseg->free) << ams->grainShift;
|
||||
amsseg->free = nowFree;
|
||||
trace->reclaimSize += reclaimedSize;
|
||||
ams->pgen.totalSize -= reclaimedSize;
|
||||
/* preservedInPlaceCount is updated on fix */
|
||||
trace->preservedInPlaceSize +=
|
||||
(amsseg->grains - amsseg->free) << ams->grainShift;
|
||||
trace->preservedInPlaceSize += (grains - amsseg->free) << ams->grainShift;
|
||||
|
||||
if (amsseg->free == amsseg->grains && SegBuffer(seg) == NULL) {
|
||||
if (amsseg->free == grains && SegBuffer(seg) == NULL) {
|
||||
/* No survivors */
|
||||
SegFree(seg);
|
||||
} else {
|
||||
|
|
@ -1382,6 +1543,24 @@ void AMSReclaim(Pool pool, Trace trace, Seg seg)
|
|||
}
|
||||
|
||||
|
||||
/* AMSFreeWalk -- free block walking method of the pool class */
|
||||
|
||||
static void AMSFreeWalk(Pool pool, FreeBlockStepMethod f, void *p)
|
||||
{
|
||||
AMS ams;
|
||||
Ring node, ring, nextNode; /* for iterating over the segments */
|
||||
|
||||
AVERT(Pool, pool);
|
||||
ams = Pool2AMS(pool);
|
||||
AVERT(AMS, ams);
|
||||
|
||||
ring = &ams->segRing;
|
||||
RING_FOR(node, ring, nextNode) {
|
||||
AMSSegFreeWalk(RING_ELT(AMSSeg, segRing, node), f, p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* AMSDescribe -- the pool class description method
|
||||
*
|
||||
* Iterates over the segments, describing all of them.
|
||||
|
|
@ -1441,41 +1620,60 @@ DEFINE_CLASS(AMSPoolClass, this)
|
|||
this->bufferClass = RankBufClassGet;
|
||||
this->bufferFill = AMSBufferFill;
|
||||
this->bufferEmpty = AMSBufferEmpty;
|
||||
this->whiten = AMSWhiten;
|
||||
this->whiten = AMSCondemn;
|
||||
this->blacken = AMSBlacken;
|
||||
this->scan = AMSScan;
|
||||
this->fix = AMSFix;
|
||||
this->fixEmergency = AMSFix;
|
||||
this->reclaim = AMSReclaim;
|
||||
this->freewalk = AMSFreeWalk;
|
||||
this->describe = AMSDescribe;
|
||||
}
|
||||
|
||||
|
||||
/* AMSDebugMixin - find debug mixin in class AMSDebug */
|
||||
|
||||
static PoolDebugMixin AMSDebugMixin(Pool pool)
|
||||
{
|
||||
AMS ams;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
ams = Pool2AMS(pool);
|
||||
AVERT(AMS, ams);
|
||||
/* Can't check AMSDebug, because this is called during init */
|
||||
return &(AMS2AMSDebug(ams)->debug);
|
||||
}
|
||||
|
||||
|
||||
/* AMSDebugPoolClass -- the class definition for the debug version */
|
||||
|
||||
DEFINE_POOL_CLASS(AMSDebugPoolClass, this)
|
||||
{
|
||||
INHERIT_CLASS(this, AMSPoolClass);
|
||||
PoolClassMixInDebug(this);
|
||||
this->name = "AMSDBG";
|
||||
this->size = sizeof(AMSDebugStruct);
|
||||
this->debugMixin = AMSDebugMixin;
|
||||
}
|
||||
|
||||
|
||||
/* AMSCheck -- the check method for an AMS */
|
||||
|
||||
Bool AMSCheck(AMS ams)
|
||||
{
|
||||
CHECKS(AMS, ams);
|
||||
CHECKD(Pool, AMS2Pool(ams));
|
||||
CHECKL(PoolCheck(AMS2Pool(ams)));
|
||||
CHECKL(IsSubclassPoly(AMS2Pool(ams)->class, AMSPoolClassGet()));
|
||||
CHECKL(PoolAlignment(AMS2Pool(ams)) == ((Size)1 << ams->grainShift));
|
||||
CHECKL(PoolAlignment(AMS2Pool(ams)) == AMS2Pool(ams)->format->alignment);
|
||||
CHECKD(Chain, ams->chain);
|
||||
CHECKD(PoolGen, &ams->pgen);
|
||||
CHECKL(SizeIsAligned(ams->size, ArenaAlign(PoolArena(AMS2Pool(ams)))));
|
||||
CHECKL(ams->iterate != NULL);
|
||||
CHECKL(FUNCHECK(ams->segSize));
|
||||
CHECKL(RingCheck(&ams->segRing));
|
||||
CHECKL(ams->allocRing != NULL);
|
||||
CHECKL(ams->segsDestroy != NULL);
|
||||
CHECKL(ams->segClass != NULL);
|
||||
CHECKL(FUNCHECK(ams->allocRing));
|
||||
CHECKL(FUNCHECK(ams->segsDestroy));
|
||||
CHECKL(FUNCHECK(ams->segClass));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* mps_class_ams -- return the pool class descriptor to the client */
|
||||
|
||||
mps_class_t mps_class_ams(void)
|
||||
{
|
||||
return (mps_class_t)AMSPoolClassGet();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,14 +2,17 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* .purpose: Internal interface to AMS functionality.
|
||||
*/
|
||||
* .purpose: Internal interface to AMS functionality. */
|
||||
|
||||
#ifndef poolams_h
|
||||
#define poolams_h
|
||||
|
||||
#include "mpm.h"
|
||||
#include "mpmtypes.h"
|
||||
#include "mpmst.h"
|
||||
#include "ring.h"
|
||||
#include "bt.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
|
|
@ -32,19 +35,6 @@ typedef void (*AMSSegsDestroyFunction)(AMS ams);
|
|||
typedef Res (*AMSSegSizePolicyFunction)(Size *sizeReturn,
|
||||
Pool pool, Size size,
|
||||
RankSet rankSet);
|
||||
/* AMSObjectFunction is the type of the method that an */
|
||||
/* AMSIterateFunction applies to each object in a segment. */
|
||||
typedef Res (*AMSObjectFunction)(
|
||||
/* the segment */ Seg seg,
|
||||
/* the object grain index */ Index i,
|
||||
/* the address of the object */Addr p,
|
||||
/* " " after the object */Addr next,
|
||||
/* the iteration closure */ void *closure);
|
||||
|
||||
#define AMSObjectFunctionCheck(f) \
|
||||
((f) != NULL) /* that's the best we can do */
|
||||
|
||||
typedef Res (*AMSIterateFunction)(Seg seg, AMSObjectFunction f, void *closure);
|
||||
|
||||
|
||||
typedef struct AMSStruct {
|
||||
|
|
@ -53,12 +43,12 @@ typedef struct AMSStruct {
|
|||
Chain chain; /* chain used by this pool */
|
||||
PoolGenStruct pgen; /* generation representing the pool */
|
||||
Size size; /* total segment size of the pool */
|
||||
AMSIterateFunction iterate; /* iterator function */
|
||||
AMSSegSizePolicyFunction segSize; /* SegSize policy */
|
||||
RingStruct segRing; /* ring of segments in the pool */
|
||||
AMSRingFunction allocRing; /* fn to get the ring to allocate from */
|
||||
AMSSegsDestroyFunction segsDestroy;
|
||||
AMSSegClassFunction segClass;/* fn to get the class for segments */
|
||||
Bool shareAllocTable; /* the alloc table is also used as white table */
|
||||
Sig sig; /* design.mps.pool.outer-structure.sig */
|
||||
} AMSStruct;
|
||||
|
||||
|
|
@ -70,15 +60,15 @@ typedef struct AMSSegStruct {
|
|||
Count grains; /* number of grains */
|
||||
Count free; /* number of free grains */
|
||||
Count newAlloc; /* number of grains allocated since last GC */
|
||||
Bool allocTableInUse; /* whether we use allocTable */
|
||||
Bool allocTableInUse; /* allocTable is used */
|
||||
Index firstFree; /* 1st free grain, if allocTable is not used */
|
||||
BT allocTable; /* set if grain is allocated */
|
||||
/* design.mps.poolams.colour.single */
|
||||
Bool marksChanged; /* has been marked since last scan */
|
||||
Bool ambiguousFixes; /* has been ambiguously marked since last scan */
|
||||
Bool colourTablesInUse;/* whether we use the colour tables */
|
||||
BT nongreyTable; /* set if grain not grey */
|
||||
Bool marksChanged; /* seg has been marked since last scan */
|
||||
Bool ambiguousFixes; /* seg has been ambiguously marked since last scan */
|
||||
Bool colourTablesInUse;/* the colour tables are in use */
|
||||
BT nonwhiteTable; /* set if grain not white */
|
||||
BT nongreyTable; /* set if not first grain of grey object */
|
||||
Sig sig;
|
||||
} AMSSegStruct;
|
||||
|
||||
|
|
@ -110,59 +100,62 @@ typedef struct AMSSegStruct {
|
|||
|
||||
/* colour ops */
|
||||
|
||||
#define AMSIsWhite(seg, index) \
|
||||
#define AMS_IS_WHITE(seg, index) \
|
||||
(!BTGet(Seg2AMSSeg(seg)->nonwhiteTable, index))
|
||||
|
||||
#define AMSIsGrey(seg, index) \
|
||||
#define AMS_IS_GREY(seg, index) \
|
||||
(!BTGet(Seg2AMSSeg(seg)->nongreyTable, index))
|
||||
|
||||
#define AMSIsBlack(seg, index) \
|
||||
(!AMSIsGrey(seg, index) && !AMSIsWhite(seg, index))
|
||||
#define AMS_IS_BLACK(seg, index) \
|
||||
(!AMS_IS_GREY(seg, index) && !AMS_IS_WHITE(seg, index))
|
||||
|
||||
#define AMSIsInvalidColor(seg, index) \
|
||||
(AMSIsGrey(seg, index) && AMSIsWhite(seg, index))
|
||||
#define AMS_IS_INVALID_COLOUR(seg, index) \
|
||||
(AMS_IS_GREY(seg, index) && AMS_IS_WHITE(seg, index))
|
||||
|
||||
#define AMSGreyBlacken(seg, index) \
|
||||
BEGIN \
|
||||
BTSet(Seg2AMSSeg(seg)->nongreyTable, index); \
|
||||
END
|
||||
|
||||
#define AMSWhiteGreyen(seg, index) \
|
||||
#define AMS_WHITE_GREYEN(seg, index) \
|
||||
BEGIN \
|
||||
BTSet(Seg2AMSSeg(seg)->nonwhiteTable, index); \
|
||||
BTRes(Seg2AMSSeg(seg)->nongreyTable, index); \
|
||||
END
|
||||
|
||||
#define AMSWhiteBlacken(seg, index) \
|
||||
#define AMS_GREY_BLACKEN(seg, index) \
|
||||
BEGIN \
|
||||
BTSet(Seg2AMSSeg(seg)->nongreyTable, index); \
|
||||
END
|
||||
|
||||
#define AMS_WHITE_BLACKEN(seg, index) \
|
||||
BEGIN \
|
||||
BTSet(Seg2AMSSeg(seg)->nonwhiteTable, index); \
|
||||
END
|
||||
|
||||
#define AMSRangeWhiteBlacken(seg, base, limit) \
|
||||
#define AMS_RANGE_WHITE_BLACKEN(seg, base, limit) \
|
||||
BEGIN \
|
||||
BTSetRange(Seg2AMSSeg(seg)->nonwhiteTable, base, limit); \
|
||||
END
|
||||
|
||||
#define AMSRangeWhiten(seg, base, limit) \
|
||||
#define AMS_RANGE_BLACKEN(seg, base, limit) \
|
||||
BEGIN \
|
||||
BTSetRange(Seg2AMSSeg(seg)->nonwhiteTable, base, limit); \
|
||||
BTSetRange(Seg2AMSSeg(seg)->nongreyTable, base, limit); \
|
||||
END
|
||||
|
||||
#define AMS_RANGE_WHITEN(seg, base, limit) \
|
||||
BEGIN \
|
||||
BTResRange(Seg2AMSSeg(seg)->nonwhiteTable, base, limit); \
|
||||
BTSetRange(Seg2AMSSeg(seg)->nongreyTable, base, limit); \
|
||||
END
|
||||
|
||||
#define AMSRangeBlacken(seg, base, limit) \
|
||||
BEGIN \
|
||||
BTSetRange(Seg2AMSSeg(seg)->nonwhiteTable, base, limit); \
|
||||
BTSetRange(Seg2AMSSeg(seg)->nongreyTable, base, limit); \
|
||||
END
|
||||
|
||||
#define AMSFindGrey(pos, dummy, seg, base, limit) \
|
||||
BTFindShortResRange(pos, dummy, Seg2AMSSeg(seg)->nongreyTable, \
|
||||
base, limit, 1) \
|
||||
base, limit, 1)
|
||||
|
||||
#define AMSFindWhite(pos, dummy, seg, base, limit) \
|
||||
BTFindShortResRange(pos, dummy, Seg2AMSSeg(seg)->nonwhiteTable, \
|
||||
base, limit, 1) \
|
||||
base, limit, 1)
|
||||
|
||||
#define AMS_FIND_WHITE_RANGE(baseOut, limitOut, seg, base, limit) \
|
||||
BTFindLongResRange(baseOut, limitOut, Seg2AMSSeg(seg)->nonwhiteTable, \
|
||||
base, limit, 1)
|
||||
|
||||
#define AMS_ALLOCED(seg, index) \
|
||||
(Seg2AMSSeg(seg)->allocTableInUse \
|
||||
|
|
@ -172,25 +165,19 @@ typedef struct AMSSegStruct {
|
|||
|
||||
/* the rest */
|
||||
|
||||
extern Res AMSInitInternal(AMS ams, Format format, Chain chain);
|
||||
extern Res AMSInitInternal(AMS ams, Format format, Chain chain,
|
||||
Bool shareAllocTable);
|
||||
extern void AMSFinish(Pool pool);
|
||||
extern Bool AMSCheck(AMS ams);
|
||||
|
||||
extern Res AMSBufferInit(Pool pool, Buffer buffer, va_list args);
|
||||
extern Res AMSBufferFill(Addr *baseReturn, Addr *limitReturn,
|
||||
Pool pool, Buffer buffer, Size size,
|
||||
Bool withReservoirPermit);
|
||||
extern void AMSBufferEmpty(Pool pool, Buffer buffer,
|
||||
Addr init, Addr limit);
|
||||
|
||||
extern Res AMSWhiten(Pool pool, Trace trace, Seg seg);
|
||||
extern Res AMSScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg);
|
||||
extern Res AMSFix(Pool pool, ScanState ss, Seg seg, Ref *refIO);
|
||||
extern void AMSBlacken(Pool pool, TraceSet traceSet, Seg seg);
|
||||
extern void AMSReclaim(Pool pool, Trace trace, Seg seg);
|
||||
|
||||
#define AMSChain(ams) ((ams)->chain)
|
||||
|
||||
extern void AMSSegFreeWalk(AMSSeg amsseg, FreeBlockStepMethod f, void *p);
|
||||
|
||||
extern void AMSSegFreeCheck(AMSSeg amsseg);
|
||||
|
||||
|
||||
typedef SegClass AMSSegClass;
|
||||
typedef SegClassStruct AMSSegClassStruct;
|
||||
|
|
@ -202,6 +189,7 @@ typedef PoolClass AMSPoolClass;
|
|||
typedef PoolClassStruct AMSPoolClassStruct;
|
||||
|
||||
extern AMSPoolClass AMSPoolClassGet(void);
|
||||
extern AMSPoolClass AMSDebugPoolClassGet(void);
|
||||
|
||||
|
||||
#endif /* poolams_h */
|
||||
|
|
|
|||
28
mps/code/poolamsi.c
Normal file
28
mps/code/poolamsi.c
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/* impl.c.poolamsi: AUTOMATIC MARK & SWEEP POOL CLASS C INTERFACE
|
||||
*
|
||||
* $Id: poolamsi.c,v 1.2 2002/02/01 14:27:28 pekka Exp $
|
||||
* $HopeName: MMsrc!poolamsi.c(trunk.2) $
|
||||
* Copyright (C) 2002 Global Graphics Software.
|
||||
*/
|
||||
|
||||
#include "mpscams.h"
|
||||
#include "mps.h"
|
||||
#include "poolams.h"
|
||||
|
||||
SRCID(poolamsi, "$Id: poolamsi.c,v 1.2 2002/02/01 14:27:28 pekka Exp $");
|
||||
|
||||
|
||||
/* mps_class_ams -- return the AMS pool class descriptor */
|
||||
|
||||
mps_class_t mps_class_ams(void)
|
||||
{
|
||||
return (mps_class_t)AMSPoolClassGet();
|
||||
}
|
||||
|
||||
|
||||
/* mps_class_ams_debug -- return the AMS (debug) pool class descriptor */
|
||||
|
||||
mps_class_t mps_class_ams_debug(void)
|
||||
{
|
||||
return (mps_class_t)AMSDebugPoolClassGet();
|
||||
}
|
||||
|
|
@ -43,7 +43,6 @@
|
|||
#include "mpm.h"
|
||||
#include "chain.h"
|
||||
|
||||
|
||||
SRCID(poolawl, "$Id$");
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
/* impl.h.poolmfs draft impl
|
||||
*
|
||||
* MANUAL FIXED SMALL UNIT POOL
|
||||
/* impl.h.poolmfs: MANUAL FIXED SMALL UNIT POOL
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
*
|
||||
* Copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
*
|
||||
* DESIGN
|
||||
*
|
||||
* .design: See design.mps.poolmrg.
|
||||
|
|
@ -26,6 +28,7 @@
|
|||
* and MRG pools, whatever that might be.
|
||||
*/
|
||||
|
||||
#include "ring.h"
|
||||
#include "mpm.h"
|
||||
#include "poolmrg.h"
|
||||
|
||||
|
|
@ -34,12 +37,11 @@ SRCID(poolmrg, "$Id$");
|
|||
|
||||
/* Types */
|
||||
|
||||
/* enumerate the states of a Guardian */
|
||||
/* enumerate the states of a guardian */
|
||||
enum {
|
||||
MRGGuardianFREE = 1,
|
||||
MRGGuardianPREFINAL,
|
||||
MRGGuardianFINAL,
|
||||
MRGGuardianPOSTFINAL
|
||||
MRGGuardianFINAL
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -47,7 +49,7 @@ enum {
|
|||
|
||||
typedef struct LinkStruct *Link;
|
||||
typedef struct LinkStruct {
|
||||
int state; /* Free, Prefinal, Final, Postfinal */
|
||||
int state; /* Free, Prefinal, Final */
|
||||
union {
|
||||
MessageStruct messageStruct; /* state = Final */
|
||||
RingStruct linkRing; /* state one of {Free, Prefinal} */
|
||||
|
|
@ -323,9 +325,11 @@ static Count MRGGuardiansPerSeg(MRG mrg)
|
|||
|
||||
/* design.mps.poolmrg.guardian.assoc */
|
||||
|
||||
|
||||
#define refPartOfIndex(refseg, index) \
|
||||
((RefPart)SegBase(RefSeg2Seg(refseg)) + (index))
|
||||
|
||||
|
||||
static RefPart MRGRefPartOfLink(Link link, Arena arena)
|
||||
{
|
||||
Seg seg;
|
||||
|
|
@ -349,9 +353,12 @@ static RefPart MRGRefPartOfLink(Link link, Arena arena)
|
|||
return refPartOfIndex(linkseg->refSeg, index);
|
||||
}
|
||||
|
||||
|
||||
#define linkOfIndex(linkseg, index) \
|
||||
((Link)SegBase(LinkSeg2Seg(linkseg)) + (index))
|
||||
|
||||
|
||||
#if 0
|
||||
static Link MRGLinkOfRefPart(RefPart refPart, Arena arena)
|
||||
{
|
||||
Seg seg;
|
||||
|
|
@ -374,6 +381,7 @@ static Link MRGLinkOfRefPart(RefPart refPart, Arena arena)
|
|||
|
||||
return linkOfIndex(refseg->linkSeg, index);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* MRGGuardianInit -- Initialises both parts of a guardian */
|
||||
|
|
@ -395,35 +403,26 @@ static void MRGGuardianInit(MRG mrg, Link link, RefPart refPart)
|
|||
/* MRGMessage* -- Implementation of MRG's MessageClass */
|
||||
|
||||
|
||||
/* MRGMessageDelete -- deletes the message (frees up the memory) */
|
||||
/* MRGMessageDelete -- deletes the message (frees up the guardian) */
|
||||
|
||||
static void MRGMessageDelete(Message message)
|
||||
{
|
||||
RefPart refPart;
|
||||
Pool pool;
|
||||
Arena arena;
|
||||
Link link;
|
||||
Bool b;
|
||||
|
||||
AVERT(Message, message);
|
||||
|
||||
arena = MessageArena(message);
|
||||
|
||||
{ /* Calculate pool */
|
||||
Bool b;
|
||||
Seg seg;
|
||||
b = SegOfAddr(&seg, arena, (Addr)message);
|
||||
AVER(b);
|
||||
|
||||
pool = SegPool(seg);
|
||||
}
|
||||
b = PoolOfAddr(&pool, arena, (Addr)message);
|
||||
AVER(b);
|
||||
AVER(pool->class == PoolClassMRG());
|
||||
|
||||
link = linkOfMessage(message);
|
||||
MessageFinish(message);
|
||||
AVER(link->state == MRGGuardianFINAL);
|
||||
link->state = MRGGuardianPOSTFINAL;
|
||||
refPart = MRGRefPartOfLink(link, arena);
|
||||
PoolFree(pool, (Addr)refPart, sizeof(RefPartStruct));
|
||||
MessageFinish(message);
|
||||
MRGGuardianInit(Pool2MRG(pool), link, MRGRefPartOfLink(link, arena));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -547,7 +546,7 @@ failLinkSegAlloc:
|
|||
}
|
||||
|
||||
|
||||
/* MRGFinalise -- finalize the indexth guardian in the segment */
|
||||
/* MRGFinalize -- finalize the indexth guardian in the segment */
|
||||
|
||||
static void MRGFinalize(Arena arena, MRGLinkSeg linkseg, Index index)
|
||||
{
|
||||
|
|
@ -686,6 +685,8 @@ static void MRGFinish(Pool pool)
|
|||
}
|
||||
|
||||
|
||||
/* MRGRegister -- register an object for finalization */
|
||||
|
||||
Res MRGRegister(Pool pool, Ref ref)
|
||||
{
|
||||
Ring freeNode;
|
||||
|
|
@ -707,7 +708,6 @@ Res MRGRegister(Pool pool, Ref ref)
|
|||
|
||||
/* design.mps.poolmrg.alloc.grow */
|
||||
if (RingIsSingle(&mrg->freeRing)) {
|
||||
/* .refseg.useless: refseg isn't used */
|
||||
/* @@@@ Should the client be able to use the reservoir for this? */
|
||||
res = MRGSegPairCreate(&junk, mrg, /* withReservoirPermit */ FALSE);
|
||||
if (res != ResOK)
|
||||
|
|
@ -731,32 +731,49 @@ Res MRGRegister(Pool pool, Ref ref)
|
|||
}
|
||||
|
||||
|
||||
/* MRGFree -- free a guardian */
|
||||
/* MRGDeregister -- deregister (once) an object for finalization */
|
||||
|
||||
static void MRGFree(Pool pool, Addr old, Size size)
|
||||
Res MRGDeregister(Pool pool, Ref obj)
|
||||
{
|
||||
MRG mrg;
|
||||
Ring node, nextNode;
|
||||
Count nGuardians; /* guardians per seg */
|
||||
Arena arena;
|
||||
Link link;
|
||||
RefPart refPart;
|
||||
MRG mrg;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
AVER(old != (Addr)0);
|
||||
AVER(size == sizeof(RefPartStruct));
|
||||
/* Can't check obj */
|
||||
|
||||
mrg = Pool2MRG(pool);
|
||||
AVERT(MRG, mrg);
|
||||
|
||||
refPart = (RefPart)old;
|
||||
|
||||
nGuardians = MRGGuardiansPerSeg(mrg);
|
||||
arena = PoolArena(pool);
|
||||
AVERT(Arena, arena);
|
||||
|
||||
/* design.mps.poolmrg.guardian.ref.free */
|
||||
link = MRGLinkOfRefPart(refPart, arena);
|
||||
AVER(link->state == MRGGuardianPOSTFINAL);
|
||||
/* map over the segments */
|
||||
RING_FOR(node, &mrg->refRing, nextNode) {
|
||||
MRGRefSeg refSeg = RING_ELT(MRGRefSeg, mrgRing, node);
|
||||
MRGLinkSeg linkSeg;
|
||||
Count i;
|
||||
Link link;
|
||||
RefPart refPart;
|
||||
|
||||
MRGGuardianInit(mrg, link, refPart);
|
||||
AVERT(MRGRefSeg, refSeg);
|
||||
linkSeg = refSeg->linkSeg;
|
||||
/* map over each guardian in the segment */
|
||||
for(i = 0, link = (Link)SegBase(LinkSeg2Seg(linkSeg)),
|
||||
refPart = (RefPart)SegBase(RefSeg2Seg(refSeg));
|
||||
i < nGuardians;
|
||||
++i, ++link, ++refPart) {
|
||||
/* check if it's allocated and points to obj */
|
||||
if (link->state == MRGGuardianPREFINAL
|
||||
&& MRGRefPartRef(arena, refPart) == obj) {
|
||||
RingRemove(&link->the.linkRing);
|
||||
RingFinish(&link->the.linkRing);
|
||||
MRGGuardianInit(mrg, link, refPart);
|
||||
return ResOK;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ResFAIL;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -833,7 +850,6 @@ DEFINE_POOL_CLASS(MRGPoolClass, this)
|
|||
this->attr |= (AttrSCAN | AttrFREE | AttrINCR_RB);
|
||||
this->init = MRGInit;
|
||||
this->finish = MRGFinish;
|
||||
this->free = MRGFree;
|
||||
this->grey = PoolTrivGrey;
|
||||
this->blacken = PoolTrivBlacken;
|
||||
this->scan = MRGScan;
|
||||
|
|
|
|||
|
|
@ -1,19 +1,20 @@
|
|||
/* impl.h.amc draft impl
|
||||
*
|
||||
* MANUAL RANK GUARDIAN POOL CLASS
|
||||
/* impl.h.poolmrg: MANUAL RANK GUARDIAN POOL CLASS INTERFACE
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
*
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (c) 2002 Global Graphics Software.
|
||||
*/
|
||||
|
||||
#ifndef poolmrg_h
|
||||
#define poolmrg_h
|
||||
|
||||
#include "mpm.h"
|
||||
#include "mpmtypes.h"
|
||||
|
||||
typedef struct MRGStruct *MRG;
|
||||
|
||||
extern PoolClass PoolClassMRG(void);
|
||||
extern Res MRGRegister(Pool, Ref);
|
||||
extern Res MRGDeregister(Pool, Ref);
|
||||
|
||||
#endif /* poolmrg_h */
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* **** RESTRICTION: This pool may not allocate from the arena control
|
||||
* pool, since it is used to implement that pool.
|
||||
|
|
@ -37,14 +38,7 @@ SRCID(poolmv, "$Id$");
|
|||
#define mvSpanPool(mv) MFSPool(&(mv)->spanPoolStruct)
|
||||
|
||||
|
||||
#define PoolPoolMV(pool) PARENT(MVStruct, poolStruct, pool)
|
||||
|
||||
|
||||
Pool (MVPool)(MV mv)
|
||||
{
|
||||
AVERT(MV, mv);
|
||||
return &mv->poolStruct;
|
||||
}
|
||||
#define Pool2MV(pool) PARENT(MVStruct, poolStruct, pool)
|
||||
|
||||
|
||||
/* MVDebug -- MV Debug pool class */
|
||||
|
|
@ -57,8 +51,8 @@ typedef struct MVDebugStruct {
|
|||
typedef MVDebugStruct *MVDebug;
|
||||
|
||||
|
||||
#define MVPoolMVDebug(mv) PARENT(MVDebugStruct, MVStruct, mv)
|
||||
#define MVDebugPoolMV(mvd) (&((mvd)->MVStruct))
|
||||
#define MV2MVDebug(mv) PARENT(MVDebugStruct, MVStruct, mv)
|
||||
#define MVDebug2MV(mvd) (&((mvd)->MVStruct))
|
||||
|
||||
|
||||
/* MVBlockStruct -- block structure
|
||||
|
|
@ -207,7 +201,7 @@ static Res MVInit(Pool pool, va_list arg)
|
|||
AVER(maxSize > 0);
|
||||
AVER(extendBy <= maxSize);
|
||||
|
||||
mv = PoolPoolMV(pool);
|
||||
mv = Pool2MV(pool);
|
||||
arena = PoolArena(pool);
|
||||
|
||||
/* At 100% fragmentation we will need one block descriptor for every other */
|
||||
|
|
@ -255,7 +249,7 @@ static void MVFinish(Pool pool)
|
|||
MVSpan span;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
mv = PoolPoolMV(pool);
|
||||
mv = Pool2MV(pool);
|
||||
AVERT(MV, mv);
|
||||
|
||||
/* Destroy all the spans attached to the pool. */
|
||||
|
|
@ -477,7 +471,7 @@ static Res MVAlloc(Addr *pReturn, Pool pool, Size size,
|
|||
|
||||
AVER(pReturn != NULL);
|
||||
AVERT(Pool, pool);
|
||||
mv = PoolPoolMV(pool);
|
||||
mv = Pool2MV(pool);
|
||||
AVERT(MV, mv);
|
||||
AVER(size > 0);
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
|
@ -530,8 +524,10 @@ static Res MVAlloc(Addr *pReturn, Pool pool, Size size,
|
|||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
limit = AddrAdd(base, regionSize);
|
||||
|
||||
DebugPoolFreeSplat(pool, base, limit);
|
||||
|
||||
span->size = regionSize;
|
||||
span->tract = TractOfBaseAddr(arena, base);
|
||||
span->mv = mv;
|
||||
|
|
@ -551,7 +547,6 @@ static Res MVAlloc(Addr *pReturn, Pool pool, Size size,
|
|||
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;
|
||||
|
|
@ -581,7 +576,7 @@ static void MVFree(Pool pool, Addr old, Size size)
|
|||
Tract tract;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
mv = PoolPoolMV(pool);
|
||||
mv = Pool2MV(pool);
|
||||
AVERT(MV, mv);
|
||||
|
||||
AVER(old != (Addr)0);
|
||||
|
|
@ -632,10 +627,10 @@ static PoolDebugMixin MVDebugMixin(Pool pool)
|
|||
MV mv;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
mv = PoolPoolMV(pool);
|
||||
mv = Pool2MV(pool);
|
||||
AVERT(MV, mv);
|
||||
/* Can't check MVDebug, because this is called during MVDebug init */
|
||||
return &(MVPoolMVDebug(mv)->debug);
|
||||
return &(MV2MVDebug(mv)->debug);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -650,7 +645,7 @@ static Res MVDescribe(Pool pool, mps_lib_FILE *stream)
|
|||
Ring spans, node = NULL, nextNode; /* gcc whinge stop */
|
||||
|
||||
if(!CHECKT(Pool, pool)) return ResFAIL;
|
||||
mv = PoolPoolMV(pool);
|
||||
mv = Pool2MV(pool);
|
||||
if(!CHECKT(MV, mv)) return ResFAIL;
|
||||
if(stream == NULL) return ResFAIL;
|
||||
|
||||
|
|
@ -808,7 +803,7 @@ size_t mps_mv_free_size(mps_pool_t mps_pool)
|
|||
pool = (Pool)mps_pool;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
mv = PoolPoolMV(pool);
|
||||
mv = Pool2MV(pool);
|
||||
AVERT(MV, mv);
|
||||
|
||||
spans = &mv->spans;
|
||||
|
|
@ -834,7 +829,7 @@ size_t mps_mv_size(mps_pool_t mps_pool)
|
|||
pool = (Pool)mps_pool;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
mv = PoolPoolMV(pool);
|
||||
mv = Pool2MV(pool);
|
||||
AVERT(MV, mv);
|
||||
arena = PoolArena(pool);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
/* .impl.h.poolmv: MANUAL VARIABLE POOL
|
||||
/* impl.h.poolmv: MANUAL VARIABLE POOL
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* .purpose: This is the interface to the manual-variable pool class.
|
||||
*
|
||||
|
|
@ -49,8 +50,7 @@ extern PoolClass PoolClassMV(void);
|
|||
|
||||
extern Bool MVCheck(MV mv);
|
||||
|
||||
#define MVPool(mv) (&(mv)->poolStruct)
|
||||
extern Pool (MVPool)(MV mv);
|
||||
#define MV2Pool(mv) (&(mv)->poolStruct)
|
||||
|
||||
|
||||
#endif /* poolmv_h */
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
/* impl.c.poolmvff: First Fit Manual Variable Pool
|
||||
/* impl.c.poolmvff: Manual Variable First Fit Pool
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* .purpose: This is a pool class for manually managed objects of
|
||||
* variable size where address-ordered first fit is an appropriate
|
||||
|
|
@ -53,8 +54,8 @@ typedef struct MVFFStruct { /* MVFF pool outer structure */
|
|||
} MVFFStruct;
|
||||
|
||||
|
||||
#define PoolPoolMVFF(pool) PARENT(MVFFStruct, poolStruct, pool)
|
||||
#define MVFFPool(mvff) (&((mvff)->poolStruct))
|
||||
#define Pool2MVFF(pool) PARENT(MVFFStruct, poolStruct, pool)
|
||||
#define MVFF2Pool(mvff) (&((mvff)->poolStruct))
|
||||
#define CBSOfMVFF(mvff) (&((mvff)->cbsStruct))
|
||||
#define MVFFOfCBS(cbs) PARENT(MVFFStruct, cbsStruct, cbs)
|
||||
|
||||
|
|
@ -71,8 +72,8 @@ typedef struct MVFFDebugStruct {
|
|||
typedef MVFFDebugStruct *MVFFDebug;
|
||||
|
||||
|
||||
#define MVFFPoolMVFFDebug(mvff) PARENT(MVFFDebugStruct, mvffStruct, mvff)
|
||||
#define MVFFDebugPoolMVFF(mvffd) (&((mvffd)->mvffStruct))
|
||||
#define MVFF2MVFFDebug(mvff) PARENT(MVFFDebugStruct, mvffStruct, mvff)
|
||||
#define MVFFDebug2MVFF(mvffd) (&((mvffd)->mvffStruct))
|
||||
|
||||
|
||||
/* MVFFAddToFreeList -- Add given range to free list
|
||||
|
|
@ -126,7 +127,7 @@ static void MVFFFreeSegs(MVFF mvff, Addr base, Addr limit)
|
|||
if (AddrOffset(base, limit) < mvff->minSegSize)
|
||||
return; /* not large enough for entire segments */
|
||||
|
||||
arena = PoolArena(MVFFPool(mvff));
|
||||
arena = PoolArena(MVFF2Pool(mvff));
|
||||
b = SegOfAddr(&seg, arena, base);
|
||||
AVER(b);
|
||||
|
||||
|
|
@ -143,13 +144,13 @@ static void MVFFFreeSegs(MVFF mvff, Addr base, Addr limit)
|
|||
mvff->total -= AddrOffset(segBase, segLimit);
|
||||
SegFree(seg);
|
||||
}
|
||||
|
||||
|
||||
/* Avoid calling SegNext if the next segment would fail */
|
||||
/* the loop test, mainly because there might not be a */
|
||||
/* next segment. */
|
||||
if (segLimit == limit) /* segment ends at end of range */
|
||||
break;
|
||||
|
||||
|
||||
b = SegNext(&seg, arena, segBase);
|
||||
AVER(b);
|
||||
segBase = SegBase(seg);
|
||||
|
|
@ -181,7 +182,7 @@ static Res MVFFAddSeg(Seg *segReturn,
|
|||
AVER(size > 0);
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
|
||||
pool = MVFFPool(mvff);
|
||||
pool = MVFF2Pool(mvff);
|
||||
arena = PoolArena(pool);
|
||||
align = ArenaAlign(arena);
|
||||
|
||||
|
|
@ -211,6 +212,7 @@ static Res MVFFAddSeg(Seg *segReturn,
|
|||
|
||||
mvff->total += segSize;
|
||||
base = SegBase(seg); limit = AddrAdd(base, segSize);
|
||||
DebugPoolFreeSplat(pool, base, limit);
|
||||
MVFFAddToFreeList(&base, &limit, mvff);
|
||||
AVER(base <= SegBase(seg));
|
||||
if (mvff->minSegSize > segSize) mvff->minSegSize = segSize;
|
||||
|
|
@ -242,7 +244,7 @@ static Bool MVFFFindFirstFree(Addr *baseReturn, Addr *limitReturn,
|
|||
AVER(limitReturn != NULL);
|
||||
AVERT(MVFF, mvff);
|
||||
AVER(size > 0);
|
||||
AVER(SizeIsAligned(size, PoolAlignment(MVFFPool(mvff))));
|
||||
AVER(SizeIsAligned(size, PoolAlignment(MVFF2Pool(mvff))));
|
||||
|
||||
findDelete = mvff->slotHigh ? CBSFindDeleteHIGH : CBSFindDeleteLOW;
|
||||
|
||||
|
|
@ -268,7 +270,7 @@ static Res MVFFAlloc(Addr *aReturn, Pool pool, Size size,
|
|||
Bool foundBlock;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
mvff = PoolPoolMVFF(pool);
|
||||
mvff = Pool2MVFF(pool);
|
||||
AVERT(MVFF, mvff);
|
||||
|
||||
AVER(aReturn != NULL);
|
||||
|
|
@ -313,7 +315,7 @@ static void MVFFFree(Pool pool, Addr old, Size size)
|
|||
MVFF mvff;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
mvff = PoolPoolMVFF(pool);
|
||||
mvff = Pool2MVFF(pool);
|
||||
AVERT(MVFF, mvff);
|
||||
|
||||
AVER(old != (Addr)0);
|
||||
|
|
@ -348,7 +350,7 @@ static Res MVFFBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
AVER(baseReturn != NULL);
|
||||
AVER(limitReturn != NULL);
|
||||
AVERT(Pool, pool);
|
||||
mvff = PoolPoolMVFF(pool);
|
||||
mvff = Pool2MVFF(pool);
|
||||
AVERT(MVFF, mvff);
|
||||
AVERT(Buffer, buffer);
|
||||
AVER(size > 0);
|
||||
|
|
@ -389,7 +391,7 @@ static void MVFFBufferEmpty(Pool pool, Buffer buffer,
|
|||
MVFF mvff;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
mvff = PoolPoolMVFF(pool);
|
||||
mvff = Pool2MVFF(pool);
|
||||
AVERT(MVFF, mvff);
|
||||
AVERT(Buffer, buffer);
|
||||
AVER(BufferIsReady(buffer));
|
||||
|
|
@ -436,7 +438,7 @@ static Res MVFFInit(Pool pool, va_list arg)
|
|||
AVER(BoolCheck(arenaHigh));
|
||||
AVER(BoolCheck(firstFit));
|
||||
|
||||
mvff = PoolPoolMVFF(pool);
|
||||
mvff = Pool2MVFF(pool);
|
||||
arena = PoolArena(pool);
|
||||
|
||||
mvff->extendBy = extendBy;
|
||||
|
|
@ -452,7 +454,7 @@ static Res MVFFInit(Pool pool, va_list arg)
|
|||
res = ControlAlloc(&p, arena, sizeof(SegPrefStruct), FALSE);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
|
||||
mvff->segPref = (SegPref)p;
|
||||
*mvff->segPref = *SegPrefDefault();
|
||||
SegPrefExpress(mvff->segPref, arenaHigh ? SegPrefHigh : SegPrefLow, NULL);
|
||||
|
|
@ -463,14 +465,21 @@ static Res MVFFInit(Pool pool, va_list arg)
|
|||
mvff->total = 0;
|
||||
mvff->free = 0;
|
||||
|
||||
CBSInit(arena, CBSOfMVFF(mvff), (void *)mvff, NULL, NULL, NULL, NULL,
|
||||
mvff->extendBy, align, TRUE, TRUE);
|
||||
res = CBSInit(arena, CBSOfMVFF(mvff), (void *)mvff, NULL, NULL, NULL, NULL,
|
||||
mvff->extendBy, align, TRUE, TRUE);
|
||||
|
||||
if (res != ResOK)
|
||||
goto failInit;
|
||||
|
||||
mvff->sig = MVFFSig;
|
||||
AVERT(MVFF, mvff);
|
||||
EVENT_PPWWWUUU(PoolInitMVFF, pool, arena, extendBy, avgSize, align,
|
||||
slotHigh, arenaHigh, firstFit);
|
||||
return ResOK;
|
||||
|
||||
failInit:
|
||||
ControlFree(arena, p, sizeof(SegPrefStruct));
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -484,7 +493,7 @@ static void MVFFFinish(Pool pool)
|
|||
Ring ring, node, nextNode;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
mvff = PoolPoolMVFF(pool);
|
||||
mvff = Pool2MVFF(pool);
|
||||
AVERT(MVFF, mvff);
|
||||
|
||||
ring = PoolSegRing(pool);
|
||||
|
|
@ -493,7 +502,7 @@ static void MVFFFinish(Pool pool)
|
|||
AVER(SegPool(seg) == pool);
|
||||
SegFree(seg);
|
||||
}
|
||||
|
||||
|
||||
/* Could maintain mvff->total here and check it falls to zero, */
|
||||
/* but that would just make the function slow. If only we had */
|
||||
/* a way to do operations only if AVERs are turned on. */
|
||||
|
|
@ -514,10 +523,10 @@ static PoolDebugMixin MVFFDebugMixin(Pool pool)
|
|||
MVFF mvff;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
mvff = PoolPoolMVFF(pool);
|
||||
mvff = Pool2MVFF(pool);
|
||||
AVERT(MVFF, mvff);
|
||||
/* Can't check MVFFDebug, because this is called during init */
|
||||
return &(MVFFPoolMVFFDebug(mvff)->debug);
|
||||
return &(MVFF2MVFFDebug(mvff)->debug);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -529,7 +538,7 @@ static Res MVFFDescribe(Pool pool, mps_lib_FILE *stream)
|
|||
MVFF mvff;
|
||||
|
||||
if (!CHECKT(Pool, pool)) return ResFAIL;
|
||||
mvff = PoolPoolMVFF(pool);
|
||||
mvff = Pool2MVFF(pool);
|
||||
if (!CHECKT(MVFF, mvff)) return ResFAIL;
|
||||
if (stream == NULL) return ResFAIL;
|
||||
|
||||
|
|
@ -551,7 +560,7 @@ static Res MVFFDescribe(Pool pool, mps_lib_FILE *stream)
|
|||
|
||||
res = WriteF(stream, "}\n", NULL);
|
||||
|
||||
return res;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -613,9 +622,9 @@ size_t mps_mvff_free_size(mps_pool_t mps_pool)
|
|||
|
||||
pool = (Pool)mps_pool;
|
||||
AVERT(Pool, pool);
|
||||
mvff = PoolPoolMVFF(pool);
|
||||
mvff = Pool2MVFF(pool);
|
||||
AVERT(MVFF, mvff);
|
||||
|
||||
|
||||
return (size_t)mvff->free;
|
||||
}
|
||||
|
||||
|
|
@ -628,7 +637,7 @@ size_t mps_mvff_size(mps_pool_t mps_pool)
|
|||
|
||||
pool = (Pool)mps_pool;
|
||||
AVERT(Pool, pool);
|
||||
mvff = PoolPoolMVFF(pool);
|
||||
mvff = Pool2MVFF(pool);
|
||||
AVERT(MVFF, mvff);
|
||||
|
||||
return (size_t)mvff->total;
|
||||
|
|
@ -640,16 +649,16 @@ size_t mps_mvff_size(mps_pool_t mps_pool)
|
|||
static Bool MVFFCheck(MVFF mvff)
|
||||
{
|
||||
CHECKS(MVFF, mvff);
|
||||
CHECKD(Pool, MVFFPool(mvff));
|
||||
CHECKL(IsSubclassPoly(MVFFPool(mvff)->class, MVFFPoolClassGet()));
|
||||
CHECKD(Pool, MVFF2Pool(mvff));
|
||||
CHECKL(IsSubclassPoly(MVFF2Pool(mvff)->class, MVFFPoolClassGet()));
|
||||
CHECKD(SegPref, mvff->segPref);
|
||||
CHECKL(mvff->extendBy > 0); /* see .arg.check */
|
||||
CHECKL(mvff->minSegSize >= ArenaAlign(PoolArena(MVFFPool(mvff))));
|
||||
CHECKL(mvff->minSegSize >= ArenaAlign(PoolArena(MVFF2Pool(mvff))));
|
||||
CHECKL(mvff->avgSize > 0); /* see .arg.check */
|
||||
CHECKL(mvff->avgSize <= mvff->extendBy); /* see .arg.check */
|
||||
CHECKL(mvff->total >= mvff->free);
|
||||
CHECKL(SizeIsAligned(mvff->free, PoolAlignment(MVFFPool(mvff))));
|
||||
CHECKL(SizeIsAligned(mvff->total, ArenaAlign(PoolArena(MVFFPool(mvff)))));
|
||||
CHECKL(SizeIsAligned(mvff->free, PoolAlignment(MVFF2Pool(mvff))));
|
||||
CHECKL(SizeIsAligned(mvff->total, ArenaAlign(PoolArena(MVFF2Pool(mvff)))));
|
||||
CHECKD(CBS, CBSOfMVFF(mvff));
|
||||
CHECKL(BoolCheck(mvff->slotHigh));
|
||||
CHECKL(BoolCheck(mvff->firstFit));
|
||||
|
|
@ -673,7 +682,7 @@ void mps_mvff_stat(mps_pool_t mps_pool)
|
|||
|
||||
pool = (Pool)mps_pool;
|
||||
AVERT(Pool, pool);
|
||||
mvff = PoolPoolMVFF(pool);
|
||||
mvff = Pool2MVFF(pool);
|
||||
AVERT(MVFF, mvff);
|
||||
|
||||
METER_EMIT(&CBSOfMVFF(mvff)->splaySearch);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ static Bool testit(ArenaClass class, ...)
|
|||
|
||||
die(PoolCreate(&pool, arena, PoolClassN()), "PoolNCreate");
|
||||
res = PoolAlloc(&p, pool, 1, /* withReservoirPermit */ FALSE);
|
||||
if(res == ResOK) {
|
||||
if (res == ResOK) {
|
||||
fprintf(stderr,
|
||||
"Error: Unexpectedly succeeded in"
|
||||
"allocating block from PoolN\n");
|
||||
|
|
@ -40,7 +40,7 @@ static Bool testit(ArenaClass class, ...)
|
|||
|
||||
int main(void)
|
||||
{
|
||||
if(testit((ArenaClass)mps_arena_class_vm(), (Size)200000)) {
|
||||
if (testit((ArenaClass)mps_arena_class_vm(), (Size)600000)) {
|
||||
fprintf(stderr, "Conclusion: Defects found.\n");
|
||||
} else {
|
||||
fprintf(stderr, "Conclusion: Failed to find any defects.\n");
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@
|
|||
#include "mpscsnc.h"
|
||||
#include "mpm.h"
|
||||
|
||||
|
||||
SRCID(poolsnc, "$Id$");
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,41 +0,0 @@
|
|||
@rem impl.bat.proddw
|
||||
@rem Script that automates building and collating a dylan product
|
||||
rem $Id$
|
||||
rem Copyright (c) 2001 Ravenbrook Limited.
|
||||
nmake /f w3i3mv.nmk VARIETY=ci mmdw.lib mpsplan.lib
|
||||
nmake /f w3i3mv.nmk VARIETY=hi mmdw.lib mpsplan.lib
|
||||
nmake /f w3i3mv.nmk VARIETY=he mmdw.lib mpsplan.lib
|
||||
nmake /f w3i3mv.nmk VARIETY=wi mmdw.lib mpsplan.lib
|
||||
rmdir /Q/S dylan
|
||||
mkdir dylan
|
||||
mkdir dylan\mps
|
||||
mkdir dylan\mps\include
|
||||
mkdir dylan\mps\lib
|
||||
mkdir dylan\mps\lib\w3i3
|
||||
mkdir dylan\mps\lib\w3i3\ci
|
||||
mkdir dylan\mps\lib\w3i3\hi
|
||||
mkdir dylan\mps\lib\w3i3\he
|
||||
mkdir dylan\mps\lib\w3i3\wi
|
||||
mkdir dylan\mps\src
|
||||
copy mps.h dylan\mps\include
|
||||
copy mpsavm.h dylan\mps\include
|
||||
copy mpscamc.h dylan\mps\include
|
||||
copy mpscawl.h dylan\mps\include
|
||||
copy mpsclo.h dylan\mps\include
|
||||
copy mpscsnc.h dylan\mps\include
|
||||
copy mpscmv.h dylan\mps\include
|
||||
copy mpsio.h dylan\mps\include
|
||||
copy mpslib.h dylan\mps\include
|
||||
copy mpstd.h dylan\mps\include
|
||||
copy mpsw3.h dylan\mps\include
|
||||
copy mpswin.h dylan\mps\include
|
||||
copy w3i3mv\ci\mmdw.lib dylan\mps\lib\w3i3\ci
|
||||
copy w3i3mv\hi\mmdw.lib dylan\mps\lib\w3i3\hi
|
||||
copy w3i3mv\he\mmdw.lib dylan\mps\lib\w3i3\he
|
||||
copy w3i3mv\wi\mmdw.lib dylan\mps\lib\w3i3\wi
|
||||
copy w3i3mv\ci\mpsplan.lib dylan\mps\lib\w3i3\ci
|
||||
copy w3i3mv\hi\mpsplan.lib dylan\mps\lib\w3i3\hi
|
||||
copy w3i3mv\he\mpsplan.lib dylan\mps\lib\w3i3\he
|
||||
copy w3i3mv\wi\mpsplan.lib dylan\mps\lib\w3i3\wi
|
||||
copy mpsliban.c dylan\mps\src
|
||||
copy mpsioan.c dylan\mps\src
|
||||
|
|
@ -2,7 +2,6 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mpm.h"
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
|
||||
#include "mpm.h"
|
||||
|
||||
|
||||
SRCID(protocol, "$Id$");
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mpm.h"
|
||||
|
|
|
|||
|
|
@ -347,7 +347,7 @@ void ReservoirSetLimit(Reservoir reservoir, Size size)
|
|||
if (needed > reservoir->reservoirSize) {
|
||||
/* Try to grow the reservoir */
|
||||
reservoir->reservoirLimit = needed;
|
||||
ReservoirEnsureFull(reservoir);
|
||||
(void)ReservoirEnsureFull(reservoir);
|
||||
} else {
|
||||
/* Shrink the reservoir */
|
||||
reservoirShrink(reservoir, needed);
|
||||
|
|
@ -372,7 +372,7 @@ Size ReservoirLimit(Reservoir reservoir)
|
|||
Size ReservoirAvailable(Reservoir reservoir)
|
||||
{
|
||||
AVERT(Reservoir, reservoir);
|
||||
ReservoirEnsureFull(reservoir);
|
||||
(void)ReservoirEnsureFull(reservoir);
|
||||
return reservoir->reservoirSize;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
#include "check.h"
|
||||
#include "misc.h"
|
||||
|
||||
|
||||
SRCID(ring, "$Id$");
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (C) 2001 Global Graphics Software.
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -96,7 +97,7 @@ extern Ring (RingNext)(Ring ring);
|
|||
|
||||
/* .ring.elt: See design.mps.ring.elt */
|
||||
#define RING_ELT(type, field, node) \
|
||||
((type)((char *)(node) - (size_t)(&((type)0)->field)))
|
||||
((type)(void *)((char *)(node) - (size_t)(&((type)0)->field)))
|
||||
|
||||
/* .ring.for: See design.mps.ring.for */
|
||||
#define RING_FOR(node, ring, next) \
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (C) 2002 Global Graphics Software.
|
||||
*/
|
||||
|
||||
|
||||
#include "mpscmv.h"
|
||||
#include "mpscmvff.h"
|
||||
#include "mpslib.h"
|
||||
|
|
@ -37,6 +37,8 @@ struct itimerspec; /* stop complaints from time.h */
|
|||
#define classCOUNT 4
|
||||
|
||||
|
||||
/* make -- allocate an object */
|
||||
|
||||
static mps_res_t make(mps_addr_t *p, mps_sac_t sac, size_t size)
|
||||
{
|
||||
mps_res_t res;
|
||||
|
|
@ -46,9 +48,11 @@ static mps_res_t make(mps_addr_t *p, mps_sac_t sac, size_t size)
|
|||
}
|
||||
|
||||
|
||||
static mps_res_t stress(mps_class_t class, mps_arena_t arena,
|
||||
/* stress -- create a pool of the requested type and allocate in it */
|
||||
|
||||
static mps_res_t stress(mps_class_t class,
|
||||
size_t classes_count, mps_sac_classes_s *classes,
|
||||
size_t (*size)(int i), ...)
|
||||
size_t (*size)(int i), mps_arena_t arena, ...)
|
||||
{
|
||||
mps_res_t res;
|
||||
mps_pool_t pool;
|
||||
|
|
@ -58,7 +62,7 @@ static mps_res_t stress(mps_class_t class, mps_arena_t arena,
|
|||
int *ps[testSetSIZE];
|
||||
size_t ss[testSetSIZE];
|
||||
|
||||
va_start(arg, size);
|
||||
va_start(arg, arena);
|
||||
res = mps_pool_create_v(&pool, arena, class, arg);
|
||||
va_end(arg);
|
||||
if (res != MPS_RES_OK)
|
||||
|
|
@ -129,6 +133,8 @@ static mps_res_t stress(mps_class_t class, mps_arena_t arena,
|
|||
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
|
||||
/* randomSize8 -- produce sizes both latge and small */
|
||||
|
||||
static size_t randomSize8(int i)
|
||||
{
|
||||
size_t maxSize = 2 * 160 * 0x2000;
|
||||
|
|
@ -140,7 +146,10 @@ static size_t randomSize8(int i)
|
|||
}
|
||||
|
||||
|
||||
static mps_pool_debug_option_s debugOptions = { (void *)"postpost", 8 };
|
||||
/* testInArena -- test all the pool classes in the given arena */
|
||||
|
||||
static mps_pool_debug_option_s debugOptions =
|
||||
{ (void *)"postpost", 8, NULL, 0 };
|
||||
|
||||
static mps_sac_classes_s classes[4] = { {8, 1, 1}, {16, 1, 2}, {136, 9, 5},
|
||||
{topClassSIZE, 9, 4} };
|
||||
|
|
@ -148,15 +157,15 @@ static mps_sac_classes_s classes[4] = { {8, 1, 1}, {16, 1, 2}, {136, 9, 5},
|
|||
static int testInArena(mps_arena_t arena)
|
||||
{
|
||||
printf("MVFF\n\n");
|
||||
die(stress(mps_class_mvff(), arena, classCOUNT, classes, randomSize8,
|
||||
die(stress(mps_class_mvff(), classCOUNT, classes, randomSize8, arena,
|
||||
(size_t)65536, (size_t)32, (size_t)4, TRUE, TRUE, TRUE),
|
||||
"stress MVFF");
|
||||
printf("MV debug\n\n");
|
||||
die(stress(mps_class_mv_debug(), arena, classCOUNT, classes, randomSize8,
|
||||
die(stress(mps_class_mv_debug(), classCOUNT, classes, randomSize8, arena,
|
||||
&debugOptions, (size_t)65536, (size_t)32, (size_t)65536),
|
||||
"stress MV debug");
|
||||
printf("MV\n\n");
|
||||
die(stress(mps_class_mv(), arena, classCOUNT, classes, randomSize8,
|
||||
die(stress(mps_class_mv(), classCOUNT, classes, randomSize8, arena,
|
||||
(size_t)65536, (size_t)32, (size_t)65536),
|
||||
"stress MV");
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -637,7 +637,7 @@ Bool SegCheck(Seg seg)
|
|||
|
||||
/* Each tract of the segment must agree about white traces */
|
||||
TRACT_TRACT_FOR(tract, addr, arena, seg->firstTract, seg->limit) {
|
||||
Seg trseg;
|
||||
Seg trseg = NULL; /* suppress compiler warning */
|
||||
|
||||
UNUSED(trseg); /* @@@@ unused in hot varieties */
|
||||
CHECKL(TractCheck(tract)); /* design.mps.check.type.no-sig */
|
||||
|
|
@ -1241,9 +1241,9 @@ static void gcSegSetWhite(Seg seg, TraceSet white)
|
|||
limit = SegLimit(seg);
|
||||
/* Each tract of the segment records white traces */
|
||||
TRACT_TRACT_FOR(tract, addr, arena, seg->firstTract, limit) {
|
||||
Seg trseg;
|
||||
Seg trseg = NULL; /* suppress compiler warning */
|
||||
|
||||
UNUSED(trseg); /* @@@@ hack: unused in hot varieties */
|
||||
UNUSED(trseg); /* @@@@ unused in hot varieties */
|
||||
AVER_CRITICAL(TractCheck(tract)); /* design.mps.check.type.no-sig */
|
||||
AVER_CRITICAL(TRACT_SEG(&trseg, tract) && (trseg == seg));
|
||||
TractSetWhite(tract, white);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (c) 2002 Global Graphics Software.
|
||||
*
|
||||
* .design: Adapted from amsss.c (because AMS already supports
|
||||
* a protocol for subclassing AMS segments). Defines a new pool
|
||||
|
|
@ -343,7 +344,7 @@ static Res AMSTInit(Pool pool, va_list args)
|
|||
res = ChainCreate(&chain, pool->arena, 1, &genParam);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
res = AMSInitInternal(Pool2AMS(pool), format, chain);
|
||||
res = AMSInitInternal(Pool2AMS(pool), format, chain, FALSE);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
amst = Pool2AMST(pool);
|
||||
|
|
@ -704,6 +705,8 @@ static mps_class_t mps_class_amst(void)
|
|||
}
|
||||
|
||||
|
||||
/* AMS collection parameters */
|
||||
|
||||
#define exactRootsCOUNT 50
|
||||
#define ambigRootsCOUNT 100
|
||||
#define sizeScale 4
|
||||
|
|
@ -717,6 +720,8 @@ static mps_class_t mps_class_amst(void)
|
|||
#define stressTestFREQ 40
|
||||
|
||||
|
||||
/* static variables for the test */
|
||||
|
||||
static mps_pool_t pool;
|
||||
static mps_ap_t ap;
|
||||
static mps_addr_t exactRoots[exactRootsCOUNT];
|
||||
|
|
@ -724,6 +729,8 @@ static mps_addr_t ambigRoots[ambigRootsCOUNT];
|
|||
static size_t totalSize = 0;
|
||||
|
||||
|
||||
/* make -- object allocation and init */
|
||||
|
||||
static mps_addr_t make(void)
|
||||
{
|
||||
size_t length = rnd() % 20, size = (length+2) * sizeof(mps_word_t);
|
||||
|
|
@ -744,6 +751,8 @@ static mps_addr_t make(void)
|
|||
}
|
||||
|
||||
|
||||
/* test -- the actual stress test */
|
||||
|
||||
static void *test(void *arg, size_t s)
|
||||
{
|
||||
mps_arena_t arena;
|
||||
|
|
|
|||
|
|
@ -1,27 +0,0 @@
|
|||
; impl.asm.spi3: STACK PROBE
|
||||
;
|
||||
; $Id$
|
||||
; Copyright (c) 2001 Ravenbrook Limited.
|
||||
;
|
||||
; This function reads a location that is probeDepth words beyond
|
||||
; the current stack pointer. On intel platforms the stack grows
|
||||
; downwards so this means reading from a location with a lesser address.
|
||||
;
|
||||
; The registers edi, esi, ebx are the registers defined to be preserved
|
||||
; across function calls, so we do not use those.
|
||||
|
||||
.386
|
||||
.model flat
|
||||
.code
|
||||
|
||||
_StackProbe proc public ; (Size probeDepth)
|
||||
push ebp ; frame pointer
|
||||
mov ebp,esp
|
||||
mov eax, [ebp+08]
|
||||
neg eax
|
||||
mov eax, [esp+eax*4] ; do the actual probe
|
||||
leave
|
||||
ret ; return
|
||||
_StackProbe endp
|
||||
|
||||
end
|
||||
24
mps/code/spi3.c
Normal file
24
mps/code/spi3.c
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/* impl.c.spi3: STACK PROBE
|
||||
*
|
||||
* $Id: spi3.c,v 1.2 2002/02/01 13:56:52 pekka Exp $
|
||||
* $HopeName: MMsrc!spi3.c(trunk.2) $
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (C) 2001 Global Graphics Software.
|
||||
*
|
||||
* This function reads a location that is probeDepth words beyond
|
||||
* the current stack pointer. On intel platforms the stack grows
|
||||
* downwards so this means reading from a location with a lesser address.
|
||||
*/
|
||||
|
||||
|
||||
#include "mpm.h"
|
||||
|
||||
|
||||
void StackProbe(Size depth)
|
||||
{
|
||||
__asm {
|
||||
mov eax, depth
|
||||
neg eax
|
||||
mov eax, [esp+eax*4] /* do the actual probe */
|
||||
}
|
||||
}
|
||||
160
mps/code/splay.c
160
mps/code/splay.c
|
|
@ -17,10 +17,11 @@
|
|||
#include "splay.h"
|
||||
#include "mpm.h"
|
||||
|
||||
|
||||
SRCID(splay, "$Id$");
|
||||
|
||||
|
||||
/* Basic getter and setter methods */
|
||||
|
||||
#define SplayTreeRoot(t) RVALUE((t)->root)
|
||||
#define SplayTreeSetRoot(t, r) BEGIN ((t)->root = (r)); END
|
||||
#define SplayNodeLeftChild(n) RVALUE((n)->left)
|
||||
|
|
@ -30,9 +31,11 @@ SRCID(splay, "$Id$");
|
|||
#define SplayNodeSetRightChild(n, child) \
|
||||
BEGIN ((n)->right = (child)); END
|
||||
|
||||
|
||||
#define SplayCompare(tree, key, node) \
|
||||
(((tree)->compare)((key), (node)))
|
||||
|
||||
|
||||
Bool SplayTreeCheck(SplayTree tree)
|
||||
{
|
||||
UNUSED(tree);
|
||||
|
|
@ -42,6 +45,7 @@ Bool SplayTreeCheck(SplayTree tree)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
Bool SplayNodeCheck(SplayNode node)
|
||||
{
|
||||
UNUSED(node);
|
||||
|
|
@ -64,6 +68,7 @@ void SplayTreeInit(SplayTree tree, SplayCompareMethod compare,
|
|||
AVERT(SplayTree, tree);
|
||||
}
|
||||
|
||||
|
||||
void SplayNodeInit(SplayNode node)
|
||||
{
|
||||
AVER(node != NULL);
|
||||
|
|
@ -75,6 +80,7 @@ void SplayNodeInit(SplayNode node)
|
|||
AVERT(SplayNode, node);
|
||||
}
|
||||
|
||||
|
||||
void SplayNodeFinish(SplayNode node)
|
||||
{
|
||||
AVERT(SplayNode, node);
|
||||
|
|
@ -84,6 +90,7 @@ void SplayNodeFinish(SplayNode node)
|
|||
SplayNodeSetRightChild(node, NULL);
|
||||
}
|
||||
|
||||
|
||||
void SplayTreeFinish(SplayTree tree)
|
||||
{
|
||||
AVERT(SplayTree, tree);
|
||||
|
|
@ -91,6 +98,7 @@ void SplayTreeFinish(SplayTree tree)
|
|||
tree->compare = NULL;
|
||||
}
|
||||
|
||||
|
||||
static void SplayNodeUpdate(SplayTree tree, SplayNode node)
|
||||
{
|
||||
AVERT(SplayTree, tree);
|
||||
|
|
@ -130,6 +138,7 @@ static void SplayLinkRight(SplayNode *topIO, SplayNode *rightIO)
|
|||
SplayNodeSetLeftChild(*rightIO, NULL);
|
||||
}
|
||||
|
||||
|
||||
/* SplayLinkLeft -- Move top to right child of top
|
||||
*
|
||||
* Link the current top node into the right child of the left tree,
|
||||
|
|
@ -156,6 +165,7 @@ static void SplayLinkLeft(SplayNode *topIO, SplayNode *leftIO) {
|
|||
SplayNodeSetRightChild(*leftIO, NULL);
|
||||
}
|
||||
|
||||
|
||||
/* SplayRotateLeft -- Rotate right child edge of node
|
||||
*
|
||||
* Rotates node, right child of node, and left child of right
|
||||
|
|
@ -177,7 +187,7 @@ static void SplayRotateLeft(SplayNode *nodeIO, SplayTree tree) {
|
|||
SplayNodeSetLeftChild(nodeRight, *nodeIO);
|
||||
*nodeIO = nodeRight;
|
||||
|
||||
if(tree->updateNode != NULL) {
|
||||
if (tree->updateNode != NULL) {
|
||||
SplayNodeUpdate(tree, SplayNodeLeftChild(nodeRight));
|
||||
/* Don't need to update new root because we know that we will */
|
||||
/* do either a link or an assemble next, and that will sort it */
|
||||
|
|
@ -187,6 +197,7 @@ static void SplayRotateLeft(SplayNode *nodeIO, SplayTree tree) {
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
/* SplayRotateRight -- Rotate left child edge of node
|
||||
*
|
||||
* Rotates node, left child of node, and right child of left
|
||||
|
|
@ -208,7 +219,7 @@ static void SplayRotateRight(SplayNode *nodeIO, SplayTree tree) {
|
|||
SplayNodeSetRightChild(nodeLeft, *nodeIO);
|
||||
*nodeIO = nodeLeft;
|
||||
|
||||
if(tree->updateNode != NULL) {
|
||||
if (tree->updateNode != NULL) {
|
||||
SplayNodeUpdate(tree, SplayNodeRightChild(nodeLeft));
|
||||
/* Don't need to update new root because we know that we will */
|
||||
/* do either a link or an assemble next, and that will sort it */
|
||||
|
|
@ -218,6 +229,7 @@ static void SplayRotateRight(SplayNode *nodeIO, SplayTree tree) {
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
/* SplayAssemble -- Assemble left right and top trees into one
|
||||
*
|
||||
* We do this by moving the children of the top tree to the last and
|
||||
|
|
@ -241,11 +253,11 @@ static void SplayAssemble(SplayTree tree, SplayNode top,
|
|||
AVER(rightTop == NULL ||
|
||||
(SplayNodeCheck(rightTop) && SplayNodeCheck(rightFirst)));
|
||||
|
||||
if(leftTop != NULL) {
|
||||
if (leftTop != NULL) {
|
||||
SplayNodeSetRightChild(leftLast, SplayNodeLeftChild(top));
|
||||
SplayNodeSetLeftChild(top, leftTop);
|
||||
|
||||
if(tree->updateNode != NULL) {
|
||||
if (tree->updateNode != NULL) {
|
||||
/* Update client property using pointer reversal (Ugh!). */
|
||||
SplayNode node, parent, rightChild;
|
||||
|
||||
|
|
@ -274,11 +286,11 @@ static void SplayAssemble(SplayTree tree, SplayNode top,
|
|||
}
|
||||
/* otherwise leave top->left alone */
|
||||
|
||||
if(rightTop != NULL) {
|
||||
if (rightTop != NULL) {
|
||||
SplayNodeSetLeftChild(rightFirst, SplayNodeRightChild(top));
|
||||
SplayNodeSetRightChild(top, rightTop);
|
||||
|
||||
if(tree->updateNode != NULL) {
|
||||
if (tree->updateNode != NULL) {
|
||||
/* Update client property using pointer reversal (Ugh!). */
|
||||
SplayNode node, parent, leftChild;
|
||||
|
||||
|
|
@ -307,10 +319,11 @@ static void SplayAssemble(SplayTree tree, SplayNode top,
|
|||
}
|
||||
/* otherwise leave top->right alone */
|
||||
|
||||
if(tree->updateNode != NULL)
|
||||
if (tree->updateNode != NULL)
|
||||
SplayNodeUpdate(tree, top);
|
||||
}
|
||||
|
||||
|
||||
/* SplaySplay -- Splay the tree (top-down) around a given key
|
||||
*
|
||||
* If the key is not found, splays around an arbitrary neighbour.
|
||||
|
|
@ -324,7 +337,7 @@ static Bool SplaySplay(SplayNode *nodeReturn, SplayTree tree,
|
|||
void *key, SplayCompareMethod compareMethod) {
|
||||
/* The sides structure avoids a boundary case in SplayLink* */
|
||||
SplayNodeStruct sides; /* rightTop and leftTop */
|
||||
SplayNode top, leftLast, rightFirst;
|
||||
SplayNode top, leftLast, rightFirst;
|
||||
Bool found;
|
||||
Compare compareTop;
|
||||
|
||||
|
|
@ -334,14 +347,14 @@ static Bool SplaySplay(SplayNode *nodeReturn, SplayTree tree,
|
|||
|
||||
top = SplayTreeRoot(tree); /* will be copied back at end */
|
||||
|
||||
if(top == NULL) {
|
||||
if (top == NULL) {
|
||||
*nodeReturn = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* short-circuit case where node is already top */
|
||||
compareTop = (*compareMethod)(key, top);
|
||||
if(compareTop == CompareEQUAL) {
|
||||
if (compareTop == CompareEQUAL) {
|
||||
*nodeReturn = top;
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -356,7 +369,7 @@ static Bool SplaySplay(SplayNode *nodeReturn, SplayTree tree,
|
|||
|
||||
case CompareLESS: {
|
||||
SplayNode topLeft = SplayNodeLeftChild(top);
|
||||
if(topLeft == NULL) {
|
||||
if (topLeft == NULL) {
|
||||
found = FALSE;
|
||||
goto assemble;
|
||||
} else {
|
||||
|
|
@ -371,14 +384,14 @@ static Bool SplaySplay(SplayNode *nodeReturn, SplayTree tree,
|
|||
} /* break; */
|
||||
|
||||
case CompareLESS: { /* zig-zig */
|
||||
if(SplayNodeLeftChild(topLeft) == NULL)
|
||||
if (SplayNodeLeftChild(topLeft) == NULL)
|
||||
goto terminalZig;
|
||||
SplayRotateRight(&top, tree);
|
||||
SplayLinkRight(&top, &rightFirst);
|
||||
} break;
|
||||
|
||||
case CompareGREATER: { /* zig-zag */
|
||||
if(SplayNodeRightChild(topLeft) == NULL)
|
||||
if (SplayNodeRightChild(topLeft) == NULL)
|
||||
goto terminalZig;
|
||||
SplayLinkRight(&top, &rightFirst);
|
||||
SplayLinkLeft(&top, &leftLast);
|
||||
|
|
@ -393,7 +406,7 @@ static Bool SplaySplay(SplayNode *nodeReturn, SplayTree tree,
|
|||
|
||||
case CompareGREATER: {
|
||||
SplayNode topRight = SplayNodeRightChild(top);
|
||||
if(topRight == NULL) {
|
||||
if (topRight == NULL) {
|
||||
found = FALSE;
|
||||
goto assemble;
|
||||
} else {
|
||||
|
|
@ -408,14 +421,14 @@ static Bool SplaySplay(SplayNode *nodeReturn, SplayTree tree,
|
|||
} /* break; */
|
||||
|
||||
case CompareGREATER: { /* zag-zag */
|
||||
if(SplayNodeRightChild(topRight) == NULL)
|
||||
if (SplayNodeRightChild(topRight) == NULL)
|
||||
goto terminalZag;
|
||||
SplayRotateLeft(&top, tree);
|
||||
SplayLinkLeft(&top, &leftLast);
|
||||
} break;
|
||||
|
||||
case CompareLESS: { /* zag-zig */
|
||||
if(SplayNodeLeftChild(topRight) == NULL)
|
||||
if (SplayNodeLeftChild(topRight) == NULL)
|
||||
goto terminalZag;
|
||||
SplayLinkLeft(&top, &leftLast);
|
||||
SplayLinkRight(&top, &rightFirst);
|
||||
|
|
@ -439,7 +452,7 @@ static Bool SplaySplay(SplayNode *nodeReturn, SplayTree tree,
|
|||
}
|
||||
compareTop = (*compareMethod)(key, top);
|
||||
} /* end while(TRUE) */
|
||||
|
||||
|
||||
terminalZig:
|
||||
SplayLinkRight(&top, &rightFirst);
|
||||
found = FALSE;
|
||||
|
|
@ -476,9 +489,9 @@ Res SplayTreeInsert(SplayTree tree, SplayNode node, void *key) {
|
|||
AVER(SplayNodeLeftChild(node) == NULL);
|
||||
AVER(SplayNodeRightChild(node) == NULL);
|
||||
|
||||
if(SplayTreeRoot(tree) == NULL) {
|
||||
if (SplayTreeRoot(tree) == NULL) {
|
||||
SplayTreeSetRoot(tree, node);
|
||||
} else if(SplaySplay(&neighbour, tree, key, tree->compare)) {
|
||||
} else if (SplaySplay(&neighbour, tree, key, tree->compare)) {
|
||||
return ResFAIL;
|
||||
} else {
|
||||
AVER(SplayTreeRoot(tree) == neighbour);
|
||||
|
|
@ -504,7 +517,7 @@ Res SplayTreeInsert(SplayTree tree, SplayNode node, void *key) {
|
|||
} break;
|
||||
}
|
||||
|
||||
if(tree->updateNode != NULL) {
|
||||
if (tree->updateNode != NULL) {
|
||||
SplayNodeUpdate(tree, neighbour);
|
||||
SplayNodeUpdate(tree, node);
|
||||
}
|
||||
|
|
@ -530,21 +543,21 @@ Res SplayTreeDelete(SplayTree tree, SplayNode node, void *key) {
|
|||
found = SplaySplay(&del, tree, key, tree->compare);
|
||||
AVER(!found || del == node);
|
||||
|
||||
if(!found) {
|
||||
if (!found) {
|
||||
return ResFAIL;
|
||||
} else if(SplayNodeLeftChild(node) == NULL) {
|
||||
} else if (SplayNodeLeftChild(node) == NULL) {
|
||||
SplayTreeSetRoot(tree, SplayNodeRightChild(node));
|
||||
} else if(SplayNodeRightChild(node) == NULL) {
|
||||
} else if (SplayNodeRightChild(node) == NULL) {
|
||||
SplayTreeSetRoot(tree, SplayNodeLeftChild(node));
|
||||
} else {
|
||||
rightHalf = SplayNodeRightChild(node);
|
||||
SplayTreeSetRoot(tree, SplayNodeLeftChild(node));
|
||||
if(SplaySplay(&leftLast, tree, key, tree->compare)) {
|
||||
if (SplaySplay(&leftLast, tree, key, tree->compare)) {
|
||||
return ResFAIL;
|
||||
} else {
|
||||
AVER(SplayNodeRightChild(leftLast) == NULL);
|
||||
SplayNodeSetRightChild(leftLast, rightHalf);
|
||||
if(tree->updateNode != NULL) {
|
||||
if (tree->updateNode != NULL) {
|
||||
SplayNodeUpdate(tree, leftLast);
|
||||
}
|
||||
}
|
||||
|
|
@ -562,14 +575,13 @@ Res SplayTreeDelete(SplayTree tree, SplayNode node, void *key) {
|
|||
* design.mps.splay.impl.search.
|
||||
*/
|
||||
|
||||
|
||||
Res SplayTreeSearch(SplayNode *nodeReturn, SplayTree tree, void *key) {
|
||||
SplayNode node;
|
||||
|
||||
AVERT(SplayTree, tree);
|
||||
AVER(nodeReturn != NULL);
|
||||
|
||||
if(SplaySplay(&node, tree, key, tree->compare)) {
|
||||
if (SplaySplay(&node, tree, key, tree->compare)) {
|
||||
*nodeReturn = node;
|
||||
} else {
|
||||
return ResFAIL;
|
||||
|
|
@ -593,20 +605,20 @@ static SplayNode SplayTreePredecessor(SplayTree tree, void *key) {
|
|||
oldRoot = SplayTreeRoot(tree);
|
||||
AVERT(SplayNode, oldRoot);
|
||||
|
||||
if(SplayNodeLeftChild(oldRoot) == NULL) {
|
||||
if (SplayNodeLeftChild(oldRoot) == NULL) {
|
||||
newRoot = NULL; /* No predecessor */
|
||||
} else {
|
||||
/* temporarily chop off the right half-tree, inclusive of root */
|
||||
SplayTreeSetRoot(tree, SplayNodeLeftChild(oldRoot));
|
||||
SplayNodeSetLeftChild(oldRoot, NULL);
|
||||
if(SplaySplay(&newRoot, tree, key, tree->compare)) {
|
||||
if (SplaySplay(&newRoot, tree, key, tree->compare)) {
|
||||
NOTREACHED; /* Another matching node found */
|
||||
} else {
|
||||
AVER(SplayNodeRightChild(newRoot) == NULL);
|
||||
SplayNodeSetRightChild(newRoot, oldRoot);
|
||||
}
|
||||
|
||||
if(tree->updateNode != NULL) {
|
||||
if (tree->updateNode != NULL) {
|
||||
SplayNodeUpdate(tree, oldRoot);
|
||||
SplayNodeUpdate(tree, newRoot);
|
||||
}
|
||||
|
|
@ -630,20 +642,20 @@ static SplayNode SplayTreeSuccessor(SplayTree tree, void *key) {
|
|||
oldRoot = SplayTreeRoot(tree);
|
||||
AVERT(SplayNode, oldRoot);
|
||||
|
||||
if(SplayNodeRightChild(oldRoot) == NULL) {
|
||||
if (SplayNodeRightChild(oldRoot) == NULL) {
|
||||
newRoot = NULL; /* No successor */
|
||||
} else {
|
||||
/* temporarily chop off the left half-tree, inclusive of root */
|
||||
SplayTreeSetRoot(tree, SplayNodeRightChild(oldRoot));
|
||||
SplayNodeSetRightChild(oldRoot, NULL);
|
||||
if(SplaySplay(&newRoot, tree, key, tree->compare)) {
|
||||
if (SplaySplay(&newRoot, tree, key, tree->compare)) {
|
||||
NOTREACHED; /* Another matching node found */
|
||||
} else {
|
||||
AVER(SplayNodeLeftChild(newRoot) == NULL);
|
||||
SplayNodeSetLeftChild(newRoot, oldRoot);
|
||||
}
|
||||
|
||||
if(tree->updateNode != NULL) {
|
||||
if (tree->updateNode != NULL) {
|
||||
SplayNodeUpdate(tree, oldRoot);
|
||||
SplayNodeUpdate(tree, newRoot);
|
||||
}
|
||||
|
|
@ -670,9 +682,9 @@ Res SplayTreeNeighbours(SplayNode *leftReturn, SplayNode *rightReturn,
|
|||
AVER(leftReturn != NULL);
|
||||
AVER(rightReturn != NULL);
|
||||
|
||||
if(SplaySplay(&neighbour, tree, key, tree->compare)) {
|
||||
if (SplaySplay(&neighbour, tree, key, tree->compare)) {
|
||||
return ResFAIL;
|
||||
} else if(neighbour == NULL) {
|
||||
} else if (neighbour == NULL) {
|
||||
*leftReturn = *rightReturn = NULL;
|
||||
} else {
|
||||
switch(SplayCompare(tree, key, neighbour)) {
|
||||
|
|
@ -700,7 +712,7 @@ Res SplayTreeNeighbours(SplayNode *leftReturn, SplayNode *rightReturn,
|
|||
/* SplayTreeFirst, SplayTreeNext -- Iterators
|
||||
*
|
||||
* SplayTreeFirst receives a key that must precede all
|
||||
* nodes in the tree. It returns NULL if the tree is empty.
|
||||
* nodes in the tree. It returns NULL if the tree is empty.
|
||||
* Otherwise, it splays the tree to the first node, and returns the
|
||||
* new root. See design.mps.splay.function.splay.tree.first.
|
||||
*
|
||||
|
|
@ -714,9 +726,9 @@ SplayNode SplayTreeFirst(SplayTree tree, void *zeroKey) {
|
|||
SplayNode node;
|
||||
AVERT(SplayTree, tree);
|
||||
|
||||
if(SplayTreeRoot(tree) == NULL) {
|
||||
if (SplayTreeRoot(tree) == NULL) {
|
||||
node = NULL;
|
||||
} else if(SplaySplay(&node, tree, zeroKey, tree->compare)) {
|
||||
} else if (SplaySplay(&node, tree, zeroKey, tree->compare)) {
|
||||
NOTREACHED;
|
||||
} else {
|
||||
AVER(SplayNodeLeftChild(node) == NULL);
|
||||
|
|
@ -751,44 +763,40 @@ static Res SplayNodeDescribe(SplayNode node, mps_lib_FILE *stream,
|
|||
SplayNodeDescribeMethod nodeDescribe) {
|
||||
Res res;
|
||||
|
||||
AVERT(SplayNode, node);
|
||||
#if defined(CHECK)
|
||||
if (!SplayNodeCheck(node)) return ResFAIL;
|
||||
/* stream and nodeDescribe checked by SplayTreeDescribe */
|
||||
#endif
|
||||
|
||||
res = WriteF(stream, "( ", NULL);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
if (res != ResOK) return res;
|
||||
|
||||
if(SplayNodeLeftChild(node) != NULL) {
|
||||
if (SplayNodeLeftChild(node) != NULL) {
|
||||
res = SplayNodeDescribe(SplayNodeLeftChild(node), stream, nodeDescribe);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
if (res != ResOK) return res;
|
||||
|
||||
res = WriteF(stream, " / ", NULL);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
if (res != ResOK) return res;
|
||||
}
|
||||
|
||||
res = (*nodeDescribe)(node, stream);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
if (res != ResOK) return res;
|
||||
|
||||
if(SplayNodeRightChild(node) != NULL) {
|
||||
if (SplayNodeRightChild(node) != NULL) {
|
||||
res = WriteF(stream, " \\ ", NULL);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
if (res != ResOK) return res;
|
||||
|
||||
res = SplayNodeDescribe(SplayNodeRightChild(node), stream, nodeDescribe);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
if (res != ResOK) return res;
|
||||
}
|
||||
|
||||
res = WriteF(stream, " )", NULL);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
if (res != ResOK) return res;
|
||||
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
SplayTestNodeMethod testNode;
|
||||
SplayTestTreeMethod testTree;
|
||||
|
|
@ -816,10 +824,10 @@ static Compare SplayFindFirstCompare(void *key, SplayNode node)
|
|||
testTree = closure->testTree;
|
||||
tree = closure->tree;
|
||||
|
||||
if(SplayNodeLeftChild(node) != NULL &&
|
||||
if (SplayNodeLeftChild(node) != NULL &&
|
||||
(*testTree)(tree, SplayNodeLeftChild(node), closureP, closureS)) {
|
||||
return CompareLESS;
|
||||
} else if((*testNode)(tree, node, closureP, closureS)) {
|
||||
} else if ((*testNode)(tree, node, closureP, closureS)) {
|
||||
return CompareEQUAL;
|
||||
} else {
|
||||
AVER(SplayNodeRightChild(node) != NULL &&
|
||||
|
|
@ -847,10 +855,10 @@ static Compare SplayFindLastCompare(void *key, SplayNode node)
|
|||
testTree = closure->testTree;
|
||||
tree = closure->tree;
|
||||
|
||||
if(SplayNodeRightChild(node) != NULL &&
|
||||
if (SplayNodeRightChild(node) != NULL &&
|
||||
(*testTree)(tree, SplayNodeRightChild(node), closureP, closureS)) {
|
||||
return CompareGREATER;
|
||||
} else if((*testNode)(tree, node, closureP, closureS)) {
|
||||
} else if ((*testNode)(tree, node, closureP, closureS)) {
|
||||
return CompareEQUAL;
|
||||
} else {
|
||||
AVER(SplayNodeLeftChild(node) != NULL &&
|
||||
|
|
@ -887,7 +895,7 @@ Bool SplayFindFirst(SplayNode *nodeReturn, SplayTree tree,
|
|||
|
||||
node = SplayTreeRoot(tree);
|
||||
|
||||
if(node == NULL || !(*testTree)(tree, node, closureP, closureS))
|
||||
if (node == NULL || !(*testTree)(tree, node, closureP, closureS))
|
||||
return FALSE; /* no suitable nodes in tree */
|
||||
|
||||
closureStruct.p = closureP;
|
||||
|
|
@ -896,8 +904,8 @@ Bool SplayFindFirst(SplayNode *nodeReturn, SplayTree tree,
|
|||
closureStruct.testTree = testTree;
|
||||
closureStruct.tree = tree;
|
||||
|
||||
if(SplaySplay(&node, tree, (void *)&closureStruct,
|
||||
&SplayFindFirstCompare)) {
|
||||
if (SplaySplay(&node, tree, (void *)&closureStruct,
|
||||
&SplayFindFirstCompare)) {
|
||||
*nodeReturn = node;
|
||||
return TRUE;
|
||||
} else {
|
||||
|
|
@ -923,7 +931,7 @@ Bool SplayFindLast(SplayNode *nodeReturn, SplayTree tree,
|
|||
|
||||
node = SplayTreeRoot(tree);
|
||||
|
||||
if(node == NULL || !(*testTree)(tree, node, closureP, closureS))
|
||||
if (node == NULL || !(*testTree)(tree, node, closureP, closureS))
|
||||
return FALSE; /* no suitable nodes in tree */
|
||||
|
||||
closureStruct.p = closureP;
|
||||
|
|
@ -932,8 +940,8 @@ Bool SplayFindLast(SplayNode *nodeReturn, SplayTree tree,
|
|||
closureStruct.testTree = testTree;
|
||||
closureStruct.tree = tree;
|
||||
|
||||
if(SplaySplay(&node, tree, (void *)&closureStruct,
|
||||
&SplayFindLastCompare)) {
|
||||
if (SplaySplay(&node, tree, (void *)&closureStruct,
|
||||
&SplayFindLastCompare)) {
|
||||
*nodeReturn = node;
|
||||
return TRUE;
|
||||
} else {
|
||||
|
|
@ -952,7 +960,7 @@ Bool SplayRoot(SplayNode *nodeReturn, SplayTree tree)
|
|||
AVERT(SplayTree, tree);
|
||||
|
||||
node = SplayTreeRoot(tree);
|
||||
if(node == NULL)
|
||||
if (node == NULL)
|
||||
return FALSE;
|
||||
else {
|
||||
*nodeReturn = node;
|
||||
|
|
@ -997,21 +1005,21 @@ Res SplayTreeDescribe(SplayTree tree, mps_lib_FILE *stream,
|
|||
SplayNodeDescribeMethod nodeDescribe) {
|
||||
Res res;
|
||||
|
||||
if(!SplayTreeCheck(tree)) return ResFAIL;
|
||||
if(stream == NULL) return ResFAIL;
|
||||
if(!FUNCHECK(nodeDescribe)) return ResFAIL;
|
||||
#if defined(CHECK)
|
||||
if (!SplayTreeCheck(tree)) return ResFAIL;
|
||||
if (stream == NULL) return ResFAIL;
|
||||
if (!FUNCHECK(nodeDescribe)) return ResFAIL;
|
||||
#endif
|
||||
|
||||
res = WriteF(stream,
|
||||
"Splay $P {\n", (WriteFP)tree,
|
||||
" compare $F\n", (WriteFF)tree->compare,
|
||||
NULL);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
if (res != ResOK) return res;
|
||||
|
||||
if(SplayTreeRoot(tree) != NULL) {
|
||||
if (SplayTreeRoot(tree) != NULL) {
|
||||
res = SplayNodeDescribe(SplayTreeRoot(tree), stream, nodeDescribe);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
if (res != ResOK) return res;
|
||||
}
|
||||
|
||||
res = WriteF(stream, "\n}\n", NULL);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
/* impl.h.ss
|
||||
* STACK SCANNING
|
||||
/* impl.h.ss: STACK SCANNING
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
SRCID(sslii3, "$Id$");
|
||||
|
||||
|
||||
/* .assume.asm.order */
|
||||
#define ASMV(x) __asm__ volatile (x)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
! impl.s.sssos8
|
||||
! impl.s.sssos8: STACK SCANNING
|
||||
!
|
||||
! STACK SCANNING
|
||||
!
|
||||
! $Id$
|
||||
!
|
||||
|
|
|
|||
63
mps/code/sssus8.c
Normal file
63
mps/code/sssus8.c
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/* impl.c.sssus8: SPARC STACK SCANNING
|
||||
*
|
||||
* $HopeName: MMsrc!sssus8.c(trunk.1) $
|
||||
* $Id: sssus8.c,v 1.1 2002/02/15 19:12:02 pekka Exp $
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (c) 2002 Global Graphics Software.
|
||||
*
|
||||
* This scans the stack and fixes the registers which may contain
|
||||
* roots. See design.mps.thread-manager.
|
||||
*
|
||||
* .roots: The non-global registers are preserved into the stackframe
|
||||
* by the "ta 3" instruction. This leaves the global registers.
|
||||
* According to the Sparc Architecture Manual:
|
||||
* %g1 is assumed to be volatile across procedure calls
|
||||
* %g2...%g4 are "reserved for use by application programmer"
|
||||
* %g5...%g7 are "nonvolatile and reserved for (as-yet-undefined)
|
||||
* use by the execution environment"
|
||||
* To be safe %g2 to %g7 are pushed onto the stack before scanning
|
||||
* it just in case.
|
||||
*
|
||||
* ASSUMPTIONS
|
||||
*
|
||||
* .assume.align: The stack pointer is assumed to be aligned on a word
|
||||
* boundary.
|
||||
*
|
||||
* .assume.asm.stack: The compiler must not do wacky things with the
|
||||
* stack pointer around a call since we need to ensure that the
|
||||
* callee-save regs are visible during TraceScanArea.
|
||||
*
|
||||
* .assume.asm.order: The volatile modifier should prevent movement
|
||||
* of code, which might break .assume.asm.stack.
|
||||
*/
|
||||
|
||||
#include "mpm.h"
|
||||
#include <alloca.h>
|
||||
|
||||
SRCID(sssus8, "$Id: sssus8.c,v 1.1 2002/02/15 19:12:02 pekka Exp $");
|
||||
|
||||
|
||||
/* .assume.asm.order */
|
||||
#define ASMV(x) __asm__ volatile (x)
|
||||
|
||||
|
||||
Res StackScan(ScanState ss, Addr *stackBot)
|
||||
{
|
||||
Addr *stackTop;
|
||||
Res res;
|
||||
void *globals;
|
||||
|
||||
/* We expect C will save the caller's window, but we don't really care, */
|
||||
/* because it's bound to be an MPS window. */
|
||||
globals = alloca(24); /* for 6 globals */
|
||||
ASMV("std %%g2, [%0]" : : "r" (globals)); /* double stores */
|
||||
ASMV("std %%g4, [%0 + 8]" : : "r" (globals));
|
||||
ASMV("std %%g6, [%0 + 16]" : : "r" (globals));
|
||||
ASMV("ta 3"); /* flushes register windows onto stack */
|
||||
ASMV("mov %%sp, %0" : "=r" (stackTop)); /* stackTop = sp */
|
||||
|
||||
AVER(AddrIsAligned((Addr)stackTop, sizeof(Addr))); /* .assume.align */
|
||||
res = TraceScanArea(ss, stackTop, stackBot);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
@ -1,6 +1,4 @@
|
|||
! impl.s.sssus8
|
||||
!
|
||||
! STACK SCANNING
|
||||
! impl.s.sssus8: STACK SCANNING
|
||||
!
|
||||
! $Id$
|
||||
!
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
# impl.gmk.sus8lc: BUILD FOR SUNOS/SPARC V8/LCC PLATFORM
|
||||
#
|
||||
# $Id$
|
||||
# Copyright (c) 2001 Ravenbrook Limited.
|
||||
#
|
||||
# This is the GNU makefile for platform.sus8lc.
|
||||
|
||||
PFM = sus8lc
|
||||
|
||||
MPMPF = mpsliban.c mpsioan.c lockan.c than.c vmsu.c \
|
||||
protsu.c prmcan.c span.c
|
||||
MPMS = sssus8.s
|
||||
|
||||
include lc.gmk
|
||||
|
|
@ -13,7 +13,6 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
SRCID(teletest, "$Id$");
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,15 +2,17 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* .purpose: A library of functions that may be of use to unit tests.
|
||||
*/
|
||||
|
||||
#include "testlib.h"
|
||||
#include "mps.h"
|
||||
#include "mpm.h"
|
||||
#include "misc.h" /* for NOOP */
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#ifdef MPS_OS_IA
|
||||
struct itimerspec; /* stop complaints from time.h */
|
||||
#endif
|
||||
|
|
@ -19,16 +21,16 @@ struct itimerspec; /* stop complaints from time.h */
|
|||
|
||||
/* rnd -- a random number generator
|
||||
*
|
||||
* I nabbed it from "ML for the Working Programmer"
|
||||
* Originally from:
|
||||
* I nabbed it from "ML for the Working Programmer", originally from:
|
||||
* Stephen K Park & Keith W Miller (1988). Random number generators:
|
||||
* good one are to find. Communications of the ACM, 31:1192-1201
|
||||
* good one are to find. Communications of the ACM, 31:1192-1201.
|
||||
*/
|
||||
|
||||
unsigned long rnd(void)
|
||||
{
|
||||
static unsigned long seed = 1;
|
||||
double s;
|
||||
|
||||
s = seed;
|
||||
s *= 16807.0;
|
||||
s = fmod(s, 2147483647.0); /* 2^31 - 1 */
|
||||
|
|
@ -37,13 +39,32 @@ unsigned long rnd(void)
|
|||
}
|
||||
|
||||
|
||||
/* rnd_addr -- a random address generator
|
||||
*
|
||||
* rnd gives 31 random bits, we run it repeatedly to get enough bits.
|
||||
*/
|
||||
|
||||
#define ADDR_BITS (sizeof(mps_addr_t) * CHAR_BIT)
|
||||
|
||||
mps_addr_t rnd_addr(void)
|
||||
{
|
||||
mps_word_t res;
|
||||
unsigned bits;
|
||||
|
||||
for (bits = 0, res = 0; bits < ADDR_BITS;
|
||||
bits += 31, res = res << 31 | (mps_word_t)rnd())
|
||||
NOOP;
|
||||
return (mps_addr_t)res;
|
||||
}
|
||||
|
||||
|
||||
/* randomize -- randomize the generator, or initialize to replay */
|
||||
|
||||
void randomize(int argc, char **argv)
|
||||
{
|
||||
int i, k, n;
|
||||
|
||||
if(argc > 1) {
|
||||
if (argc > 1) {
|
||||
n = sscanf(argv[1], "%d", &k);
|
||||
die((n == 1) ? MPS_RES_OK : MPS_RES_FAIL, "randomize");
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* .purpose: A library of functions that may be of use to unit tests.
|
||||
*/
|
||||
|
|
@ -14,6 +15,9 @@
|
|||
|
||||
/* Include system header hackery. */
|
||||
#include "mpstd.h"
|
||||
#ifdef MPS_OS_W3
|
||||
#include "mpswin.h"
|
||||
#endif
|
||||
#ifdef MPS_OS_SU
|
||||
#include "ossu.h"
|
||||
#endif
|
||||
|
|
@ -52,12 +56,12 @@
|
|||
#pragma warning(disable: 4701)
|
||||
#endif
|
||||
|
||||
/* In white-hot versions, absolutely no checking is done. This leads to
|
||||
* many spurious warnings because parameters are suddenly unused, etc.
|
||||
* We aren't interested in these.
|
||||
|
||||
/* Non-checking varieties give many spurious warnings because parameters
|
||||
* are suddenly unused, etc. We aren't interested in these.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_VAR_WI)
|
||||
#if defined(CHECK_NONE)
|
||||
|
||||
/* "unreferenced formal parameter" */
|
||||
#pragma warning(disable: 4100)
|
||||
|
|
@ -140,6 +144,14 @@ extern void verror(const char *format, va_list args);
|
|||
extern unsigned long rnd(void);
|
||||
|
||||
|
||||
/* rnd_addr -- random number generator
|
||||
*
|
||||
* rnd_addr() generates a sequence of addresses all over the address space.
|
||||
*/
|
||||
|
||||
extern mps_addr_t rnd_addr(void);
|
||||
|
||||
|
||||
/* randomize -- randomize the generator, or initialize to replay
|
||||
*
|
||||
* randomize(argc, argv) randomizes the rnd generator (using time(3))
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* .design: design.mps.trace. */
|
||||
|
||||
|
|
@ -1543,7 +1544,9 @@ Bool TracePoll(Globals globals)
|
|||
|
||||
res = TraceCreate(&trace, arena);
|
||||
AVER(res == ResOK); /* succeeds because no other trace is busy */
|
||||
traceCondemnAll(trace);
|
||||
res = traceCondemnAll(trace);
|
||||
if (res != ResOK) /* should try some other trace, really @@@@ */
|
||||
goto failCondemn;
|
||||
finishingTime = ArenaAvail(arena)
|
||||
- trace->condemned * (1.0 - TraceTopGenMortality);
|
||||
if (finishingTime < 0)
|
||||
|
|
@ -1574,7 +1577,7 @@ Bool TracePoll(Globals globals)
|
|||
res = TraceCreate(&trace, arena);
|
||||
AVER(res == ResOK);
|
||||
res = ChainCondemnAuto(&mortality, firstChain, trace);
|
||||
if (res != ResOK)
|
||||
if (res != ResOK) /* should try some other trace, really @@@@ */
|
||||
goto failCondemn;
|
||||
trace->chain = firstChain;
|
||||
ChainStartGC(firstChain, trace);
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "tract.h"
|
||||
#include "boot.h"
|
||||
#include "bt.h"
|
||||
#include "mpm.h"
|
||||
|
||||
SRCID(tract, "$Id$");
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "mpmtypes.h"
|
||||
#include "ring.h"
|
||||
#include "bt.h"
|
||||
|
||||
|
||||
/* TractStruct -- tract structure
|
||||
|
|
@ -231,11 +232,11 @@ extern Index IndexOfAddr(Chunk chunk, Addr addr);
|
|||
AddrAdd((chunk)->base, ChunkPagesToSize(chunk, i))
|
||||
|
||||
|
||||
/* TractIsContiguousRange -- do base and limit define a contiguous range */
|
||||
/* TractAverContiguousRange -- verify that range is contiguous */
|
||||
|
||||
#define AverTractIsContiguousRange(arena, rangeBase, rangeLimit) \
|
||||
#define TractAverContiguousRange(arena, rangeBase, rangeLimit) \
|
||||
BEGIN \
|
||||
Chunk _ch; \
|
||||
Chunk _ch = NULL; \
|
||||
\
|
||||
UNUSED(_ch); \
|
||||
AVER(ChunkOfAddr(&_ch, arena, rangeBase) && (rangeLimit) <= _ch->limit); \
|
||||
|
|
@ -255,7 +256,7 @@ extern Bool TractNext(Tract *tractReturn, Arena arena, Addr addr);
|
|||
|
||||
#define TRACT_TRACT_FOR(tract, addr, arena, firstTract, limit) \
|
||||
tract = (firstTract); addr = TractBase(tract); \
|
||||
AverTractIsContiguousRange(arena, addr, limit); \
|
||||
TractAverContiguousRange(arena, addr, limit); \
|
||||
for(; tract != NULL; \
|
||||
(addr = AddrAdd(addr, (arena)->alignment)), \
|
||||
(addr < (limit) ? \
|
||||
|
|
|
|||
|
|
@ -10,14 +10,12 @@
|
|||
*
|
||||
* DESIGN
|
||||
*
|
||||
* .design: See design.mps.version-library, but to let you in on a
|
||||
* secret it works by declaring a string with all the necessary info
|
||||
* in.
|
||||
*/
|
||||
* .design: See design.mps.version-library, but - to let you in on a
|
||||
* secret - it works by declaring a string with all the necessary info
|
||||
* in. */
|
||||
|
||||
#include "mpm.h"
|
||||
|
||||
|
||||
SRCID(version, "$Id$");
|
||||
|
||||
|
||||
|
|
@ -28,7 +26,7 @@ SRCID(version, "$Id$");
|
|||
* whatever.
|
||||
*/
|
||||
|
||||
#define MPS_RELEASE "$Id$ *** DEVELOPMENT ONLY ***"
|
||||
#define MPS_RELEASE "release.epcore.chub"
|
||||
|
||||
|
||||
/* MPSCopyrightNotice -- copyright notice for the binary
|
||||
|
|
@ -38,7 +36,7 @@ SRCID(version, "$Id$");
|
|||
*/
|
||||
|
||||
char MPSCopyrightNotice[] =
|
||||
"Copyright (c) 2001 Ravenbrook Limited.";
|
||||
"Copyright (c) 2002 Ravenbrook Limited and Global Graphics Software.";
|
||||
|
||||
|
||||
/* MPSVersion -- return version string
|
||||
|
|
|
|||
|
|
@ -195,7 +195,7 @@ void VMUnmap(VM vm, Addr base, Addr limit)
|
|||
AVER(AddrIsAligned(limit, VMANPageALIGNMENT));
|
||||
|
||||
size = AddrOffset(base, limit);
|
||||
memset((void *)base, VM_JUNKBYTE, size);
|
||||
memset((void *)base, 0xCD, size);
|
||||
|
||||
AVER(vm->mapped >= size);
|
||||
vm->mapped -= size;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited.
|
||||
* Copyright (c) 2002 Global Graphics Software.
|
||||
*
|
||||
* DESIGN
|
||||
*
|
||||
|
|
@ -44,6 +45,7 @@
|
|||
|
||||
/* Open sesame magic */
|
||||
#define _POSIX_SOURCE
|
||||
#define _XOPEN_SOURCE 500
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
|
|
@ -56,12 +58,6 @@
|
|||
SRCID(vmso, "$Id$");
|
||||
|
||||
|
||||
/* Fix up unprototyped system calls. */
|
||||
|
||||
extern int close(int fd);
|
||||
extern int munmap(caddr_t addr, size_t len);
|
||||
|
||||
|
||||
/* VMStruct -- virtual memory structure */
|
||||
|
||||
#define VMSig ((Sig)0x519B3999) /* SIGnature VM */
|
||||
|
|
@ -78,6 +74,8 @@ typedef struct VMStruct {
|
|||
} VMStruct;
|
||||
|
||||
|
||||
/* VMAlign -- return the page size */
|
||||
|
||||
Align VMAlign(VM vm)
|
||||
{
|
||||
AVERT(VM, vm);
|
||||
|
|
@ -85,6 +83,8 @@ Align VMAlign(VM vm)
|
|||
}
|
||||
|
||||
|
||||
/* VMCheck -- check a VM structure */
|
||||
|
||||
Bool VMCheck(VM vm)
|
||||
{
|
||||
CHECKS(VM, vm);
|
||||
|
|
@ -102,9 +102,11 @@ Bool VMCheck(VM vm)
|
|||
}
|
||||
|
||||
|
||||
/* VMCreate -- reserve some virtual address space, and create a VM structure */
|
||||
|
||||
Res VMCreate(VM *vmReturn, Size size)
|
||||
{
|
||||
caddr_t addr;
|
||||
void *addr;
|
||||
Align align;
|
||||
int zero_fd;
|
||||
int none_fd;
|
||||
|
|
@ -137,7 +139,7 @@ Res VMCreate(VM *vmReturn, Size size)
|
|||
}
|
||||
|
||||
/* Map in a page to store the descriptor on. */
|
||||
addr = mmap((caddr_t)0, (size_t)SizeAlignUp(sizeof(VMStruct), align),
|
||||
addr = mmap((void *)0, (size_t)SizeAlignUp(sizeof(VMStruct), align),
|
||||
PROT_READ | PROT_WRITE, MAP_PRIVATE,
|
||||
zero_fd, (off_t)0);
|
||||
if(addr == MAP_FAILED) {
|
||||
|
|
@ -152,7 +154,7 @@ Res VMCreate(VM *vmReturn, Size size)
|
|||
vm->align = align;
|
||||
|
||||
/* .map.reserve: See .assume.not-last. */
|
||||
addr = mmap((caddr_t)0, (size_t)size, PROT_NONE, MAP_SHARED,
|
||||
addr = mmap((void *)0, (size_t)size, PROT_NONE, MAP_SHARED,
|
||||
none_fd, (off_t)0);
|
||||
if(addr == MAP_FAILED) {
|
||||
AVER(errno == ENOMEM); /* .assume.mmap.err */
|
||||
|
|
@ -175,7 +177,7 @@ Res VMCreate(VM *vmReturn, Size size)
|
|||
return ResOK;
|
||||
|
||||
failReserve:
|
||||
(void)munmap((caddr_t)vm, (size_t)SizeAlignUp(sizeof(VMStruct), align));
|
||||
(void)munmap((void *)vm, (size_t)SizeAlignUp(sizeof(VMStruct), align));
|
||||
failVMMap:
|
||||
(void)close(none_fd); /* see .close.fail */
|
||||
failNoneOpen:
|
||||
|
|
@ -184,6 +186,8 @@ failNoneOpen:
|
|||
}
|
||||
|
||||
|
||||
/* VMDestroy -- destroy the VM structure */
|
||||
|
||||
void VMDestroy(VM vm)
|
||||
{
|
||||
int r;
|
||||
|
|
@ -199,9 +203,9 @@ void VMDestroy(VM vm)
|
|||
vm->sig = SigInvalid;
|
||||
|
||||
zero_fd = vm->zero_fd; none_fd = vm->none_fd;
|
||||
r = munmap((caddr_t)vm->base, (size_t)AddrOffset(vm->base, vm->limit));
|
||||
r = munmap((void *)vm->base, (size_t)AddrOffset(vm->base, vm->limit));
|
||||
AVER(r == 0);
|
||||
r = munmap((caddr_t)vm,
|
||||
r = munmap((void *)vm,
|
||||
(size_t)SizeAlignUp(sizeof(VMStruct), vm->align));
|
||||
AVER(r == 0);
|
||||
/* .close.fail: We ignore failure from close() as there's very */
|
||||
|
|
@ -213,12 +217,17 @@ void VMDestroy(VM vm)
|
|||
}
|
||||
|
||||
|
||||
/* VMBase -- return the base address of the memory reserved */
|
||||
|
||||
Addr VMBase(VM vm)
|
||||
{
|
||||
AVERT(VM, vm);
|
||||
return vm->base;
|
||||
}
|
||||
|
||||
|
||||
/* VMLimit -- return the limit address of the memory reserved */
|
||||
|
||||
Addr VMLimit(VM vm)
|
||||
{
|
||||
AVERT(VM, vm);
|
||||
|
|
@ -226,12 +235,17 @@ Addr VMLimit(VM vm)
|
|||
}
|
||||
|
||||
|
||||
/* VMReserved -- return the amount of address space reserved */
|
||||
|
||||
Size VMReserved(VM vm)
|
||||
{
|
||||
AVERT(VM, vm);
|
||||
return vm->reserved;
|
||||
}
|
||||
|
||||
|
||||
/* VMMapped -- return the amount of memory actually mapped */
|
||||
|
||||
Size VMMapped(VM vm)
|
||||
{
|
||||
AVERT(VM, vm);
|
||||
|
|
@ -239,10 +253,12 @@ Size VMMapped(VM vm)
|
|||
}
|
||||
|
||||
|
||||
/* VMMap -- map the given range of memory */
|
||||
|
||||
Res VMMap(VM vm, Addr base, Addr limit)
|
||||
{
|
||||
Size size;
|
||||
caddr_t addr;
|
||||
void *addr;
|
||||
|
||||
AVERT(VM, vm);
|
||||
AVER(base < limit);
|
||||
|
|
@ -258,7 +274,7 @@ Res VMMap(VM vm, Addr base, Addr limit)
|
|||
/* Check it won't lose any bits. */
|
||||
AVER(size <= (Size)(size_t)-1);
|
||||
|
||||
addr = mmap((caddr_t)base, (size_t)size,
|
||||
addr = mmap((void *)base, (size_t)size,
|
||||
PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
MAP_PRIVATE | MAP_FIXED,
|
||||
vm->zero_fd, (off_t)0);
|
||||
|
|
@ -266,7 +282,7 @@ Res VMMap(VM vm, Addr base, Addr limit)
|
|||
AVER(errno == EAGAIN); /* .assume.mmap.err */
|
||||
return ResMEMORY;
|
||||
}
|
||||
AVER(addr == (caddr_t)base);
|
||||
AVER(addr == (void *)base);
|
||||
|
||||
vm->mapped += size;
|
||||
|
||||
|
|
@ -275,10 +291,12 @@ Res VMMap(VM vm, Addr base, Addr limit)
|
|||
}
|
||||
|
||||
|
||||
/* VMUnmap -- unmap the given range of memory */
|
||||
|
||||
void VMUnmap(VM vm, Addr base, Addr limit)
|
||||
{
|
||||
Size size;
|
||||
caddr_t addr;
|
||||
void *addr;
|
||||
|
||||
AVERT(VM, vm);
|
||||
AVER(base < limit);
|
||||
|
|
@ -296,10 +314,10 @@ void VMUnmap(VM vm, Addr base, Addr limit)
|
|||
size = AddrOffset(base, limit);
|
||||
/* Check it won't lose any bits. */
|
||||
AVER(size <= (Size)(size_t)-1);
|
||||
addr = mmap((caddr_t)base, (size_t)size,
|
||||
addr = mmap((void *)base, (size_t)size,
|
||||
PROT_NONE, MAP_SHARED | MAP_FIXED,
|
||||
vm->none_fd, (off_t)AddrOffset(vm->base, base));
|
||||
AVER(addr == (caddr_t)base);
|
||||
AVER(addr == (void *)base);
|
||||
|
||||
vm->mapped -= size;
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue