mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-01-30 04:10:54 -08:00
Catch-up merge from master/...@185556 to branch/2014-03-30/addrset.
Copied from Perforce Change: 185563 ServerID: perforce.ravenbrook.com
This commit is contained in:
commit
42f18f93af
116 changed files with 1597 additions and 934 deletions
|
|
@ -16,5 +16,8 @@ TAGS
|
|||
*.dSYM
|
||||
code/*/*/*.d
|
||||
*.pyc
|
||||
test/obj
|
||||
test/test/log
|
||||
test/test/obj
|
||||
....gcda
|
||||
....gcno
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
/* abq.c: QUEUE IMPLEMENTATION
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .purpose: A fixed-length FIFO queue.
|
||||
*
|
||||
|
|
@ -185,18 +185,10 @@ Res ABQDescribe(ABQ abq, ABQDescribeElement describeElement, mps_lib_FILE *strea
|
|||
if(res != ResOK)
|
||||
return res;
|
||||
|
||||
res = METER_WRITE(abq->push, stream);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
res = METER_WRITE(abq->pop, stream);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
res = METER_WRITE(abq->peek, stream);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
res = METER_WRITE(abq->delete, stream);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
METER_WRITE(abq->push, stream);
|
||||
METER_WRITE(abq->pop, stream);
|
||||
METER_WRITE(abq->peek, stream);
|
||||
METER_WRITE(abq->delete, stream);
|
||||
|
||||
res = WriteF(stream, "}\n", NULL);
|
||||
if(res != ResOK)
|
||||
|
|
@ -311,7 +303,7 @@ static void *ABQElement(ABQ abq, Index index) {
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -7,15 +7,16 @@
|
|||
#include "abq.h"
|
||||
#include "mps.h"
|
||||
#include "mpsavm.h"
|
||||
#include "mpscmfs.h"
|
||||
#include "mpstd.h"
|
||||
#include "testlib.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h> /* printf */
|
||||
|
||||
|
||||
SRCID(abqtest, "$Id$");
|
||||
|
||||
|
||||
static mps_pool_t pool;
|
||||
static ABQStruct abq; /* the ABQ which we will use */
|
||||
static Size abqSize; /* the size of the current ABQ */
|
||||
|
||||
|
|
@ -50,9 +51,12 @@ static TestBlock testBlocks = NULL;
|
|||
|
||||
static TestBlock CreateTestBlock(unsigned no)
|
||||
{
|
||||
TestBlock b = malloc(sizeof(TestBlockStruct));
|
||||
cdie(b != NULL, "malloc");
|
||||
TestBlock b;
|
||||
mps_addr_t p;
|
||||
|
||||
die(mps_alloc(&p, pool, sizeof(TestBlockStruct)), "alloc");
|
||||
|
||||
b = p;
|
||||
b->next = testBlocks;
|
||||
b->id = no;
|
||||
b->base = 0;
|
||||
|
|
@ -78,7 +82,7 @@ static void DestroyTestBlock(TestBlock b)
|
|||
}
|
||||
}
|
||||
|
||||
free(b);
|
||||
mps_free(pool, b, sizeof(TestBlockStruct));
|
||||
}
|
||||
|
||||
typedef struct TestClosureStruct *TestClosure;
|
||||
|
|
@ -146,9 +150,6 @@ static void step(void)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#define testArenaSIZE (((size_t)4)<<20)
|
||||
|
||||
extern int main(int argc, char *argv[])
|
||||
{
|
||||
mps_arena_t arena;
|
||||
|
|
@ -158,9 +159,14 @@ extern int main(int argc, char *argv[])
|
|||
|
||||
abqSize = 0;
|
||||
|
||||
die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE),
|
||||
die(mps_arena_create_k(&arena, mps_arena_class_vm(), mps_args_none),
|
||||
"mps_arena_create");
|
||||
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MFS_UNIT_SIZE, sizeof(TestBlockStruct));
|
||||
die(mps_pool_create_k(&pool, arena, mps_class_mfs(), args), "pool_create");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
die(ABQInit((Arena)arena, &abq, NULL, ABQ_SIZE, sizeof(TestBlock)),
|
||||
"ABQInit");
|
||||
|
||||
|
|
|
|||
|
|
@ -35,14 +35,14 @@
|
|||
#include "fmtscheme.h"
|
||||
|
||||
#define OBJ_LEN (1u << 4)
|
||||
#define OBJ_COUNT 1
|
||||
#define OBJ_COUNT 10
|
||||
|
||||
static void test_air(int interior, int stack)
|
||||
{
|
||||
size_t n_finalized = 0;
|
||||
size_t i, j;
|
||||
obj_t *s[OBJ_COUNT] = {0};
|
||||
mps_root_t root;
|
||||
mps_root_t root = NULL;
|
||||
if (!stack) {
|
||||
mps_addr_t *p = (void *)s;
|
||||
die(mps_root_create_table(&root, scheme_arena, mps_rank_ambig(), 0, p,
|
||||
|
|
@ -90,20 +90,15 @@ static mps_gen_param_s obj_gen_params[] = {
|
|||
{ 170, 0.45 }
|
||||
};
|
||||
|
||||
static void test_main(int interior, int stack)
|
||||
static void test_main(void *marker, int interior, int stack)
|
||||
{
|
||||
mps_res_t res;
|
||||
mps_chain_t obj_chain;
|
||||
mps_fmt_t obj_fmt;
|
||||
mps_thr_t thread;
|
||||
mps_root_t reg_root;
|
||||
void *marker = ▮
|
||||
mps_root_t reg_root = NULL;
|
||||
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, 1 << 20);
|
||||
MPS_ARGS_DONE(args);
|
||||
res = mps_arena_create_k(&scheme_arena, mps_arena_class_vm(), args);
|
||||
} MPS_ARGS_END(args);
|
||||
res = mps_arena_create_k(&scheme_arena, mps_arena_class_vm(), mps_args_none);
|
||||
if (res != MPS_RES_OK) error("Couldn't create arena");
|
||||
|
||||
res = mps_chain_create(&obj_chain, scheme_arena,
|
||||
|
|
@ -149,12 +144,14 @@ static void test_main(int interior, int stack)
|
|||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
void *marker = ▮
|
||||
|
||||
testlib_init(argc, argv);
|
||||
|
||||
test_main(TRUE, TRUE);
|
||||
test_main(TRUE, FALSE);
|
||||
/* not test_main(FALSE, TRUE) -- see .fail.lii6ll. */
|
||||
test_main(FALSE, FALSE);
|
||||
test_main(marker, TRUE, TRUE);
|
||||
test_main(marker, TRUE, FALSE);
|
||||
/* not test_main(marker, FALSE, TRUE) -- see .fail.lii6ll. */
|
||||
test_main(marker, FALSE, FALSE);
|
||||
|
||||
printf("%s: Conclusion: Failed to find any defects.\n", argv[0]);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -12,13 +12,10 @@
|
|||
#include "mpscamc.h"
|
||||
#include "mpsavm.h"
|
||||
#include "mpstd.h"
|
||||
#ifdef MPS_OS_W3
|
||||
#include "mpsw3.h"
|
||||
#endif
|
||||
#include "mps.h"
|
||||
#include "mpslib.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <stdio.h> /* fflush, printf, putchar */
|
||||
|
||||
|
||||
/* These values have been tuned in the hope of getting one dynamic collection. */
|
||||
|
|
@ -81,19 +78,6 @@ static void report(mps_arena_t arena)
|
|||
printf(" not_condemned %"PRIuLONGEST"\n", (ulongest_t)not_condemned);
|
||||
printf(" clock: %"PRIuLONGEST"\n", (ulongest_t)mps_message_clock(arena, message));
|
||||
printf("}\n");
|
||||
|
||||
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.
|
||||
*
|
||||
* GDR 2013-03-12: Fiddling with the commit limit was causing
|
||||
* the test to fail sometimes (see job003440), so I've commented
|
||||
* out this feature.
|
||||
*/
|
||||
/* die(mps_arena_commit_limit_set(arena, 2 * testArenaSIZE), "set limit"); */
|
||||
}
|
||||
|
||||
} else {
|
||||
cdie(0, "unknown message type");
|
||||
break;
|
||||
|
|
@ -101,14 +85,12 @@ static void report(mps_arena_t arena)
|
|||
|
||||
mps_message_discard(arena, message);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* make -- create one new object */
|
||||
|
||||
static mps_addr_t make(void)
|
||||
static mps_addr_t make(size_t rootsCount)
|
||||
{
|
||||
size_t length = rnd() % (2*avLEN);
|
||||
size_t size = (length+2) * sizeof(mps_word_t);
|
||||
|
|
@ -119,7 +101,7 @@ static mps_addr_t make(void)
|
|||
MPS_RESERVE_BLOCK(res, p, ap, size);
|
||||
if (res)
|
||||
die(res, "MPS_RESERVE_BLOCK");
|
||||
res = dylan_init(p, size, exactRoots, exactRootsCOUNT);
|
||||
res = dylan_init(p, size, exactRoots, rootsCount);
|
||||
if (res)
|
||||
die(res, "dylan_init");
|
||||
} while(!mps_commit(ap, p, size));
|
||||
|
|
@ -141,7 +123,7 @@ static void test_stepper(mps_addr_t object, mps_fmt_t fmt, mps_pool_t pool,
|
|||
|
||||
/* test -- the body of the test */
|
||||
|
||||
static void test(mps_arena_t arena)
|
||||
static void test(mps_arena_t arena, mps_class_t pool_class, size_t roots_count)
|
||||
{
|
||||
mps_fmt_t format;
|
||||
mps_chain_t chain;
|
||||
|
|
@ -157,7 +139,7 @@ static void test(mps_arena_t arena)
|
|||
die(dylan_fmt(&format, arena), "fmt_create");
|
||||
die(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create");
|
||||
|
||||
die(mps_pool_create(&pool, arena, mps_class_amc(), format, chain),
|
||||
die(mps_pool_create(&pool, arena, pool_class, format, chain),
|
||||
"pool_create(amc)");
|
||||
|
||||
die(mps_ap_create(&ap, pool, mps_rank_exact()), "BufferCreate");
|
||||
|
|
@ -269,13 +251,13 @@ static void test(mps_arena_t arena)
|
|||
i = (r >> 1) % exactRootsCOUNT;
|
||||
if (exactRoots[i] != objNULL)
|
||||
cdie(dylan_check(exactRoots[i]), "dying root check");
|
||||
exactRoots[i] = make();
|
||||
exactRoots[i] = make(roots_count);
|
||||
if (exactRoots[(exactRootsCOUNT-1) - i] != objNULL)
|
||||
dylan_write(exactRoots[(exactRootsCOUNT-1) - i],
|
||||
exactRoots, exactRootsCOUNT);
|
||||
} else {
|
||||
i = (r >> 1) % ambigRootsCOUNT;
|
||||
ambigRoots[(ambigRootsCOUNT-1) - i] = make();
|
||||
ambigRoots[(ambigRootsCOUNT-1) - i] = make(roots_count);
|
||||
/* Create random interior pointers */
|
||||
ambigRoots[i] = (mps_addr_t)((char *)(ambigRoots[i/2]) + 1);
|
||||
}
|
||||
|
|
@ -313,13 +295,10 @@ int main(int argc, char *argv[])
|
|||
"arena_create");
|
||||
mps_message_type_enable(arena, mps_message_type_gc());
|
||||
mps_message_type_enable(arena, mps_message_type_gc_start());
|
||||
/* GDR 2013-03-12: Fiddling with the commit limit was causing
|
||||
* the test to fail sometimes (see job003440), so I've commented
|
||||
* out this feature.
|
||||
*/
|
||||
/*die(mps_arena_commit_limit_set(arena, testArenaSIZE), "set limit");*/
|
||||
die(mps_arena_commit_limit_set(arena, 2*testArenaSIZE), "set limit");
|
||||
die(mps_thread_reg(&thread, arena), "thread_reg");
|
||||
test(arena);
|
||||
test(arena, mps_class_amc(), exactRootsCOUNT);
|
||||
test(arena, mps_class_amcz(), 0);
|
||||
mps_thread_dereg(thread);
|
||||
report(arena);
|
||||
mps_arena_destroy(arena);
|
||||
|
|
|
|||
|
|
@ -12,12 +12,9 @@
|
|||
#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 <stdio.h> /* fflush, printf, putchar */
|
||||
|
||||
|
||||
/* These values have been tuned in the hope of getting one dynamic collection. */
|
||||
|
|
@ -51,7 +48,7 @@ static mps_addr_t exactRoots[exactRootsCOUNT];
|
|||
static mps_addr_t ambigRoots[ambigRootsCOUNT];
|
||||
static mps_addr_t bogusRoots[bogusRootsCOUNT];
|
||||
|
||||
static mps_addr_t make(void)
|
||||
static mps_addr_t make(size_t roots_count)
|
||||
{
|
||||
size_t length = rnd() % (2*avLEN);
|
||||
size_t size = (length+2) * sizeof(mps_word_t);
|
||||
|
|
@ -63,7 +60,7 @@ static mps_addr_t make(void)
|
|||
if (res)
|
||||
die(res, "MPS_RESERVE_BLOCK");
|
||||
userP = (mps_addr_t)((char*)p + headerSIZE);
|
||||
res = dylan_init(userP, size, exactRoots, exactRootsCOUNT);
|
||||
res = dylan_init(userP, size, exactRoots, roots_count);
|
||||
if (res)
|
||||
die(res, "dylan_init");
|
||||
((int*)p)[0] = realHeader;
|
||||
|
|
@ -94,27 +91,14 @@ static void report(mps_arena_t arena)
|
|||
printf("not_condemned %"PRIuLONGEST"\n", (ulongest_t)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.
|
||||
*
|
||||
* GDR 2013-03-07: Fiddling with the commit limit was causing
|
||||
* the test to fail sometimes (see job003432), so I've commented
|
||||
* out this feature.
|
||||
*/
|
||||
/*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)
|
||||
static void *test(mps_arena_t arena, mps_class_t pool_class, size_t roots_count)
|
||||
{
|
||||
mps_arena_t arena;
|
||||
mps_fmt_t format;
|
||||
mps_chain_t chain;
|
||||
mps_root_t exactRoot, ambigRoot, bogusRoot;
|
||||
|
|
@ -125,13 +109,10 @@ static void *test(void *arg, size_t s)
|
|||
mps_ap_t busy_ap;
|
||||
mps_addr_t busy_init;
|
||||
|
||||
arena = (mps_arena_t)arg;
|
||||
(void)s; /* unused */
|
||||
|
||||
die(EnsureHeaderFormat(&format, arena), "fmt_create");
|
||||
die(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create");
|
||||
|
||||
die(mps_pool_create(&pool, arena, mps_class_amc(), format, chain),
|
||||
die(mps_pool_create(&pool, arena, pool_class, format, chain),
|
||||
"pool_create(amc)");
|
||||
|
||||
die(mps_ap_create(&ap, pool, mps_rank_exact()), "BufferCreate");
|
||||
|
|
@ -220,13 +201,13 @@ static void *test(void *arg, size_t s)
|
|||
i = (r >> 1) % exactRootsCOUNT;
|
||||
if (exactRoots[i] != objNULL)
|
||||
die(HeaderFormatCheck(exactRoots[i]), "wrapper check");
|
||||
exactRoots[i] = make();
|
||||
exactRoots[i] = make(roots_count);
|
||||
if (exactRoots[(exactRootsCOUNT-1) - i] != objNULL)
|
||||
dylan_write(exactRoots[(exactRootsCOUNT-1) - i],
|
||||
exactRoots, exactRootsCOUNT);
|
||||
} else {
|
||||
i = (r >> 1) % ambigRootsCOUNT;
|
||||
ambigRoots[(ambigRootsCOUNT-1) - i] = make();
|
||||
ambigRoots[(ambigRootsCOUNT-1) - i] = make(roots_count);
|
||||
/* Create random interior pointers */
|
||||
ambigRoots[i] = (mps_addr_t)((char *)(ambigRoots[i/2]) + 1);
|
||||
}
|
||||
|
|
@ -261,20 +242,16 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
mps_arena_t arena;
|
||||
mps_thr_t thread;
|
||||
void *r;
|
||||
|
||||
testlib_init(argc, argv);
|
||||
|
||||
die(mps_arena_create(&arena, mps_arena_class_vm(), 3*testArenaSIZE),
|
||||
die(mps_arena_create(&arena, mps_arena_class_vm(), 2*testArenaSIZE),
|
||||
"arena_create\n");
|
||||
mps_message_type_enable(arena, mps_message_type_gc());
|
||||
/* GDR 2013-03-07: Fiddling with the commit limit was causing
|
||||
* the test to fail sometimes (see job003432), so I've commented
|
||||
* out this feature.
|
||||
*/
|
||||
/*die(mps_arena_commit_limit_set(arena, testArenaSIZE), "set limit");*/
|
||||
die(mps_arena_commit_limit_set(arena, 2*testArenaSIZE), "set limit");
|
||||
die(mps_thread_reg(&thread, arena), "thread_reg");
|
||||
mps_tramp(&r, test, arena, 0);
|
||||
test(arena, mps_class_amc(), exactRootsCOUNT);
|
||||
test(arena, mps_class_amcz(), 0);
|
||||
mps_thread_dereg(thread);
|
||||
mps_arena_destroy(arena);
|
||||
|
||||
|
|
|
|||
|
|
@ -4,21 +4,34 @@
|
|||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (c) 2002 Global Graphics Software.
|
||||
*
|
||||
* .posix: This is Posix only.
|
||||
* .mode: This test case has two modes:
|
||||
*
|
||||
* .mode.walk: In this mode, the main thread parks the arena half way
|
||||
* through the test case and runs mps_arena_formatted_objects_walk().
|
||||
* This checks that walking works while the other threads continue to
|
||||
* allocate in the background.
|
||||
*
|
||||
* .mode.commit: In this mode, the arena's commit limit is set. This
|
||||
* checks that the MPS can make progress inside a tight limit in the
|
||||
* presence of allocation on multiple threads. But this is
|
||||
* incompatible with .mode.walk: if the arena is parked, then the
|
||||
* arena has no chance to make progress.
|
||||
*/
|
||||
|
||||
#define _POSIX_C_SOURCE 199309L
|
||||
|
||||
#include "fmtdy.h"
|
||||
#include "fmtdytst.h"
|
||||
#include "testlib.h"
|
||||
#include "testthr.h"
|
||||
#include "mpslib.h"
|
||||
#include "mpscamc.h"
|
||||
#include "mpsavm.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <stdio.h> /* fflush, printf, putchar */
|
||||
|
||||
enum {
|
||||
ModeWALK = 0, /* .mode.walk */
|
||||
ModeCOMMIT = 1 /* .mode.commit */
|
||||
};
|
||||
|
||||
|
||||
/* These values have been tuned in the hope of getting one dynamic collection. */
|
||||
|
|
@ -43,7 +56,6 @@ static mps_gen_param_s testChain[genCOUNT] = {
|
|||
#define objNULL ((mps_addr_t)MPS_WORD_CONST(0xDECEA5ED))
|
||||
|
||||
|
||||
static mps_pool_t pool;
|
||||
static mps_addr_t exactRoots[exactRootsCOUNT];
|
||||
static mps_addr_t ambigRoots[ambigRootsCOUNT];
|
||||
|
||||
|
|
@ -67,26 +79,20 @@ static void report(mps_arena_t arena)
|
|||
printf("not_condemned %"PRIuLONGEST"\n", (ulongest_t)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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mps_arena_t arena;
|
||||
mps_fmt_t format;
|
||||
mps_chain_t chain;
|
||||
mps_root_t exactRoot, ambigRoot;
|
||||
unsigned long objs = 0;
|
||||
static mps_arena_t arena;
|
||||
static mps_fmt_t format;
|
||||
static mps_chain_t chain;
|
||||
static mps_root_t exactRoot, ambigRoot;
|
||||
static unsigned long objs = 0;
|
||||
|
||||
|
||||
/* make -- create one new object */
|
||||
|
||||
static mps_addr_t make(mps_ap_t ap)
|
||||
static mps_addr_t make(mps_ap_t ap, size_t roots_count)
|
||||
{
|
||||
size_t length = rnd() % (2*avLEN);
|
||||
size_t size = (length+2) * sizeof(mps_word_t);
|
||||
|
|
@ -97,7 +103,7 @@ static mps_addr_t make(mps_ap_t ap)
|
|||
MPS_RESERVE_BLOCK(res, p, ap, size);
|
||||
if (res)
|
||||
die(res, "MPS_RESERVE_BLOCK");
|
||||
res = dylan_init(p, size, exactRoots, exactRootsCOUNT);
|
||||
res = dylan_init(p, size, exactRoots, roots_count);
|
||||
if (res)
|
||||
die(res, "dylan_init");
|
||||
} while(!mps_commit(ap, p, size));
|
||||
|
|
@ -108,16 +114,16 @@ static mps_addr_t make(mps_ap_t ap)
|
|||
|
||||
/* test_stepper -- stepping function for walk */
|
||||
|
||||
static void test_stepper(mps_addr_t object, mps_fmt_t fmt, mps_pool_t pol,
|
||||
static void test_stepper(mps_addr_t object, mps_fmt_t fmt, mps_pool_t pool,
|
||||
void *p, size_t s)
|
||||
{
|
||||
testlib_unused(object); testlib_unused(fmt); testlib_unused(pol);
|
||||
testlib_unused(object); testlib_unused(fmt); testlib_unused(pool);
|
||||
testlib_unused(s);
|
||||
(*(unsigned long *)p)++;
|
||||
}
|
||||
|
||||
|
||||
/* init -- initialize pool and roots */
|
||||
/* init -- initialize roots and chain */
|
||||
|
||||
static void init(void)
|
||||
{
|
||||
|
|
@ -126,9 +132,6 @@ static void init(void)
|
|||
die(dylan_fmt(&format, arena), "fmt_create");
|
||||
die(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create");
|
||||
|
||||
die(mps_pool_create(&pool, arena, mps_class_amc(), format, chain),
|
||||
"pool_create(amc)");
|
||||
|
||||
for(i = 0; i < exactRootsCOUNT; ++i)
|
||||
exactRoots[i] = objNULL;
|
||||
for(i = 0; i < ambigRootsCOUNT; ++i)
|
||||
|
|
@ -146,13 +149,12 @@ static void init(void)
|
|||
}
|
||||
|
||||
|
||||
/* finish -- finish pool and roots */
|
||||
/* finish -- finish roots and chain */
|
||||
|
||||
static void finish(void)
|
||||
{
|
||||
mps_root_destroy(exactRoot);
|
||||
mps_root_destroy(ambigRoot);
|
||||
mps_pool_destroy(pool);
|
||||
mps_chain_destroy(chain);
|
||||
mps_fmt_destroy(format);
|
||||
}
|
||||
|
|
@ -160,7 +162,7 @@ static void finish(void)
|
|||
|
||||
/* churn -- create an object and install into roots */
|
||||
|
||||
static void churn(mps_ap_t ap)
|
||||
static void churn(mps_ap_t ap, size_t roots_count)
|
||||
{
|
||||
size_t i;
|
||||
size_t r;
|
||||
|
|
@ -171,22 +173,52 @@ static void churn(mps_ap_t ap)
|
|||
i = (r >> 1) % exactRootsCOUNT;
|
||||
if (exactRoots[i] != objNULL)
|
||||
cdie(dylan_check(exactRoots[i]), "dying root check");
|
||||
exactRoots[i] = make(ap);
|
||||
exactRoots[i] = make(ap, roots_count);
|
||||
if (exactRoots[(exactRootsCOUNT-1) - i] != objNULL)
|
||||
dylan_write(exactRoots[(exactRootsCOUNT-1) - i],
|
||||
exactRoots, exactRootsCOUNT);
|
||||
} else {
|
||||
i = (r >> 1) % ambigRootsCOUNT;
|
||||
ambigRoots[(ambigRootsCOUNT-1) - i] = make(ap);
|
||||
ambigRoots[(ambigRootsCOUNT-1) - i] = make(ap, roots_count);
|
||||
/* Create random interior pointers */
|
||||
ambigRoots[i] = (mps_addr_t)((char *)(ambigRoots[i/2]) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
typedef struct closure_s {
|
||||
mps_pool_t pool;
|
||||
size_t roots_count;
|
||||
} closure_s, *closure_t;
|
||||
|
||||
static void *kid_thread(void *arg)
|
||||
{
|
||||
void *marker = ▮
|
||||
mps_thr_t thread;
|
||||
mps_root_t reg_root;
|
||||
mps_ap_t ap;
|
||||
closure_t cl = arg;
|
||||
|
||||
die(mps_thread_reg(&thread, (mps_arena_t)arena), "thread_reg");
|
||||
die(mps_root_create_reg(®_root, arena, mps_rank_ambig(), 0, thread,
|
||||
mps_stack_scan_ambig, marker, 0), "root_create");
|
||||
|
||||
die(mps_ap_create(&ap, cl->pool, mps_rank_exact()), "BufferCreate(fooey)");
|
||||
while(mps_collections(arena) < collectionsCOUNT) {
|
||||
churn(ap, cl->roots_count);
|
||||
}
|
||||
mps_ap_destroy(ap);
|
||||
|
||||
mps_root_destroy(reg_root);
|
||||
mps_thread_dereg(thread);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* test -- the body of the test */
|
||||
|
||||
static void *test(void *arg, size_t s)
|
||||
static void *test_pool(mps_class_t pool_class, size_t roots_count, int mode)
|
||||
{
|
||||
size_t i;
|
||||
mps_word_t collections, rampSwitch;
|
||||
|
|
@ -194,9 +226,19 @@ static void *test(void *arg, size_t s)
|
|||
int ramping;
|
||||
mps_ap_t ap, busy_ap;
|
||||
mps_addr_t busy_init;
|
||||
mps_pool_t pool;
|
||||
testthr_t kids[10];
|
||||
closure_s cl;
|
||||
int walked = FALSE, ramped = FALSE;
|
||||
|
||||
arena = (mps_arena_t)arg;
|
||||
(void)s; /* unused */
|
||||
die(mps_pool_create(&pool, arena, pool_class, format, chain),
|
||||
"pool_create(amc)");
|
||||
|
||||
cl.pool = pool;
|
||||
cl.roots_count = roots_count;
|
||||
|
||||
for (i = 0; i < sizeof(kids)/sizeof(kids[0]); ++i)
|
||||
testthr_create(&kids[i], kid_thread, &cl);
|
||||
|
||||
die(mps_ap_create(&ap, pool, mps_rank_exact()), "BufferCreate");
|
||||
die(mps_ap_create(&busy_ap, pool, mps_rank_exact()), "BufferCreate 2");
|
||||
|
|
@ -217,21 +259,23 @@ static void *test(void *arg, size_t s)
|
|||
|
||||
if (collections != c) {
|
||||
collections = c;
|
||||
printf("\nCollection %lu started, %lu objects.\n", c, objs);
|
||||
printf("\nCollection %lu started, %lu objects, committed=%lu.\n",
|
||||
c, objs, (unsigned long)mps_arena_committed(arena));
|
||||
report(arena);
|
||||
|
||||
for (i = 0; i < exactRootsCOUNT; ++i)
|
||||
cdie(exactRoots[i] == objNULL || dylan_check(exactRoots[i]),
|
||||
"all roots check");
|
||||
|
||||
if (collections == collectionsCOUNT / 2) {
|
||||
if (mode == ModeWALK && collections >= collectionsCOUNT / 2 && !walked) {
|
||||
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);
|
||||
walked = TRUE;
|
||||
}
|
||||
if (collections == rampSwitch) {
|
||||
if (collections >= rampSwitch && !ramped) {
|
||||
int begin_ramp = !ramping
|
||||
|| /* Every other time, switch back immediately. */ (collections & 1);
|
||||
|
||||
|
|
@ -256,9 +300,10 @@ static void *test(void *arg, size_t s)
|
|||
ramping = 1;
|
||||
}
|
||||
}
|
||||
ramped = TRUE;
|
||||
}
|
||||
|
||||
churn(ap);
|
||||
churn(ap, roots_count);
|
||||
|
||||
r = (size_t)rnd();
|
||||
|
||||
|
|
@ -276,79 +321,45 @@ static void *test(void *arg, size_t s)
|
|||
mps_ap_destroy(busy_ap);
|
||||
mps_ap_destroy(ap);
|
||||
|
||||
for (i = 0; i < sizeof(kids)/sizeof(kids[0]); ++i)
|
||||
testthr_join(&kids[i], NULL);
|
||||
|
||||
mps_pool_destroy(pool);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void *fooey2(void *arg, size_t s)
|
||||
{
|
||||
mps_ap_t ap;
|
||||
|
||||
(void)arg; (void)s; /* unused */
|
||||
die(mps_ap_create(&ap, pool, mps_rank_exact()), "BufferCreate(fooey)");
|
||||
while(mps_collections(arena) < collectionsCOUNT) {
|
||||
churn(ap);
|
||||
}
|
||||
mps_ap_destroy(ap);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void *fooey(void* childIsFinishedReturn)
|
||||
{
|
||||
void *r;
|
||||
mps_thr_t thread;
|
||||
void *marker = ▮
|
||||
mps_root_t reg_root;
|
||||
|
||||
die(mps_thread_reg(&thread, (mps_arena_t)arena), "thread_reg");
|
||||
die(mps_root_create_reg(®_root, arena, mps_rank_ambig(), 0, thread,
|
||||
mps_stack_scan_ambig, marker, 0), "root_create");
|
||||
mps_tramp(&r, fooey2, NULL, 0);
|
||||
mps_root_destroy(reg_root);
|
||||
mps_thread_dereg(thread);
|
||||
*(int *)childIsFinishedReturn = 1;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
static void test_arena(int mode)
|
||||
{
|
||||
mps_thr_t thread;
|
||||
mps_root_t reg_root;
|
||||
void *marker = ▮
|
||||
pthread_t kids[10];
|
||||
unsigned i;
|
||||
void *r;
|
||||
int childIsFinished = 0;
|
||||
|
||||
testlib_init(argc, argv);
|
||||
|
||||
die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE),
|
||||
"arena_create");
|
||||
if (mode == ModeCOMMIT)
|
||||
die(mps_arena_commit_limit_set(arena, 2 * testArenaSIZE), "set limit");
|
||||
mps_message_type_enable(arena, mps_message_type_gc());
|
||||
init();
|
||||
die(mps_thread_reg(&thread, arena), "thread_reg");
|
||||
die(mps_root_create_reg(®_root, arena, mps_rank_ambig(), 0, thread,
|
||||
mps_stack_scan_ambig, marker, 0), "root_create");
|
||||
for (i = 0; i < sizeof(kids)/sizeof(kids[0]); ++i) {
|
||||
int err = pthread_create(&kids[i], NULL, fooey, (void *)&childIsFinished);
|
||||
if (err != 0)
|
||||
error("pthread_create returned %d", err);
|
||||
}
|
||||
mps_tramp(&r, test, arena, 0);
|
||||
mps_stack_scan_ambig, marker, 0), "root_create");
|
||||
|
||||
test_pool(mps_class_amc(), exactRootsCOUNT, mode);
|
||||
test_pool(mps_class_amcz(), 0, mode);
|
||||
|
||||
mps_root_destroy(reg_root);
|
||||
mps_thread_dereg(thread);
|
||||
|
||||
for (i = 0; i < sizeof(kids)/sizeof(kids[0]); ++i) {
|
||||
int err = pthread_join(kids[i], NULL);
|
||||
if (err != 0)
|
||||
error("pthread_join returned %d", err);
|
||||
}
|
||||
|
||||
finish();
|
||||
report(arena);
|
||||
mps_arena_destroy(arena);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
testlib_init(argc, argv);
|
||||
test_arena(ModeWALK);
|
||||
test_arena(ModeCOMMIT);
|
||||
|
||||
printf("%s: Conclusion: Failed to find any defects.\n", argv[0]);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -15,14 +15,9 @@
|
|||
#include "mpscams.h"
|
||||
#include "mpsavm.h"
|
||||
#include "mpstd.h"
|
||||
#ifdef MPS_OS_W3
|
||||
#include "mpsw3.h"
|
||||
#endif
|
||||
#include "mps.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <stdio.h> /* fflush, printf */
|
||||
|
||||
|
||||
#define exactRootsCOUNT 50
|
||||
|
|
|
|||
|
|
@ -13,14 +13,9 @@
|
|||
#include "mpscams.h"
|
||||
#include "mpsavm.h"
|
||||
#include "mpstd.h"
|
||||
#ifdef MPS_OS_W3
|
||||
#include "mpsw3.h"
|
||||
#endif
|
||||
#include "mps.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <stdio.h> /* fflush, printf */
|
||||
|
||||
|
||||
#define exactRootsCOUNT 50
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
#include "testlib.h"
|
||||
#include "mpslib.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h> /* printf */
|
||||
#include <stdlib.h> /* malloc */
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -14,8 +14,6 @@
|
|||
* being allocated; this requires using two adjacent zones.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "mpm.h"
|
||||
#include "poolmv.h"
|
||||
#include "testlib.h"
|
||||
|
|
@ -23,6 +21,9 @@
|
|||
#include "mpsavm.h"
|
||||
#include "mpsacl.h"
|
||||
|
||||
#include <stdio.h> /* printf */
|
||||
#include <stdlib.h> /* malloc */
|
||||
|
||||
|
||||
#define tractsSIZE 500
|
||||
|
||||
|
|
|
|||
|
|
@ -480,7 +480,7 @@ ARG_DEFINE_KEY(arena_contracted, Fun);
|
|||
|
||||
static Res VMArenaInit(Arena *arenaReturn, ArenaClass class, ArgList args)
|
||||
{
|
||||
Size userSize; /* size requested by user */
|
||||
Size userSize = VM_ARENA_SIZE_DEFAULT; /* size requested by user */
|
||||
Size chunkSize; /* size actually created */
|
||||
Size vmArenaSize; /* aligned size of VMArenaStruct */
|
||||
Res res;
|
||||
|
|
@ -495,8 +495,8 @@ static Res VMArenaInit(Arena *arenaReturn, ArenaClass class, ArgList args)
|
|||
AVER(class == VMArenaClassGet());
|
||||
AVERT(ArgList, args);
|
||||
|
||||
ArgRequire(&arg, args, MPS_KEY_ARENA_SIZE);
|
||||
userSize = arg.val.size;
|
||||
if (ArgPick(&arg, args, MPS_KEY_ARENA_SIZE))
|
||||
userSize = arg.val.size;
|
||||
|
||||
AVER(userSize > 0);
|
||||
|
||||
|
|
@ -593,6 +593,8 @@ static void VMArenaFinish(Arena arena)
|
|||
AVERT(VMArena, vmArena);
|
||||
arenaVM = vmArena->vm;
|
||||
|
||||
EVENT1(ArenaDestroy, vmArena);
|
||||
|
||||
/* destroy all chunks, including the primary */
|
||||
arena->primary = NULL;
|
||||
RING_FOR(node, &arena->chunkRing, next) {
|
||||
|
|
@ -612,7 +614,6 @@ static void VMArenaFinish(Arena arena)
|
|||
|
||||
VMUnmap(arenaVM, VMBase(arenaVM), VMLimit(arenaVM));
|
||||
VMDestroy(arenaVM);
|
||||
EVENT1(ArenaDestroy, vmArena);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* arg.h: Keyword argument lists
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2013-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .source: See <design/keyword-arguments.rst>.
|
||||
*/
|
||||
|
|
@ -28,6 +28,7 @@ typedef struct mps_key_s {
|
|||
} KeyStruct;
|
||||
|
||||
#define ARG_DEFINE_KEY(id, type) \
|
||||
extern const KeyStruct _mps_key_##id; \
|
||||
const KeyStruct _mps_key_##id = {KeySig, #id, ArgCheck##type}
|
||||
|
||||
#define argsNone mps_args_none
|
||||
|
|
@ -62,7 +63,7 @@ extern Bool ArgCheckPool(Arg arg);
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -16,10 +16,9 @@
|
|||
#include "mpslib.h"
|
||||
#include "mps.h"
|
||||
#include "mpstd.h"
|
||||
#ifdef MPS_OS_W3
|
||||
#include "mpsw3.h"
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include <stdio.h> /* printf */
|
||||
#include <string.h> /* strlen */
|
||||
|
||||
|
||||
#define testArenaSIZE ((size_t)64<<20)
|
||||
|
|
|
|||
|
|
@ -17,10 +17,9 @@
|
|||
#include "mpslib.h"
|
||||
#include "mps.h"
|
||||
#include "mpstd.h"
|
||||
#ifdef MPS_OS_W3
|
||||
#include "mpsw3.h"
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include <string.h> /* strlen */
|
||||
#include <stdio.h> /* printf */
|
||||
|
||||
|
||||
#define testArenaSIZE ((size_t)64<<20)
|
||||
|
|
|
|||
|
|
@ -13,16 +13,13 @@
|
|||
#include "mpsavm.h"
|
||||
#include "fmtdy.h"
|
||||
#include "testlib.h"
|
||||
#include "testthr.h"
|
||||
#include "mpslib.h"
|
||||
#include "mps.h"
|
||||
#include "mpstd.h"
|
||||
#ifdef MPS_OS_W3
|
||||
#include "mpsw3.h"
|
||||
#endif
|
||||
#include <string.h>
|
||||
#if defined(MPS_OS_LI) || defined(MPS_OS_FR) || defined(MPS_OS_XC)
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h> /* printf, puts */
|
||||
#include <string.h> /* strlen */
|
||||
|
||||
|
||||
#define testArenaSIZE ((size_t)64<<20)
|
||||
|
|
@ -314,7 +311,7 @@ static void *setup_thr(void *v)
|
|||
int main(int argc, char *argv[])
|
||||
{
|
||||
mps_arena_t arena;
|
||||
pthread_t pthread1;
|
||||
testthr_t thread1;
|
||||
|
||||
testlib_init(argc, argv);
|
||||
|
||||
|
|
@ -324,9 +321,9 @@ int main(int argc, char *argv[])
|
|||
|
||||
die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE),
|
||||
"arena_create\n");
|
||||
pthread_create(&pthread1, NULL, setup_thr, (void *)arena);
|
||||
testthr_create(&thread1, setup_thr, arena);
|
||||
setup_thr(arena);
|
||||
pthread_join(pthread1, NULL);
|
||||
testthr_join(&thread1, NULL);
|
||||
mps_arena_destroy(arena);
|
||||
|
||||
printf("%s: Conclusion: Failed to find any defects.\n", argv[0]);
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
#include "testlib.h"
|
||||
#include "mpslib.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h> /* printf */
|
||||
|
||||
SRCID(btcv, "$Id$");
|
||||
|
||||
|
|
|
|||
|
|
@ -10,11 +10,10 @@
|
|||
#include "mpsavm.h"
|
||||
#include "testlib.h"
|
||||
#include "mpslib.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include "mpstd.h"
|
||||
#include <time.h>
|
||||
|
||||
#include <stdio.h> /* fflush, fgets, printf, putchar, puts */
|
||||
#include <stdlib.h> /* exit, strtol */
|
||||
|
||||
SRCID(bttest, "$Id$");
|
||||
|
||||
|
|
|
|||
|
|
@ -980,14 +980,14 @@ Bool BufferIsTrappedByMutator(Buffer buffer)
|
|||
*
|
||||
* Just represent the two patterns by two different pointers to dummies. */
|
||||
|
||||
AllocPatternStruct AllocPatternRampStruct = {'\0'};
|
||||
static AllocPatternStruct AllocPatternRampStruct = {'\0'};
|
||||
|
||||
AllocPattern AllocPatternRamp(void)
|
||||
{
|
||||
return &AllocPatternRampStruct;
|
||||
}
|
||||
|
||||
AllocPatternStruct AllocPatternRampCollectAllStruct = {'\0'};
|
||||
static AllocPatternStruct AllocPatternRampCollectAllStruct = {'\0'};
|
||||
|
||||
AllocPattern AllocPatternRampCollectAll(void)
|
||||
{
|
||||
|
|
@ -1075,7 +1075,7 @@ static Res bufferTrivInit(Buffer buffer, Pool pool, ArgList args)
|
|||
AVERT(Buffer, buffer);
|
||||
AVERT(Pool, pool);
|
||||
UNUSED(args);
|
||||
EVENT3(BufferInit, buffer, pool, buffer->isMutator);
|
||||
EVENT3(BufferInit, buffer, pool, BOOL(buffer->isMutator));
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
|
@ -1288,7 +1288,7 @@ static Res segBufInit(Buffer buffer, Pool pool, ArgList args)
|
|||
segbuf->rankSet = RankSetEMPTY;
|
||||
|
||||
AVERT(SegBuf, segbuf);
|
||||
EVENT3(BufferInitSeg, buffer, pool, buffer->isMutator);
|
||||
EVENT3(BufferInitSeg, buffer, pool, BOOL(buffer->isMutator));
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
|
@ -1515,7 +1515,7 @@ static Res rankBufInit(Buffer buffer, Pool pool, ArgList args)
|
|||
BufferSetRankSet(buffer, RankSetSingle(rank));
|
||||
|
||||
/* There's nothing to check that the superclass doesn't, so no AVERT. */
|
||||
EVENT4(BufferInitRank, buffer, pool, buffer->isMutator, rank);
|
||||
EVENT4(BufferInitRank, buffer, pool, BOOL(buffer->isMutator), rank);
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1174,8 +1174,7 @@ static Res cbsDescribe(Land land, mps_lib_FILE *stream)
|
|||
res = SplayTreeDescribe(cbsSplay(cbs), stream, describe);
|
||||
if (res != ResOK) return res;
|
||||
|
||||
res = METER_WRITE(cbs->treeSearch, stream);
|
||||
if (res != ResOK) return res;
|
||||
METER_WRITE(cbs->treeSearch, stream);
|
||||
|
||||
res = WriteF(stream, "}\n", NULL);
|
||||
return res;
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@ SNC = poolsnc.c
|
|||
POOLN = pooln.c
|
||||
MV2 = poolmv2.c
|
||||
MVFF = poolmvff.c
|
||||
TESTLIB = testlib.c
|
||||
TESTLIB = testlib.c testthrix.c
|
||||
FMTDY = fmtdy.c fmtno.c
|
||||
FMTDYTST = fmtdy.c fmtno.c fmtdytst.c
|
||||
FMTHETST = fmthe.c fmtdy.c fmtno.c fmtdytst.c
|
||||
|
|
@ -294,6 +294,7 @@ TEST_TARGETS=\
|
|||
landtest \
|
||||
locbwcss \
|
||||
lockcov \
|
||||
lockut \
|
||||
locusss \
|
||||
locv \
|
||||
messtest \
|
||||
|
|
@ -492,6 +493,9 @@ $(PFM)/$(VARIETY)/locbwcss: $(PFM)/$(VARIETY)/locbwcss.o \
|
|||
$(PFM)/$(VARIETY)/lockcov: $(PFM)/$(VARIETY)/lockcov.o \
|
||||
$(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a
|
||||
|
||||
$(PFM)/$(VARIETY)/lockut: $(PFM)/$(VARIETY)/lockut.o \
|
||||
$(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a
|
||||
|
||||
$(PFM)/$(VARIETY)/locusss: $(PFM)/$(VARIETY)/locusss.o \
|
||||
$(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# commpost.nmk: SECOND COMMON FRAGMENT FOR PLATFORMS USING NMAKE -*- makefile -*-
|
||||
#
|
||||
# $Id$
|
||||
# Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
# Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
|
|
@ -146,6 +146,10 @@ $(PFM)\$(VARIETY)\awluthe.exe: $(PFM)\$(VARIETY)\awluthe.obj \
|
|||
$(FMTTESTOBJ) \
|
||||
$(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
|
||||
|
||||
$(PFM)\$(VARIETY)\awlutth.exe: $(PFM)\$(VARIETY)\awlutth.obj \
|
||||
$(FMTTESTOBJ) \
|
||||
$(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
|
||||
|
||||
$(PFM)\$(VARIETY)\btcv.exe: $(PFM)\$(VARIETY)\btcv.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
|
||||
|
||||
|
|
@ -155,6 +159,9 @@ $(PFM)\$(VARIETY)\bttest.exe: $(PFM)\$(VARIETY)\bttest.obj \
|
|||
$(PFM)\$(VARIETY)\cvmicv.exe: $(PFM)\$(VARIETY)\cvmicv.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
|
||||
|
||||
$(PFM)\$(VARIETY)\djbench.exe: $(PFM)\$(VARIETY)\djbench.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
|
||||
|
||||
$(PFM)\$(VARIETY)\exposet0.exe: $(PFM)\$(VARIETY)\exposet0.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
|
||||
|
||||
|
|
@ -170,6 +177,9 @@ $(PFM)\$(VARIETY)\finaltest.exe: $(PFM)\$(VARIETY)\finaltest.obj \
|
|||
$(PFM)\$(VARIETY)\fotest.exe: $(PFM)\$(VARIETY)\fotest.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
|
||||
|
||||
$(PFM)\$(VARIETY)\gcbench.exe: $(PFM)\$(VARIETY)\gcbench.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
|
||||
|
||||
$(PFM)\$(VARIETY)\landtest.exe: $(PFM)\$(VARIETY)\landtest.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
|
||||
|
||||
|
|
@ -179,7 +189,7 @@ $(PFM)\$(VARIETY)\locbwcss.exe: $(PFM)\$(VARIETY)\locbwcss.obj \
|
|||
$(PFM)\$(VARIETY)\lockcov.exe: $(PFM)\$(VARIETY)\lockcov.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
|
||||
|
||||
$(PFM)\$(VARIETY)\lockutw3.exe: $(PFM)\$(VARIETY)\lockutw3.obj \
|
||||
$(PFM)\$(VARIETY)\lockut.exe: $(PFM)\$(VARIETY)\lockut.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
|
||||
|
||||
$(PFM)\$(VARIETY)\locusss.exe: $(PFM)\$(VARIETY)\locusss.obj \
|
||||
|
|
@ -306,7 +316,7 @@ $(PFM)\$(VARIETY)\sqlite3.obj:
|
|||
|
||||
# C. COPYRIGHT AND LICENSE
|
||||
#
|
||||
# Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
# Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
# All rights reserved. This is an open source license. Contact
|
||||
# Ravenbrook for commercial licensing options.
|
||||
#
|
||||
|
|
|
|||
|
|
@ -58,23 +58,27 @@ TEST_TARGETS=\
|
|||
airtest.exe \
|
||||
amcss.exe \
|
||||
amcsshe.exe \
|
||||
amcssth.exe \
|
||||
amsss.exe \
|
||||
amssshe.exe \
|
||||
apss.exe \
|
||||
arenacv.exe \
|
||||
awlut.exe \
|
||||
awluthe.exe \
|
||||
awlutth.exe \
|
||||
btcv.exe \
|
||||
bttest.exe \
|
||||
djbench.exe \
|
||||
exposet0.exe \
|
||||
expt825.exe \
|
||||
finalcv.exe \
|
||||
finaltest.exe \
|
||||
fotest.exe \
|
||||
gcbench.exe \
|
||||
landtest.exe \
|
||||
locbwcss.exe \
|
||||
lockcov.exe \
|
||||
lockutw3.exe \
|
||||
lockut.exe \
|
||||
locusss.exe \
|
||||
locv.exe \
|
||||
messtest.exe \
|
||||
|
|
@ -178,7 +182,7 @@ SNC = <poolsnc>
|
|||
DW = <fmtdy> <fmtno>
|
||||
FMTTEST = <fmthe> <fmtdy> <fmtno> <fmtdytst>
|
||||
FMTSCHEME = <fmtscheme>
|
||||
TESTLIB = <testlib>
|
||||
TESTLIB = <testlib> <testthrw3> <getoptl>
|
||||
|
||||
|
||||
# CHECK PARAMETERS
|
||||
|
|
@ -226,9 +230,6 @@ TESTLIB = <testlib>
|
|||
!IFNDEF TESTLIB
|
||||
!ERROR commpre.nmk: TESTLIB not defined
|
||||
!ENDIF
|
||||
!IFNDEF TESTLIB
|
||||
!ERROR commpre.nmk: TESTLIB not defined
|
||||
!ENDIF
|
||||
|
||||
|
||||
# DECLARATIONS
|
||||
|
|
|
|||
|
|
@ -231,6 +231,16 @@
|
|||
#define ATTRIBUTE_NO_SANITIZE_ADDRESS
|
||||
#endif
|
||||
|
||||
/* Attribute for functions that do not return.
|
||||
* GCC: <http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html>
|
||||
* Clang: <http://clang.llvm.org/docs/AttributeReference.html#id1>
|
||||
*/
|
||||
#if defined(MPS_BUILD_GC) || defined(MPS_BUILD_LL)
|
||||
#define ATTRIBUTE_NORETURN __attribute__((__noreturn__))
|
||||
#else
|
||||
#define ATTRIBUTE_NORETURN
|
||||
#endif
|
||||
|
||||
|
||||
/* EPVMDefaultSubsequentSegSIZE is a default for the alignment of
|
||||
* subsequent segments (non-initial at each save level) in EPVM. See
|
||||
|
|
@ -356,6 +366,8 @@
|
|||
pool to be very heavily used. */
|
||||
#define CONTROL_EXTEND_BY 4096
|
||||
|
||||
#define VM_ARENA_SIZE_DEFAULT ((Size)1 << 20)
|
||||
|
||||
|
||||
/* Stack configuration */
|
||||
|
||||
|
|
|
|||
|
|
@ -13,13 +13,13 @@
|
|||
|
||||
#include "mps.c"
|
||||
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include "getopt.h"
|
||||
#include "testlib.h"
|
||||
#include "testthr.h"
|
||||
|
||||
#include <stdio.h> /* fprintf, stderr */
|
||||
#include <stdlib.h> /* alloca, exit, EXIT_SUCCESS, EXIT_FAILURE */
|
||||
#include <time.h> /* CLOCKS_PER_SEC, clock */
|
||||
|
||||
#define DJMUST(expr) \
|
||||
do { \
|
||||
|
|
@ -56,6 +56,7 @@ static mps_bool_t zoned = TRUE; /* arena allocates using zones */
|
|||
\
|
||||
for (k = 0; k < nblocks; ++k) { \
|
||||
blocks[k].p = NULL; \
|
||||
blocks[k].s = 0; \
|
||||
} \
|
||||
\
|
||||
for (j = 0; j < npass; ++j) { \
|
||||
|
|
@ -135,24 +136,14 @@ typedef void *(*dj_t)(void *);
|
|||
|
||||
static void weave(dj_t dj)
|
||||
{
|
||||
pthread_t *threads = alloca(sizeof(threads[0]) * nthreads);
|
||||
testthr_t *threads = alloca(sizeof(threads[0]) * nthreads);
|
||||
unsigned t;
|
||||
|
||||
for (t = 0; t < nthreads; ++t) {
|
||||
int err = pthread_create(&threads[t], NULL, dj, NULL);
|
||||
if (err != 0) {
|
||||
fprintf(stderr, "Unable to create thread: %d\n", err);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
for (t = 0; t < nthreads; ++t)
|
||||
testthr_create(&threads[t], dj, NULL);
|
||||
|
||||
for (t = 0; t < nthreads; ++t) {
|
||||
int err = pthread_join(threads[t], NULL);
|
||||
if (err != 0) {
|
||||
fprintf(stderr, "Unable to join thread: %d\n", err);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
for (t = 0; t < nthreads; ++t)
|
||||
testthr_join(&threads[t], NULL);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -321,7 +312,8 @@ int main(int argc, char *argv[]) {
|
|||
argv += optind;
|
||||
|
||||
printf("seed: %lu\n", seed);
|
||||
|
||||
(void)fflush(stdout);
|
||||
|
||||
while (argc > 0) {
|
||||
for (i = 0; i < sizeof(pools) / sizeof(pools[0]); ++i)
|
||||
if (strcmp(argv[0], pools[i].name) == 0)
|
||||
|
|
|
|||
|
|
@ -44,13 +44,13 @@ char EventBuffer[EventKindLIMIT][EventBufferSIZE];
|
|||
char *EventLast[EventKindLIMIT];
|
||||
|
||||
/* Pointers to the last even written out of each buffer. */
|
||||
char *EventWritten[EventKindLIMIT];
|
||||
static char *EventWritten[EventKindLIMIT];
|
||||
|
||||
EventControlSet EventKindControl; /* Bit set used to control output. */
|
||||
|
||||
|
||||
/* A single event structure output once per buffer flush. */
|
||||
EventEventClockSyncStruct eventClockSyncStruct;
|
||||
static EventEventClockSyncStruct eventClockSyncStruct;
|
||||
|
||||
|
||||
/* eventClockSync -- Populate and write the clock sync event. */
|
||||
|
|
@ -422,7 +422,7 @@ void EventDump(mps_lib_FILE *stream)
|
|||
|
||||
for (kind = 0; kind < EventKindLIMIT; ++kind) {
|
||||
for (event = (Event)EventLast[kind];
|
||||
event < (Event)(EventBuffer[kind] + EventBufferSIZE);
|
||||
(char *)event < EventBuffer[kind] + EventBufferSIZE;
|
||||
event = (Event)((char *)event + event->any.size)) {
|
||||
/* Try to keep going even if there's an error, because this is used as a
|
||||
backtrace and we'll take what we can get. */
|
||||
|
|
|
|||
|
|
@ -197,6 +197,12 @@ static Res eventRead(Bool *eofOut, EventUnion *event, FILE *stream)
|
|||
return ResIO;
|
||||
}
|
||||
|
||||
if (event->any.size < sizeof(event->any))
|
||||
return ResFAIL; /* invalid size: too small */
|
||||
|
||||
if (event->any.size > sizeof(*event))
|
||||
return ResFAIL; /* invalid size: too large */
|
||||
|
||||
/* Read the rest of the event. */
|
||||
rest = event->any.size - sizeof(event->any);
|
||||
if (rest > 0) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* <code/eventcom.h> -- Event Logging Common Definitions
|
||||
*
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* $Id$
|
||||
*
|
||||
* .sources: mps.design.telemetry
|
||||
|
|
@ -56,7 +56,8 @@ ENUM_DECLARE(EventKind)
|
|||
|
||||
enum EventDefinitionsEnum {
|
||||
EVENT_LIST(EVENT_ENUM, X)
|
||||
EventEnumWarningSuppressor /* suppress comma-at-end-of-enum warning */
|
||||
/* suppress comma-at-end-of-enum warning */
|
||||
EventEnumWarningSuppressor = USHRT_MAX
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -89,7 +90,11 @@ typedef Word EventFW; /* word */
|
|||
typedef unsigned EventFU; /* unsigned integer */
|
||||
typedef char EventFS[EventStringLengthMAX + sizeof('\0')]; /* string */
|
||||
typedef double EventFD; /* double */
|
||||
typedef int EventFB; /* boolean */
|
||||
/* EventFB must be unsigned (even though Bool is a typedef for int)
|
||||
* because it used as the type of a bitfield with width 1, and we need
|
||||
* the legals values of the field to be 0 and 1 (not 0 and -1 which
|
||||
* would be the case for int : 1). */
|
||||
typedef unsigned EventFB; /* Boolean */
|
||||
|
||||
/* Event packing bitfield specifiers */
|
||||
#define EventFP_BITFIELD
|
||||
|
|
@ -133,7 +138,7 @@ typedef union EventUnion {
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ typedef sqlite3_int64 int64;
|
|||
* and for reporting errors.
|
||||
*/
|
||||
|
||||
unsigned int verbosity = 0;
|
||||
static unsigned int verbosity = 0;
|
||||
|
||||
#define LOG_ALWAYS 0
|
||||
#define LOG_OFTEN 1
|
||||
|
|
@ -533,7 +533,7 @@ static void logFileCompleted(sqlite3 *db,
|
|||
|
||||
/* An array of table-creation statement strings. */
|
||||
|
||||
const char *createStatements[] = {
|
||||
static const char *createStatements[] = {
|
||||
"CREATE TABLE IF NOT EXISTS event_kind (name TEXT,"
|
||||
" description TEXT,"
|
||||
" enum INTEGER PRIMARY KEY)",
|
||||
|
|
@ -571,7 +571,7 @@ static void makeTables(sqlite3 *db)
|
|||
}
|
||||
}
|
||||
|
||||
const char *glueTables[] = {
|
||||
static const char *glueTables[] = {
|
||||
"event_kind",
|
||||
"event_type",
|
||||
"event_param",
|
||||
|
|
|
|||
|
|
@ -29,15 +29,20 @@
|
|||
* $Id$
|
||||
*/
|
||||
|
||||
#include "mps.h"
|
||||
#include "mpsavm.h"
|
||||
#include "mpscmvff.h"
|
||||
#include "check.h"
|
||||
#include "config.h"
|
||||
#include "eventdef.h"
|
||||
#include "eventcom.h"
|
||||
#include "table.h"
|
||||
#include "testlib.h" /* for ulongest_t and associated print formats */
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h> /* exit, EXIT_FAILURE, EXIT_SUCCESS */
|
||||
#include <string.h> /* strcpy, strlen */
|
||||
|
||||
static const char *prog; /* program name */
|
||||
static const char *logFileName = NULL;
|
||||
|
|
@ -106,15 +111,19 @@ static void parseArgs(int argc, char *argv[])
|
|||
|
||||
static void *tableAlloc(void *closure, size_t size)
|
||||
{
|
||||
UNUSED(closure);
|
||||
return malloc(size);
|
||||
mps_pool_t pool = closure;
|
||||
mps_addr_t p;
|
||||
mps_res_t res;
|
||||
res = mps_alloc(&p, pool, size);
|
||||
if (res != MPS_RES_OK)
|
||||
everror("allocation failed: %d", res);
|
||||
return p;
|
||||
}
|
||||
|
||||
static void tableFree(void *closure, void *p, size_t size)
|
||||
{
|
||||
UNUSED(closure);
|
||||
UNUSED(size);
|
||||
free(p);
|
||||
mps_pool_t pool = closure;
|
||||
mps_free(pool, p, size);
|
||||
}
|
||||
|
||||
/* Printing routines */
|
||||
|
|
@ -171,7 +180,7 @@ static double parseDouble(char **pInOut)
|
|||
|
||||
#define MAX_STRING_LENGTH 1024
|
||||
|
||||
char strBuf[MAX_STRING_LENGTH];
|
||||
static char strBuf[MAX_STRING_LENGTH];
|
||||
|
||||
static char *parseString(char **pInOut)
|
||||
{
|
||||
|
|
@ -215,21 +224,21 @@ static Table internTable; /* dictionary of intern ids to strings */
|
|||
|
||||
static Table labelTable; /* dictionary of addrs to intern ids */
|
||||
|
||||
static void createTables(void)
|
||||
static void createTables(mps_pool_t pool)
|
||||
{
|
||||
Res res;
|
||||
/* MPS intern IDs are serials from zero up, so we can use -1
|
||||
* and -2 as specials. */
|
||||
res = TableCreate(&internTable,
|
||||
(size_t)1<<4,
|
||||
tableAlloc, tableFree, NULL,
|
||||
tableAlloc, tableFree, pool,
|
||||
(Word)-1, (Word)-2);
|
||||
if (res != ResOK)
|
||||
everror("Couldn't make intern table.");
|
||||
|
||||
/* We assume that 0 and 1 are invalid as Addrs. */
|
||||
res = TableCreate(&labelTable, (size_t)1<<7,
|
||||
tableAlloc, tableFree, NULL,
|
||||
tableAlloc, tableFree, pool,
|
||||
0, 1);
|
||||
if (res != ResOK)
|
||||
everror("Couldn't make label table.");
|
||||
|
|
@ -238,19 +247,19 @@ static void createTables(void)
|
|||
/* recordIntern -- record an interned string in the table. a copy of
|
||||
* the string from the parsed buffer into a newly-allocated block. */
|
||||
|
||||
static void recordIntern(char *p)
|
||||
static void recordIntern(mps_pool_t pool, char *p)
|
||||
{
|
||||
ulongest_t stringId;
|
||||
char *string;
|
||||
char *copy;
|
||||
mps_addr_t copy;
|
||||
size_t len;
|
||||
Res res;
|
||||
|
||||
stringId = parseHex(&p);
|
||||
string = parseString(&p);
|
||||
len = strlen(string);
|
||||
copy = malloc(len+1);
|
||||
if (copy == NULL)
|
||||
res = mps_alloc(©, pool, len + 1);
|
||||
if (res != MPS_RES_OK)
|
||||
everror("Couldn't allocate space for a string.");
|
||||
(void)strcpy(copy, string);
|
||||
res = TableDefine(internTable, (Word)stringId, (void *)copy);
|
||||
|
|
@ -258,12 +267,55 @@ static void recordIntern(char *p)
|
|||
everror("Couldn't create an intern mapping.");
|
||||
}
|
||||
|
||||
/* recordLabel records a label (an association between an address and
|
||||
* a string ID). Note that the event log may have been generated on a
|
||||
* platform with addresses larger than Word on the current platform.
|
||||
* If that happens then we are scuppered because our Table code uses
|
||||
* Word as the key type: there's nothing we can do except detect this
|
||||
* bad case (see also the EventInit handling and warning code).
|
||||
/* Over time there may be multiple labels associated with an address,
|
||||
* so we keep a list, recording for each label the clock when the
|
||||
* association was made. This means that printAddr can select the
|
||||
* label that was in force at the time of the event.
|
||||
*/
|
||||
|
||||
typedef struct LabelStruct *Label;
|
||||
typedef struct LabelStruct {
|
||||
ulongest_t clock; /* clock of this label */
|
||||
ulongest_t id; /* string id of this label */
|
||||
} LabelStruct;
|
||||
|
||||
typedef struct LabelListStruct *LabelList;
|
||||
typedef struct LabelListStruct {
|
||||
size_t n; /* number of labels in array */
|
||||
Label labels; /* labels, sorted in order by clock */
|
||||
} LabelListStruct;
|
||||
|
||||
/* labelFind returns the index of the first entry in list with a clock
|
||||
* value that's greater than 'clock', or list->n if there is no such
|
||||
* label. The list is assumed to be sorted.
|
||||
*/
|
||||
|
||||
static size_t labelFind(LabelList list, ulongest_t clock)
|
||||
{
|
||||
size_t low = 0, high = list->n;
|
||||
while (low < high) {
|
||||
size_t mid = (low + high) / 2;
|
||||
assert(NONNEGATIVE(mid) && mid < list->n);
|
||||
if (list->labels[mid].clock > clock) {
|
||||
high = mid;
|
||||
} else {
|
||||
low = mid + 1;
|
||||
}
|
||||
}
|
||||
assert(NONNEGATIVE(low) && low <= list->n);
|
||||
assert(low == list->n || list->labels[low].clock > clock);
|
||||
return low;
|
||||
}
|
||||
|
||||
/* recordLabel records a label: an association (made at the time given
|
||||
* by 'clock') between an address and a string ID. These are encoded
|
||||
* as two hexadecimal numbers in the string pointed to by 'p'.
|
||||
*
|
||||
* Note that the event log may have been generated on a platform with
|
||||
* addresses larger than Word on the current platform. If that happens
|
||||
* then we are scuppered because our Table code uses Word as the key
|
||||
* type: there's nothing we can do except detect this bad case (see
|
||||
* also the EventInit handling and warning code).
|
||||
*
|
||||
* We can and do handle the case where string IDs (which are Words on
|
||||
* the MPS platform) are larger than void* on the current platform.
|
||||
|
|
@ -274,25 +326,50 @@ static void recordIntern(char *p)
|
|||
* probably a bad idea and maybe doomed to failure.
|
||||
*/
|
||||
|
||||
static void recordLabel(char *p)
|
||||
static void recordLabel(mps_pool_t pool, ulongest_t clock, char *p)
|
||||
{
|
||||
ulongest_t address;
|
||||
ulongest_t *stringIdP;
|
||||
LabelList list;
|
||||
Label newlabels;
|
||||
mps_addr_t tmp;
|
||||
size_t pos;
|
||||
Res res;
|
||||
|
||||
|
||||
address = parseHex(&p);
|
||||
if (address > (Word)-1) {
|
||||
(void)printf("label address too large!");
|
||||
return;
|
||||
}
|
||||
|
||||
stringIdP = malloc(sizeof(ulongest_t));
|
||||
if (stringIdP == NULL)
|
||||
everror("Can't allocate space for a string's ID");
|
||||
*stringIdP = parseHex(&p);
|
||||
res = TableDefine(labelTable, (Word)address, (void *)stringIdP);
|
||||
|
||||
if (TableLookup(&tmp, labelTable, address)) {
|
||||
list = tmp;
|
||||
} else {
|
||||
/* First label for this address */
|
||||
res = mps_alloc(&tmp, pool, sizeof(LabelListStruct));
|
||||
if (res != MPS_RES_OK)
|
||||
everror("Can't allocate space for a label list");
|
||||
list = tmp;
|
||||
list->n = 0;
|
||||
res = TableDefine(labelTable, (Word)address, list);
|
||||
if (res != ResOK)
|
||||
everror("Couldn't create a label mapping.");
|
||||
}
|
||||
|
||||
res = mps_alloc(&tmp, pool, sizeof(LabelStruct) * (list->n + 1));
|
||||
if (res != ResOK)
|
||||
everror("Couldn't create an intern mapping.");
|
||||
everror("Couldn't allocate space for list of labels.");
|
||||
newlabels = tmp;
|
||||
|
||||
pos = labelFind(list, clock);
|
||||
memcpy(newlabels, list->labels, sizeof(LabelStruct) * pos);
|
||||
newlabels[pos].clock = clock;
|
||||
newlabels[pos].id = parseHex(&p);
|
||||
memcpy(newlabels + pos + 1, list->labels + pos,
|
||||
sizeof(LabelStruct) * (list->n - pos));
|
||||
if (list->n > 0)
|
||||
mps_free(pool, list->labels, sizeof(LabelStruct) * list->n);
|
||||
list->labels = newlabels;
|
||||
++ list->n;
|
||||
}
|
||||
|
||||
/* output code */
|
||||
|
|
@ -308,20 +385,23 @@ static int hexWordWidth = (MPS_WORD_WIDTH+3)/4;
|
|||
/* printAddr -- output a ulongest_t in hex, with the interned string
|
||||
* if the value is in the label table */
|
||||
|
||||
static void printAddr(ulongest_t addr, const char *ident)
|
||||
static void printAddr(ulongest_t clock, ulongest_t addr, const char *ident)
|
||||
{
|
||||
ulongest_t label;
|
||||
void *alias;
|
||||
void *tmp;
|
||||
|
||||
printf("%s:%0*" PRIXLONGEST, ident, hexWordWidth, addr);
|
||||
if (TableLookup(&alias, labelTable, addr)) {
|
||||
label = *(ulongest_t*)alias;
|
||||
putchar('[');
|
||||
if (TableLookup(&alias, internTable, label))
|
||||
printStr((char *)alias);
|
||||
else
|
||||
printf("unknown label %" PRIuLONGEST, label);
|
||||
putchar(']');
|
||||
if (TableLookup(&tmp, labelTable, addr)) {
|
||||
LabelList list = tmp;
|
||||
size_t pos = labelFind(list, clock);
|
||||
if (pos > 0) {
|
||||
ulongest_t id = list->labels[pos - 1].id;
|
||||
putchar('[');
|
||||
if (TableLookup(&tmp, internTable, id))
|
||||
printStr((char *)tmp);
|
||||
else
|
||||
printf("unknown label %" PRIXLONGEST, id);
|
||||
putchar(']');
|
||||
}
|
||||
}
|
||||
putchar(' ');
|
||||
}
|
||||
|
|
@ -332,7 +412,7 @@ static void printAddr(ulongest_t addr, const char *ident)
|
|||
|
||||
#define processParamA(ident) \
|
||||
val_hex = parseHex(&p); \
|
||||
printAddr(val_hex, #ident);
|
||||
printAddr(clock, val_hex, #ident);
|
||||
|
||||
#define processParamP processParamA
|
||||
#define processParamW processParamA
|
||||
|
|
@ -375,7 +455,7 @@ static const char *eventName[EventCodeMAX+EventCodeMAX];
|
|||
|
||||
/* readLog -- read and parse log. Returns the number of events written. */
|
||||
|
||||
static void readLog(FILE *input)
|
||||
static void readLog(mps_pool_t pool, FILE *input)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
|
@ -415,9 +495,9 @@ static void readLog(FILE *input)
|
|||
|
||||
/* for a few particular codes, we do local processing. */
|
||||
if (code == EventInternCode) {
|
||||
recordIntern(q);
|
||||
recordIntern(pool, q);
|
||||
} else if (code == EventLabelCode) {
|
||||
recordLabel(q);
|
||||
recordLabel(pool, clock, q);
|
||||
} else if (code == EventEventInitCode) {
|
||||
ulongest_t major, median, minor, maxCode, maxNameLen, wordWidth, clocksPerSec;
|
||||
major = parseHex(&q); /* EVENT_VERSION_MAJOR */
|
||||
|
|
@ -476,6 +556,9 @@ static void readLog(FILE *input)
|
|||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
mps_arena_t arena;
|
||||
mps_pool_t pool;
|
||||
mps_res_t res;
|
||||
FILE *input;
|
||||
|
||||
parseArgs(argc, argv);
|
||||
|
|
@ -488,8 +571,20 @@ int main(int argc, char *argv[])
|
|||
everror("unable to open %s", logFileName);
|
||||
}
|
||||
|
||||
createTables();
|
||||
readLog(input);
|
||||
res = mps_arena_create_k(&arena, mps_arena_class_vm(), mps_args_none);
|
||||
if (res != MPS_RES_OK)
|
||||
everror("failed to create arena: %d", res);
|
||||
|
||||
res = mps_pool_create_k(&pool, arena, mps_class_mvff(), mps_args_none);
|
||||
if (res != MPS_RES_OK)
|
||||
everror("failed to create pool: %d", res);
|
||||
|
||||
createTables(pool);
|
||||
readLog(pool, input);
|
||||
|
||||
mps_pool_destroy(pool);
|
||||
mps_arena_destroy(arena);
|
||||
|
||||
(void)fclose(input);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,12 +19,9 @@
|
|||
#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 <stdio.h> /* fflush, printf, puts, stdout */
|
||||
|
||||
|
||||
/* These values have been tuned in the hope of getting one dynamic collection. */
|
||||
|
|
@ -75,12 +72,6 @@ static void report(mps_arena_t arena)
|
|||
printf("not_condemned %"PRIuLONGEST"\n", (ulongest_t)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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -115,15 +106,7 @@ static void test_stepper(mps_addr_t object, mps_fmt_t fmt, mps_pool_t pool,
|
|||
testlib_unused(fmt);
|
||||
testlib_unused(pool);
|
||||
testlib_unused(s);
|
||||
#ifdef MPS_OS_W3
|
||||
__try {
|
||||
dylan_mutate(object);
|
||||
} __except(EXCEPTION_EXECUTE_HANDLER) {
|
||||
error("Unexpected exception.\n");
|
||||
}
|
||||
#else
|
||||
dylan_mutate(object);
|
||||
#endif
|
||||
|
||||
(*(unsigned long *)p)++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,10 +34,8 @@
|
|||
#include "fmtdy.h"
|
||||
#include "fmtdytst.h"
|
||||
#include "mpstd.h"
|
||||
#ifdef MPS_OS_W3
|
||||
#include "mpsw3.h"
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <stdio.h> /* printf, fflush, stdout */
|
||||
|
||||
|
||||
#define testArenaSIZE ((size_t)16<<20)
|
||||
|
|
|
|||
|
|
@ -26,10 +26,8 @@
|
|||
#include "fmtdy.h"
|
||||
#include "fmtdytst.h"
|
||||
#include "mpstd.h"
|
||||
#ifdef MPS_OS_W3
|
||||
#include "mpsw3.h"
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <stdio.h> /* printf */
|
||||
|
||||
|
||||
#define testArenaSIZE ((size_t)16<<20)
|
||||
|
|
|
|||
|
|
@ -22,14 +22,13 @@
|
|||
#include "mpscamc.h"
|
||||
#include "mpscams.h"
|
||||
#include "mpscawl.h"
|
||||
#include "mpsclo.h"
|
||||
#include "mpsavm.h"
|
||||
#include "fmtdy.h"
|
||||
#include "fmtdytst.h"
|
||||
#include "mpstd.h"
|
||||
#ifdef MPS_OS_W3
|
||||
#include "mpsw3.h"
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <stdio.h> /* fflush, printf, stdout */
|
||||
|
||||
|
||||
#define testArenaSIZE ((size_t)16<<20)
|
||||
|
|
@ -160,16 +159,16 @@ static void test_trees(const char *name, mps_arena_t arena, mps_ap_t ap,
|
|||
while (mps_message_poll(arena)) {
|
||||
mps_message_t message;
|
||||
mps_addr_t objaddr;
|
||||
cdie(mps_message_get(&message, arena,
|
||||
mps_message_type_finalization()),
|
||||
"get");
|
||||
cdie(mps_message_get(&message, arena, mps_message_type_finalization()),
|
||||
"message_get");
|
||||
mps_message_finalization_ref(&objaddr, arena, message);
|
||||
mps_message_discard(arena, message);
|
||||
++ final_this_time;
|
||||
}
|
||||
finals += final_this_time;
|
||||
printf("%"PRIuLONGEST" objects finalized: total %"PRIuLONGEST
|
||||
" of %"PRIuLONGEST"\n", final_this_time, finals, object_count);
|
||||
" of %"PRIuLONGEST"\n", (ulongest_t)final_this_time,
|
||||
(ulongest_t)finals, (ulongest_t)object_count);
|
||||
}
|
||||
cdie(finals == object_count, "Not all objects were finalized.");
|
||||
}
|
||||
|
|
@ -183,6 +182,8 @@ static void *test(mps_arena_t arena, mps_class_t pool_class)
|
|||
|
||||
die(mps_fmt_create_A(&fmt, arena, dylan_fmt_A()), "fmt_create\n");
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
/* Allocate into generation 0 so that they get finalized quickly. */
|
||||
MPS_ARGS_ADD(args, MPS_KEY_GEN, 0);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_FORMAT, fmt);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_AWL_FIND_DEPENDENT, test_awl_find_dependent);
|
||||
die(mps_pool_create_k(&pool, arena, pool_class, args),
|
||||
|
|
@ -221,8 +222,10 @@ int main(int argc, char *argv[])
|
|||
die(mps_thread_reg(&thread, arena), "thread_reg\n");
|
||||
|
||||
test(arena, mps_class_amc());
|
||||
/* TODO: test(arena, mps_class_ams()); */
|
||||
/* TODO: test(arena, mps_class_awl()); */
|
||||
test(arena, mps_class_amcz());
|
||||
test(arena, mps_class_ams());
|
||||
test(arena, mps_class_awl());
|
||||
/* TODO: test(arena, mps_class_lo()); */
|
||||
|
||||
mps_thread_dereg(thread);
|
||||
mps_arena_destroy(arena);
|
||||
|
|
|
|||
|
|
@ -73,8 +73,12 @@ mps_res_t dylan_make_wrappers(void)
|
|||
* If the raw memory is large enough, initialises it to a dylan-vector,
|
||||
* whose slots are initialised to either dylan-ints, or valid refs, at
|
||||
* random.
|
||||
* Caller must supply an array of (at least 1) valid refs to copy, via
|
||||
* the "refs" and "nr_refs" arguments.
|
||||
*
|
||||
* Caller must supply an array of valid refs to copy, via the "refs"
|
||||
* and "nr_refs" arguments. If "nr_refs" is 0, all slots are
|
||||
* initialized to dylan-ints: this may be useful for making leaf
|
||||
* objects.
|
||||
*
|
||||
* (Makes a pad if the raw memory is too small to hold a dylan-vector)
|
||||
*/
|
||||
|
||||
|
|
@ -100,7 +104,7 @@ mps_res_t dylan_init(mps_addr_t addr, size_t size,
|
|||
for(i = 0; i < t; ++i) {
|
||||
mps_word_t r = rnd();
|
||||
|
||||
if(r & 1)
|
||||
if(nr_refs == 0 || (r & 1))
|
||||
p[2+i] = ((r & ~(mps_word_t)3) | 1); /* random int */
|
||||
else
|
||||
p[2+i] = (mps_word_t)refs[(r >> 1) % nr_refs]; /* random ptr */
|
||||
|
|
|
|||
|
|
@ -12,14 +12,8 @@
|
|||
|
||||
/* special objects */
|
||||
|
||||
obj_t obj_empty; /* (), the empty list */
|
||||
obj_t obj_eof; /* end of file */
|
||||
obj_t obj_error; /* error indicator */
|
||||
obj_t obj_true; /* #t, boolean true */
|
||||
obj_t obj_false; /* #f, boolean false */
|
||||
obj_t obj_undefined; /* undefined result indicator */
|
||||
obj_t obj_tail; /* tail recursion indicator */
|
||||
obj_t obj_deleted; /* deleted key in hashtable */
|
||||
static obj_t obj_true; /* #t, boolean true */
|
||||
static obj_t obj_false; /* #f, boolean false */
|
||||
|
||||
|
||||
/* MPS globals */
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
#include "mpmtypes.h"
|
||||
#include "poolmfs.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h> /* printf */
|
||||
|
||||
|
||||
#define testArenaSIZE ((((size_t)3)<<24) - 4)
|
||||
|
|
@ -181,7 +181,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE),
|
||||
"mps_arena_create");
|
||||
alignment = (1 << (rnd() % 4)) * MPS_PF_ALIGN;
|
||||
alignment = sizeof(void *) << (rnd() % 4);
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_EXTEND_BY, (64 + rnd() % 64) * 1024);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MEAN_SIZE, (1 + rnd() % 8) * 8);
|
||||
|
|
@ -200,7 +200,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE),
|
||||
"mps_arena_create");
|
||||
alignment = (1 << (rnd() % 4)) * MPS_PF_ALIGN;
|
||||
alignment = sizeof(void *) << (rnd() % 4);
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ALIGN, alignment);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MIN_SIZE, (1 + rnd() % 4) * 4);
|
||||
|
|
|
|||
|
|
@ -7,18 +7,16 @@
|
|||
*/
|
||||
|
||||
#include "mps.c"
|
||||
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include "getopt.h"
|
||||
#include "testlib.h"
|
||||
|
||||
#include "testthr.h"
|
||||
#include "fmtdy.h"
|
||||
#include "fmtdytst.h"
|
||||
|
||||
#include <stdio.h> /* fprintf, printf, putchars, sscanf, stderr, stdout */
|
||||
#include <stdlib.h> /* alloca, exit, EXIT_FAILURE, EXIT_SUCCESS, strtoul */
|
||||
#include <time.h> /* clock, CLOCKS_PER_SEC */
|
||||
|
||||
#define RESMUST(expr) \
|
||||
do { \
|
||||
mps_res_t res = (expr); \
|
||||
|
|
@ -56,7 +54,7 @@ typedef struct gcthread_s *gcthread_t;
|
|||
typedef void *(*gcthread_fn_t)(gcthread_t thread);
|
||||
|
||||
struct gcthread_s {
|
||||
pthread_t pthread;
|
||||
testthr_t thread;
|
||||
mps_thr_t mps_thread;
|
||||
mps_root_t reg_root;
|
||||
mps_ap_t ap;
|
||||
|
|
@ -189,23 +187,12 @@ static void weave(gcthread_fn_t fn)
|
|||
|
||||
for (t = 0; t < nthreads; ++t) {
|
||||
gcthread_t thread = &threads[t];
|
||||
int err;
|
||||
thread->fn = fn;
|
||||
err = pthread_create(&thread->pthread, NULL, start, thread);
|
||||
if (err != 0) {
|
||||
fprintf(stderr, "Unable to create thread: %d\n", err);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
testthr_create(&thread->thread, start, thread);
|
||||
}
|
||||
|
||||
for (t = 0; t < nthreads; ++t) {
|
||||
gcthread_t thread = &threads[t];
|
||||
int err = pthread_join(thread->pthread, NULL);
|
||||
if (err != 0) {
|
||||
fprintf(stderr, "Unable to join thread: %d\n", err);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
for (t = 0; t < nthreads; ++t)
|
||||
testthr_join(&threads[t].thread, NULL);
|
||||
}
|
||||
|
||||
static void weave1(gcthread_fn_t fn)
|
||||
|
|
@ -331,8 +318,8 @@ int main(int argc, char *argv[]) {
|
|||
double mort = 0.0;
|
||||
cap = (size_t)strtoul(optarg, &p, 10);
|
||||
switch(toupper(*p)) {
|
||||
case 'G': cap *= 1024; /* fall through */
|
||||
case 'M': cap *= 1024; /* fall through */
|
||||
case 'G': cap <<= 20; p++; break;
|
||||
case 'M': cap <<= 10; p++; break;
|
||||
case 'K': p++; break;
|
||||
default: cap = 0; break;
|
||||
}
|
||||
|
|
@ -353,9 +340,9 @@ int main(int argc, char *argv[]) {
|
|||
char *p;
|
||||
arenasize = (unsigned)strtoul(optarg, &p, 10);
|
||||
switch(toupper(*p)) {
|
||||
case 'G': arenasize *= 1024;
|
||||
case 'M': arenasize *= 1024;
|
||||
case 'K': arenasize *= 1024; break;
|
||||
case 'G': arenasize <<= 30; break;
|
||||
case 'M': arenasize <<= 20; break;
|
||||
case 'K': arenasize <<= 10; break;
|
||||
case '\0': break;
|
||||
default:
|
||||
fprintf(stderr, "Bad arena size %s\n", optarg);
|
||||
|
|
@ -432,7 +419,8 @@ int main(int argc, char *argv[]) {
|
|||
argv += optind;
|
||||
|
||||
printf("seed: %lu\n", seed);
|
||||
|
||||
(void)fflush(stdout);
|
||||
|
||||
while (argc > 0) {
|
||||
for (i = 0; i < sizeof(pools) / sizeof(pools[0]); ++i)
|
||||
if (strcmp(argv[0], pools[i].name) == 0)
|
||||
|
|
|
|||
|
|
@ -48,8 +48,6 @@
|
|||
#ifndef _GETOPT_H_
|
||||
#define _GETOPT_H_
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
/*
|
||||
* GNU-like getopt_long()/getopt_long_only() with 4.4BSD optreset extension.
|
||||
* getopt() is declared here too for GNU programs.
|
||||
|
|
@ -72,7 +70,6 @@ struct option {
|
|||
int val;
|
||||
};
|
||||
|
||||
__BEGIN_DECLS
|
||||
int getopt_long(int, char * const *, const char *,
|
||||
const struct option *, int *);
|
||||
int getopt_long_only(int, char * const *, const char *,
|
||||
|
|
@ -88,6 +85,5 @@ extern int optind, opterr, optopt;
|
|||
#define _OPTRESET_DECLARED
|
||||
extern int optreset; /* getopt(3) external variable */
|
||||
#endif
|
||||
__END_DECLS
|
||||
|
||||
#endif /* !_GETOPT_H_ */
|
||||
|
|
|
|||
|
|
@ -397,25 +397,7 @@ void GlobalsFinish(Globals arenaGlobals)
|
|||
Arena arena;
|
||||
Rank rank;
|
||||
|
||||
/* Check that the tear-down is complete: that the client has
|
||||
* destroyed all data structures associated with the arena. We do
|
||||
* this *before* calling AVERT(Globals, arenaGlobals) because the
|
||||
* AVERT will crash if there are any remaining data structures, and
|
||||
* it is politer to assert than to crash. (The crash would happen
|
||||
* because by this point in the code the control pool has been
|
||||
* destroyed and so the address space containing all these rings has
|
||||
* potentially been unmapped, and so RingCheck dereferences a
|
||||
* pointer into that unmapped memory.) See job000652. */
|
||||
arena = GlobalsArena(arenaGlobals);
|
||||
AVER(RingIsSingle(&arena->formatRing));
|
||||
AVER(RingIsSingle(&arena->chainRing));
|
||||
AVER(RingIsSingle(&arena->messageRing));
|
||||
AVER(RingIsSingle(&arena->threadRing));
|
||||
for(rank = 0; rank < RankLIMIT; ++rank)
|
||||
AVER(RingIsSingle(&arena->greyRing[rank]));
|
||||
AVER(RingIsSingle(&arenaGlobals->poolRing));
|
||||
AVER(RingIsSingle(&arenaGlobals->rootRing));
|
||||
|
||||
AVERT(Globals, arenaGlobals);
|
||||
|
||||
STATISTIC_STAT(EVENT2(ArenaWriteFaults, arena,
|
||||
|
|
@ -445,6 +427,7 @@ void GlobalsPrepareToDestroy(Globals arenaGlobals)
|
|||
TraceId ti;
|
||||
Trace trace;
|
||||
Chain defaultChain;
|
||||
Rank rank;
|
||||
|
||||
AVERT(Globals, arenaGlobals);
|
||||
|
||||
|
|
@ -499,6 +482,31 @@ void GlobalsPrepareToDestroy(Globals arenaGlobals)
|
|||
arena->finalPool = NULL;
|
||||
PoolDestroy(pool);
|
||||
}
|
||||
|
||||
/* Check that the tear-down is complete: that the client has
|
||||
* destroyed all data structures associated with the arena. We do
|
||||
* this here rather than in GlobalsFinish because by the time that
|
||||
* is called, the control pool has been destroyed and so the address
|
||||
* space containing all these rings has potentially been unmapped,
|
||||
* and so RingCheck dereferences a pointer into that unmapped memory
|
||||
* and we get a crash instead of an assertion. See job000652.
|
||||
*/
|
||||
AVER(RingIsSingle(&arena->formatRing));
|
||||
AVER(RingIsSingle(&arena->chainRing));
|
||||
AVER(RingIsSingle(&arena->messageRing));
|
||||
AVER(RingIsSingle(&arena->threadRing));
|
||||
AVER(RingIsSingle(&arenaGlobals->rootRing));
|
||||
for(rank = 0; rank < RankLIMIT; ++rank)
|
||||
AVER(RingIsSingle(&arena->greyRing[rank]));
|
||||
|
||||
/* At this point the following pools still exist:
|
||||
* 0. arena->freeCBSBlockPoolStruct
|
||||
* 1. arena->reservoirStruct
|
||||
* 2. arena->controlPoolStruct
|
||||
* 3. arena->controlPoolStruct.blockPoolStruct
|
||||
* 4. arena->controlPoolStruct.spanPoolStruct
|
||||
*/
|
||||
AVER(RingLength(&arenaGlobals->poolRing) == 5);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -617,6 +625,7 @@ void ArenaLeaveRecursive(Arena arena)
|
|||
* version. The format is platform-specific. We won't necessarily
|
||||
* publish this. */
|
||||
|
||||
extern MutatorFaultContext mps_exception_info;
|
||||
MutatorFaultContext mps_exception_info = NULL;
|
||||
|
||||
|
||||
|
|
@ -1131,7 +1140,7 @@ void ArenaSetEmergency(Arena arena, Bool emergency)
|
|||
AVERT(Arena, arena);
|
||||
AVERT(Bool, emergency);
|
||||
|
||||
EVENT2(ArenaSetEmergency, arena, emergency);
|
||||
EVENT2(ArenaSetEmergency, arena, BOOL(emergency));
|
||||
|
||||
arena->emergency = emergency;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,9 +26,7 @@
|
|||
#include "poolmfs.h"
|
||||
#include "testlib.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <stdio.h> /* printf */
|
||||
|
||||
SRCID(landtest, "$Id$");
|
||||
|
||||
|
|
|
|||
|
|
@ -17,10 +17,13 @@ CFLAGSCOMPILER := \
|
|||
-Waggregate-return \
|
||||
-Wall \
|
||||
-Wcast-qual \
|
||||
-Wconversion \
|
||||
-Wduplicate-enum \
|
||||
-Werror \
|
||||
-Wextra \
|
||||
-Winline \
|
||||
-Wmissing-prototypes \
|
||||
-Wmissing-variable-declarations \
|
||||
-Wnested-externs \
|
||||
-Wno-extended-offsetof \
|
||||
-Wpointer-arith \
|
||||
|
|
|
|||
|
|
@ -11,8 +11,7 @@
|
|||
#include "mpslib.h"
|
||||
#include "mps.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h> /* printf */
|
||||
|
||||
|
||||
/* some constants */
|
||||
|
|
|
|||
|
|
@ -4,19 +4,37 @@
|
|||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*/
|
||||
|
||||
#include "mps.h"
|
||||
#include "mpsavm.h"
|
||||
#include "mpscmfs.h"
|
||||
#include "mpm.h"
|
||||
#include "testlib.h"
|
||||
#include "mpslib.h"
|
||||
#include <stdlib.h> /* for malloc & free */
|
||||
|
||||
#include <stdio.h> /* printf */
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
Lock a = malloc(LockSize());
|
||||
Lock b = malloc(LockSize());
|
||||
mps_arena_t arena;
|
||||
mps_pool_t pool;
|
||||
mps_addr_t p;
|
||||
Lock a, b;
|
||||
|
||||
testlib_init(argc, argv);
|
||||
|
||||
die(mps_arena_create_k(&arena, mps_arena_class_vm(), mps_args_none),
|
||||
"arena_create");
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MFS_UNIT_SIZE, LockSize());
|
||||
die(mps_pool_create_k(&pool, arena, mps_class_mfs(), args), "pool_create");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
die(mps_alloc(&p, pool, LockSize()), "alloc a");
|
||||
a = p;
|
||||
die(mps_alloc(&p, pool, LockSize()), "alloc b");
|
||||
b = p;
|
||||
|
||||
Insist(a != NULL);
|
||||
Insist(b != NULL);
|
||||
|
||||
|
|
@ -44,8 +62,11 @@ int main(int argc, char *argv[])
|
|||
LockReleaseMPM(a);
|
||||
LockFinish(a);
|
||||
LockReleaseGlobalRecursive();
|
||||
free(a);
|
||||
free(b);
|
||||
|
||||
mps_free(pool, a, LockSize());
|
||||
mps_free(pool, b, LockSize());
|
||||
mps_pool_destroy(pool);
|
||||
mps_arena_destroy(arena);
|
||||
|
||||
printf("%s: Conclusion: Failed to find any defects.\n", argv[0]);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1,30 +1,26 @@
|
|||
/* lockutw3.c: LOCK UTILIZATION TEST
|
||||
/* lockut.c: LOCK UTILIZATION TEST
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*/
|
||||
|
||||
#include <stdlib.h> /* malloc */
|
||||
|
||||
#include "mps.h"
|
||||
#include "mpsavm.h"
|
||||
#include "mpscmfs.h"
|
||||
#include "mpm.h"
|
||||
#include "testlib.h"
|
||||
#include "mpslib.h"
|
||||
#include "testthr.h"
|
||||
|
||||
#include "mpswin.h"
|
||||
|
||||
|
||||
#ifndef MPS_OS_W3
|
||||
#error "Relies on Win32 threads"
|
||||
#endif
|
||||
#include <stdio.h> /* printf */
|
||||
|
||||
|
||||
#define nTHREADS 4
|
||||
|
||||
static Lock lock;
|
||||
unsigned long shared, tmp;
|
||||
static unsigned long shared, tmp;
|
||||
|
||||
|
||||
void incR(unsigned long i)
|
||||
static void incR(unsigned long i)
|
||||
{
|
||||
LockClaimRecursive(lock);
|
||||
if (i < 100) {
|
||||
|
|
@ -40,7 +36,7 @@ void incR(unsigned long i)
|
|||
}
|
||||
|
||||
|
||||
void inc(unsigned long i)
|
||||
static void inc(unsigned long i)
|
||||
{
|
||||
incR( (i+1) >>1);
|
||||
i >>= 1;
|
||||
|
|
@ -59,23 +55,33 @@ void inc(unsigned long i)
|
|||
|
||||
|
||||
#define COUNT 100000l
|
||||
DWORD WINAPI thread0(void *p)
|
||||
static void *thread0(void *p)
|
||||
{
|
||||
(void)p;
|
||||
testlib_unused(p);
|
||||
inc(COUNT);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
DWORD id;
|
||||
HANDLE t[10];
|
||||
mps_arena_t arena;
|
||||
mps_pool_t pool;
|
||||
mps_addr_t p;
|
||||
testthr_t t[10];
|
||||
unsigned i;
|
||||
|
||||
testlib_init(argc, argv);
|
||||
|
||||
lock = malloc(LockSize());
|
||||
die(mps_arena_create_k(&arena, mps_arena_class_vm(), mps_args_none),
|
||||
"arena_create");
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MFS_UNIT_SIZE, LockSize());
|
||||
die(mps_pool_create_k(&pool, arena, mps_class_mfs(), args), "pool_create");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
die(mps_alloc(&p, pool, LockSize()), "alloc");
|
||||
lock = p;
|
||||
Insist(lock != NULL);
|
||||
|
||||
LockInit(lock);
|
||||
|
|
@ -84,17 +90,19 @@ int main(int argc, char *argv[])
|
|||
shared = 0;
|
||||
|
||||
for(i = 0; i < nTHREADS; i++)
|
||||
t[i] = CreateThread(NULL, 0, thread0, NULL, 0, &id);
|
||||
testthr_create(&t[i], thread0, NULL);
|
||||
|
||||
for(i = 0; i < nTHREADS; i++) {
|
||||
cdie(WaitForSingleObject(t[i], INFINITE) == WAIT_OBJECT_0,
|
||||
"WaitForSingleObject");
|
||||
}
|
||||
for(i = 0; i < nTHREADS; i++)
|
||||
testthr_join(&t[i], NULL);
|
||||
|
||||
Insist(shared == nTHREADS*COUNT);
|
||||
|
||||
LockFinish(lock);
|
||||
|
||||
mps_free(pool, lock, LockSize());
|
||||
mps_pool_destroy(pool);
|
||||
mps_arena_destroy(arena);
|
||||
|
||||
printf("%s: Conclusion: Failed to find any defects.\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -12,8 +12,7 @@
|
|||
#include "mpslib.h"
|
||||
#include "mps.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h> /* printf */
|
||||
|
||||
|
||||
/* some constants */
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@
|
|||
#include "mpsclo.h"
|
||||
#include "mpsavm.h"
|
||||
|
||||
#include <stdio.h> /* printf */
|
||||
|
||||
|
||||
#define testArenaSIZE ((size_t)16<<20)
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@
|
|||
#include "testlib.h"
|
||||
#include "mpslib.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h> /* printf */
|
||||
|
||||
SRCID(messtest, "$Id$");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* meter.h: METER INTERFACE
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .sources: mps.design.metrics.
|
||||
*
|
||||
|
|
@ -45,9 +45,12 @@ extern void MeterEmit(Meter meter);
|
|||
#define METER_ACC(meter, delta) \
|
||||
STATISTIC(MeterAccumulate(&(meter), delta))
|
||||
#if defined(STATISTICS)
|
||||
#define METER_WRITE(meter, stream) MeterWrite(&(meter), stream)
|
||||
#define METER_WRITE(meter, stream) BEGIN \
|
||||
Res _res = MeterWrite(&(meter), (stream)); \
|
||||
if (_res != ResOK) return _res; \
|
||||
END
|
||||
#elif defined(STATISTICS_NONE)
|
||||
#define METER_WRITE(meter, stream) (ResOK)
|
||||
#define METER_WRITE(meter, stream) NOOP
|
||||
#else
|
||||
#error "No statistics configured."
|
||||
#endif
|
||||
|
|
@ -59,7 +62,7 @@ extern void MeterEmit(Meter meter);
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* misc.h: MISCELLANEOUS DEFINITIONS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (C) 2001 Global Graphics Software.
|
||||
*
|
||||
* Small general things which are useful for C but aren't part of the
|
||||
|
|
@ -50,6 +50,7 @@ typedef const struct SrcIdStruct {
|
|||
#define SRCID(id, scmid) \
|
||||
static SrcIdStruct id ## FileSrcIdStruct = \
|
||||
{__FILE__, (scmid), __DATE__, __TIME__}; \
|
||||
extern SrcId id ## SrcId; \
|
||||
SrcId id ## SrcId = &id ## FileSrcIdStruct
|
||||
|
||||
|
||||
|
|
@ -170,6 +171,16 @@ typedef const struct SrcIdStruct {
|
|||
((type *)(void *)((char *)(p) - offsetof(type, field)))
|
||||
|
||||
|
||||
/* BITFIELD -- coerce a value into a bitfield
|
||||
*
|
||||
* This coerces value to the given width and type in a way that avoids
|
||||
* warnings from gcc -Wconversion about possible loss of data.
|
||||
*/
|
||||
|
||||
#define BITFIELD(type, value, width) ((type)value & (((type)1 << (width)) - 1))
|
||||
#define BOOL(v) BITFIELD(unsigned, (v), 1)
|
||||
|
||||
|
||||
/* Bit Sets -- sets of integers in [0,N-1].
|
||||
*
|
||||
* Can be used on any unsigned integral type, ty. These definitions
|
||||
|
|
@ -191,6 +202,7 @@ typedef const struct SrcIdStruct {
|
|||
#define BS_SUB(s1, s2) BS_SUPER((s2), (s1))
|
||||
#define BS_IS_SINGLE(s) ( ((s) != 0) && (((s) & ((s)-1)) == 0) )
|
||||
#define BS_SYM_DIFF(s1, s2) ((s1) ^ (s2))
|
||||
#define BS_BITFIELD(ty, s) BITFIELD(ty ## Set, (s), ty ## LIMIT)
|
||||
|
||||
|
||||
#endif /* misc_h */
|
||||
|
|
@ -198,7 +210,7 @@ typedef const struct SrcIdStruct {
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -174,16 +174,16 @@ Word (WordAlignDown)(Word word, Align alignment)
|
|||
|
||||
/* SizeIsP2 -- test whether a size is a power of two */
|
||||
|
||||
Bool SizeIsP2(Size size)
|
||||
Bool (SizeIsP2)(Size size)
|
||||
{
|
||||
return WordIsP2((Word)size);
|
||||
return SizeIsP2(size);
|
||||
}
|
||||
|
||||
/* WordIsP2 -- tests whether a word is a power of two */
|
||||
|
||||
Bool WordIsP2(Word word)
|
||||
Bool (WordIsP2)(Word word)
|
||||
{
|
||||
return word > 0 && (word & (word - 1)) == 0;
|
||||
return WordIsP2(word);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -143,11 +143,13 @@ extern Bool ResIsAllocFailure(Res res);
|
|||
* SizeFloorLog2 returns the floor of the logarithm in base 2 of size.
|
||||
* size can be any positive non-zero value. */
|
||||
|
||||
extern Bool SizeIsP2(Size size);
|
||||
extern Bool (SizeIsP2)(Size size);
|
||||
#define SizeIsP2(size) WordIsP2((Word)size)
|
||||
extern Shift SizeLog2(Size size);
|
||||
extern Shift SizeFloorLog2(Size size);
|
||||
|
||||
extern Bool WordIsP2(Word word);
|
||||
extern Bool (WordIsP2)(Word word);
|
||||
#define WordIsP2(word) ((word) > 0 && ((word) & ((word) - 1)) == 0)
|
||||
|
||||
/* Formatted Output -- see <design/writef/>, <code/mpm.c> */
|
||||
|
||||
|
|
@ -709,10 +711,10 @@ extern Addr (SegLimit)(Seg seg);
|
|||
|
||||
#define SegSummary(seg) (((GCSeg)(seg))->summary)
|
||||
|
||||
#define SegSetPM(seg, mode) ((void)((seg)->pm = (mode)))
|
||||
#define SegSetSM(seg, mode) ((void)((seg)->sm = (mode)))
|
||||
#define SegSetDepth(seg, d) ((void)((seg)->depth = (d)))
|
||||
#define SegSetNailed(seg, ts) ((void)((seg)->nailed = (ts)))
|
||||
#define SegSetPM(seg, mode) ((void)((seg)->pm = BS_BITFIELD(Access, (mode))))
|
||||
#define SegSetSM(seg, mode) ((void)((seg)->sm = BS_BITFIELD(Access, (mode))))
|
||||
#define SegSetDepth(seg, d) ((void)((seg)->depth = BITFIELD(unsigned, (d), ShieldDepthWIDTH)))
|
||||
#define SegSetNailed(seg, ts) ((void)((seg)->nailed = BS_BITFIELD(Trace, (ts))))
|
||||
|
||||
|
||||
/* Buffer Interface -- see <code/buffer.c> */
|
||||
|
|
|
|||
|
|
@ -7,19 +7,14 @@
|
|||
|
||||
#include "mpscmv.h"
|
||||
#include "mpscmvff.h"
|
||||
#include "mpscmfs.h"
|
||||
#include "mpslib.h"
|
||||
#include "mpsavm.h"
|
||||
#include "testlib.h"
|
||||
#include "mpslib.h"
|
||||
#include "mps.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
/* TODO: Decide whether we should support the MPS pool class externally,
|
||||
create mpscmfs.h, and replace this extern with proper use of its
|
||||
interface. */
|
||||
extern mps_class_t PoolClassMFS(void);
|
||||
#include <stdio.h> /* printf */
|
||||
|
||||
|
||||
#define testArenaSIZE ((((size_t)64)<<20) - 4)
|
||||
|
|
@ -156,8 +151,7 @@ static void testInArena(mps_arena_t arena, mps_pool_debug_option_s *options)
|
|||
|
||||
printf("MFS\n");
|
||||
fixedSizeSize = 13;
|
||||
die(stress(PoolClassMFS(),
|
||||
fixedSize, arena, (size_t)100000, fixedSizeSize),
|
||||
die(stress(mps_class_mfs(), fixedSize, arena, (size_t)100000, fixedSizeSize),
|
||||
"stress MFS");
|
||||
|
||||
printf("MV\n");
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* mpmst.h: MEMORY POOL MANAGER DATA STRUCTURES
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (C) 2001 Global Graphics Software.
|
||||
*
|
||||
* .design: This header file crosses module boundaries. The relevant
|
||||
|
|
@ -275,8 +275,8 @@ typedef struct SegStruct { /* segment structure */
|
|||
RingStruct poolRing; /* link in list of segs in pool */
|
||||
Addr limit; /* limit of segment */
|
||||
unsigned depth : ShieldDepthWIDTH; /* see <code/shield.c#def.depth> */
|
||||
AccessSet pm : AccessSetWIDTH; /* protection mode, <code/shield.c> */
|
||||
AccessSet sm : AccessSetWIDTH; /* shield mode, <code/shield.c> */
|
||||
AccessSet pm : AccessLIMIT; /* protection mode, <code/shield.c> */
|
||||
AccessSet sm : AccessLIMIT; /* shield mode, <code/shield.c> */
|
||||
TraceSet grey : TraceLIMIT; /* traces for which seg is grey */
|
||||
TraceSet white : TraceLIMIT; /* traces for which seg is white */
|
||||
TraceSet nailed : TraceLIMIT; /* traces for which seg has nailed objects */
|
||||
|
|
@ -817,7 +817,7 @@ typedef struct AllocPatternStruct {
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -287,7 +287,7 @@ typedef Res (*LandDescribeMethod)(Land land, mps_lib_FILE *stream);
|
|||
#define AccessSetEMPTY ((AccessSet)0) /* <design/type/#access-set> */
|
||||
#define AccessREAD ((AccessSet)(1<<0))
|
||||
#define AccessWRITE ((AccessSet)(1<<1))
|
||||
#define AccessSetWIDTH (2)
|
||||
#define AccessLIMIT (2)
|
||||
#define RefSetEMPTY BS_EMPTY(RefSet)
|
||||
#define RefSetUNIV BS_UNIV(RefSet)
|
||||
#define ZoneSetEMPTY BS_EMPTY(ZoneSet)
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@
|
|||
3114A65B156E95B4001E0AA3 /* PBXTargetDependency */,
|
||||
2231BB6D18CA986B002D6322 /* PBXTargetDependency */,
|
||||
31D60034156D3D5A00337B26 /* PBXTargetDependency */,
|
||||
2286E4C918F4389E004111E2 /* PBXTargetDependency */,
|
||||
2231BB6F18CA986D002D6322 /* PBXTargetDependency */,
|
||||
3114A5A0156E915A001E0AA3 /* PBXTargetDependency */,
|
||||
3114A6A7156E9739001E0AA3 /* PBXTargetDependency */,
|
||||
|
|
@ -88,6 +89,10 @@
|
|||
224CC793175E1821002FF81B /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; };
|
||||
224CC79F175E321C002FF81B /* mv2test.c in Sources */ = {isa = PBXBuildFile; fileRef = 3114A686156E9674001E0AA3 /* mv2test.c */; };
|
||||
224CC7A0175E322C002FF81B /* fotest.c in Sources */ = {isa = PBXBuildFile; fileRef = 224CC79E175E3202002FF81B /* fotest.c */; };
|
||||
22561A9818F4265D00372C66 /* testthrix.c in Sources */ = {isa = PBXBuildFile; fileRef = 22561A9718F4263300372C66 /* testthrix.c */; };
|
||||
22561A9918F4266600372C66 /* testthrix.c in Sources */ = {isa = PBXBuildFile; fileRef = 22561A9718F4263300372C66 /* testthrix.c */; };
|
||||
22561A9A18F426BB00372C66 /* testthrix.c in Sources */ = {isa = PBXBuildFile; fileRef = 22561A9718F4263300372C66 /* testthrix.c */; };
|
||||
22561A9B18F426F300372C66 /* testthrix.c in Sources */ = {isa = PBXBuildFile; fileRef = 22561A9718F4263300372C66 /* testthrix.c */; };
|
||||
2291A5B1175CAB2F001D4920 /* fmtdy.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC6156BE48D00753214 /* fmtdy.c */; };
|
||||
2291A5B2175CAB2F001D4920 /* fmtdytst.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC7156BE48D00753214 /* fmtdytst.c */; };
|
||||
2291A5B3175CAB2F001D4920 /* fmthe.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAE4156BE6D500753214 /* fmthe.c */; };
|
||||
|
|
@ -113,6 +118,10 @@
|
|||
22C2ACA718BE400A006B3677 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; };
|
||||
22C2ACA918BE400A006B3677 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; };
|
||||
22C2ACB018BE4049006B3677 /* nailboardtest.c in Sources */ = {isa = PBXBuildFile; fileRef = 22C2ACA018BE3FEC006B3677 /* nailboardtest.c */; };
|
||||
22F846B518F437B900982BA7 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; };
|
||||
22F846B718F437B900982BA7 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; };
|
||||
22F846BE18F437D700982BA7 /* lockut.c in Sources */ = {isa = PBXBuildFile; fileRef = 22F846AF18F4379C00982BA7 /* lockut.c */; };
|
||||
22F846BF18F437E000982BA7 /* testthrix.c in Sources */ = {isa = PBXBuildFile; fileRef = 22561A9718F4263300372C66 /* testthrix.c */; };
|
||||
22FA176916E8D6FC0098B23F /* fmtdy.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC6156BE48D00753214 /* fmtdy.c */; };
|
||||
22FA176A16E8D6FC0098B23F /* fmtdytst.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC7156BE48D00753214 /* fmtdytst.c */; };
|
||||
22FA176B16E8D6FC0098B23F /* fmthe.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAE4156BE6D500753214 /* fmthe.c */; };
|
||||
|
|
@ -327,6 +336,13 @@
|
|||
remoteGlobalIDString = 2D604B9B16514B1A003AAF46;
|
||||
remoteInfo = mpseventtxt;
|
||||
};
|
||||
2286E4C818F4389E004111E2 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 22F846B018F437B900982BA7;
|
||||
remoteInfo = lockut;
|
||||
};
|
||||
2291A5AE175CAB2F001D4920 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */;
|
||||
|
|
@ -418,6 +434,13 @@
|
|||
remoteGlobalIDString = 3104AFF1156D37A0000A585A;
|
||||
remoteInfo = all;
|
||||
};
|
||||
22F846B218F437B900982BA7 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 31EEABFA156AAF9D00714D05;
|
||||
remoteInfo = mps;
|
||||
};
|
||||
22FA176616E8D6FC0098B23F /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */;
|
||||
|
|
@ -955,6 +978,15 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
22F846B818F437B900982BA7 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = /usr/share/man/man1/;
|
||||
dstSubfolderSpec = 0;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
22FA177016E8D6FC0098B23F /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
|
@ -1297,6 +1329,8 @@
|
|||
2231BB6918CA983C002D6322 /* locusss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = locusss.c; sourceTree = "<group>"; };
|
||||
224CC799175E1821002FF81B /* fotest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fotest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
224CC79E175E3202002FF81B /* fotest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fotest.c; sourceTree = "<group>"; };
|
||||
22561A9618F4263300372C66 /* testthr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = testthr.h; sourceTree = "<group>"; };
|
||||
22561A9718F4263300372C66 /* testthrix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testthrix.c; sourceTree = "<group>"; };
|
||||
2291A5A8175CAA51001D4920 /* poolmv2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = poolmv2.h; sourceTree = "<group>"; };
|
||||
2291A5A9175CAA9B001D4920 /* awlutth.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = awlutth.c; sourceTree = "<group>"; };
|
||||
2291A5AA175CAA9B001D4920 /* exposet0.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = exposet0.c; sourceTree = "<group>"; };
|
||||
|
|
@ -1317,6 +1351,8 @@
|
|||
22C2ACAF18BE400A006B3677 /* nailboardtest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = nailboardtest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
22E30E821886FF1400D98EA9 /* nailboard.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nailboard.c; sourceTree = "<group>"; };
|
||||
22E30E831886FF1400D98EA9 /* nailboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nailboard.h; sourceTree = "<group>"; };
|
||||
22F846AF18F4379C00982BA7 /* lockut.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lockut.c; sourceTree = "<group>"; };
|
||||
22F846BD18F437B900982BA7 /* lockut */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = lockut; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
22C5C99A18EC6AEC004C63D4 /* failover.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = failover.c; sourceTree = "<group>"; };
|
||||
22C5C99B18EC6AEC004C63D4 /* failover.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = failover.h; sourceTree = "<group>"; };
|
||||
22C5C99C18EC6AEC004C63D4 /* land.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = land.c; sourceTree = "<group>"; };
|
||||
|
|
@ -1331,8 +1367,6 @@
|
|||
22FACED5188807FF000FDBC1 /* fmtno.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fmtno.h; sourceTree = "<group>"; };
|
||||
22FACED6188807FF000FDBC1 /* fmtscheme.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fmtscheme.c; sourceTree = "<group>"; };
|
||||
22FACED7188807FF000FDBC1 /* fmtscheme.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fmtscheme.h; sourceTree = "<group>"; };
|
||||
22FACED8188807FF000FDBC1 /* locbwcss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = locbwcss.c; sourceTree = "<group>"; };
|
||||
22FACED9188807FF000FDBC1 /* locusss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = locusss.c; sourceTree = "<group>"; };
|
||||
22FACEDA1888088A000FDBC1 /* ss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ss.c; sourceTree = "<group>"; };
|
||||
22FACEDB188808D5000FDBC1 /* mpscmfs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mpscmfs.h; sourceTree = "<group>"; };
|
||||
22FACEDC18880933000FDBC1 /* poolmfs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = poolmfs.h; sourceTree = "<group>"; };
|
||||
|
|
@ -1670,6 +1704,14 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
22F846B618F437B900982BA7 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
22F846B718F437B900982BA7 /* libmps.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
22FA176E16E8D6FC0098B23F /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
|
@ -2087,6 +2129,7 @@
|
|||
3124CAB3156BE1B700753214 /* Tests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
22F846AF18F4379C00982BA7 /* lockut.c */,
|
||||
3114A63D156E94EA001E0AA3 /* abqtest.c */,
|
||||
22FACED1188807FF000FDBC1 /* airtest.c */,
|
||||
3124CAF5156BE81100753214 /* amcss.c */,
|
||||
|
|
@ -2134,6 +2177,8 @@
|
|||
3114A628156E949A001E0AA3 /* teletest.c */,
|
||||
31EEAC9E156AB73400714D05 /* testlib.c */,
|
||||
2291A5F0175CB7A4001D4920 /* testlib.h */,
|
||||
22561A9618F4263300372C66 /* testthr.h */,
|
||||
22561A9718F4263300372C66 /* testthrix.c */,
|
||||
3114A6BA156E9768001E0AA3 /* walkt0.c */,
|
||||
31D6005E156D3F4A00337B26 /* zcoll.c */,
|
||||
31D6007B156D3FCC00337B26 /* zmess.c */,
|
||||
|
|
@ -2227,6 +2272,7 @@
|
|||
2231BB6718CA97DC002D6322 /* locusss */,
|
||||
22FACEED18880983000FDBC1 /* airtest */,
|
||||
22C2ACAF18BE400A006B3677 /* nailboardtest */,
|
||||
22F846BD18F437B900982BA7 /* lockut */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -2558,6 +2604,24 @@
|
|||
productReference = 22C2ACAF18BE400A006B3677 /* nailboardtest */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
22F846B018F437B900982BA7 /* lockut */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 22F846B918F437B900982BA7 /* Build configuration list for PBXNativeTarget "lockut" */;
|
||||
buildPhases = (
|
||||
22F846B318F437B900982BA7 /* Sources */,
|
||||
22F846B618F437B900982BA7 /* Frameworks */,
|
||||
22F846B818F437B900982BA7 /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
22F846B118F437B900982BA7 /* PBXTargetDependency */,
|
||||
);
|
||||
name = lockut;
|
||||
productName = lockcov;
|
||||
productReference = 22F846BD18F437B900982BA7 /* lockut */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
22FA176416E8D6FC0098B23F /* amcssth */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 22FA177116E8D6FC0098B23F /* Build configuration list for PBXNativeTarget "amcssth" */;
|
||||
|
|
@ -3284,6 +3348,7 @@
|
|||
2231BB4C18CA97D8002D6322 /* locbwcss */,
|
||||
31D60026156D3D3E00337B26 /* lockcov */,
|
||||
2231BB5A18CA97DC002D6322 /* locusss */,
|
||||
22F846B018F437B900982BA7 /* lockut */,
|
||||
3114A58F156E913C001E0AA3 /* locv */,
|
||||
3114A694156E971B001E0AA3 /* messtest */,
|
||||
31EEAC64156AB52600714D05 /* mpmss */,
|
||||
|
|
@ -3363,6 +3428,7 @@
|
|||
2291A5B3175CAB2F001D4920 /* fmthe.c in Sources */,
|
||||
2291A5B4175CAB2F001D4920 /* fmtno.c in Sources */,
|
||||
2291A5B5175CAB2F001D4920 /* testlib.c in Sources */,
|
||||
22561A9918F4266600372C66 /* testthrix.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
@ -3408,6 +3474,16 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
22F846B318F437B900982BA7 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
22F846BE18F437D700982BA7 /* lockut.c in Sources */,
|
||||
22F846B518F437B900982BA7 /* testlib.c in Sources */,
|
||||
22F846BF18F437E000982BA7 /* testthrix.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
22FA176716E8D6FC0098B23F /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
|
@ -3418,6 +3494,7 @@
|
|||
22FA176B16E8D6FC0098B23F /* fmthe.c in Sources */,
|
||||
22FA176C16E8D6FC0098B23F /* fmtno.c in Sources */,
|
||||
22FA176D16E8D6FC0098B23F /* testlib.c in Sources */,
|
||||
22561A9818F4265D00372C66 /* testthrix.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
@ -3694,6 +3771,7 @@
|
|||
318DA8D31892B27E0089718C /* testlib.c in Sources */,
|
||||
6313D47318A4028E00EB03EF /* djbench.c in Sources */,
|
||||
318DA8D21892B13B0089718C /* getoptl.c in Sources */,
|
||||
22561A9A18F426BB00372C66 /* testthrix.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
@ -3801,6 +3879,7 @@
|
|||
6313D47518A40C6300EB03EF /* fmtdytst.c in Sources */,
|
||||
6313D47618A40C7B00EB03EF /* fmtdy.c in Sources */,
|
||||
6313D46A18A400B200EB03EF /* getoptl.c in Sources */,
|
||||
22561A9B18F426F300372C66 /* testthrix.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
@ -3842,6 +3921,11 @@
|
|||
target = 2D604B9B16514B1A003AAF46 /* mpseventtxt */;
|
||||
targetProxy = 2275798816C5422900B662B0 /* PBXContainerItemProxy */;
|
||||
};
|
||||
2286E4C918F4389E004111E2 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 22F846B018F437B900982BA7 /* lockut */;
|
||||
targetProxy = 2286E4C818F4389E004111E2 /* PBXContainerItemProxy */;
|
||||
};
|
||||
2291A5AD175CAB2F001D4920 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 31EEABFA156AAF9D00714D05 /* mps */;
|
||||
|
|
@ -3907,6 +3991,11 @@
|
|||
target = 3104AFF1156D37A0000A585A /* all */;
|
||||
targetProxy = 22CDE92D16E9EB9300366D0A /* PBXContainerItemProxy */;
|
||||
};
|
||||
22F846B118F437B900982BA7 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 31EEABFA156AAF9D00714D05 /* mps */;
|
||||
targetProxy = 22F846B218F437B900982BA7 /* PBXContainerItemProxy */;
|
||||
};
|
||||
22FA176516E8D6FC0098B23F /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 31EEABFA156AAF9D00714D05 /* mps */;
|
||||
|
|
@ -4410,6 +4499,27 @@
|
|||
};
|
||||
name = Release;
|
||||
};
|
||||
22F846BA18F437B900982BA7 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = lockut;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
22F846BB18F437B900982BA7 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = lockut;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
22F846BC18F437B900982BA7 /* RASH */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = lockut;
|
||||
};
|
||||
name = RASH;
|
||||
};
|
||||
22FA177216E8D6FC0098B23F /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
|
|
@ -5547,6 +5657,16 @@
|
|||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
22F846B918F437B900982BA7 /* Build configuration list for PBXNativeTarget "lockut" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
22F846BA18F437B900982BA7 /* Debug */,
|
||||
22F846BB18F437B900982BA7 /* Release */,
|
||||
22F846BC18F437B900982BA7 /* RASH */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
22FA177116E8D6FC0098B23F /* Build configuration list for PBXNativeTarget "amcssth" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
|
|
|||
|
|
@ -15,13 +15,8 @@
|
|||
#include "fmtdytst.h"
|
||||
#include "mps.h"
|
||||
#include "mpstd.h"
|
||||
#ifdef MPS_OS_W3
|
||||
# include "mpsw3.h"
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <stdio.h> /* printf */
|
||||
|
||||
|
||||
#define exactRootsCOUNT 49
|
||||
|
|
|
|||
|
|
@ -11,11 +11,15 @@
|
|||
#ifndef mpswin_h
|
||||
#define mpswin_h
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
/* Speed up the build process by excluding parts of windows.h that we
|
||||
* don't use. See <http://support.microsoft.com/kb/166474> */
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#else
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#endif /* mpswin_h */
|
||||
|
||||
|
|
|
|||
|
|
@ -30,26 +30,36 @@ static Count nailboardLevels(Count nails)
|
|||
}
|
||||
|
||||
|
||||
/* nailboardNails -- return the total number of nails in the board */
|
||||
|
||||
static Count nailboardNails(Nailboard board)
|
||||
{
|
||||
return RangeSize(&board->range) >> board->alignShift;
|
||||
}
|
||||
|
||||
|
||||
/* nailboardLevelBits -- return the number of bits in the bit table
|
||||
* for the given level.
|
||||
*/
|
||||
|
||||
static Count nailboardLevelBits(Nailboard board, Index level)
|
||||
static Count nailboardLevelBits(Count nails, Index level)
|
||||
{
|
||||
/* Use <= rather than < because of .check.levels. */
|
||||
AVER(level <= board->levels);
|
||||
return RangeSize(&board->range) >> (board->alignShift + level * LEVEL_SHIFT);
|
||||
Shift shift = (Shift)(level * LEVEL_SHIFT);
|
||||
return (nails + ((Count)1 << shift) - 1) >> shift;
|
||||
}
|
||||
|
||||
Bool NailboardCheck(Nailboard board)
|
||||
{
|
||||
Index i;
|
||||
Count nails;
|
||||
CHECKS(Nailboard, board);
|
||||
CHECKL(RangeCheck(&board->range));
|
||||
CHECKL(0 < board->levels);
|
||||
CHECKL(board->levels == nailboardLevels(nailboardLevelBits(board, 0)));
|
||||
CHECKL(nailboardLevelBits(board, board->levels - 1) != 0);
|
||||
CHECKL(nailboardLevelBits(board, board->levels) == 0); /* .check.levels */
|
||||
nails = nailboardNails(board);
|
||||
CHECKL(board->levels == nailboardLevels(nails));
|
||||
CHECKL(nails == nailboardLevelBits(nails, 0));
|
||||
CHECKL(nailboardLevelBits(nails, board->levels - 1) != 0);
|
||||
CHECKL(nailboardLevelBits(nails, board->levels) == 1);
|
||||
CHECKL(BoolCheck(board->newNails));
|
||||
for (i = 0; i < board->levels; ++i) {
|
||||
CHECKL(board->level[i] != NULL);
|
||||
|
|
@ -80,8 +90,7 @@ static Size nailboardSize(Count nails, Count levels)
|
|||
Size size;
|
||||
size = nailboardStructSize(levels);
|
||||
for (i = 0; i < levels; ++i) {
|
||||
size += BTSize(nails);
|
||||
nails >>= LEVEL_SHIFT;
|
||||
size += BTSize(nailboardLevelBits(nails, i));
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
|
@ -130,11 +139,11 @@ Res NailboardCreate(Nailboard *boardReturn, Arena arena, Align alignment,
|
|||
|
||||
p = PointerAdd(p, nailboardStructSize(levels));
|
||||
for (i = 0; i < levels; ++i) {
|
||||
AVER(nails > 0);
|
||||
Count levelBits = nailboardLevelBits(nails, i);
|
||||
AVER(levelBits > 0);
|
||||
board->level[i] = p;
|
||||
BTResRange(board->level[i], 0, nails);
|
||||
p = PointerAdd(p, BTSize(nails));
|
||||
nails >>= LEVEL_SHIFT;
|
||||
BTResRange(board->level[i], 0, levelBits);
|
||||
p = PointerAdd(p, BTSize(levelBits));
|
||||
}
|
||||
|
||||
board->sig = NailboardSig;
|
||||
|
|
@ -154,7 +163,7 @@ void NailboardDestroy(Nailboard board, Arena arena)
|
|||
AVERT(Nailboard, board);
|
||||
AVERT(Arena, arena);
|
||||
|
||||
nails = nailboardLevelBits(board, 0);
|
||||
nails = nailboardNails(board);
|
||||
size = nailboardSize(nails, board->levels);
|
||||
|
||||
board->sig = SigInvalid;
|
||||
|
|
@ -191,8 +200,10 @@ Bool (NailboardNewNails)(Nailboard board)
|
|||
|
||||
static Index nailboardIndex(Nailboard board, Index level, Addr addr)
|
||||
{
|
||||
return AddrOffset(RangeBase(&board->range), addr)
|
||||
Index i = AddrOffset(RangeBase(&board->range), addr)
|
||||
>> (board->alignShift + level * LEVEL_SHIFT);
|
||||
AVER_CRITICAL(i < nailboardLevelBits(nailboardNails(board), level));
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -414,7 +425,7 @@ Res NailboardDescribe(Nailboard board, mps_lib_FILE *stream)
|
|||
return res;
|
||||
|
||||
for(i = 0; i < board->levels; ++i) {
|
||||
Count levelNails = nailboardLevelBits(board, i);
|
||||
Count levelNails = nailboardLevelBits(nailboardNails(board), i);
|
||||
Count resetNails = BTCountResRange(board->level[i], 0, levelNails);
|
||||
res = WriteF(stream, " Level $U ($U bits, $U set): ",
|
||||
i, levelNails, levelNails - resetNails, NULL);
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
#include "bt.h"
|
||||
#include "nailboard.h"
|
||||
|
||||
#include <stdio.h> /* printf */
|
||||
|
||||
|
||||
static void test(mps_arena_t arena)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ static Nailboard amcSegNailboard(Seg seg);
|
|||
static Bool AMCCheck(AMC amc);
|
||||
static Res AMCFix(Pool pool, ScanState ss, Seg seg, Ref *refIO);
|
||||
static Res AMCHeaderFix(Pool pool, ScanState ss, Seg seg, Ref *refIO);
|
||||
extern PoolClass AMCPoolClassGet(void);
|
||||
extern PoolClass AMCZPoolClassGet(void);
|
||||
extern BufferClass amcBufClassGet(void);
|
||||
extern SegClass amcSegClassGet(void);
|
||||
|
||||
|
|
@ -2164,7 +2164,7 @@ static void amcWalkAll(Pool pool, FormattedObjectsStepMethod f,
|
|||
Arena arena;
|
||||
Ring ring, next, node;
|
||||
|
||||
AVER(IsSubclassPoly(pool->class, AMCPoolClassGet()));
|
||||
AVER(IsSubclassPoly(pool->class, AMCZPoolClassGet()));
|
||||
|
||||
arena = PoolArena(pool);
|
||||
ring = PoolSegRing(pool);
|
||||
|
|
@ -2449,7 +2449,7 @@ static Bool AMCCheck(AMC amc)
|
|||
{
|
||||
CHECKS(AMC, amc);
|
||||
CHECKD(Pool, &amc->poolStruct);
|
||||
CHECKL(IsSubclassPoly(amc->poolStruct.class, EnsureAMCPoolClass()));
|
||||
CHECKL(IsSubclassPoly(amc->poolStruct.class, AMCZPoolClassGet()));
|
||||
CHECKL(RankSetCheck(amc->rankSet));
|
||||
CHECKD_NOSIG(Ring, &amc->genRing);
|
||||
CHECKL(BoolCheck(amc->gensBooted));
|
||||
|
|
|
|||
|
|
@ -74,6 +74,11 @@ Bool AMSSegCheck(AMSSeg amsseg)
|
|||
CHECKD_NOSIG(BT, amsseg->nongreyTable);
|
||||
CHECKD_NOSIG(BT, amsseg->nonwhiteTable);
|
||||
|
||||
/* If tables are shared, they mustn't both be in use. */
|
||||
CHECKL(!(amsseg->ams->shareAllocTable
|
||||
&& amsseg->allocTableInUse
|
||||
&& amsseg->colourTablesInUse));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -167,6 +172,10 @@ static Res amsCreateTables(AMS ams, BT *allocReturn,
|
|||
goto failWhite;
|
||||
}
|
||||
|
||||
/* Invalidate the colour tables in checking varieties. */
|
||||
AVER((BTResRange(nongreyTable, 0, length), TRUE));
|
||||
AVER((BTSetRange(nonwhiteTable, 0, length), TRUE));
|
||||
|
||||
*allocReturn = allocTable;
|
||||
*nongreyReturn = nongreyTable;
|
||||
*nonwhiteReturn = nonwhiteTable;
|
||||
|
|
@ -1023,7 +1032,8 @@ static void AMSBufferEmpty(Pool pool, Buffer buffer, Addr init, Addr limit)
|
|||
AVER(limitIndex <= amsseg->firstFree);
|
||||
if (limitIndex == amsseg->firstFree) /* is it at the end? */ {
|
||||
amsseg->firstFree = initIndex;
|
||||
} else { /* start using allocTable */
|
||||
} else if (!ams->shareAllocTable || !amsseg->colourTablesInUse) {
|
||||
/* start using allocTable */
|
||||
amsseg->allocTableInUse = TRUE;
|
||||
BTSetRange(amsseg->allocTable, 0, amsseg->firstFree);
|
||||
if (amsseg->firstFree < amsseg->grains)
|
||||
|
|
@ -1415,16 +1425,20 @@ static Res AMSFix(Pool pool, ScanState ss, Seg seg, Ref *refIO)
|
|||
/* doing that here (this can be called from RootScan, during flip). */
|
||||
|
||||
clientRef = *refIO;
|
||||
AVER_CRITICAL(SegBase(seg) <= clientRef);
|
||||
AVER_CRITICAL(clientRef < SegLimit(seg)); /* see .ref-limit */
|
||||
base = AddrSub((Addr)clientRef, format->headerSize);
|
||||
/* can get an ambiguous reference too close to the base of the
|
||||
* segment, so when we subtract the header we are not in the
|
||||
* segment any longer. This isn't a real reference,
|
||||
* so we can just skip it. */
|
||||
if (base < SegBase(seg)) {
|
||||
return ResOK;
|
||||
AVER_CRITICAL(ss->rank == RankAMBIG);
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
i = AMS_ADDR_INDEX(seg, base);
|
||||
AVER_CRITICAL(i < amsseg->grains);
|
||||
AVER_CRITICAL(!AMS_IS_INVALID_COLOUR(seg, i));
|
||||
|
||||
ss->wasMarked = TRUE;
|
||||
|
|
@ -1584,12 +1598,13 @@ static void AMSReclaim(Pool pool, Trace trace, Seg seg)
|
|||
/* preservedInPlaceCount is updated on fix */
|
||||
trace->preservedInPlaceSize += (grains - amsseg->free) << ams->grainShift;
|
||||
|
||||
/* Ensure consistency of segment even if are just about to free it */
|
||||
amsseg->colourTablesInUse = FALSE;
|
||||
SegSetWhite(seg, TraceSetDel(SegWhite(seg), trace));
|
||||
|
||||
if (amsseg->free == grains && SegBuffer(seg) == NULL) {
|
||||
/* No survivors */
|
||||
SegFree(seg);
|
||||
} else {
|
||||
amsseg->colourTablesInUse = FALSE;
|
||||
SegSetWhite(seg, TraceSetDel(SegWhite(seg), trace));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -305,10 +305,14 @@ DEFINE_SEG_CLASS(AWLSegClass, class)
|
|||
* it's possible to tweak them in a debugger.
|
||||
*/
|
||||
|
||||
extern Count AWLSegSALimit;
|
||||
Count AWLSegSALimit = AWL_SEG_SA_LIMIT;
|
||||
extern Bool AWLHaveSegSALimit;
|
||||
Bool AWLHaveSegSALimit = AWL_HAVE_SEG_SA_LIMIT;
|
||||
|
||||
extern Count AWLTotalSALimit;
|
||||
Count AWLTotalSALimit = AWL_TOTAL_SA_LIMIT;
|
||||
extern Bool AWLHaveTotalSALimit;
|
||||
Bool AWLHaveTotalSALimit = AWL_HAVE_TOTAL_SA_LIMIT;
|
||||
|
||||
|
||||
|
|
@ -558,6 +562,7 @@ static Res AWLInit(Pool pool, ArgList args)
|
|||
|
||||
AVERT(Format, format);
|
||||
pool->format = format;
|
||||
pool->alignment = format->alignment;
|
||||
|
||||
AVER(FUNCHECK(findDependent));
|
||||
awl->findDependent = findDependent;
|
||||
|
|
@ -570,7 +575,7 @@ static Res AWLInit(Pool pool, ArgList args)
|
|||
if (res != ResOK)
|
||||
goto failGenInit;
|
||||
|
||||
awl->alignShift = SizeLog2(pool->alignment);
|
||||
awl->alignShift = SizeLog2(PoolAlignment(pool));
|
||||
awl->size = (Size)0;
|
||||
|
||||
awl->succAccesses = 0;
|
||||
|
|
@ -937,7 +942,7 @@ static Res awlScanSinglePass(Bool *anyScannedReturn,
|
|||
|
||||
i = awlIndexOfAddr(base, awl, p);
|
||||
if (!BTGet(awlseg->alloc, i)) {
|
||||
p = AddrAdd(p, pool->alignment);
|
||||
p = AddrAdd(p, PoolAlignment(pool));
|
||||
continue;
|
||||
}
|
||||
hp = AddrAdd(p, format->headerSize);
|
||||
|
|
@ -954,7 +959,8 @@ static Res awlScanSinglePass(Bool *anyScannedReturn,
|
|||
}
|
||||
objectLimit = AddrSub(objectLimit, format->headerSize);
|
||||
AVER(p < objectLimit);
|
||||
p = AddrAlignUp(objectLimit, pool->alignment);
|
||||
AVER(AddrIsAligned(objectLimit, PoolAlignment(pool)));
|
||||
p = objectLimit;
|
||||
}
|
||||
AVER(p == limit);
|
||||
|
||||
|
|
@ -1051,7 +1057,7 @@ static Res AWLFix(Pool pool, ScanState ss, Seg seg, Ref *refIO)
|
|||
switch(ss->rank) {
|
||||
case RankAMBIG:
|
||||
/* not a real pointer if not aligned or not allocated */
|
||||
if (!AddrIsAligned(base, pool->alignment) || !BTGet(awlseg->alloc, i))
|
||||
if (!AddrIsAligned(base, sizeof(void *)) || !BTGet(awlseg->alloc, i))
|
||||
return ResOK;
|
||||
/* falls through */
|
||||
case RankEXACT:
|
||||
|
|
@ -1125,7 +1131,7 @@ static void AWLReclaim(Pool pool, Trace trace, Seg seg)
|
|||
}
|
||||
q = format->skip(AddrAdd(p, format->headerSize));
|
||||
q = AddrSub(q, format->headerSize);
|
||||
q = AddrAlignUp(q, pool->alignment);
|
||||
AVER(AddrIsAligned(q, PoolAlignment(pool)));
|
||||
j = awlIndexOfAddr(base, awl, q);
|
||||
AVER(j <= awlseg->grains);
|
||||
if(BTGet(awlseg->mark, i)) {
|
||||
|
|
@ -1243,13 +1249,13 @@ static void AWLWalk(Pool pool, Seg seg, FormattedObjectsStepMethod f,
|
|||
i = awlIndexOfAddr(base, awl, object);
|
||||
if (!BTGet(awlseg->alloc, i)) {
|
||||
/* This grain is free */
|
||||
object = AddrAdd(object, pool->alignment);
|
||||
object = AddrAdd(object, PoolAlignment(pool));
|
||||
continue;
|
||||
}
|
||||
object = AddrAdd(object, format->headerSize);
|
||||
next = format->skip(object);
|
||||
next = AddrSub(next, format->headerSize);
|
||||
next = AddrAlignUp(next, pool->alignment);
|
||||
AVER(AddrIsAligned(next, PoolAlignment(pool)));
|
||||
if (BTGet(awlseg->mark, i) && BTGet(awlseg->scanned, i))
|
||||
(*f)(object, pool->format, pool, p, s);
|
||||
object = next;
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ static Res MFSInit(Pool pool, ArgList args)
|
|||
mfs->sig = MFSSig;
|
||||
|
||||
AVERT(MFS, mfs);
|
||||
EVENT5(PoolInitMFS, pool, arena, extendBy, extendSelf, unitSize);
|
||||
EVENT5(PoolInitMFS, pool, arena, extendBy, BOOL(extendSelf), unitSize);
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,41 +1,16 @@
|
|||
/* poolmv.h: MANUAL VARIABLE POOL
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* .purpose: This is the interface to the manual-variable pool class.
|
||||
*
|
||||
* .mv: Manual-variable pools manage variably-sized blocks of memory in a
|
||||
* flexible manner. They have higher overheads than a fixed-size pool.
|
||||
* .mv: Manual-variable pools manage variably-sized blocks of memory
|
||||
* in a flexible manner. They have higher overheads than a fixed-size
|
||||
* pool.
|
||||
*
|
||||
* .init: This class adds the following arguments to PoolCreate:
|
||||
*
|
||||
* Size extendBy
|
||||
*
|
||||
* extendBy is the default number of bytes reserved by the pool at a time.
|
||||
* A large size will make allocation cheaper but have a higher resource
|
||||
* overhead. A typical value might be 65536. See note 2.
|
||||
*
|
||||
* Size avgSize
|
||||
*
|
||||
* avgSize is an estimate of the average size of an allocation, and is used
|
||||
* to choose the size of internal tables. An accurate estimate will
|
||||
* improve the efficiency of the pool. A low estimate will make the pool
|
||||
* less space efficient. A high estimate will make the pool less time
|
||||
* efficient. A typical value might be 32. avgSize must not be less than
|
||||
* extendBy.
|
||||
*
|
||||
* Size maxSize
|
||||
*
|
||||
* maxSize is an estimate of the maximum total size that the pool will
|
||||
* reach. Setting this parameter does not actually contrain the pool, but
|
||||
* an accurate estimate will improve the efficiency of the pool. maxSize
|
||||
* must not be less than extendBy.
|
||||
*
|
||||
* Notes
|
||||
* 2. The documentation could suggest a segment size according to the
|
||||
* distribution of allocation size requests. richard 1994-11-08
|
||||
* .design: See <design/poolmv/>
|
||||
*/
|
||||
|
||||
#ifndef poolmv_h
|
||||
|
|
@ -59,7 +34,7 @@ extern Bool MVCheck(MV mv);
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -81,7 +81,6 @@ typedef struct MVTStruct
|
|||
Bool abqOverflow; /* ABQ dropped some candidates */
|
||||
/* <design/poolmvt/#arch.ap.no-fit>.* */
|
||||
Bool splinter; /* Saved splinter */
|
||||
Seg splinterSeg; /* Saved splinter seg */
|
||||
Addr splinterBase; /* Saved splinter base */
|
||||
Addr splinterLimit; /* Saved splinter size */
|
||||
|
||||
|
|
@ -136,7 +135,7 @@ typedef struct MVTStruct
|
|||
|
||||
DEFINE_POOL_CLASS(MVTPoolClass, this)
|
||||
{
|
||||
INHERIT_CLASS(this, AbstractSegBufPoolClass);
|
||||
INHERIT_CLASS(this, AbstractBufferPoolClass);
|
||||
this->name = "MVT";
|
||||
this->size = sizeof(MVTStruct);
|
||||
this->offset = offsetof(MVTStruct, poolStruct);
|
||||
|
|
@ -311,7 +310,6 @@ static Res MVTInit(Pool pool, ArgList args)
|
|||
mvt->maxSize = maxSize;
|
||||
mvt->fragLimit = fragLimit;
|
||||
mvt->splinter = FALSE;
|
||||
mvt->splinterSeg = NULL;
|
||||
mvt->splinterBase = (Addr)0;
|
||||
mvt->splinterLimit = (Addr)0;
|
||||
|
||||
|
|
@ -400,9 +398,7 @@ static Bool MVTCheck(MVT mvt)
|
|||
if (mvt->splinter) {
|
||||
CHECKL(AddrOffset(mvt->splinterBase, mvt->splinterLimit) >=
|
||||
mvt->minSize);
|
||||
CHECKD(Seg, mvt->splinterSeg);
|
||||
CHECKL(mvt->splinterBase >= SegBase(mvt->splinterSeg));
|
||||
CHECKL(mvt->splinterLimit <= SegLimit(mvt->splinterSeg));
|
||||
CHECKL(mvt->splinterBase < mvt->splinterLimit);
|
||||
}
|
||||
CHECKL(mvt->size == mvt->allocated + mvt->available +
|
||||
mvt->unavailable);
|
||||
|
|
@ -937,7 +933,6 @@ static void MVTBufferEmpty(Pool pool, Buffer buffer,
|
|||
}
|
||||
|
||||
mvt->splinter = TRUE;
|
||||
mvt->splinterSeg = BufferSeg(buffer);
|
||||
mvt->splinterBase = base;
|
||||
mvt->splinterLimit = limit;
|
||||
}
|
||||
|
|
@ -984,8 +979,6 @@ static void MVTFree(Pool pool, Addr base, Size size)
|
|||
AVER(mvt->size == mvt->allocated + mvt->available +
|
||||
mvt->unavailable);
|
||||
METER_ACC(mvt->exceptionReturns, SegSize(seg));
|
||||
if (SegBuffer(seg) != NULL)
|
||||
BufferDetach(SegBuffer(seg), MVT2Pool(mvt));
|
||||
MVTSegFree(mvt, seg);
|
||||
return;
|
||||
}
|
||||
|
|
@ -1017,7 +1010,6 @@ static Res MVTDescribe(Pool pool, mps_lib_FILE *stream)
|
|||
" availLimit: $U \n", (WriteFU)mvt->availLimit,
|
||||
" abqOverflow: $S \n", mvt->abqOverflow?"TRUE":"FALSE",
|
||||
" splinter: $S \n", mvt->splinter?"TRUE":"FALSE",
|
||||
" splinterSeg: $P \n", (WriteFP)mvt->splinterSeg,
|
||||
" splinterBase: $A \n", (WriteFA)mvt->splinterBase,
|
||||
" splinterLimit: $A \n", (WriteFU)mvt->splinterLimit,
|
||||
" size: $U \n", (WriteFU)mvt->size,
|
||||
|
|
@ -1036,68 +1028,37 @@ static Res MVTDescribe(Pool pool, mps_lib_FILE *stream)
|
|||
res = ABQDescribe(MVTABQ(mvt), (ABQDescribeElement)RangeDescribe, stream);
|
||||
if(res != ResOK) return res;
|
||||
|
||||
res = METER_WRITE(mvt->segAllocs, stream);
|
||||
if (res != ResOK) return res;
|
||||
res = METER_WRITE(mvt->segFrees, stream);
|
||||
if (res != ResOK) return res;
|
||||
res = METER_WRITE(mvt->bufferFills, stream);
|
||||
if (res != ResOK) return res;
|
||||
res = METER_WRITE(mvt->bufferEmpties, stream);
|
||||
if (res != ResOK) return res;
|
||||
res = METER_WRITE(mvt->poolFrees, stream);
|
||||
if (res != ResOK) return res;
|
||||
res = METER_WRITE(mvt->poolSize, stream);
|
||||
if (res != ResOK) return res;
|
||||
res = METER_WRITE(mvt->poolAllocated, stream);
|
||||
if (res != ResOK) return res;
|
||||
res = METER_WRITE(mvt->poolAvailable, stream);
|
||||
if (res != ResOK) return res;
|
||||
res = METER_WRITE(mvt->poolUnavailable, stream);
|
||||
if (res != ResOK) return res;
|
||||
res = METER_WRITE(mvt->poolUtilization, stream);
|
||||
if (res != ResOK) return res;
|
||||
res = METER_WRITE(mvt->finds, stream);
|
||||
if (res != ResOK) return res;
|
||||
res = METER_WRITE(mvt->overflows, stream);
|
||||
if (res != ResOK) return res;
|
||||
res = METER_WRITE(mvt->underflows, stream);
|
||||
if (res != ResOK) return res;
|
||||
res = METER_WRITE(mvt->refills, stream);
|
||||
if (res != ResOK) return res;
|
||||
res = METER_WRITE(mvt->refillPushes, stream);
|
||||
if (res != ResOK) return res;
|
||||
res = METER_WRITE(mvt->returns, stream);
|
||||
if (res != ResOK) return res;
|
||||
res = METER_WRITE(mvt->perfectFits, stream);
|
||||
if (res != ResOK) return res;
|
||||
res = METER_WRITE(mvt->firstFits, stream);
|
||||
if (res != ResOK) return res;
|
||||
res = METER_WRITE(mvt->secondFits, stream);
|
||||
if (res != ResOK) return res;
|
||||
res = METER_WRITE(mvt->failures, stream);
|
||||
if (res != ResOK) return res;
|
||||
res = METER_WRITE(mvt->emergencyContingencies, stream);
|
||||
if (res != ResOK) return res;
|
||||
res = METER_WRITE(mvt->fragLimitContingencies, stream);
|
||||
if (res != ResOK) return res;
|
||||
res = METER_WRITE(mvt->contingencySearches, stream);
|
||||
if (res != ResOK) return res;
|
||||
res = METER_WRITE(mvt->contingencyHardSearches, stream);
|
||||
if (res != ResOK) return res;
|
||||
res = METER_WRITE(mvt->splinters, stream);
|
||||
if (res != ResOK) return res;
|
||||
res = METER_WRITE(mvt->splintersUsed, stream);
|
||||
if (res != ResOK) return res;
|
||||
res = METER_WRITE(mvt->splintersDropped, stream);
|
||||
if (res != ResOK) return res;
|
||||
res = METER_WRITE(mvt->sawdust, stream);
|
||||
if (res != ResOK) return res;
|
||||
res = METER_WRITE(mvt->exceptions, stream);
|
||||
if (res != ResOK) return res;
|
||||
res = METER_WRITE(mvt->exceptionSplinters, stream);
|
||||
if (res != ResOK) return res;
|
||||
res = METER_WRITE(mvt->exceptionReturns, stream);
|
||||
if (res != ResOK) return res;
|
||||
METER_WRITE(mvt->segAllocs, stream);
|
||||
METER_WRITE(mvt->segFrees, stream);
|
||||
METER_WRITE(mvt->bufferFills, stream);
|
||||
METER_WRITE(mvt->bufferEmpties, stream);
|
||||
METER_WRITE(mvt->poolFrees, stream);
|
||||
METER_WRITE(mvt->poolSize, stream);
|
||||
METER_WRITE(mvt->poolAllocated, stream);
|
||||
METER_WRITE(mvt->poolAvailable, stream);
|
||||
METER_WRITE(mvt->poolUnavailable, stream);
|
||||
METER_WRITE(mvt->poolUtilization, stream);
|
||||
METER_WRITE(mvt->finds, stream);
|
||||
METER_WRITE(mvt->overflows, stream);
|
||||
METER_WRITE(mvt->underflows, stream);
|
||||
METER_WRITE(mvt->refills, stream);
|
||||
METER_WRITE(mvt->refillPushes, stream);
|
||||
METER_WRITE(mvt->returns, stream);
|
||||
METER_WRITE(mvt->perfectFits, stream);
|
||||
METER_WRITE(mvt->firstFits, stream);
|
||||
METER_WRITE(mvt->secondFits, stream);
|
||||
METER_WRITE(mvt->failures, stream);
|
||||
METER_WRITE(mvt->emergencyContingencies, stream);
|
||||
METER_WRITE(mvt->fragLimitContingencies, stream);
|
||||
METER_WRITE(mvt->contingencySearches, stream);
|
||||
METER_WRITE(mvt->contingencyHardSearches, stream);
|
||||
METER_WRITE(mvt->splinters, stream);
|
||||
METER_WRITE(mvt->splintersUsed, stream);
|
||||
METER_WRITE(mvt->splintersDropped, stream);
|
||||
METER_WRITE(mvt->sawdust, stream);
|
||||
METER_WRITE(mvt->exceptions, stream);
|
||||
METER_WRITE(mvt->exceptionSplinters, stream);
|
||||
METER_WRITE(mvt->exceptionReturns, stream);
|
||||
|
||||
res = WriteF(stream, "}\n", NULL);
|
||||
return res;
|
||||
|
|
@ -1175,7 +1136,7 @@ static Res MVTSegAlloc(Seg *segReturn, MVT mvt, Size size,
|
|||
{
|
||||
/* Can't use plain old SegClass here because we need to call
|
||||
* SegBuffer() in MVTFree(). */
|
||||
Res res = SegAlloc(segReturn, GCSegClassGet(),
|
||||
Res res = SegAlloc(segReturn, SegClassGet(),
|
||||
SegPrefDefault(), size, MVT2Pool(mvt), withReservoirPermit,
|
||||
argsNone);
|
||||
|
||||
|
|
@ -1199,7 +1160,6 @@ static Res MVTSegAlloc(Seg *segReturn, MVT mvt, Size size,
|
|||
*/
|
||||
static void MVTSegFree(MVT mvt, Seg seg)
|
||||
{
|
||||
Buffer buffer;
|
||||
Size size;
|
||||
|
||||
size = SegSize(seg);
|
||||
|
|
@ -1209,16 +1169,6 @@ static void MVTSegFree(MVT mvt, Seg seg)
|
|||
mvt->size -= size;
|
||||
mvt->availLimit = mvt->size * mvt->fragLimit / 100;
|
||||
AVER(mvt->size == mvt->allocated + mvt->available + mvt->unavailable);
|
||||
|
||||
/* If the client program allocates the exactly the entire buffer then
|
||||
frees the allocated memory then we'll try to free the segment with
|
||||
the buffer still attached. It's safe, but we must detach the buffer
|
||||
first. See job003520 and job003672. */
|
||||
buffer = SegBuffer(seg);
|
||||
if (buffer != NULL) {
|
||||
AVER(BufferAP(buffer)->init == SegLimit(seg));
|
||||
BufferDetach(buffer, MVT2Pool(mvt));
|
||||
}
|
||||
|
||||
SegFree(seg);
|
||||
METER_ACC(mvt->segFrees, size);
|
||||
|
|
|
|||
|
|
@ -539,7 +539,7 @@ static Res MVFFInit(Pool pool, ArgList args)
|
|||
mvff->sig = MVFFSig;
|
||||
AVERT(MVFF, mvff);
|
||||
EVENT8(PoolInitMVFF, pool, arena, extendBy, avgSize, align,
|
||||
slotHigh, arenaHigh, firstFit);
|
||||
BOOL(slotHigh), BOOL(arenaHigh), BOOL(firstFit));
|
||||
return ResOK;
|
||||
|
||||
failFailoverInit:
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@
|
|||
#include "testlib.h"
|
||||
#include "mpslib.h"
|
||||
|
||||
#include <stdio.h> /* printf */
|
||||
|
||||
|
||||
static void testit(ArenaClass class, ArgList args)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -36,27 +36,34 @@ SRCID(prmci3li, "$Id$");
|
|||
|
||||
MRef Prmci3AddressHoldingReg(MutatorFaultContext mfc, unsigned int regnum)
|
||||
{
|
||||
MRef gregs;
|
||||
|
||||
AVER(mfc != NULL);
|
||||
AVER(NONNEGATIVE(regnum));
|
||||
AVER(regnum <= 7);
|
||||
AVER(mfc->ucontext != NULL);
|
||||
|
||||
/* TODO: The current arrangement of the fix operation (taking a Ref *)
|
||||
forces us to pun these registers (actually `int` on LII3GC). We can
|
||||
suppress the warning by casting through `void *` and this might make
|
||||
it safe, but does it really? RB 2012-09-10 */
|
||||
AVER(sizeof(void *) == sizeof(*mfc->ucontext->uc_mcontext.gregs));
|
||||
gregs = (void *)mfc->ucontext->uc_mcontext.gregs;
|
||||
|
||||
/* .source.i486 */
|
||||
/* .assume.regref */
|
||||
/* The register numbers (REG_EAX etc.) are defined in <ucontext.h>
|
||||
but only if _GNU_SOURCE is defined: see .feature.li in
|
||||
config.h. */
|
||||
/* TODO: The current arrangement of the fix operation (taking a Ref *)
|
||||
forces us to pun these registers (actually `int` on LII3GC). We can
|
||||
suppress the warning my casting through `char *` and this might make
|
||||
it safe, but does it really? RB 2012-09-10 */
|
||||
switch (regnum) {
|
||||
case 0: return (MRef)((char *)&mfc->ucontext->uc_mcontext.gregs[REG_EAX]);
|
||||
case 1: return (MRef)((char *)&mfc->ucontext->uc_mcontext.gregs[REG_ECX]);
|
||||
case 2: return (MRef)((char *)&mfc->ucontext->uc_mcontext.gregs[REG_EDX]);
|
||||
case 3: return (MRef)((char *)&mfc->ucontext->uc_mcontext.gregs[REG_EBX]);
|
||||
case 4: return (MRef)((char *)&mfc->ucontext->uc_mcontext.gregs[REG_ESP]);
|
||||
case 5: return (MRef)((char *)&mfc->ucontext->uc_mcontext.gregs[REG_EBP]);
|
||||
case 6: return (MRef)((char *)&mfc->ucontext->uc_mcontext.gregs[REG_ESI]);
|
||||
case 7: return (MRef)((char *)&mfc->ucontext->uc_mcontext.gregs[REG_EDI]);
|
||||
case 0: return &gregs[REG_EAX];
|
||||
case 1: return &gregs[REG_ECX];
|
||||
case 2: return &gregs[REG_EDX];
|
||||
case 3: return &gregs[REG_EBX];
|
||||
case 4: return &gregs[REG_ESP];
|
||||
case 5: return &gregs[REG_EBP];
|
||||
case 6: return &gregs[REG_ESI];
|
||||
case 7: return &gregs[REG_EDI];
|
||||
default:
|
||||
NOTREACHED;
|
||||
return NULL; /* Avoids compiler warning. */
|
||||
|
|
|
|||
|
|
@ -34,8 +34,13 @@ SRCID(prmci3li, "$Id$");
|
|||
|
||||
MRef Prmci3AddressHoldingReg(MutatorFaultContext mfc, unsigned int regnum)
|
||||
{
|
||||
THREAD_STATE_S *threadState;
|
||||
|
||||
AVER(mfc != NULL);
|
||||
AVER(NONNEGATIVE(regnum));
|
||||
AVER(regnum <= 7);
|
||||
AVER(mfc->threadState != NULL);
|
||||
threadState = mfc->threadState;
|
||||
|
||||
/* .source.i486 */
|
||||
/* .assume.regref */
|
||||
|
|
@ -44,17 +49,17 @@ MRef Prmci3AddressHoldingReg(MutatorFaultContext mfc, unsigned int regnum)
|
|||
config.h. */
|
||||
/* TODO: The current arrangement of the fix operation (taking a Ref *)
|
||||
forces us to pun these registers (actually `int` on LII3GC). We can
|
||||
suppress the warning my casting through `char *` and this might make
|
||||
suppress the warning by casting through `void *` and this might make
|
||||
it safe, but does it really? RB 2012-09-10 */
|
||||
switch (regnum) {
|
||||
case 0: return (MRef)((char *)&mfc->threadState->__eax);
|
||||
case 1: return (MRef)((char *)&mfc->threadState->__ecx);
|
||||
case 2: return (MRef)((char *)&mfc->threadState->__edx);
|
||||
case 3: return (MRef)((char *)&mfc->threadState->__ebx);
|
||||
case 4: return (MRef)((char *)&mfc->threadState->__esp);
|
||||
case 5: return (MRef)((char *)&mfc->threadState->__ebp);
|
||||
case 6: return (MRef)((char *)&mfc->threadState->__esi);
|
||||
case 7: return (MRef)((char *)&mfc->threadState->__edi);
|
||||
case 0: return (void *)&threadState->__eax;
|
||||
case 1: return (void *)&threadState->__ecx;
|
||||
case 2: return (void *)&threadState->__edx;
|
||||
case 3: return (void *)&threadState->__ebx;
|
||||
case 4: return (void *)&threadState->__esp;
|
||||
case 5: return (void *)&threadState->__ebp;
|
||||
case 6: return (void *)&threadState->__esi;
|
||||
case 7: return (void *)&threadState->__edi;
|
||||
default:
|
||||
NOTREACHED;
|
||||
return NULL; /* Avoids compiler warning. */
|
||||
|
|
|
|||
|
|
@ -33,12 +33,19 @@ SRCID(prmci6li, "$Id$");
|
|||
|
||||
MRef Prmci6AddressHoldingReg(MutatorFaultContext mfc, unsigned int regnum)
|
||||
{
|
||||
Word *gregs;
|
||||
MRef gregs;
|
||||
|
||||
AVER(mfc != NULL);
|
||||
AVER(NONNEGATIVE(regnum));
|
||||
AVER(regnum <= 15);
|
||||
AVER(mfc->ucontext != NULL);
|
||||
|
||||
gregs = (Word *)&mfc->ucontext->uc_mcontext.gregs;
|
||||
/* TODO: The current arrangement of the fix operation (taking a Ref *)
|
||||
forces us to pun these registers (actually `int` on LII6GC). We can
|
||||
suppress the warning by casting through `void *` and this might make
|
||||
it safe, but does it really? RB 2012-09-10 */
|
||||
AVER(sizeof(void *) == sizeof(*mfc->ucontext->uc_mcontext.gregs));
|
||||
gregs = (void *)mfc->ucontext->uc_mcontext.gregs;
|
||||
|
||||
/* .assume.regref */
|
||||
/* The register numbers (REG_RAX etc.) are defined in <ucontext.h>
|
||||
|
|
|
|||
|
|
@ -31,33 +31,38 @@ SRCID(prmci6li, "$Id$");
|
|||
|
||||
MRef Prmci6AddressHoldingReg(MutatorFaultContext mfc, unsigned int regnum)
|
||||
{
|
||||
THREAD_STATE_S *threadState;
|
||||
|
||||
AVER(mfc != NULL);
|
||||
AVER(NONNEGATIVE(regnum));
|
||||
AVER(regnum <= 15);
|
||||
AVER(mfc->threadState != NULL);
|
||||
threadState = mfc->threadState;
|
||||
|
||||
/* .assume.regref */
|
||||
/* The register numbers (REG_RAX etc.) are defined in <ucontext.h>
|
||||
but only if _XOPEN_SOURCE is defined: see .feature.xc in
|
||||
config.h. */
|
||||
/* MRef (a Word *) is not compatible with pointers to the register
|
||||
types (actually a __uint64_t). To avoid aliasing optimization
|
||||
problems, The registers are cast through (char *) */
|
||||
types (actually a __uint64_t). To avoid aliasing optimization
|
||||
problems, the registers are cast through (void *). */
|
||||
switch (regnum) {
|
||||
case 0: return (MRef)((char *)&mfc->threadState->__rax);
|
||||
case 1: return (MRef)((char *)&mfc->threadState->__rcx);
|
||||
case 2: return (MRef)((char *)&mfc->threadState->__rdx);
|
||||
case 3: return (MRef)((char *)&mfc->threadState->__rbx);
|
||||
case 4: return (MRef)((char *)&mfc->threadState->__rsp);
|
||||
case 5: return (MRef)((char *)&mfc->threadState->__rbp);
|
||||
case 6: return (MRef)((char *)&mfc->threadState->__rsi);
|
||||
case 7: return (MRef)((char *)&mfc->threadState->__rdi);
|
||||
case 8: return (MRef)((char *)&mfc->threadState->__r8);
|
||||
case 9: return (MRef)((char *)&mfc->threadState->__r9);
|
||||
case 10: return (MRef)((char *)&mfc->threadState->__r10);
|
||||
case 11: return (MRef)((char *)&mfc->threadState->__r11);
|
||||
case 12: return (MRef)((char *)&mfc->threadState->__r12);
|
||||
case 13: return (MRef)((char *)&mfc->threadState->__r13);
|
||||
case 14: return (MRef)((char *)&mfc->threadState->__r14);
|
||||
case 15: return (MRef)((char *)&mfc->threadState->__r15);
|
||||
case 0: return (void *)&threadState->__rax;
|
||||
case 1: return (void *)&threadState->__rcx;
|
||||
case 2: return (void *)&threadState->__rdx;
|
||||
case 3: return (void *)&threadState->__rbx;
|
||||
case 4: return (void *)&threadState->__rsp;
|
||||
case 5: return (void *)&threadState->__rbp;
|
||||
case 6: return (void *)&threadState->__rsi;
|
||||
case 7: return (void *)&threadState->__rdi;
|
||||
case 8: return (void *)&threadState->__r8;
|
||||
case 9: return (void *)&threadState->__r9;
|
||||
case 10: return (void *)&threadState->__r10;
|
||||
case 11: return (void *)&threadState->__r11;
|
||||
case 12: return (void *)&threadState->__r12;
|
||||
case 13: return (void *)&threadState->__r13;
|
||||
case 14: return (void *)&threadState->__r14;
|
||||
case 15: return (void *)&threadState->__r15;
|
||||
default:
|
||||
NOTREACHED;
|
||||
return NULL; /* Avoids compiler warning. */
|
||||
|
|
|
|||
|
|
@ -243,7 +243,7 @@ static void protCatchOne(void)
|
|||
different size" warnings in GCC, for the XCI3GC build. */
|
||||
mfcStruct.address = (Addr)(Word)request.code[1];
|
||||
AVER(sizeof(*mfcStruct.threadState) == sizeof(THREAD_STATE_S));
|
||||
mfcStruct.threadState = (THREAD_STATE_S *)request.old_state;
|
||||
mfcStruct.threadState = (void *)request.old_state;
|
||||
|
||||
if (ArenaAccess(mfcStruct.address,
|
||||
AccessREAD | AccessWRITE,
|
||||
|
|
@ -282,6 +282,7 @@ static void protCatchOne(void)
|
|||
* handler won't cause a deadlock.
|
||||
*/
|
||||
|
||||
ATTRIBUTE_NORETURN
|
||||
static void *protCatchThread(void *p) {
|
||||
UNUSED(p);
|
||||
for (;;)
|
||||
|
|
|
|||
|
|
@ -29,10 +29,9 @@
|
|||
#include "mpscamc.h"
|
||||
#include "mpscmv.h"
|
||||
#include "mpstd.h"
|
||||
#ifdef MPS_OS_W3
|
||||
#include "mpsw3.h"
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <stdio.h> /* printf */
|
||||
#include <stdlib.h> /* qsort */
|
||||
|
||||
|
||||
#define testArenaSIZE ((size_t)1000*1024)
|
||||
|
|
@ -51,7 +50,7 @@ static mps_addr_t isMoved(mps_addr_t object);
|
|||
static void copy(mps_addr_t object, mps_addr_t to);
|
||||
static void pad(mps_addr_t base, size_t size);
|
||||
|
||||
struct mps_fmt_A_s fmt_A_s =
|
||||
static struct mps_fmt_A_s fmt_A_s =
|
||||
{
|
||||
(mps_align_t)4,
|
||||
scan, skip, copy,
|
||||
|
|
@ -318,14 +317,14 @@ static void validate(void)
|
|||
for(i = 0; i < listl; ++i) {
|
||||
cdie(((QSCell)reg[1])->tag == QSInt, "validate int");
|
||||
if((mps_word_t)((QSCell)reg[1])->value != list[i]) {
|
||||
(void)fprintf(stdout, "mps_res_t: Element %"PRIuLONGEST" of the "
|
||||
"two lists do not match.\n", (ulongest_t)i);
|
||||
printf("mps_res_t: Element %"PRIuLONGEST" of the "
|
||||
"two lists do not match.\n", (ulongest_t)i);
|
||||
return;
|
||||
}
|
||||
reg[1] = (mps_addr_t)((QSCell)reg[1])->tail;
|
||||
}
|
||||
cdie(reg[1] == (mps_word_t)0, "validate end");
|
||||
(void)fprintf(stdout, "Note: Lists compare equal.\n");
|
||||
printf("Note: Lists compare equal.\n");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* ring.c: RING IMPLEMENTATION
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001,2003 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .intro: This is a portable implementation of Rings.
|
||||
*
|
||||
|
|
@ -52,6 +52,16 @@ Bool RingIsSingle(Ring ring)
|
|||
return (ring->next == ring);
|
||||
}
|
||||
|
||||
Size RingLength(Ring ring)
|
||||
{
|
||||
Size size = 0;
|
||||
Ring node, next;
|
||||
AVERT(Ring, ring);
|
||||
RING_FOR(node, ring, next)
|
||||
++ size;
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
/* RingInit -- initialize a ring node
|
||||
*/
|
||||
|
|
@ -131,7 +141,7 @@ Ring (RingPrev)(Ring ring)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2003 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* ring.h: RING INTERFACE
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (C) 2001 Global Graphics Software.
|
||||
*/
|
||||
|
||||
|
|
@ -30,6 +30,7 @@ typedef struct RingStruct { /* double-ended queue structure */
|
|||
extern Bool RingCheck(Ring ring);
|
||||
extern Bool RingCheckSingle(Ring ring);
|
||||
extern Bool RingIsSingle(Ring ring);
|
||||
extern Size RingLength(Ring ring);
|
||||
|
||||
/* .ring.init: */
|
||||
extern void (RingInit)(Ring ring);
|
||||
|
|
@ -115,7 +116,7 @@ extern Ring (RingPrev)(Ring ring);
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -48,18 +48,20 @@ static Bool SACCheck(SAC sac)
|
|||
CHECKL(esac->_middle > 0);
|
||||
/* check classes above middle */
|
||||
prevSize = esac->_middle;
|
||||
for (j = sac->middleIndex + 1, i = 0;
|
||||
j <= sac->classesCount; ++j, i += 2) {
|
||||
for (j = sac->middleIndex + 1, i = 0; j < sac->classesCount; ++j, i += 2) {
|
||||
CHECKL(prevSize < esac->_freelists[i]._size);
|
||||
b = sacFreeListBlockCheck(&(esac->_freelists[i]));
|
||||
if (!b) return b;
|
||||
prevSize = esac->_freelists[i]._size;
|
||||
}
|
||||
/* check overlarge class */
|
||||
CHECKL(esac->_freelists[i-2]._size == SizeMAX);
|
||||
CHECKL(esac->_freelists[i-2]._count == 0);
|
||||
CHECKL(esac->_freelists[i-2]._count_max == 0);
|
||||
CHECKL(esac->_freelists[i-2]._blocks == NULL);
|
||||
CHECKL(prevSize < esac->_freelists[i]._size);
|
||||
b = sacFreeListBlockCheck(&(esac->_freelists[i]));
|
||||
if (!b) return b;
|
||||
CHECKL(esac->_freelists[i]._size == SizeMAX);
|
||||
CHECKL(esac->_freelists[i]._count == 0);
|
||||
CHECKL(esac->_freelists[i]._count_max == 0);
|
||||
CHECKL(esac->_freelists[i]._blocks == NULL);
|
||||
/* check classes below middle */
|
||||
prevSize = esac->_middle;
|
||||
for (j = sac->middleIndex, i = 1; j > 0; --j, i += 2) {
|
||||
|
|
@ -69,6 +71,7 @@ static Bool SACCheck(SAC sac)
|
|||
prevSize = esac->_freelists[i]._size;
|
||||
}
|
||||
/* check smallest class */
|
||||
CHECKL(prevSize > esac->_freelists[i]._size);
|
||||
CHECKL(esac->_freelists[i]._size == 0);
|
||||
b = sacFreeListBlockCheck(&(esac->_freelists[i]));
|
||||
return b;
|
||||
|
|
|
|||
|
|
@ -593,7 +593,7 @@ Res SegMerge(Seg *mergedSegReturn, Seg segLo, Seg segHi,
|
|||
if (ResOK != res)
|
||||
goto failMerge;
|
||||
|
||||
EVENT3(SegMerge, segLo, segHi, withReservoirPermit);
|
||||
EVENT3(SegMerge, segLo, segHi, BOOL(withReservoirPermit));
|
||||
/* Deallocate segHi object */
|
||||
ControlFree(arena, segHi, class->size);
|
||||
AVERT(Seg, segLo);
|
||||
|
|
@ -1200,7 +1200,7 @@ static void gcSegSetGreyInternal(Seg seg, TraceSet oldGrey, TraceSet grey)
|
|||
/* Internal method. Parameters are checked by caller */
|
||||
gcseg = SegGCSeg(seg);
|
||||
arena = PoolArena(SegPool(seg));
|
||||
seg->grey = grey;
|
||||
seg->grey = BS_BITFIELD(Trace, grey);
|
||||
|
||||
/* If the segment is now grey and wasn't before, add it to the */
|
||||
/* appropriate grey list so that TraceFindGrey can locate it */
|
||||
|
|
@ -1313,11 +1313,11 @@ static void gcSegSetWhite(Seg seg, TraceSet white)
|
|||
|
||||
AVERT_CRITICAL(Tract, tract);
|
||||
AVER_CRITICAL(TRACT_SEG(&trseg, tract) && (trseg == seg));
|
||||
TractSetWhite(tract, white);
|
||||
TractSetWhite(tract, BS_BITFIELD(Trace, white));
|
||||
}
|
||||
AVER(addr == limit);
|
||||
|
||||
seg->white = white;
|
||||
seg->white = BS_BITFIELD(Trace, white);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1350,7 +1350,7 @@ static void gcSegSetRankSet(Seg seg, RankSet rankSet)
|
|||
|
||||
arena = PoolArena(SegPool(seg));
|
||||
oldRankSet = seg->rankSet;
|
||||
seg->rankSet = rankSet;
|
||||
seg->rankSet = BS_BITFIELD(Rank, rankSet);
|
||||
|
||||
if (oldRankSet == RankSetEMPTY) {
|
||||
if (rankSet != RankSetEMPTY) {
|
||||
|
|
@ -1427,7 +1427,7 @@ static void gcSegSetRankSummary(Seg seg, RankSet rankSet, RefSet summary)
|
|||
wasShielded = (seg->rankSet != RankSetEMPTY && gcseg->summary != RefSetUNIV);
|
||||
willbeShielded = (rankSet != RankSetEMPTY && summary != RefSetUNIV);
|
||||
|
||||
seg->rankSet = rankSet;
|
||||
seg->rankSet = BS_BITFIELD(Rank, rankSet);
|
||||
gcseg->summary = summary;
|
||||
|
||||
if (willbeShielded && !wasShielded) {
|
||||
|
|
|
|||
|
|
@ -21,14 +21,9 @@
|
|||
#include "mpscams.h"
|
||||
#include "mpsavm.h"
|
||||
#include "mpstd.h"
|
||||
#ifdef MPS_OS_W3
|
||||
#include "mpsw3.h"
|
||||
#endif
|
||||
#include "mps.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <stdio.h> /* fflush, printf, puts, stdout */
|
||||
|
||||
|
||||
/* Forward declarations */
|
||||
|
|
@ -791,7 +786,7 @@ static void *test(void *arg, size_t s)
|
|||
&ambigRoots[0], ambigRootsCOUNT),
|
||||
"root_create_table(ambig)");
|
||||
|
||||
(void)fputs(indent, stdout);
|
||||
puts(indent);
|
||||
|
||||
/* create an ap, and leave it busy */
|
||||
die(mps_reserve(&busy_init, busy_ap, 64), "mps_reserve busy");
|
||||
|
|
|
|||
|
|
@ -14,12 +14,9 @@
|
|||
#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 <stdio.h> /* fflush, printf, putchar, stdout */
|
||||
|
||||
#define testArenaSIZE ((size_t)((size_t)64 << 20))
|
||||
#define avLEN 3
|
||||
|
|
@ -74,19 +71,19 @@ static mps_addr_t ambigRoots[ambigRootsCOUNT];
|
|||
|
||||
/* Things we want to measure. Times are all in microseconds. */
|
||||
|
||||
double alloc_time; /* Time spent allocating */
|
||||
double max_alloc_time; /* Max time taken to allocate one object */
|
||||
double step_time; /* Time spent in mps_arena_step returning 1 */
|
||||
double max_step_time; /* Max time of mps_arena_step returning 1 */
|
||||
double no_step_time; /* Time spent in mps_arena_step returning 0 */
|
||||
double max_no_step_time; /* Max time of mps_arena_step returning 0 */
|
||||
static double alloc_time; /* Time spent allocating */
|
||||
static double max_alloc_time; /* Max time taken to allocate one object */
|
||||
static double step_time; /* Time spent in mps_arena_step returning 1 */
|
||||
static double max_step_time; /* Max time of mps_arena_step returning 1 */
|
||||
static double no_step_time; /* Time spent in mps_arena_step returning 0 */
|
||||
static double max_no_step_time; /* Max time of mps_arena_step returning 0 */
|
||||
|
||||
double total_clock_time; /* Time spent reading the clock */
|
||||
long clock_reads; /* Number of times clock is read */
|
||||
long steps; /* # of mps_arena_step calls returning 1 */
|
||||
long no_steps; /* # of mps_arena_step calls returning 0 */
|
||||
size_t alloc_bytes; /* # of bytes allocated */
|
||||
long commit_failures; /* # of times mps_commit fails */
|
||||
static double total_clock_time; /* Time spent reading the clock */
|
||||
static long clock_reads; /* Number of times clock is read */
|
||||
static long steps; /* # of mps_arena_step calls returning 1 */
|
||||
static long no_steps; /* # of mps_arena_step calls returning 0 */
|
||||
static size_t alloc_bytes; /* # of bytes allocated */
|
||||
static long commit_failures; /* # of times mps_commit fails */
|
||||
|
||||
|
||||
/* Operating-system dependent timing. Defines two functions, void
|
||||
|
|
@ -98,6 +95,8 @@ long commit_failures; /* # of times mps_commit fails */
|
|||
|
||||
#ifdef MPS_OS_W3
|
||||
|
||||
#include "mpswin.h"
|
||||
|
||||
static HANDLE currentProcess;
|
||||
|
||||
static void prepare_clock(void)
|
||||
|
|
@ -152,7 +151,7 @@ static double my_clock(void)
|
|||
* on thrush.ravenbrook.com on 2002-06-28, clock_time goes from 5.43
|
||||
* us near process start to 7.45 us later). */
|
||||
|
||||
double clock_time; /* current estimate of time to read the clock */
|
||||
static double clock_time; /* current estimate of time to read the clock */
|
||||
|
||||
/* take at least this many microseconds to set the clock */
|
||||
#define CLOCK_TIME_SET 10000
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@
|
|||
#include "testlib.h"
|
||||
#include "mpslib.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h> /* fflush, fgets, printf, stdin, stdout */
|
||||
#include <stdlib.h> /* exit, EXIT_SUCCESS, strtoul */
|
||||
|
||||
SRCID(teletest, "$Id$");
|
||||
|
||||
|
|
@ -34,8 +35,8 @@ static void callControl(mps_word_t reset, mps_word_t flip)
|
|||
old = mps_telemetry_control(reset, flip);
|
||||
new = mps_telemetry_control((mps_word_t)0, (mps_word_t)0);
|
||||
|
||||
(void)printf(WORD_FORMAT " -> " WORD_FORMAT "\n",
|
||||
(ulongest_t)old, (ulongest_t)new);
|
||||
printf(WORD_FORMAT " -> " WORD_FORMAT "\n",
|
||||
(ulongest_t)old, (ulongest_t)new);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -11,13 +11,11 @@
|
|||
#include "clock.h" /* for EVENT_CLOCK */
|
||||
#include "mps.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
|
||||
#include <time.h>
|
||||
|
||||
#include <math.h> /* fmod */
|
||||
#include <stdio.h> /* fflush, printf, stderr, sscanf, vfprintf */
|
||||
#include <stdlib.h> /* abort, exit, getenv */
|
||||
#include <time.h> /* time */
|
||||
|
||||
|
||||
/* fail -- like assert, but (notionally) returns a value, so usable in an expression */
|
||||
|
|
|
|||
|
|
@ -12,14 +12,7 @@
|
|||
|
||||
#include "mps.h"
|
||||
#include "misc.h" /* for STR */
|
||||
|
||||
/* Include system header hackery. */
|
||||
#include "mpstd.h"
|
||||
#ifdef MPS_OS_W3
|
||||
#include "mpswin.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
/* Suppress Visual C warnings at warning level 4, */
|
||||
|
|
@ -35,13 +28,10 @@
|
|||
|
||||
|
||||
/* Suppress Pelles C warnings at warning level 2 */
|
||||
/* Some of these are also done in config.h. */
|
||||
/* This is also done in config.h. */
|
||||
|
||||
#ifdef MPS_BUILD_PC
|
||||
|
||||
/* "Structured Exception Handling is not portable." (mps_tramp). */
|
||||
#pragma warn(disable: 2008)
|
||||
|
||||
/* "Unreachable code" (AVER, if condition is constantly true). */
|
||||
#pragma warn(disable: 2154)
|
||||
|
||||
|
|
@ -65,6 +55,19 @@
|
|||
#endif
|
||||
|
||||
|
||||
/* alloca -- memory allocator
|
||||
*
|
||||
* Windows calls this function _alloca() instead of alloca().
|
||||
* <http://msdn.microsoft.com/en-us/library/wb1s57t5.aspx>
|
||||
*/
|
||||
|
||||
#if defined(MPS_OS_W3)
|
||||
|
||||
#define alloca _alloca
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* ulongest_t -- longest unsigned integer type
|
||||
*
|
||||
* Define a longest unsigned integer type for testing, scanning, and
|
||||
|
|
|
|||
123
mps/code/testthr.h
Normal file
123
mps/code/testthr.h
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
/* testthr.h: MULTI-THREADED TEST INTERFACE
|
||||
*
|
||||
* $Id: //info.ravenbrook.com/project/mps/master/code/testlib.h#30 $
|
||||
* Copyright (c) 2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .purpose: Simple interface to threads that makes it possible to
|
||||
* write test cases that are portable between Windows (using the
|
||||
* implementation in testthrw3.c) and Unix (using the implementation
|
||||
* in testthrix.c).
|
||||
*/
|
||||
|
||||
#ifndef testthr_h
|
||||
#define testthr_h
|
||||
|
||||
#include "mpstd.h"
|
||||
|
||||
|
||||
/* testthr_routine_t -- type of thread routines
|
||||
*
|
||||
* Use the pthread type here and convert back and forth in the Windows
|
||||
* implementation.
|
||||
*/
|
||||
typedef void *(*testthr_routine_t)(void *);
|
||||
|
||||
|
||||
/* testthr_t -- type of thread identifiers
|
||||
*
|
||||
* It is necessary to define it here (even though it requires some
|
||||
* #ifdefs) so that clients can allocate storage for them.
|
||||
*/
|
||||
|
||||
#if defined(MPS_OS_W3)
|
||||
|
||||
#include "mpswin.h"
|
||||
|
||||
/* On Windows, a thread is identified by a HANDLE.
|
||||
* <http://msdn.microsoft.com/en-us/library/windows/desktop/aa383751.aspx>
|
||||
* But use a structure so that the thread has somewhere to store its
|
||||
* result for use by testthr_join.
|
||||
*/
|
||||
typedef struct testthr_t {
|
||||
HANDLE handle;
|
||||
testthr_routine_t start;
|
||||
void *arg; /* argument to pass to start */
|
||||
void *result; /* result returned from start */
|
||||
} testthr_t;
|
||||
|
||||
#elif defined(MPS_OS_FR) || defined(MPS_OS_LI) || defined(MPS_OS_XC)
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
/* In pthreads, a thread is identified by a pthread_t, which is
|
||||
* allowed "to be defined as a structure" [IEEE Std 1003.1, sys/types.h]
|
||||
* <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_types.h.html>
|
||||
*/
|
||||
typedef pthread_t testthr_t;
|
||||
|
||||
#else
|
||||
#error "Unknown platform: can't determine a type for testthr_t."
|
||||
#endif
|
||||
|
||||
|
||||
/* testthr_create -- create a thread
|
||||
*
|
||||
* Store the identifier of the newly created thread in *thread_o, and
|
||||
* call start, passing arg as the single parameter.
|
||||
*/
|
||||
|
||||
void testthr_create(testthr_t *thread_o, testthr_routine_t start, void *arg);
|
||||
|
||||
|
||||
/* testthr_join -- wait for a thread to complete
|
||||
*
|
||||
* Suspend execution of the calling thread until the target thread
|
||||
* terminates (if necessary), and if result_o is non-NULL, update
|
||||
* *result_o with the return value of the thread's start.
|
||||
*/
|
||||
|
||||
void testthr_join(testthr_t *thread, void **result_o);
|
||||
|
||||
#endif /* testthr_h */
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Redistributions in any form must be accompanied by information on how
|
||||
* to obtain complete source code for this software and any accompanying
|
||||
* software that uses this software. The source code must either be
|
||||
* included in the distribution or be available for no more than the cost
|
||||
* of distribution plus a nominal fee, and must be freely redistributable
|
||||
* under reasonable conditions. For an executable file, complete source
|
||||
* code means the source code for all modules it contains. It does not
|
||||
* include source code for modules or files that typically accompany the
|
||||
* major components of the operating system on which the executable file
|
||||
* runs.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
|
@ -1,45 +1,32 @@
|
|||
/* mpsw3.h: RAVENBROOK MEMORY POOL SYSTEM C INTERFACE, WINDOWS PART
|
||||
/* testthrix.c: MULTI-THREADED TEST IMPLEMENTATION (POSIX THREADS)
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .readership: customers, MPS developers.
|
||||
* .sources: <design/interface-c/>.
|
||||
* $Id: //info.ravenbrook.com/project/mps/master/code/testlib.h#30 $
|
||||
* Copyright (c) 2014 Ravenbrook Limited. See end of file for license.
|
||||
*/
|
||||
|
||||
#ifndef mpsw3_h
|
||||
#define mpsw3_h
|
||||
#include "testlib.h"
|
||||
#include "testthr.h"
|
||||
|
||||
#include "mps.h" /* needed for mps_tramp_t */
|
||||
#include "mpswin.h" /* needed for SEH filter */
|
||||
#include <string.h> /* strerror */
|
||||
|
||||
void testthr_create(testthr_t *thread_o, testthr_routine_t start, void *arg)
|
||||
{
|
||||
int res = pthread_create(thread_o, NULL, start, arg);
|
||||
if (res != 0)
|
||||
error("pthread_create failed with result %d (%s)", res, strerror(res));
|
||||
}
|
||||
|
||||
extern LONG mps_SEH_filter(LPEXCEPTION_POINTERS, void **, size_t *);
|
||||
extern void mps_SEH_handler(void *, size_t);
|
||||
|
||||
|
||||
#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); \
|
||||
void *_hp = NULL; size_t _hs = 0; \
|
||||
__try { \
|
||||
*_r_o = (*_f)(_p, _s); \
|
||||
} __except(mps_SEH_filter(GetExceptionInformation(), \
|
||||
&_hp, &_hs)) { \
|
||||
mps_SEH_handler(_hp, _hs); \
|
||||
} \
|
||||
MPS_END
|
||||
|
||||
|
||||
#endif /* mpsw3_h */
|
||||
void testthr_join(testthr_t *thread, void **result_o)
|
||||
{
|
||||
int res = pthread_join(*thread, result_o);
|
||||
if (res != 0)
|
||||
error("pthread_join failed with result %d (%s)", res, strerror(res));
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
80
mps/code/testthrw3.c
Normal file
80
mps/code/testthrw3.c
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/* testthrw3.c: MULTI-THREADED TEST IMPLEMENTATION (WINDOWS)
|
||||
*
|
||||
* $Id: //info.ravenbrook.com/project/mps/master/code/testlib.h#30 $
|
||||
* Copyright (c) 2014 Ravenbrook Limited. See end of file for license.
|
||||
*/
|
||||
|
||||
#include "testlib.h"
|
||||
#include "testthr.h"
|
||||
|
||||
static DWORD WINAPI testthr_start(LPVOID arg)
|
||||
{
|
||||
testthr_t *thread = arg;
|
||||
thread->result = (*thread->start)(thread->arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void testthr_create(testthr_t *thread_o, testthr_routine_t start, void *arg)
|
||||
{
|
||||
HANDLE res;
|
||||
thread_o->start = start;
|
||||
thread_o->arg = arg;
|
||||
res = CreateThread(NULL, 0, testthr_start, thread_o, 0, NULL);
|
||||
if (res == NULL)
|
||||
error("CreateThread failed with error %lu",
|
||||
(unsigned long)GetLastError());
|
||||
else
|
||||
thread_o->handle = res;
|
||||
}
|
||||
|
||||
void testthr_join(testthr_t *thread, void **result_o)
|
||||
{
|
||||
DWORD res = WaitForSingleObject(thread->handle, INFINITE);
|
||||
if (res != WAIT_OBJECT_0)
|
||||
error("WaitForSingleObject failed with result %lu (error %lu)",
|
||||
(unsigned long)res, (unsigned long)GetLastError());
|
||||
if (result_o)
|
||||
*result_o = thread->result;
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Redistributions in any form must be accompanied by information on how
|
||||
* to obtain complete source code for this software and any accompanying
|
||||
* software that uses this software. The source code must either be
|
||||
* included in the distribution or be available for no more than the cost
|
||||
* of distribution plus a nominal fee, and must be freely redistributable
|
||||
* under reasonable conditions. For an executable file, complete source
|
||||
* code means the source code for all modules it contains. It does not
|
||||
* include source code for modules or files that typically accompany the
|
||||
* major components of the operating system on which the executable file
|
||||
* runs.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
|
@ -797,10 +797,11 @@ void TraceDestroy(Trace trace)
|
|||
(TraceStatReclaim, trace,
|
||||
trace->reclaimCount, trace->reclaimSize));
|
||||
|
||||
EVENT1(TraceDestroy, trace);
|
||||
|
||||
trace->sig = SigInvalid;
|
||||
trace->arena->busyTraces = TraceSetDel(trace->arena->busyTraces, trace);
|
||||
trace->arena->flippedTraces = TraceSetDel(trace->arena->flippedTraces, trace);
|
||||
EVENT1(TraceDestroy, trace);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1569,7 +1570,7 @@ static void TraceStartPoolGen(Chain chain, GenDesc desc, Bool top, Index i)
|
|||
Ring n, nn;
|
||||
RING_FOR(n, &desc->locusRing, nn) {
|
||||
PoolGen gen = RING_ELT(PoolGen, genRing, n);
|
||||
EVENT11(TraceStartPoolGen, chain, top, i, desc,
|
||||
EVENT11(TraceStartPoolGen, chain, BOOL(top), i, desc,
|
||||
desc->capacity, desc->mortality, desc->zones,
|
||||
gen->pool, gen->nr, gen->totalSize,
|
||||
gen->newSizeAtCreate);
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ SRCID(version, "$Id$");
|
|||
* (assuming we've made any substantial changes to the library this year).
|
||||
*/
|
||||
|
||||
extern char MPSCopyrightNotice[];
|
||||
char MPSCopyrightNotice[] =
|
||||
"Portions copyright (c) 2010-2014 Ravenbrook Limited and Global Graphics Software.";
|
||||
|
||||
|
|
@ -59,6 +60,7 @@ char MPSCopyrightNotice[] =
|
|||
* see also guide.mps.version.
|
||||
*/
|
||||
|
||||
extern char MPSVersionString[];
|
||||
char MPSVersionString[] =
|
||||
"@(#)Ravenbrook MPS, "
|
||||
"product." MPS_PROD_STRING ", " MPS_RELEASE ", platform." MPS_PF_STRING
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* vman.c: ANSI VM: MALLOC-BASED PSEUDO MEMORY MAPPING
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*/
|
||||
|
||||
#include "mpm.h"
|
||||
|
|
@ -117,13 +117,13 @@ void VMDestroy(VM vm)
|
|||
AVER(vm->mapped == (Size)0);
|
||||
AVER(vm->reserved == AddrOffset(vm->base, vm->limit));
|
||||
|
||||
EVENT1(VMDestroy, vm);
|
||||
|
||||
memset((void *)vm->base, VMJunkBYTE, AddrOffset(vm->base, vm->limit));
|
||||
free(vm->block);
|
||||
|
||||
vm->sig = SigInvalid;
|
||||
free(vm);
|
||||
|
||||
EVENT1(VMDestroy, vm);
|
||||
free(vm);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -215,7 +215,7 @@ void VMUnmap(VM vm, Addr base, Addr limit)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* vmix.c: VIRTUAL MEMORY MAPPING FOR UNIX (ISH)
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .purpose: This is the implementation of the virtual memory mapping
|
||||
* interface (vm.h) for Unix-like operating systems. It was created
|
||||
|
|
@ -186,6 +186,8 @@ void VMDestroy(VM vm)
|
|||
AVERT(VM, vm);
|
||||
AVER(vm->mapped == (Size)0);
|
||||
|
||||
EVENT1(VMDestroy, vm);
|
||||
|
||||
/* This appears to be pretty pointless, since the descriptor */
|
||||
/* page is about to vanish completely. However, munmap might fail */
|
||||
/* for some reason, and this would ensure that it was still */
|
||||
|
|
@ -197,8 +199,6 @@ void VMDestroy(VM vm)
|
|||
r = munmap((void *)vm,
|
||||
(size_t)SizeAlignUp(sizeof(VMStruct), vm->align));
|
||||
AVER(r == 0);
|
||||
|
||||
EVENT1(VMDestroy, vm);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -304,7 +304,7 @@ void VMUnmap(VM vm, Addr base, Addr limit)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* vmw3.c: VIRTUAL MEMORY MAPPING FOR WIN32
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .design: See <design/vm/>.
|
||||
*
|
||||
|
|
@ -191,6 +191,8 @@ void VMDestroy(VM vm)
|
|||
AVERT(VM, vm);
|
||||
AVER(vm->mapped == 0);
|
||||
|
||||
EVENT1(VMDestroy, vm);
|
||||
|
||||
/* This appears to be pretty pointless, since the vm descriptor page
|
||||
* is about to vanish completely. However, the VirtualFree might
|
||||
* fail and it would be nice to have a dead sig there. */
|
||||
|
|
@ -201,7 +203,6 @@ void VMDestroy(VM vm)
|
|||
|
||||
b = VirtualFree((LPVOID)vm, (SIZE_T)0, MEM_RELEASE);
|
||||
AVER(b != 0);
|
||||
EVENT1(VMDestroy, vm);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -303,7 +304,7 @@ void VMUnmap(VM vm, Addr base, Addr limit)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -273,6 +273,20 @@ static Res rootWalk(Root root, void *p)
|
|||
}
|
||||
|
||||
|
||||
/* rootWalkGrey -- make the root grey for the trace passed as p */
|
||||
|
||||
static Res rootWalkGrey(Root root, void *p)
|
||||
{
|
||||
Trace trace = p;
|
||||
|
||||
AVERT(Root, root);
|
||||
AVERT(Trace, trace);
|
||||
|
||||
RootGrey(root, trace);
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
||||
/* ArenaRootsWalk -- walks all the root in the arena */
|
||||
|
||||
static Res ArenaRootsWalk(Globals arenaGlobals, mps_roots_stepper_t f,
|
||||
|
|
@ -315,7 +329,7 @@ static Res ArenaRootsWalk(Globals arenaGlobals, mps_roots_stepper_t f,
|
|||
}
|
||||
|
||||
/* Make the roots grey so that they are scanned */
|
||||
res = RootsIterate(arenaGlobals, (RootIterateFn)RootGrey, (void *)trace);
|
||||
res = RootsIterate(arenaGlobals, rootWalkGrey, trace);
|
||||
/* Make this trace look like any other trace. */
|
||||
arena->flippedTraces = TraceSetAdd(arena->flippedTraces, trace);
|
||||
|
||||
|
|
@ -330,6 +344,16 @@ static Res ArenaRootsWalk(Globals arenaGlobals, mps_roots_stepper_t f,
|
|||
break;
|
||||
}
|
||||
|
||||
/* Turn segments black again. */
|
||||
if (SegFirst(&seg, arena)) {
|
||||
do {
|
||||
if (PoolHasAttr(SegPool(seg), AttrGC)) {
|
||||
SegSetGrey(seg, TraceSetDel(SegGrey(seg), trace));
|
||||
SegSetWhite(seg, TraceSetDel(SegWhite(seg), trace));
|
||||
}
|
||||
} while (SegNext(&seg, arena, seg));
|
||||
}
|
||||
|
||||
rootsStepClosureFinish(rsc);
|
||||
/* Make this trace look like any other finished trace. */
|
||||
trace->state = TraceFINISHED;
|
||||
|
|
|
|||
|
|
@ -13,15 +13,12 @@
|
|||
#include "mpscamc.h"
|
||||
#include "mpscams.h"
|
||||
#include "mpscawl.h"
|
||||
#include "mpsclo.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 <stdio.h> /* printf */
|
||||
|
||||
#define testArenaSIZE ((size_t)((size_t)64 << 20))
|
||||
#define avLEN 3
|
||||
|
|
@ -216,8 +213,10 @@ int main(int argc, char *argv[])
|
|||
die(mps_thread_reg(&thread, arena), "thread_reg");
|
||||
|
||||
test(arena, mps_class_amc());
|
||||
test(arena, mps_class_awl());
|
||||
test(arena, mps_class_amcz());
|
||||
/* TODO: test(arena, mps_class_ams()); -- see job003738 */
|
||||
test(arena, mps_class_awl());
|
||||
test(arena, mps_class_lo());
|
||||
|
||||
mps_thread_dereg(thread);
|
||||
mps_arena_destroy(arena);
|
||||
|
|
|
|||
|
|
@ -62,11 +62,8 @@
|
|||
#include "fmtdy.h"
|
||||
#include "fmtdytst.h"
|
||||
#include "mpstd.h"
|
||||
#ifdef MPS_OS_W3
|
||||
#include "mpsw3.h"
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <time.h> /* clock */
|
||||
|
||||
#include <stdio.h> /* fflush, printf, putchar, puts, stdout */
|
||||
|
||||
|
||||
/* testChain -- generation parameters for the test */
|
||||
|
|
|
|||
|
|
@ -107,10 +107,8 @@
|
|||
#include "fmtdy.h"
|
||||
#include "fmtdytst.h"
|
||||
#include "mpstd.h"
|
||||
#ifdef MPS_OS_W3
|
||||
#include "mpsw3.h"
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <stdio.h> /* printf */
|
||||
|
||||
|
||||
#define testArenaSIZE ((size_t)16<<20)
|
||||
|
|
|
|||
|
|
@ -187,8 +187,8 @@ Performance might be improved by special-casing the small levels.
|
|||
_`.future.limit`: In C and C++, a pointer to "one past the last
|
||||
element of an array object" (the limit of the object in our
|
||||
terminology) is a valid pointer and can be used in pointer arithmetic.
|
||||
See §6.5.6.8–9 of [C1999]. So in theory a programmer could have such
|
||||
as pointer as the only reference keeping an object alive, and still
|
||||
See §6.5.6.8–9 of [C1999]_. So in theory a programmer could have such
|
||||
a pointer as the only reference keeping an object alive, and still
|
||||
expect to be able to subtract from it to get back to the object. The
|
||||
current nailboard implementation does not support this use case.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
# The files in this directory are generated by the "mps" extension to Sphinx,
|
||||
# except the index and the "old designs" index.
|
||||
*.rst
|
||||
*.svg
|
||||
!index.rst
|
||||
!old.rst
|
||||
|
|
|
|||
|
|
@ -18,11 +18,14 @@ from sphinx.util.console import bold
|
|||
|
||||
TYPES = '''
|
||||
|
||||
AccessSet Accumulation Addr Align AP Arg Arena Attr Bool BT Buffer
|
||||
Byte Clock Compare Count Epoch Format Fun Index LD Lock Message
|
||||
Pointer Pool PThreadext Rank RankSet Ref Res Reservoir Ring Root
|
||||
RootVar ScanState Seg Serial Shift Sig Size Space SplayNode
|
||||
SplayTree Thread Trace TraceId TraceSet ULongest VM Word
|
||||
AccessSet Accumulation Addr Align AllocFrame AllocPattern AP Arg
|
||||
Arena Attr Bool BootBlock BT Buffer BufferMode Byte Chain Chunk
|
||||
Clock Compare Count Epoch FindDelete Format FrameState Fun Globals
|
||||
Index Land LD Lock Message MessageType MutatorFaultContext Page
|
||||
Pointer Pool PThreadext Range Rank RankSet Ref Res Reservoir Ring
|
||||
Root RootMode RootVar ScanState Seg SegBuf SegPref SegPrefKind
|
||||
Serial Shift Sig Size Space SplayNode SplayTree StackContext
|
||||
Thread Trace TraceId TraceSet ULongest VM Word ZoneSet
|
||||
|
||||
'''
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ Memory Management Glossary: K
|
|||
|
||||
keyword argument
|
||||
|
||||
A argument to a function call that's identified by an
|
||||
An argument to a function call that's identified by an
|
||||
associated keyword rather than by its position in the argument
|
||||
list.
|
||||
|
||||
|
|
@ -35,5 +35,3 @@ Memory Management Glossary: K
|
|||
|
||||
The standard abbreviation is "kB", but "KB" is often used by
|
||||
people unfamiliar with the metric system.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -282,11 +282,10 @@ the format of objects allocated in it:
|
|||
that it does not look like an aligned pointer.
|
||||
|
||||
"Aligned pointer" means a word whose numeric value (that is, its
|
||||
value when treated as an unsigned integer) is a multiple of the
|
||||
architecture's :term:`natural alignment` (see
|
||||
:c:macro:`MPS_PF_ALIGN`). If you're using a 32-bit architecture,
|
||||
that means that an aligned pointer is a multiple of 4 and its bottom
|
||||
two bits are both zero.
|
||||
value when treated as an unsigned integer) is a multiple of the size
|
||||
of a pointer. For you're using a 32-bit architecture, that means
|
||||
that an aligned pointer is a multiple of 4 and its bottom two bits
|
||||
are both zero.
|
||||
|
||||
The bottom line is that references from an object in an AWL pool
|
||||
must be untagged and aligned, and integers must be tagged with a
|
||||
|
|
|
|||
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