mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-23 06:00:41 -08:00
Catch-up merge from master.
Copied from Perforce Change: 184103 ServerID: perforce.ravenbrook.com
This commit is contained in:
commit
199ef9ca11
213 changed files with 5019 additions and 3501 deletions
|
|
@ -2,6 +2,9 @@
|
|||
# $Id$
|
||||
# See <http://about.travis-ci.org/docs/user/languages/c/>.
|
||||
language: c
|
||||
compiler:
|
||||
- clang
|
||||
- gcc
|
||||
notifications:
|
||||
email:
|
||||
- mps-travis@ravenbrook.com
|
||||
|
|
|
|||
1
mps/CONTRIBUTING
Symbolic link
1
mps/CONTRIBUTING
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
contributing.rst
|
||||
|
|
@ -16,16 +16,16 @@ MAKE=@MAKE@
|
|||
MPS_TARGET_NAME=@MPS_TARGET_NAME@
|
||||
EXTRA_TARGETS=@EXTRA_TARGETS@
|
||||
prefix=$(DESTDIR)@prefix@
|
||||
MAKE_FOR_TARGET=$(MAKE) -C code -f $(MPS_TARGET_NAME).gmk EXTRA_TARGETS="$(EXTRA_TARGETS)"
|
||||
TARGET_OPTS=-C code -f $(MPS_TARGET_NAME).gmk EXTRA_TARGETS="$(EXTRA_TARGETS)"
|
||||
XCODEBUILD=xcodebuild -project code/mps.xcodeproj
|
||||
|
||||
all: @BUILD_TARGET@
|
||||
|
||||
build-via-make:
|
||||
$(MAKE_FOR_TARGET)
|
||||
$(MAKE) $(TARGET_OPTS)
|
||||
|
||||
clean-make-build:
|
||||
$(MAKE_FOR_TARGET) clean
|
||||
$(MAKE) $(TARGET_OPTS) clean
|
||||
|
||||
install-make-build: make-install-dirs build-via-make
|
||||
$(INSTALL_DATA) code/mps*.h $(prefix)/include/
|
||||
|
|
@ -68,8 +68,8 @@ make-install-dirs:
|
|||
install: @INSTALL_TARGET@
|
||||
|
||||
test-make-build: @BUILD_TARGET@
|
||||
$(MAKE_FOR_TARGET) VARIETY=cool testrun
|
||||
$(MAKE_FOR_TARGET) VARIETY=hot testrun
|
||||
$(MAKE) $(TARGET_OPTS) VARIETY=cool testrun
|
||||
$(MAKE) $(TARGET_OPTS) VARIETY=hot testrun
|
||||
|
||||
test-xcode-build:
|
||||
$(XCODEBUILD) -config Release -target testrun
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
# code/.p4ignore -- Perforce files to ignore list
|
||||
# $Id$
|
||||
# Make output
|
||||
xci3gc
|
||||
w3i3mv
|
||||
w3i6mv
|
||||
lii6gc
|
||||
lii3gc
|
||||
fri3gc
|
||||
fri6gc
|
||||
lii3gc
|
||||
lii6gc
|
||||
lii6ll
|
||||
w3i3mv
|
||||
w3i6mv
|
||||
xci3gc
|
||||
# Visual Studio junk
|
||||
Debug
|
||||
Release
|
||||
|
|
@ -15,9 +16,9 @@ Release
|
|||
*.user
|
||||
*.suo
|
||||
# Telemetry event logs
|
||||
mpsio.log
|
||||
mpsio*.log
|
||||
mpsio.log.txt
|
||||
mpsio*.sql
|
||||
mpsio*.txt
|
||||
# Build products
|
||||
*.o
|
||||
*.obj
|
||||
|
|
|
|||
|
|
@ -98,25 +98,25 @@ void ABQFinish(Arena arena, ABQ abq)
|
|||
|
||||
|
||||
/* ABQPush -- push an element onto the tail of the ABQ */
|
||||
Res ABQPush(ABQ abq, void *element)
|
||||
Bool ABQPush(ABQ abq, void *element)
|
||||
{
|
||||
AVERT(ABQ, abq);
|
||||
|
||||
METER_ACC(abq->push, ABQDepth(abq));
|
||||
|
||||
if (ABQIsFull(abq))
|
||||
return ResFAIL;
|
||||
return FALSE;
|
||||
|
||||
mps_lib_memcpy(ABQElement(abq, abq->in), element, abq->elementSize);
|
||||
abq->in = ABQNextIndex(abq, abq->in);
|
||||
|
||||
AVERT(ABQ, abq);
|
||||
return ResOK;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* ABQPop -- pop an element from the head of the ABQ */
|
||||
Res ABQPop(ABQ abq, void *elementReturn)
|
||||
Bool ABQPop(ABQ abq, void *elementReturn)
|
||||
{
|
||||
AVER(elementReturn != NULL);
|
||||
AVERT(ABQ, abq);
|
||||
|
|
@ -124,19 +124,19 @@ Res ABQPop(ABQ abq, void *elementReturn)
|
|||
METER_ACC(abq->pop, ABQDepth(abq));
|
||||
|
||||
if (ABQIsEmpty(abq))
|
||||
return ResFAIL;
|
||||
return FALSE;
|
||||
|
||||
mps_lib_memcpy(elementReturn, ABQElement(abq, abq->out), abq->elementSize);
|
||||
|
||||
abq->out = ABQNextIndex(abq, abq->out);
|
||||
|
||||
AVERT(ABQ, abq);
|
||||
return ResOK;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* ABQPeek -- peek at the head of the ABQ */
|
||||
Res ABQPeek(ABQ abq, void *elementReturn)
|
||||
Bool ABQPeek(ABQ abq, void *elementReturn)
|
||||
{
|
||||
AVER(elementReturn != NULL);
|
||||
AVERT(ABQ, abq);
|
||||
|
|
@ -144,14 +144,14 @@ Res ABQPeek(ABQ abq, void *elementReturn)
|
|||
METER_ACC(abq->peek, ABQDepth(abq));
|
||||
|
||||
if (ABQIsEmpty(abq))
|
||||
return ResFAIL;
|
||||
return FALSE;
|
||||
|
||||
mps_lib_memcpy(elementReturn, ABQElement(abq, abq->out), abq->elementSize);
|
||||
|
||||
/* Identical to pop, but don't increment out */
|
||||
|
||||
AVERT(ABQ, abq);
|
||||
return ResOK;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -29,9 +29,9 @@ typedef Bool (*ABQIterateMethod)(Bool *deleteReturn, void *element, void *closur
|
|||
extern Res ABQInit(Arena arena, ABQ abq, void *owner, Count elements, Size elementSize);
|
||||
extern Bool ABQCheck(ABQ abq);
|
||||
extern void ABQFinish(Arena arena, ABQ abq);
|
||||
extern Res ABQPush(ABQ abq, void *element);
|
||||
extern Res ABQPop(ABQ abq, void *elementReturn);
|
||||
extern Res ABQPeek(ABQ abq, void *elementReturn);
|
||||
extern Bool ABQPush(ABQ abq, void *element);
|
||||
extern Bool ABQPop(ABQ abq, void *elementReturn);
|
||||
extern Bool ABQPeek(ABQ abq, void *elementReturn);
|
||||
extern Res ABQDescribe(ABQ abq, ABQDescribeElement describeElement, mps_lib_FILE *stream);
|
||||
extern Bool ABQIsEmpty(ABQ abq);
|
||||
extern Bool ABQIsFull(ABQ abq);
|
||||
|
|
|
|||
|
|
@ -105,23 +105,20 @@ static Bool TestDeleteCallback(Bool *deleteReturn, void *element,
|
|||
|
||||
static void step(void)
|
||||
{
|
||||
Res res;
|
||||
TestBlock a;
|
||||
|
||||
switch (abqRnd(9)) {
|
||||
case 0: case 1: case 2: case 3:
|
||||
push:
|
||||
a = CreateTestBlock(pushee);
|
||||
res = ABQPush(&abq, &a);
|
||||
if (res != ResOK) {
|
||||
if (!ABQPush(&abq, &a)) {
|
||||
goto pop;
|
||||
}
|
||||
pushee++;
|
||||
break;
|
||||
case 5: case 6: case 7: case 8:
|
||||
pop:
|
||||
res = ABQPop(&abq, &a);
|
||||
if (res != ResOK){
|
||||
if (!ABQPop(&abq, &a)) {
|
||||
goto push;
|
||||
}
|
||||
if (popee == deleted) {
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ static void report(mps_arena_t arena)
|
|||
|
||||
mps_message_discard(arena, message);
|
||||
|
||||
if (condemned > (gen1SIZE + gen2SIZE + (size_t)128) * 1024)
|
||||
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.
|
||||
|
|
@ -104,7 +104,8 @@ static void report(mps_arena_t arena)
|
|||
* 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")*/;
|
||||
/*die(mps_arena_commit_limit_set(arena, 2 * testArenaSIZE), "set limit");*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -165,7 +166,7 @@ static void *test(void *arg, size_t s)
|
|||
ramping = 1;
|
||||
objs = 0;
|
||||
while (collections < collectionsCOUNT) {
|
||||
unsigned long c;
|
||||
mps_word_t c;
|
||||
size_t r;
|
||||
|
||||
c = mps_collections(arena);
|
||||
|
|
|
|||
|
|
@ -298,14 +298,15 @@ static void *fooey(void* childIsFinishedReturn)
|
|||
{
|
||||
void *r;
|
||||
mps_thr_t thread;
|
||||
mps_thr_t thread2;
|
||||
void *marker = ▮
|
||||
mps_root_t reg_root;
|
||||
|
||||
/* register the thread twice, just to make sure it works */
|
||||
die(mps_thread_reg(&thread, (mps_arena_t)arena), "thread_reg");
|
||||
die(mps_thread_reg(&thread2, (mps_arena_t)arena), "thread2_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);
|
||||
mps_thread_dereg(thread2);
|
||||
*(int *)childIsFinishedReturn = 1;
|
||||
return r;
|
||||
}
|
||||
|
|
@ -316,7 +317,8 @@ int main(int argc, char *argv[])
|
|||
mps_thr_t thread;
|
||||
mps_root_t reg_root;
|
||||
void *marker = ▮
|
||||
pthread_t pthread1;
|
||||
pthread_t kids[10];
|
||||
unsigned i;
|
||||
void *r;
|
||||
int childIsFinished = 0;
|
||||
|
||||
|
|
@ -330,14 +332,19 @@ int main(int argc, char *argv[])
|
|||
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");
|
||||
pthread_create(&pthread1, NULL, fooey, (void *)&childIsFinished);
|
||||
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_root_destroy(reg_root);
|
||||
mps_thread_dereg(thread);
|
||||
|
||||
while (!childIsFinished) {
|
||||
struct timespec req = {1, 0};
|
||||
(void)nanosleep(&req, NULL);
|
||||
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();
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ static mps_addr_t make(void)
|
|||
/* test -- the actual stress test */
|
||||
|
||||
static mps_pool_debug_option_s freecheckOptions =
|
||||
{ NULL, 0, (void *)"Dead", 4 };
|
||||
{ NULL, 0, (const void *)"Dead", 4 };
|
||||
|
||||
static void *test(void *arg, size_t haveAmbigous)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -128,21 +128,21 @@ static size_t randomSizeAligned(unsigned long i)
|
|||
|
||||
|
||||
static mps_pool_debug_option_s bothOptions8 = {
|
||||
/* .fence_template = */ (void *)"postpost",
|
||||
/* .fence_template = */ (const void *)"postpost",
|
||||
/* .fence_size = */ 8,
|
||||
/* .free_template = */ (void *)"DEAD",
|
||||
/* .free_template = */ (const void *)"DEAD",
|
||||
/* .free_size = */ 4
|
||||
};
|
||||
|
||||
static mps_pool_debug_option_s bothOptions16 = {
|
||||
/* .fence_template = */ (void *)"postpostpostpost",
|
||||
/* .fence_template = */ (const void *)"postpostpostpost",
|
||||
/* .fence_size = */ 16,
|
||||
/* .free_template = */ (void *)"DEAD",
|
||||
/* .free_template = */ (const void *)"DEAD",
|
||||
/* .free_size = */ 4
|
||||
};
|
||||
|
||||
static mps_pool_debug_option_s fenceOptions = {
|
||||
/* .fence_template = */ (void *)"\0XXX ''\"\"'' XXX\0",
|
||||
/* .fence_template = */ (const void *)"\0XXX ''\"\"'' XXX\0",
|
||||
/* .fence_size = */ 16,
|
||||
/* .free_template = */ NULL,
|
||||
/* .free_size = */ 0
|
||||
|
|
@ -158,7 +158,7 @@ static void testInArena(mps_arena_t arena, mps_pool_debug_option_s *options)
|
|||
/* yet (MV Debug works here, because it fakes it through PoolAlloc). */
|
||||
printf("MVFF\n");
|
||||
res = stress(mps_class_mvff(), randomSizeAligned, arena,
|
||||
(size_t)65536, (size_t)32, sizeof(void *), TRUE, TRUE, TRUE);
|
||||
(size_t)65536, (size_t)32, (mps_align_t)MPS_PF_ALIGN, TRUE, TRUE, TRUE);
|
||||
if (res == MPS_RES_COMMIT_LIMIT) return;
|
||||
die(res, "stress MVFF");
|
||||
|
||||
|
|
|
|||
|
|
@ -763,6 +763,26 @@ Bool ArenaHasAddr(Arena arena, Addr addr)
|
|||
}
|
||||
|
||||
|
||||
/* ArenaAddrObject -- find client pointer to object containing addr
|
||||
* See job003589.
|
||||
*/
|
||||
|
||||
Res ArenaAddrObject(Addr *pReturn, Arena arena, Addr addr)
|
||||
{
|
||||
Seg seg;
|
||||
Pool pool;
|
||||
|
||||
AVER(pReturn != NULL);
|
||||
AVERT(Arena, arena);
|
||||
|
||||
if (!SegOfAddr(&seg, arena, addr)) {
|
||||
return ResFAIL;
|
||||
}
|
||||
pool = SegPool(seg);
|
||||
return PoolAddrObject(pReturn, pool, seg, addr);
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
|
|
|
|||
|
|
@ -568,6 +568,7 @@ static Res VMArenaInit(Arena *arenaReturn, ArenaClass class, ArgList args)
|
|||
nono.l = -1;
|
||||
vmArena->blacklist = ZoneSetAdd(arena, vmArena->blacklist, nono.addr);
|
||||
}
|
||||
EVENT2(ArenaBlacklistZone, vmArena, vmArena->blacklist);
|
||||
|
||||
for(gen = (Index)0; gen < VMArenaGenCount; gen++) {
|
||||
vmArena->genZoneSet[gen] = ZoneSetEMPTY;
|
||||
|
|
@ -1473,9 +1474,19 @@ static Res vmAllocComm(Addr *baseReturn, Tract *baseTractReturn,
|
|||
|
||||
if (pref->isGen) {
|
||||
Serial gen = vmGenOfSegPref(vmArena, pref);
|
||||
if (!ZoneSetSuper(vmArena->genZoneSet[gen], zones)) {
|
||||
/* Tracking the whole zoneset for each generation number gives
|
||||
* more understandable telemetry than just reporting the added
|
||||
* zones. */
|
||||
EVENT3(ArenaGenZoneAdd, arena, gen, ZoneSetUnion(vmArena->genZoneSet[gen], zones));
|
||||
}
|
||||
|
||||
vmArena->genZoneSet[gen] = ZoneSetUnion(vmArena->genZoneSet[gen], zones);
|
||||
}
|
||||
|
||||
if (ZoneSetInter(vmArena->freeSet, zones) != ZoneSetEMPTY) {
|
||||
EVENT2(ArenaUseFreeZone, arena, ZoneSetInter(vmArena->freeSet, zones));
|
||||
}
|
||||
vmArena->freeSet = ZoneSetDiff(vmArena->freeSet, zones);
|
||||
|
||||
*baseReturn = base;
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ Bool ArgCheckdouble(Arg arg) {
|
|||
|
||||
ARG_DEFINE_KEY(args_end, Shouldnt);
|
||||
|
||||
ArgStruct mps_args_none[] = {{MPS_KEY_ARGS_END}};
|
||||
ArgStruct mps_args_none[] = {{MPS_KEY_ARGS_END, {0}}};
|
||||
|
||||
|
||||
/* KeyCheck -- check the validity of an argument key */
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ static void initialise_wrapper(mps_word_t *wrapper)
|
|||
* .assume.dylan-obj
|
||||
*/
|
||||
|
||||
static mps_word_t *alloc_string(char *s, mps_ap_t ap)
|
||||
static mps_word_t *alloc_string(const char *s, mps_ap_t ap)
|
||||
{
|
||||
size_t l;
|
||||
size_t objsize;
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ static void initialise_wrapper(mps_word_t *wrapper)
|
|||
* .assume.dylan-obj
|
||||
*/
|
||||
|
||||
static mps_word_t *alloc_string(char *s, mps_ap_t ap)
|
||||
static mps_word_t *alloc_string(const char *s, mps_ap_t ap)
|
||||
{
|
||||
size_t l;
|
||||
size_t objsize;
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ static mps_word_t wrapper_wrapper[] = {
|
|||
UNINIT, /* class */
|
||||
0, /* Extra word */
|
||||
(mps_word_t)4<<2|2, /* F */
|
||||
(mps_word_t)2<<(MPS_WORD_WIDTH - 8), /* V */
|
||||
(mps_word_t)2<<(MPS_WORD_WIDTH - 8), /* V (version 2) */
|
||||
(mps_word_t)1<<2|1, /* VL */
|
||||
1 /* patterns */
|
||||
};
|
||||
|
|
@ -82,7 +82,7 @@ static void initialise_wrapper(mps_word_t *wrapper)
|
|||
/* create a dylan string object (byte vector) whose contents
|
||||
* are the string s (including the terminating NUL)
|
||||
* .assume.dylan-obj */
|
||||
static mps_word_t *alloc_string(char *s, mps_ap_t ap)
|
||||
static mps_word_t *alloc_string(const char *s, mps_ap_t ap)
|
||||
{
|
||||
size_t l;
|
||||
size_t objsize;
|
||||
|
|
@ -120,7 +120,7 @@ static mps_word_t *alloc_table(unsigned long n, mps_ap_t ap)
|
|||
size_t objsize;
|
||||
void *p;
|
||||
mps_word_t *object;
|
||||
objsize = (4 + n) * sizeof(mps_word_t);
|
||||
objsize = (3 + n) * sizeof(mps_word_t);
|
||||
objsize = (objsize + MPS_PF_ALIGN-1)/MPS_PF_ALIGN*MPS_PF_ALIGN;
|
||||
do {
|
||||
unsigned long i;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* bt.c: BIT TABLES
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* READERSHIP
|
||||
*
|
||||
|
|
@ -683,6 +683,9 @@ static Bool BTFindResRange(Index *baseReturn, Index *limitReturn,
|
|||
if (resBase != minLimit) {
|
||||
/* Already found the start of next candidate range */
|
||||
minLimit = resBase + minLength;
|
||||
/* minLimit might just have gone out of bounds, but in that
|
||||
* case resBase >= resLimit and so the loop will exit. */
|
||||
AVER(minLimit <= searchLimit || resBase >= resLimit);
|
||||
} else {
|
||||
foundRes = FALSE;
|
||||
}
|
||||
|
|
@ -776,7 +779,11 @@ static Bool BTFindResRangeHigh(Index *baseReturn, Index *limitReturn,
|
|||
unseenLimit = minBase;
|
||||
resLimit = setIndex;
|
||||
if (resLimit != minBase) {
|
||||
/* Already found the start of next candidate range */
|
||||
/* Already found the start of next candidate range. This wraps
|
||||
* round if minLength > resLimit (all the variables are
|
||||
* unsigned so this behaviour is defined), but that means that
|
||||
* resLimit <= resBase and so the loop will exit. */
|
||||
AVER(resLimit >= minLength || resLimit <= resBase);
|
||||
minBase = resLimit - minLength;
|
||||
} else {
|
||||
foundRes = FALSE;
|
||||
|
|
@ -1020,7 +1027,7 @@ Count BTCountResRange(BT bt, Index base, Index limit)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2013 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 @@
|
|||
/* bttest.c: BIT TABLE TEST
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -240,7 +240,7 @@ static void help(void)
|
|||
|
||||
|
||||
static struct commandShapeStruct {
|
||||
char *name;
|
||||
const char *name;
|
||||
Count min_args;
|
||||
Count max_args;
|
||||
void (*fun)(void);
|
||||
|
|
@ -266,12 +266,12 @@ static struct commandShapeStruct {
|
|||
typedef struct commandShapeStruct *commandShape;
|
||||
|
||||
|
||||
static void obeyCommand(char *command)
|
||||
static void obeyCommand(const char *command)
|
||||
{
|
||||
commandShape shape = commandShapes;
|
||||
while(shape->name != NULL) {
|
||||
char *csp = shape->name;
|
||||
char *p = command;
|
||||
const char *csp = shape->name;
|
||||
const char *p = command;
|
||||
while (*csp == *p) {
|
||||
csp++;
|
||||
p++;
|
||||
|
|
@ -387,7 +387,7 @@ extern int main(int argc, char *argv[])
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2013 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 @@
|
|||
/* buffer.c: ALLOCATION BUFFER IMPLEMENTATION
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .purpose: This is (part of) the implementation of allocation buffers.
|
||||
* Several macros which also form part of the implementation are in
|
||||
|
|
@ -22,7 +22,8 @@
|
|||
* .trans.mod: There are several instances where pool structures are
|
||||
* directly accessed by this module because <code/pool.c> does not provide
|
||||
* an adequate (or adequately documented) interface. They bear this
|
||||
* tag. */
|
||||
* tag.
|
||||
*/
|
||||
|
||||
#include "mpm.h"
|
||||
|
||||
|
|
@ -409,9 +410,9 @@ void BufferFinish(Buffer buffer)
|
|||
|
||||
/* BufferIsReset -- test whether a buffer is in the "reset" state
|
||||
*
|
||||
* A buffer is "reset" when it is not attached. In this state all of
|
||||
* the pointers into the region are zero. This condition is checked by
|
||||
* BufferCheck. */
|
||||
* A buffer is "reset" when it is not attached. In this state, the
|
||||
* base, init, alloc, and limit pointers are all zero. This condition
|
||||
* is checked by BufferCheck. */
|
||||
|
||||
Bool BufferIsReset(Buffer buffer)
|
||||
{
|
||||
|
|
@ -1486,12 +1487,11 @@ static void rankBufVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs)
|
|||
AVER(ArgListCheck(args));
|
||||
}
|
||||
|
||||
|
||||
/* rankBufInit -- RankBufClass init method */
|
||||
|
||||
static Res rankBufInit(Buffer buffer, Pool pool, ArgList args)
|
||||
{
|
||||
Rank rank;
|
||||
Rank rank = BUFFER_RANK_DEFAULT;
|
||||
BufferClass super;
|
||||
Res res;
|
||||
ArgStruct arg;
|
||||
|
|
@ -1499,7 +1499,7 @@ static Res rankBufInit(Buffer buffer, Pool pool, ArgList args)
|
|||
AVERT(Buffer, buffer);
|
||||
AVERT(Pool, pool);
|
||||
AVER(ArgListCheck(args));
|
||||
ArgRequire(&arg, args, MPS_KEY_RANK);
|
||||
if (ArgPick(&arg, args, MPS_KEY_RANK))
|
||||
rank = arg.val.rank;
|
||||
AVER(RankCheck(rank));
|
||||
|
||||
|
|
@ -1536,7 +1536,7 @@ DEFINE_CLASS(RankBufClass, class)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2013 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 @@
|
|||
/* check.h: ASSERTION INTERFACE
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* .aver: This header defines a family of AVER and NOTREACHED macros.
|
||||
|
|
@ -309,12 +309,25 @@ extern unsigned CheckLevel;
|
|||
COMPATLVALUE(((s1 *)0)->f1, ((s2 *)0)->f2))
|
||||
|
||||
|
||||
/* NONNEGATIVE -- test that value is greater than or equal to zero
|
||||
*
|
||||
* We'd like to write "x >= 0" but when x belongs to an unsigned
|
||||
* integral type then this results in a "comparison of unsigned
|
||||
* expression >= 0 is always true" warning from GCC if -Wextra is
|
||||
* specified. We also don't want to remove these assertions because
|
||||
* they protect us against errors if the type of x should ever be
|
||||
* changed to a signed type on some platform.
|
||||
*
|
||||
* Note that this macro evaluates its argument twice.
|
||||
*/
|
||||
#define NONNEGATIVE(x) ((x) == 0 || (x) > 0)
|
||||
|
||||
#endif /* check_h */
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -78,9 +78,18 @@ typedef union EventClockUnion {
|
|||
|
||||
#elif defined(MPS_ARCH_I6)
|
||||
|
||||
#if defined(MPS_BUILD_MV)
|
||||
|
||||
#define EVENT_CLOCK_PRINT(stream, clock) \
|
||||
fprintf(stream, "%016llX", (clock));
|
||||
|
||||
#else
|
||||
|
||||
#define EVENT_CLOCK_PRINT(stream, clock) \
|
||||
fprintf(stream, "%016lX", (clock));
|
||||
|
||||
#endif
|
||||
|
||||
#define EVENT_CLOCK_WRITE(stream, clock) \
|
||||
WriteF(stream, "$W", (WriteFW)(clock), NULL)
|
||||
|
||||
|
|
|
|||
|
|
@ -134,6 +134,9 @@ ifeq ($(VARIETY),cool)
|
|||
CFLAGS=$(CFLAGSCOMMON) $(CFCOOL)
|
||||
CFLAGSLAX=$(CFLAGSCOMMONLAX) $(CFCOOL)
|
||||
else
|
||||
ifneq ($(VARIETY),)
|
||||
$(error Variety "$(VARIETY)" not recognized: must be rash/hot/cool)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
|
@ -160,7 +163,7 @@ FMTDY = fmtdy.c fmtno.c
|
|||
FMTDYTST = fmtdy.c fmtno.c fmtdytst.c
|
||||
FMTHETST = fmthe.c fmtdy.c fmtno.c fmtdytst.c
|
||||
PLINTH = mpsliban.c mpsioan.c
|
||||
EVENTPROC = eventcnv.c eventpro.c table.c
|
||||
EVENTPROC = eventcnv.c table.c
|
||||
MPMCOMMON = abq.c arena.c arenacl.c arenavm.c arg.c boot.c bt.c \
|
||||
buffer.c cbs.c dbgpool.c dbgpooli.c event.c format.c \
|
||||
freelist.c global.c ld.c locus.c message.c meter.c mpm.c mpsi.c \
|
||||
|
|
@ -221,19 +224,18 @@ LIB_TARGETS=mps.a mpsplan.a
|
|||
# If it is suitable for running regularly (for example, after every
|
||||
# build) as an automated test case, add it to AUTO_TEST_TARGETS.
|
||||
|
||||
AUTO_TEST_TARGETS=abqtest amcss amcsshe amsss amssshe apss \
|
||||
arenacv awlut awluthe btcv exposet0 expt825 fbmtest finalcv \
|
||||
AUTO_TEST_TARGETS=abqtest amcss amcsshe amcssth amsss amssshe apss \
|
||||
arenacv awlut awluthe awlutth btcv exposet0 expt825 fbmtest finalcv \
|
||||
finaltest fotest lockcov locv messtest mpmss mpsicv mv2test \
|
||||
poolncv qs sacss segsmss steptest walkt0 zmess
|
||||
|
||||
# If it is not runnable as an automated test case, but is buildable,
|
||||
# add it to OTHER_TEST_TARGETS with a note.
|
||||
#
|
||||
# awlutth -- fails (job003506).
|
||||
# bttest and teletest -- interactive and so cannot be run unattended.
|
||||
# zcoll -- takes too long to be useful as a regularly run smoke test.
|
||||
|
||||
OTHER_TEST_TARGETS=awlutth bttest teletest zcoll
|
||||
OTHER_TEST_TARGETS=bttest teletest zcoll
|
||||
|
||||
# This target records programs that we were once able to build but
|
||||
# can't at the moment:
|
||||
|
|
@ -439,7 +441,7 @@ $(PFM)/$(VARIETY)/zmess: $(PFM)/$(VARIETY)/zmess.o \
|
|||
$(FMTDYTSTOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a
|
||||
|
||||
$(PFM)/$(VARIETY)/mpseventcnv: $(PFM)/$(VARIETY)/eventcnv.o \
|
||||
$(PFM)/$(VARIETY)/eventpro.o $(PFM)/$(VARIETY)/mps.a
|
||||
$(PFM)/$(VARIETY)/mps.a
|
||||
|
||||
$(PFM)/$(VARIETY)/mpseventtxt: $(PFM)/$(VARIETY)/eventtxt.o \
|
||||
$(PFM)/$(VARIETY)/mps.a
|
||||
|
|
@ -449,7 +451,7 @@ $(PFM)/$(VARIETY)/mpseventsql: $(PFM)/$(VARIETY)/eventsql.o \
|
|||
|
||||
$(PFM)/$(VARIETY)/replay: $(PFM)/$(VARIETY)/replay.o \
|
||||
$(PFM)/$(VARIETY)/eventrep.o \
|
||||
$(PFM)/$(VARIETY)/eventpro.o $(PFM)/$(VARIETY)/table.o \
|
||||
$(PFM)/$(VARIETY)/table.o \
|
||||
$(PFM)/$(VARIETY)/mps.a
|
||||
|
||||
$(PFM)/$(VARIETY)/mpsplan.a: $(PLINTHOBJ)
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ mpsicv.cov:
|
|||
|
||||
testrun: $(AUTO_TEST_TARGETS)
|
||||
!IFDEF VARIETY
|
||||
set MPS_TESTLIB_NOABORT=true
|
||||
..\tool\testrun.bat $(PFM) $(VARIETY) $(AUTO_TEST_TARGETS)
|
||||
!ELSE
|
||||
$(MAKE) /nologo /f $(PFM).nmk VARIETY=hot testrun
|
||||
|
|
@ -152,6 +153,9 @@ $(PFM)\$(VARIETY)\btcv.exe: $(PFM)\$(VARIETY)\btcv.obj \
|
|||
$(PFM)\$(VARIETY)\bttest.exe: $(PFM)\$(VARIETY)\bttest.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
|
||||
|
||||
$(PFM)\$(VARIETY)\cvmicv.exe: $(PFM)\$(VARIETY)\cvmicv.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
|
||||
|
||||
$(PFM)\$(VARIETY)\exposet0.exe: $(PFM)\$(VARIETY)\exposet0.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
|
||||
|
||||
|
|
@ -219,15 +223,16 @@ $(PFM)\$(VARIETY)\walkt0.exe: $(PFM)\$(VARIETY)\walkt0.obj \
|
|||
$(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
|
||||
|
||||
$(PFM)\$(VARIETY)\zcoll.exe: $(PFM)\$(VARIETY)\zcoll.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) \
|
||||
$(TESTLIBOBJ)
|
||||
$(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
|
||||
|
||||
$(PFM)\$(VARIETY)\zmess.exe: $(PFM)\$(VARIETY)\zmess.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) \
|
||||
$(TESTLIBOBJ)
|
||||
$(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
|
||||
|
||||
$(PFM)\$(VARIETY)\ztfm.exe: $(PFM)\$(VARIETY)\ztfm.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
|
||||
|
||||
$(PFM)\$(VARIETY)\mpseventcnv.exe: $(PFM)\$(VARIETY)\eventcnv.obj \
|
||||
$(PFM)\$(VARIETY)\eventpro.obj $(PFM)\$(VARIETY)\mps.lib
|
||||
$(PFM)\$(VARIETY)\mps.lib
|
||||
|
||||
$(PFM)\$(VARIETY)\mpseventtxt.exe: $(PFM)\$(VARIETY)\eventtxt.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib
|
||||
|
|
@ -237,7 +242,7 @@ $(PFM)\$(VARIETY)\mpseventsql.exe: $(PFM)\$(VARIETY)\eventsql.obj \
|
|||
|
||||
$(PFM)\$(VARIETY)\replay.exe: $(PFM)\$(VARIETY)\replay.obj \
|
||||
$(PFM)\$(VARIETY)\eventrep.obj \
|
||||
$(PFM)\$(VARIETY)\eventpro.obj $(PFM)\$(VARIETY)\table.obj \
|
||||
$(PFM)\$(VARIETY)\table.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib
|
||||
|
||||
# Have to rename the object file, because the names must match, or
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* config.h: MPS CONFIGURATION
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2003, 2006 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (c) 2002 Global Graphics Software.
|
||||
*
|
||||
* PURPOSE
|
||||
|
|
@ -219,6 +219,11 @@
|
|||
#define EPVMDefaultSubsequentSegSIZE ((Size)64 * 1024)
|
||||
|
||||
|
||||
/* Buffer Configuration -- see <code/buffer.c> */
|
||||
|
||||
#define BUFFER_RANK_DEFAULT (mps_rank_exact())
|
||||
|
||||
|
||||
/* CBS Configuration -- see <code/cbs.c> */
|
||||
|
||||
#define CBS_EXTEND_BY_DEFAULT ((Size)4096)
|
||||
|
|
@ -236,6 +241,11 @@
|
|||
#define FMT_CLASS_DEFAULT (&FormatDefaultClass)
|
||||
|
||||
|
||||
/* Pool AMS Configuration -- see <code/poolams.c> */
|
||||
|
||||
#define AMS_SUPPORT_AMBIGUOUS_DEFAULT FALSE
|
||||
|
||||
|
||||
/* Pool MV Configuration -- see <code/poolmv.c> */
|
||||
|
||||
#define MV_EXTEND_BY_DEFAULT ((Size)65536)
|
||||
|
|
@ -312,9 +322,11 @@
|
|||
*/
|
||||
#if defined(MPS_ARCH_I3) && defined(MPS_BUILD_MV)
|
||||
#define StackProbeDEPTH ((Size)500)
|
||||
#elif defined(MPS_PF_W3I6MV)
|
||||
#define StackProbeDEPTH ((Size)500)
|
||||
#else
|
||||
#define StackProbeDEPTH ((Size)0)
|
||||
#endif /* MPS_ARCH_I3 */
|
||||
#endif
|
||||
|
||||
|
||||
/* Shield Configuration -- see <code/shield.c> */
|
||||
|
|
@ -344,19 +356,46 @@
|
|||
* pthrdext.c sigaction etc. <signal.h> _XOPEN_SOURCE
|
||||
* vmix.c MAP_ANON <sys/mman.h> _GNU_SOURCE
|
||||
*
|
||||
* Unfortunately it's not possible to localize these feature
|
||||
* specifications around the individual headers: all headers share a
|
||||
* common set of features (via <feature.h>) and so all sources in the
|
||||
* same compilation unit must turn on the same set of features.
|
||||
* It is not possible to localize these feature specifications around
|
||||
* the individual headers: all headers share a common set of features
|
||||
* (via <feature.h>) and so all sources in the same compilation unit
|
||||
* must turn on the same set of features.
|
||||
*
|
||||
* See "Feature Test Macros" in the GCC Manual:
|
||||
* See "Feature Test Macros" in the Glibc Manual:
|
||||
* <http://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html>
|
||||
*/
|
||||
|
||||
#if defined(MPS_OS_LI)
|
||||
|
||||
#define _XOPEN_SOURCE 500
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* .feature.xc: OS X feature specification
|
||||
*
|
||||
* The MPS needs the following symbols which are not defined by default
|
||||
*
|
||||
* Source Symbols Header Feature
|
||||
* =========== ========================= ============= ====================
|
||||
* prmci3li.c __eax etc. <ucontext.h> _XOPEN_SOURCE
|
||||
* prmci6li.c __rax etc. <ucontext.h> _XOPEN_SOURCE
|
||||
*
|
||||
* It is not possible to localize these feature specifications around
|
||||
* the individual headers: all headers share a common set of features
|
||||
* (via <sys/cdefs.h>) and so all sources in the same compilation unit
|
||||
* must turn on the same set of features.
|
||||
*/
|
||||
|
||||
#if defined(MPS_OS_XC)
|
||||
|
||||
#if !defined(_XOPEN_SOURCE)
|
||||
#define _XOPEN_SOURCE
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -369,17 +408,40 @@
|
|||
|
||||
#if defined(MPS_OS_FR)
|
||||
#define PROT_SIGNAL (SIGSEGV)
|
||||
#elif defined(MPS_OS_XC)
|
||||
#define PROT_SIGNAL (SIGBUS)
|
||||
#endif
|
||||
|
||||
#if defined(MPS_OS_XC)
|
||||
#define PROT_SIGINFO_GOOD(info) (1)
|
||||
#elif defined(MPS_OS_FR)
|
||||
#if defined(MPS_OS_FR)
|
||||
#define PROT_SIGINFO_GOOD(info) ((info)->si_code == SEGV_ACCERR)
|
||||
#endif
|
||||
|
||||
|
||||
/* Almost all of protxc.c etc. are architecture-independent, but unfortunately
|
||||
the Mach headers don't provide architecture neutral symbols for simple
|
||||
things like thread states. These definitions fix that. */
|
||||
|
||||
#if defined(MPS_OS_XC)
|
||||
#if defined(MPS_ARCH_I6)
|
||||
|
||||
#define THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT
|
||||
#define THREAD_STATE_FLAVOR x86_THREAD_STATE64
|
||||
#define THREAD_STATE_S x86_thread_state64_t
|
||||
|
||||
#elif defined(MPS_ARCH_I3)
|
||||
|
||||
#define THREAD_STATE_COUNT x86_THREAD_STATE32_COUNT
|
||||
#define THREAD_STATE_FLAVOR x86_THREAD_STATE32
|
||||
#define THREAD_STATE_S x86_thread_state32_t
|
||||
|
||||
#else
|
||||
|
||||
#error "Unknown OS X architecture"
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/* Tracer Configuration -- see <code/trace.c> */
|
||||
|
||||
#define TraceLIMIT ((size_t)1)
|
||||
|
|
@ -458,7 +520,7 @@
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2003, 2006 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -80,7 +80,8 @@ failWrite:
|
|||
void EventFlush(EventKind kind)
|
||||
{
|
||||
AVER(eventInited);
|
||||
AVER(0 <= kind && kind < EventKindLIMIT);
|
||||
AVER(NONNEGATIVE(kind));
|
||||
AVER(kind < EventKindLIMIT);
|
||||
|
||||
AVER(EventBuffer[kind] <= EventLast[kind]);
|
||||
AVER(EventLast[kind] <= EventWritten[kind]);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* eventcnv.c: Simple event log converter
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* This is a command-line tool that converts a binary format telemetry output
|
||||
* stream from the MPS into a more-portable textual format.
|
||||
|
|
@ -37,7 +37,6 @@
|
|||
#include "config.h"
|
||||
#include "eventdef.h"
|
||||
#include "eventcom.h"
|
||||
#include "eventpro.h"
|
||||
#include "testlib.h" /* for ulongest_t and associated print formats */
|
||||
|
||||
#include <stddef.h> /* for size_t */
|
||||
|
|
@ -57,7 +56,7 @@
|
|||
#define TELEMETRY_FILENAME_ENVAR "MPS_TELEMETRY_FILENAME"
|
||||
|
||||
static EventClock eventTime; /* current event time */
|
||||
static char *prog; /* program name */
|
||||
static const char *prog; /* program name */
|
||||
|
||||
/* Errors and Warnings */
|
||||
|
||||
|
|
@ -183,19 +182,63 @@ static void printParamS(const char *str)
|
|||
putchar('"');
|
||||
}
|
||||
|
||||
|
||||
/* EventRead -- read one event from the file */
|
||||
|
||||
static Res eventRead(Bool *eofOut, EventUnion *event, FILE *stream)
|
||||
{
|
||||
size_t n;
|
||||
size_t rest;
|
||||
|
||||
/* Read the prefix common to all event structures, in order to decode the
|
||||
event size. */
|
||||
n = fread(&event->any, sizeof(event->any), 1, stream);
|
||||
if (n < 1) {
|
||||
if (feof(stream)) {
|
||||
*eofOut = TRUE;
|
||||
return ResOK;
|
||||
}
|
||||
return ResIO;
|
||||
}
|
||||
|
||||
/* Read the rest of the event. */
|
||||
rest = event->any.size - sizeof(event->any);
|
||||
if (rest > 0) {
|
||||
n = fread((char *)event + sizeof(event->any), rest, 1, stream);
|
||||
if (n < 1) {
|
||||
if (feof(stream))
|
||||
return ResFAIL; /* truncated event */
|
||||
else
|
||||
return ResIO;
|
||||
}
|
||||
}
|
||||
|
||||
*eofOut = FALSE;
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
/* readLog -- read and parse log */
|
||||
|
||||
static void readLog(EventProc proc)
|
||||
static void readLog(FILE *stream)
|
||||
{
|
||||
while (TRUE) { /* loop for each event */
|
||||
Event event;
|
||||
for(;;) { /* loop for each event */
|
||||
EventUnion eventUnion;
|
||||
Event event = &eventUnion;
|
||||
EventCode code;
|
||||
Res res;
|
||||
Bool eof = FALSE; /* suppress warnings about uninitialized use */
|
||||
|
||||
/* Read and parse event. */
|
||||
res = EventRead(&event, proc);
|
||||
if (res == ResFAIL) break; /* eof */
|
||||
if (res != ResOK) everror("Truncated log");
|
||||
res = eventRead(&eof, event, stream);
|
||||
if (res == ResFAIL)
|
||||
everror("Truncated log");
|
||||
else if (res == ResIO)
|
||||
everror("I/O error reading log");
|
||||
else if (res != ResOK)
|
||||
everror("Unknown error reading log");
|
||||
if (eof)
|
||||
break;
|
||||
|
||||
eventTime = event->any.clock;
|
||||
code = event->any.code;
|
||||
|
||||
|
|
@ -244,22 +287,9 @@ static void readLog(EventProc proc)
|
|||
|
||||
putchar('\n');
|
||||
fflush(stdout);
|
||||
EventDestroy(proc, event);
|
||||
} /* while(!feof(input)) */
|
||||
}
|
||||
|
||||
/* logReader -- reader function for a file log */
|
||||
|
||||
static FILE *input;
|
||||
|
||||
static Res logReader(void *file, void *p, size_t len)
|
||||
{
|
||||
size_t n;
|
||||
|
||||
n = fread(p, 1, len, (FILE *)file);
|
||||
return (n < len) ? (feof((FILE *)file) ? ResFAIL : ResIO) : ResOK;
|
||||
}
|
||||
|
||||
|
||||
/* CHECKCONV -- check t2 can be cast to t1 without loss */
|
||||
|
||||
|
|
@ -271,9 +301,8 @@ static Res logReader(void *file, void *p, size_t len)
|
|||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *filename;
|
||||
EventProc proc;
|
||||
Res res;
|
||||
const char *filename;
|
||||
FILE *input;
|
||||
|
||||
assert(CHECKCONV(ulongest_t, Word));
|
||||
assert(CHECKCONV(ulongest_t, Addr));
|
||||
|
|
@ -295,20 +324,15 @@ int main(int argc, char *argv[])
|
|||
everror("unable to open \"%s\"\n", filename);
|
||||
}
|
||||
|
||||
res = EventProcCreate(&proc, logReader, (void *)input);
|
||||
if (res != ResOK)
|
||||
everror("Can't init EventProc module: error %d.", res);
|
||||
readLog(input);
|
||||
|
||||
readLog(proc);
|
||||
|
||||
EventProcDestroy(proc);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2012 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
|
||||
#define EVENT_VERSION_MAJOR ((unsigned)1)
|
||||
#define EVENT_VERSION_MEDIAN ((unsigned)1)
|
||||
#define EVENT_VERSION_MINOR ((unsigned)4)
|
||||
#define EVENT_VERSION_MINOR ((unsigned)6)
|
||||
|
||||
|
||||
/* EVENT_LIST -- list of event types and general properties
|
||||
|
|
@ -68,7 +68,7 @@
|
|||
*/
|
||||
|
||||
#define EventNameMAX ((size_t)19)
|
||||
#define EventCodeMAX ((EventCode)0x0082)
|
||||
#define EventCodeMAX ((EventCode)0x0086)
|
||||
|
||||
#define EVENT_LIST(EVENT, X) \
|
||||
/* 0123456789012345678 <- don't exceed without changing EventNameMAX */ \
|
||||
|
|
@ -176,7 +176,7 @@
|
|||
EVENT(X, MessagesDropped , 0x006D, TRUE, Arena) \
|
||||
EVENT(X, MessagesExist , 0x006E, TRUE, Arena) \
|
||||
EVENT(X, ChainCondemnAuto , 0x006F, TRUE, Trace) \
|
||||
EVENT(X, TraceFindGrey , 0x0070, TRUE, Trace) \
|
||||
EVENT(X, TraceFindGrey , 0x0070, TRUE, Seg) \
|
||||
EVENT(X, TraceBandAdvance , 0x0071, TRUE, Trace) \
|
||||
EVENT(X, AWLDeclineTotal , 0x0072, TRUE, Trace) \
|
||||
EVENT(X, AWLDeclineSeg , 0x0073, TRUE, Trace) \
|
||||
|
|
@ -188,7 +188,12 @@
|
|||
EVENT(X, VMCompact , 0x0079, TRUE, Arena) \
|
||||
EVENT(X, amcScanNailed , 0x0080, TRUE, Seg) \
|
||||
EVENT(X, AMCTraceEnd , 0x0081, TRUE, Trace) \
|
||||
EVENT(X, TraceStartPoolGen , 0x0082, TRUE, Trace)
|
||||
EVENT(X, TraceStartPoolGen , 0x0082, TRUE, Trace) \
|
||||
/* new events for performance analysis of large heaps. */ \
|
||||
EVENT(X, TraceCondemnZones , 0x0083, TRUE, Trace) \
|
||||
EVENT(X, ArenaGenZoneAdd , 0x0084, TRUE, Arena) \
|
||||
EVENT(X, ArenaUseFreeZone , 0x0085, TRUE, Arena) \
|
||||
EVENT(X, ArenaBlacklistZone , 0x0086, TRUE, Arena)
|
||||
|
||||
|
||||
/* Remember to update EventNameMAX and EventCodeMAX above!
|
||||
|
|
@ -721,6 +726,24 @@
|
|||
PARAM(X, 9, W, totalSize) /* total size of pool gen */ \
|
||||
PARAM(X, 10, W, newSizeAtCreate) /* new size of pool gen at trace create */
|
||||
|
||||
#define EVENT_TraceCondemnZones_PARAMS(PARAM, X) \
|
||||
PARAM(X, 0, P, trace) /* the trace */ \
|
||||
PARAM(X, 1, W, condemnedSet) /* the condemned zoneSet */ \
|
||||
PARAM(X, 2, W, white) /* the trace's white zoneSet */
|
||||
|
||||
#define EVENT_ArenaGenZoneAdd_PARAMS(PARAM, X) \
|
||||
PARAM(X, 0, P, arena) /* the arena */ \
|
||||
PARAM(X, 1, W, gen) /* the generation number */ \
|
||||
PARAM(X, 2, W, zoneSet) /* the new zoneSet */
|
||||
|
||||
#define EVENT_ArenaUseFreeZone_PARAMS(PARAM, X) \
|
||||
PARAM(X, 0, P, arena) /* the arena */ \
|
||||
PARAM(X, 1, W, zoneSet) /* zones that aren't free any longer */
|
||||
|
||||
#define EVENT_ArenaBlacklistZone_PARAMS(PARAM, X) \
|
||||
PARAM(X, 0, P, arena) /* the arena */ \
|
||||
PARAM(X, 1, W, zoneSet) /* the blacklist zoneset */
|
||||
|
||||
|
||||
#endif /* eventdef_h */
|
||||
|
||||
|
|
|
|||
|
|
@ -1,463 +0,0 @@
|
|||
/* eventpro.c: Event processing routines
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "table.h"
|
||||
#include "eventdef.h"
|
||||
#include "eventcom.h"
|
||||
#include "eventpro.h"
|
||||
#include "misc.h"
|
||||
#include "mpmtypes.h"
|
||||
#include "testlib.h" /* for ulongest_t and associated print formats */
|
||||
|
||||
#include <assert.h> /* assert */
|
||||
#include <stdlib.h> /* size_t */
|
||||
#include <string.h> /* strcmp */
|
||||
|
||||
struct EventProcStruct {
|
||||
EventProcReader reader; /* reader fn */
|
||||
void *readerP; /* closure pointer for reader fn */
|
||||
Table internTable; /* dictionary of intern ids to symbols */
|
||||
Table labelTable; /* dictionary of addrs to intern ids */
|
||||
void *cachedEvent;
|
||||
};
|
||||
|
||||
|
||||
/* error -- error signalling
|
||||
*
|
||||
* Should integrate with client exceptions, but that'll do for now.
|
||||
*/
|
||||
|
||||
#define error(fmt, arg) assert(((void)fmt, FALSE));
|
||||
|
||||
|
||||
/* PointerAdd -- add offset to pointer
|
||||
*
|
||||
* Copy of the def in mpm.h which we can't include
|
||||
*/
|
||||
|
||||
#define PointerAdd(p, s) ((void *)((char *)(p) + (s)))
|
||||
|
||||
|
||||
/* sizeAlignUp -- align size_t values up */
|
||||
|
||||
#define sizeAlignUp(w, a) (((w) + (a) - 1) & ~((size_t)(a) - 1))
|
||||
|
||||
|
||||
/* EventSizeAlign -- Calculate actual size of event in the output
|
||||
*
|
||||
* Calculates the actual size of an event in the output, given the size
|
||||
* of the structure. This has to agree with the writing (EVENT_END).
|
||||
*/
|
||||
|
||||
/* TODO: Should read this and other layout information from an event file
|
||||
header in order to be able to process events from other architectures. */
|
||||
|
||||
#define EventSizeAlign(size) sizeAlignUp(size, MPS_PF_ALIGN)
|
||||
|
||||
|
||||
|
||||
/* Event types */
|
||||
|
||||
|
||||
/* eventTypes -- an array containing info about the event types */
|
||||
|
||||
typedef struct {
|
||||
char *name; /* Event name e.g. "TraceStart" */
|
||||
EventCode code;
|
||||
size_t size; /* event record size, rounded up from structure */
|
||||
Count count; /* Parameter count */
|
||||
char *format; /* string format, e.g. "PPW" */
|
||||
} eventRecord;
|
||||
|
||||
#define EVENT_COUNT_PARAM(X, index, sort, ident) + 1
|
||||
|
||||
#define EVENT_FORMAT_PARAM(X, index, sort, ident) #sort
|
||||
|
||||
#define EVENT_INIT(X, name, code, always, kind) \
|
||||
{#name, \
|
||||
code, \
|
||||
EventSizeAlign(sizeof(Event##name##Struct)), \
|
||||
0 EVENT_##name##_PARAMS(EVENT_COUNT_PARAM, X), \
|
||||
"" EVENT_##name##_PARAMS(EVENT_FORMAT_PARAM, X)},
|
||||
|
||||
static eventRecord eventTypes[] = {
|
||||
{"(unused)", 0, 0, 0, ""},
|
||||
EVENT_LIST(EVENT_INIT, X)
|
||||
};
|
||||
|
||||
#define eventTypeCount (sizeof(eventTypes) / sizeof(eventRecord))
|
||||
|
||||
|
||||
/* eventcode2Index -- find index in eventTypes for the given code */
|
||||
|
||||
static size_t eventCode2Index(EventCode code, Bool errorp)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for(i = 0; i < eventTypeCount; ++i)
|
||||
if (eventTypes[i].code == code)
|
||||
return i;
|
||||
if (errorp)
|
||||
error("Unknown event code %0"PRIwWORD PRIXLONGEST, (ulongest_t)code);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* EventName2Code -- find event code for the given event name */
|
||||
|
||||
EventCode EventName2Code(char *name)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for(i = 0; i < eventTypeCount; ++i)
|
||||
if (strcmp(eventTypes[i].name, name) == 0) {
|
||||
assert(eventTypes[i].code <= EventCodeMAX);
|
||||
return eventTypes[i].code;
|
||||
}
|
||||
error("Unknown event name %s", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* EventCode2Name -- find event name for the given event code */
|
||||
|
||||
char *EventCode2Name(EventCode code)
|
||||
{
|
||||
return eventTypes[eventCode2Index(code, TRUE)].name;
|
||||
}
|
||||
|
||||
|
||||
/* EventCode2Format -- find format for the given event code */
|
||||
|
||||
char *EventCode2Format(EventCode code)
|
||||
{
|
||||
return eventTypes[eventCode2Index(code, TRUE)].format;
|
||||
}
|
||||
|
||||
|
||||
Bool EventCodeIsValid(EventCode code)
|
||||
{
|
||||
return (eventCode2Index(code, FALSE) != 0);
|
||||
}
|
||||
|
||||
|
||||
/* EventStrings */
|
||||
|
||||
|
||||
/* eventStringCopy -- copy an event string */
|
||||
|
||||
static Res stringCopy(char **str_o, char *str)
|
||||
{
|
||||
char *newStr;
|
||||
size_t len, size;
|
||||
|
||||
len = strlen(str);
|
||||
size = len + sizeof('\0');
|
||||
newStr = (char *)malloc(size);
|
||||
if (newStr == NULL) return ResMEMORY;
|
||||
memcpy(newStr, str, size);
|
||||
*str_o = newStr;
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
||||
static void eventStringDestroy(char *str)
|
||||
{
|
||||
free(str);
|
||||
}
|
||||
|
||||
|
||||
/* Labels */
|
||||
|
||||
|
||||
/* Symbol -- representation of an interned string */
|
||||
|
||||
typedef struct symbolStruct {
|
||||
Word id;
|
||||
char *name;
|
||||
} symbolStruct;
|
||||
typedef struct symbolStruct *Symbol;
|
||||
|
||||
|
||||
/* Label -- representation of a labelled address */
|
||||
|
||||
typedef struct labelStruct {
|
||||
Word id;
|
||||
EventClock time;
|
||||
Addr addr;
|
||||
} labelStruct;
|
||||
typedef struct labelStruct *Label;
|
||||
|
||||
|
||||
/* AddrLabel -- return intern id for given addr (or 0 if none) */
|
||||
|
||||
Word AddrLabel(EventProc proc, Addr addr)
|
||||
{
|
||||
void *entry;
|
||||
|
||||
if (TableLookup(&entry, proc->labelTable, (Word)addr))
|
||||
return ((Label)entry)->id;
|
||||
else
|
||||
return (Word)0;
|
||||
}
|
||||
|
||||
|
||||
/* LabelText -- return text for given intern id (or NULL if none) */
|
||||
|
||||
char *LabelText(EventProc proc, Word id)
|
||||
{
|
||||
void *entry;
|
||||
|
||||
if (TableLookup(&entry, proc->internTable, id))
|
||||
return ((Symbol)entry)->name;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Processing */
|
||||
|
||||
|
||||
/* EventRead -- read one event from the file and allocate descriptor */
|
||||
|
||||
#define internStrOffset (offsetof(EventInternStruct, f1.str))
|
||||
|
||||
Res EventRead(Event *eventReturn, EventProc proc)
|
||||
{
|
||||
Res res;
|
||||
EventAnyStruct anyStruct;
|
||||
Event event;
|
||||
|
||||
/* Read the prefix common to all event structures, in order to decode the
|
||||
event size. */
|
||||
res = proc->reader(proc->readerP, &anyStruct, sizeof(anyStruct));
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
/* Get memory for the event. */
|
||||
if (proc->cachedEvent != NULL) {
|
||||
event = proc->cachedEvent;
|
||||
proc->cachedEvent = NULL;
|
||||
} else {
|
||||
/* This is too long for most events, but never mind. */
|
||||
event = (Event)malloc(sizeof(EventUnion));
|
||||
if (event == NULL)
|
||||
return ResMEMORY;
|
||||
}
|
||||
|
||||
/* Copy the event prefix and read the rest of the event into the memory. */
|
||||
event->any = anyStruct;
|
||||
res = proc->reader(proc->readerP,
|
||||
PointerAdd(event, sizeof(anyStruct)),
|
||||
anyStruct.size - sizeof(anyStruct));
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
*eventReturn = event;
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
||||
/* EventRecord -- record event in databases
|
||||
*
|
||||
* Currently only labels are tracked, but perhaps there will be other
|
||||
* stuff in the future.
|
||||
*/
|
||||
|
||||
Res EventRecord(EventProc proc, Event event, EventClock etime)
|
||||
{
|
||||
Res res;
|
||||
|
||||
switch(event->any.code) {
|
||||
case EventInternCode: { /* id, label */
|
||||
Symbol sym = malloc(sizeof(symbolStruct));
|
||||
|
||||
if (sym == NULL) return ResMEMORY;
|
||||
sym->id = event->Intern.f0;
|
||||
res = stringCopy(&sym->name, event->Intern.f1);
|
||||
if (res != ResOK) {
|
||||
free(sym);
|
||||
return res;
|
||||
}
|
||||
res = TableDefine(proc->internTable, sym->id, sym);
|
||||
} break;
|
||||
case EventLabelCode: { /* addr, id */
|
||||
Label label = malloc(sizeof(labelStruct));
|
||||
void *entry;
|
||||
|
||||
if (label == NULL) return ResMEMORY;
|
||||
label->id = event->Label.f1;
|
||||
/* If events were in time order we'd be able to assert that
|
||||
TableLookup(&entry, proc->internTable, label->id) */
|
||||
label->time = etime;
|
||||
label->addr = event->Label.f0;
|
||||
if (TableLookup(&entry, proc->labelTable, (Word)label->addr))
|
||||
res = TableRedefine(proc->labelTable, (Word)label->addr, label);
|
||||
else
|
||||
res = TableDefine(proc->labelTable, (Word)label->addr, label);
|
||||
} break;
|
||||
default:
|
||||
res = ResOK;
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* EventDestroy -- destroy an event */
|
||||
|
||||
void EventDestroy(EventProc proc, Event event)
|
||||
{
|
||||
if (proc->cachedEvent == NULL)
|
||||
proc->cachedEvent = event;
|
||||
else
|
||||
free(event);
|
||||
}
|
||||
|
||||
|
||||
/* initialization and finishing */
|
||||
|
||||
|
||||
/* Checking macros, copied from check.h */
|
||||
|
||||
#define COMPATLVALUE(lv1, lv2) \
|
||||
((void)sizeof((lv1) = (lv2)), (void)sizeof((lv2) = (lv1)), TRUE)
|
||||
|
||||
#define COMPATTYPE(t1, t2) \
|
||||
(sizeof(t1) == sizeof(t2) && \
|
||||
COMPATLVALUE(*((t1 *)0), *((t2 *)0)))
|
||||
|
||||
#define COMPATFIELDAPPROX(s1, f1, s2, f2) \
|
||||
(sizeof(((s1 *)0)->f1) == sizeof(((s2 *)0)->f2) && \
|
||||
offsetof(s1, f1) == offsetof(s2, f2))
|
||||
|
||||
#define COMPATFIELD(s1, f1, s2, f2) \
|
||||
(COMPATFIELDAPPROX(s1, f1, s2, f2) && \
|
||||
COMPATLVALUE(((s1 *)0)->f1, ((s2 *)0)->f2))
|
||||
|
||||
|
||||
/* EventProcCreate -- initialize the module */
|
||||
|
||||
static void *tableAlloc(void *closure, size_t size)
|
||||
{
|
||||
UNUSED(closure);
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
static void tableFree(void *closure, void *p, size_t size)
|
||||
{
|
||||
UNUSED(closure);
|
||||
UNUSED(size);
|
||||
free(p);
|
||||
}
|
||||
|
||||
Res EventProcCreate(EventProc *procReturn,
|
||||
EventProcReader reader,
|
||||
void *readerP)
|
||||
{
|
||||
Res res;
|
||||
EventProc proc = malloc(sizeof(struct EventProcStruct));
|
||||
|
||||
if (proc == NULL) return ResMEMORY;
|
||||
|
||||
/* check event struct access */
|
||||
assert(COMPATFIELD(EventUnion, any.code, EventInternStruct, code));
|
||||
assert(COMPATFIELD(EventUnion, any.clock, EventInternStruct, clock));
|
||||
/* check use of labelTable */
|
||||
assert(sizeof(Word) >= sizeof(Addr));
|
||||
|
||||
proc->reader = reader; proc->readerP = readerP;
|
||||
res = TableCreate(&proc->internTable,
|
||||
(size_t)1<<4,
|
||||
tableAlloc, tableFree, NULL,
|
||||
(Word)-1, (Word)-2); /* because MPS IDs are serials from zero up */
|
||||
if (res != ResOK) goto failIntern;
|
||||
res = TableCreate(&proc->labelTable, (size_t)1<<7,
|
||||
tableAlloc, tableFree, NULL,
|
||||
0, 1); /* no Addrs down here */
|
||||
if (res != ResOK) goto failLabel;
|
||||
proc->cachedEvent = NULL;
|
||||
*procReturn = proc;
|
||||
return ResOK;
|
||||
|
||||
failLabel:
|
||||
TableDestroy(proc->internTable);
|
||||
failIntern:
|
||||
free(proc);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* EventProcDestroy -- finish the module */
|
||||
|
||||
static void deallocItem(void *closure, Word key, void *value)
|
||||
{
|
||||
UNUSED(key);
|
||||
UNUSED(closure);
|
||||
free(value);
|
||||
}
|
||||
|
||||
static void deallocSym(void *closure, Word key, void *value)
|
||||
{
|
||||
UNUSED(key);
|
||||
UNUSED(closure);
|
||||
eventStringDestroy(((Symbol)value)->name);
|
||||
free(value);
|
||||
}
|
||||
|
||||
void EventProcDestroy(EventProc proc)
|
||||
{
|
||||
TableMap(proc->labelTable, deallocItem, NULL);
|
||||
TableMap(proc->internTable, deallocSym, NULL);
|
||||
TableDestroy(proc->labelTable);
|
||||
TableDestroy(proc->internTable);
|
||||
if (proc->cachedEvent != NULL)
|
||||
free(proc->cachedEvent);
|
||||
free(proc);
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 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.
|
||||
*/
|
||||
|
|
@ -154,14 +154,14 @@ static void sqlite_error(int res, sqlite3 *db, const char *format, ...)
|
|||
|
||||
/* global control variables set by command-line parameters. */
|
||||
|
||||
static char *prog; /* program name */
|
||||
static const char *prog; /* program name */
|
||||
static int rebuild = FALSE;
|
||||
static int deleteDatabase = FALSE;
|
||||
static int runTests = FALSE;
|
||||
static int force = FALSE;
|
||||
static int progress = FALSE;
|
||||
static char *databaseName = NULL;
|
||||
static char *logFileName = NULL;
|
||||
static const char *databaseName = NULL;
|
||||
static const char *logFileName = NULL;
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (c) 2012 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2012-2013 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* This is a command-line tool that converts events from a text-format
|
||||
* MPS telemetry file into a more human-readable format.
|
||||
|
|
@ -45,8 +45,8 @@
|
|||
#pragma warning( disable : 4996 )
|
||||
#endif
|
||||
|
||||
static char *prog; /* program name */
|
||||
static char *logFileName = NULL;
|
||||
static const char *prog; /* program name */
|
||||
static const char *logFileName = NULL;
|
||||
|
||||
/* everror -- error signalling */
|
||||
|
||||
|
|
@ -500,7 +500,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2012 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2012-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ static void *test(void *arg, size_t s)
|
|||
collections = 0;
|
||||
objs = 0;
|
||||
while (collections < collectionsCOUNT) {
|
||||
unsigned long c;
|
||||
mps_word_t c;
|
||||
size_t r;
|
||||
|
||||
c = mps_collections(arena);
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
|
||||
#define testArenaSIZE ((((size_t)3)<<24) - 4)
|
||||
#define testSetSIZE 2000
|
||||
#define testSetSIZE 200
|
||||
#define testLOOPS 10
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
# gc.gmk: GNUMAKEFILE FRAGMENT FOR GNU CC
|
||||
#
|
||||
# $Id$
|
||||
# Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
# Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
#
|
||||
# This file is included by platform makefiles that use the GNU CC
|
||||
# compiler. It defines the compiler-specific variables that the
|
||||
|
|
@ -12,10 +12,10 @@
|
|||
CC = gcc
|
||||
CFLAGSDEBUG = -O -g3
|
||||
CFLAGSOPT = -O2 -g3
|
||||
CFLAGSCOMPILER := -Wall -Werror -Wpointer-arith \
|
||||
CFLAGSCOMPILER := -Wall -Wextra -Werror -Wpointer-arith \
|
||||
-Wstrict-prototypes -Wmissing-prototypes \
|
||||
-Winline -Waggregate-return -Wnested-externs \
|
||||
-Wcast-qual -Wshadow # -Wstrict-aliasing=2
|
||||
-Wcast-qual -Wshadow -Wwrite-strings # -Wstrict-aliasing=2
|
||||
CFLAGSCOMPILERSTRICT := -ansi -pedantic -Wshadow
|
||||
|
||||
# A different set of compiler flags for less strict compilation, for
|
||||
|
|
@ -38,7 +38,7 @@ endef
|
|||
|
||||
# C. COPYRIGHT AND LICENSE
|
||||
#
|
||||
# Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
# Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
# All rights reserved. This is an open source license. Contact
|
||||
# Ravenbrook for commercial licensing options.
|
||||
#
|
||||
|
|
|
|||
|
|
@ -518,6 +518,10 @@ void arenaEnterLock(Arena arena, int recursive)
|
|||
the client if so. */
|
||||
AVER(TESTT(Arena, arena));
|
||||
|
||||
/* It's critical that the stack probe is outside the lock, because
|
||||
* the stack probe may cause arbitrary code to run (via a signal or
|
||||
* exception handler) and that code may enter the MPS. If we took
|
||||
* the lock first then this would deadlock. */
|
||||
StackProbe(StackProbeDEPTH);
|
||||
lock = ArenaGlobals(arena)->lock;
|
||||
if(recursive) {
|
||||
|
|
@ -626,13 +630,17 @@ Bool ArenaAccess(Addr addr, AccessSet mode, MutatorFaultContext context)
|
|||
if (SegOfAddr(&seg, arena, addr)) {
|
||||
mps_exception_info = NULL;
|
||||
arenaReleaseRingLock();
|
||||
/* An access in a different thread may have already caused the
|
||||
* protection to be cleared. This avoids calling TraceAccess on
|
||||
* protection that has already been cleared on a separate thread. */
|
||||
/* An access in a different thread (or even in the same thread,
|
||||
* via a signal or exception handler) may have already caused
|
||||
* the protection to be cleared. This avoids calling TraceAccess
|
||||
* on protection that has already been cleared on a separate
|
||||
* thread. */
|
||||
mode &= SegPM(seg);
|
||||
if (mode != AccessSetEMPTY) {
|
||||
res = PoolAccess(SegPool(seg), seg, addr, mode, context);
|
||||
AVER(res == ResOK); /* Mutator can't continue unless this succeeds */
|
||||
} else {
|
||||
/* Protection was already cleared: nothing to do now. */
|
||||
}
|
||||
EVENT4(ArenaAccess, arena, count, addr, mode);
|
||||
ArenaLeave(arena);
|
||||
|
|
@ -646,6 +654,11 @@ Bool ArenaAccess(Addr addr, AccessSet mode, MutatorFaultContext context)
|
|||
EVENT4(ArenaAccess, arena, count, addr, mode);
|
||||
ArenaLeave(arena);
|
||||
return TRUE;
|
||||
} else {
|
||||
/* No segment or root was found at the address: this must mean
|
||||
* that activity in another thread (or even in the same thread,
|
||||
* via a signal or exception handler) caused the segment or root
|
||||
* to go away. So there's nothing to do now. */
|
||||
}
|
||||
|
||||
ArenaLeave(arena);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
# gp.gmk: GNUMAKEFILE FRAGMENT FOR GNU CC/GPROF
|
||||
#
|
||||
# $Id$
|
||||
# Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
# Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
#
|
||||
# This file is included by platform makefiles that use the GNU CC
|
||||
# compiler with gprof. It defines the compiler specific variables
|
||||
|
|
@ -12,10 +12,10 @@
|
|||
|
||||
CC = gcc
|
||||
CFLAGSCOMPILER = \
|
||||
-ansi -pedantic -Wall -Werror -Wpointer-arith \
|
||||
-ansi -pedantic -Wall -Wextra -Werror -Wpointer-arith \
|
||||
-Wstrict-prototypes -Wmissing-prototypes \
|
||||
-Winline -Waggregate-return -Wnested-externs \
|
||||
-Wcast-qual -Wshadow -pg
|
||||
-Wcast-qual -Wshadow -Wwrite-strings -pg
|
||||
CFLAGSDEBUG = -g -ggdb3
|
||||
CFLAGSOPT = -O -g -ggdb3
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ include comm.gmk
|
|||
|
||||
# C. COPYRIGHT AND LICENSE
|
||||
#
|
||||
# Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
# Copyright (C) 2001-2013 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 @@
|
|||
/* ld.c: LOCATION DEPENDENCY IMPLEMENTATION
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .def: A location dependency records the fact that the bit-patterns
|
||||
* of some references will be used directly (most likely for
|
||||
|
|
@ -102,7 +102,7 @@ void LDAdd(mps_ld_t ld, Arena arena, Addr addr)
|
|||
}
|
||||
|
||||
|
||||
/* LDIsStale -- check whether a dependency is stale
|
||||
/* LDIsStaleAny -- check whether any dependency is stale
|
||||
*
|
||||
* .stale.thread-safe: This function is thread safe. It will return a
|
||||
* correct (but possibly conservative) answer regardless of the number
|
||||
|
|
@ -122,12 +122,10 @@ void LDAdd(mps_ld_t ld, Arena arena, Addr addr)
|
|||
* .stale.old: Otherwise, if the dependency is older than the length
|
||||
* of the history, check it against all movement that has ever occured.
|
||||
*/
|
||||
Bool LDIsStale(mps_ld_t ld, Arena arena, Addr addr)
|
||||
Bool LDIsStaleAny(mps_ld_t ld, Arena arena)
|
||||
{
|
||||
RefSet rs;
|
||||
|
||||
UNUSED(addr);
|
||||
|
||||
AVER(ld->_epoch <= arena->epoch);
|
||||
/* AVERT(Arena, arena) -- .stale.thread-safe */
|
||||
|
||||
|
|
@ -148,6 +146,19 @@ Bool LDIsStale(mps_ld_t ld, Arena arena, Addr addr)
|
|||
}
|
||||
|
||||
|
||||
/* LDIsStale -- check whether a particular dependency is stale
|
||||
*
|
||||
* .stale.conservative: In fact we just ignore the address and test if
|
||||
* any dependency is stale. This is conservatively correct (no false
|
||||
* negatives) but provides a hook for future improvement.
|
||||
*/
|
||||
Bool LDIsStale(mps_ld_t ld, Arena arena, Addr addr)
|
||||
{
|
||||
UNUSED(addr);
|
||||
return LDIsStaleAny(ld, arena);
|
||||
}
|
||||
|
||||
|
||||
/* LDAge -- age the arena by adding a moved set
|
||||
*
|
||||
* This stores the fact that a set of references has changed in
|
||||
|
|
@ -212,7 +223,7 @@ void LDMerge(mps_ld_t ld, Arena arena, mps_ld_t from)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
60
mps/code/lii6ll.gmk
Normal file
60
mps/code/lii6ll.gmk
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
# -*- makefile -*-
|
||||
#
|
||||
# lii6ll.gmk: BUILD FOR LINUX/x64/Clang PLATFORM
|
||||
#
|
||||
# $Id$
|
||||
# Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
|
||||
PFM = lii6ll
|
||||
|
||||
THREADSRC = lockli.c thix.c pthrdext.c
|
||||
THREADLIB = -lpthread
|
||||
|
||||
MPMPF = ${THREADSRC} vmix.c \
|
||||
protix.c protli.c proti6.c prmci6li.c ssixi6.c span.c
|
||||
|
||||
LIBS = -lm ${THREADLIB}
|
||||
|
||||
include ll.gmk
|
||||
include comm.gmk
|
||||
|
||||
|
||||
# C. COPYRIGHT AND LICENSE
|
||||
#
|
||||
# Copyright (C) 2001-2013 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.
|
||||
77
mps/code/ll.gmk
Normal file
77
mps/code/ll.gmk
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
# -*- makefile -*-
|
||||
#
|
||||
# ll.gmk: GNUMAKEFILE FRAGMENT FOR CLANG/LLVM
|
||||
#
|
||||
# $Id$
|
||||
# Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
#
|
||||
# This file is included by platform makefiles that use the Clang/LLVM
|
||||
# compiler. It defines the compiler-specific variables that the
|
||||
# common makefile fragment (<code/comm.gmk>) requires.
|
||||
|
||||
CC = clang
|
||||
CFLAGSDEBUG = -O -g3
|
||||
CFLAGSOPT = -O2 -g3
|
||||
CFLAGSCOMPILER := -Wall -Werror -Wpointer-arith \
|
||||
-Wstrict-prototypes -Wmissing-prototypes \
|
||||
-Winline -Waggregate-return -Wnested-externs \
|
||||
-Wcast-qual -Wshadow # -Wstrict-aliasing=2
|
||||
CFLAGSCOMPILERSTRICT := -pedantic -Wno-extended-offsetof
|
||||
|
||||
# A different set of compiler flags for less strict compilation, for
|
||||
# instance when we need to #include a third-party header file that
|
||||
# won't fly with -ansi -pedantic. Use sparingly!
|
||||
CFLAGSCOMPILERLAX :=
|
||||
|
||||
# clang -MM generates a dependency line of the form:
|
||||
# thing.o : thing.c ...
|
||||
# The sed line converts this into:
|
||||
# <pfm>/<variety>/thing.o <pfm>/<variety>/thing.d : thing.c ...
|
||||
# If interrupted, this is liable to leave a zero-length file behind.
|
||||
|
||||
define gendep
|
||||
$(SHELL) -ec "$(CC) $(CFLAGS) -MM $< | \
|
||||
sed '/:/s!$*.o!$(@D)/& $(@D)/$*.d!' > $@"
|
||||
[ -s $@ ] || rm -f $@
|
||||
endef
|
||||
|
||||
|
||||
# C. COPYRIGHT AND LICENSE
|
||||
#
|
||||
# Copyright (C) 2001-2013 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.
|
||||
|
|
@ -154,12 +154,14 @@ static void testInArena(mps_arena_t arena)
|
|||
int i;
|
||||
|
||||
die(mps_pool_create(&hipool, arena, mps_class_mvff(),
|
||||
chunkSize, chunkSize, 1024,
|
||||
chunkSize, chunkSize,
|
||||
(mps_align_t)1024,
|
||||
TRUE, TRUE, TRUE),
|
||||
"Create HI MFFV");
|
||||
|
||||
die(mps_pool_create(&lopool, arena, mps_class_mvff(),
|
||||
chunkSize, chunkSize, 1024,
|
||||
chunkSize, chunkSize,
|
||||
(mps_align_t)1024,
|
||||
FALSE, FALSE, TRUE),
|
||||
"Create LO MFFV");
|
||||
|
||||
|
|
@ -178,8 +180,6 @@ static void testInArena(mps_arena_t arena)
|
|||
|
||||
if (lostat->max > histat->min) {
|
||||
error("\nFOUND PROBLEM - low range overlaps high\n");
|
||||
} else if (lostat->ncCount != 0 || histat->ncCount != 0) {
|
||||
error("\nFOUND POSSIBLE PROBLEM - some non-contiguous allocations\n");
|
||||
} else {
|
||||
printf("\nNo problems detected.\n");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* meter.c: METERS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* TRANSGRESSIONS
|
||||
*
|
||||
|
|
@ -18,7 +18,7 @@ SRCID(meter, "$Id$");
|
|||
|
||||
/* MeterInit -- initialize a meter */
|
||||
|
||||
void MeterInit(Meter meter, char *name, void *owner)
|
||||
void MeterInit(Meter meter, const char *name, void *owner)
|
||||
{
|
||||
Word sym;
|
||||
|
||||
|
|
@ -104,7 +104,7 @@ void MeterEmit(Meter meter)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2013 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 @@
|
|||
/* meter.h: METER INTERFACE
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .sources: mps.design.metrics.
|
||||
*
|
||||
|
|
@ -24,7 +24,7 @@ typedef struct MeterStruct *Meter;
|
|||
|
||||
typedef struct MeterStruct
|
||||
{
|
||||
char *name;
|
||||
const char *name;
|
||||
Count count;
|
||||
double total;
|
||||
double meanSquared;
|
||||
|
|
@ -33,7 +33,7 @@ typedef struct MeterStruct
|
|||
} MeterStruct;
|
||||
|
||||
|
||||
extern void MeterInit(Meter meter, char* name, void *owner);
|
||||
extern void MeterInit(Meter meter, const char *name, void *owner);
|
||||
extern void MeterAccumulate(Meter meter, Size amount);
|
||||
extern Res MeterWrite(Meter meter, mps_lib_FILE *stream);
|
||||
extern void MeterEmit(Meter meter);
|
||||
|
|
@ -59,7 +59,7 @@ extern void MeterEmit(Meter meter);
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
/* mpm.h: MEMORY POOL MANAGER DEFINITIONS
|
||||
*
|
||||
* $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) 2002 Global Graphics Software.
|
||||
*
|
||||
* .trans.bufferinit: The Buffer data structure has an Init field and
|
||||
* an Init method, there's a name clash. We resolve this by calling the
|
||||
* accessor BufferGetInit. */
|
||||
* accessor BufferGetInit.
|
||||
*/
|
||||
|
||||
#ifndef mpm_h
|
||||
#define mpm_h
|
||||
|
|
@ -210,6 +211,7 @@ extern Res (PoolFix)(Pool pool, ScanState ss, Seg seg, Addr *refIO);
|
|||
extern Res PoolFixEmergency(Pool pool, ScanState ss, Seg seg, Addr *refIO);
|
||||
extern void PoolReclaim(Pool pool, Trace trace, Seg seg);
|
||||
extern void PoolTraceEnd(Pool pool, Trace trace);
|
||||
extern Res PoolAddrObject(Addr *pReturn, Pool pool, Seg seg, Addr addr);
|
||||
extern void PoolWalk(Pool pool, Seg seg, FormattedObjectsStepMethod f,
|
||||
void *v, size_t s);
|
||||
extern void PoolFreeWalk(Pool pool, FreeBlockStepMethod f, void *p);
|
||||
|
|
@ -259,6 +261,7 @@ extern Res PoolTrivFramePush(AllocFrame *frameReturn, Pool pool, Buffer buf);
|
|||
extern Res PoolNoFramePop(Pool pool, Buffer buf, AllocFrame frame);
|
||||
extern Res PoolTrivFramePop(Pool pool, Buffer buf, AllocFrame frame);
|
||||
extern void PoolNoFramePopPending(Pool pool, Buffer buf, AllocFrame frame);
|
||||
extern Res PoolNoAddrObject(Addr *pReturn, Pool pool, Seg seg, Addr addr);
|
||||
extern void PoolNoWalk(Pool pool, Seg seg, FormattedObjectsStepMethod step,
|
||||
void *p, size_t s);
|
||||
extern void PoolNoFreeWalk(Pool pool, FreeBlockStepMethod f, void *p);
|
||||
|
|
@ -497,8 +500,6 @@ extern Ring GlobalsRememberedSummaryRing(Globals);
|
|||
#define ArenaGlobals(arena) (&(arena)->globals)
|
||||
#define GlobalsArena(glob) PARENT(ArenaStruct, globals, glob)
|
||||
|
||||
#define ArenaRootRing(arena) (&(arena)->rootRing)
|
||||
#define ArenaTraceRing(arena) (&(arena)->traceRing)
|
||||
#define ArenaThreadRing(arena) (&(arena)->threadRing)
|
||||
#define ArenaEpoch(arena) ((arena)->epoch) /* .epoch.ts */
|
||||
#define ArenaTrace(arena, ti) (&(arena)->trace[ti])
|
||||
|
|
@ -534,6 +535,7 @@ extern void ArenaRestoreProtection(Globals globals);
|
|||
extern Res ArenaStartCollect(Globals globals, int why);
|
||||
extern Res ArenaCollect(Globals globals, int why);
|
||||
extern Bool ArenaHasAddr(Arena arena, Addr addr);
|
||||
extern Res ArenaAddrObject(Addr *pReturn, Arena arena, Addr addr);
|
||||
|
||||
extern void ArenaSetEmergency(Arena arena, Bool emergency);
|
||||
extern Bool ArenaEmergency(Arena arean);
|
||||
|
|
@ -907,6 +909,7 @@ extern Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc);
|
|||
|
||||
extern void LDReset(mps_ld_t ld, Arena arena);
|
||||
extern void LDAdd(mps_ld_t ld, Arena arena, Addr addr);
|
||||
extern Bool LDIsStaleAny(mps_ld_t ld, Arena arena);
|
||||
extern Bool LDIsStale(mps_ld_t ld, Arena arena, Addr addr);
|
||||
extern void LDAge(Arena arena, RefSet moved);
|
||||
extern void LDMerge(mps_ld_t ld, Arena arena, mps_ld_t from);
|
||||
|
|
@ -1016,7 +1019,7 @@ extern void StackProbe(Size depth);
|
|||
|
||||
/* 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -131,21 +131,21 @@ static size_t fixedSize(int i)
|
|||
|
||||
|
||||
static mps_pool_debug_option_s bothOptions8 = {
|
||||
/* .fence_template = */ (void *)"postpost",
|
||||
/* .fence_template = */ (const void *)"postpost",
|
||||
/* .fence_size = */ 8,
|
||||
/* .free_template = */ (void *)"DEAD",
|
||||
/* .free_template = */ (const void *)"DEAD",
|
||||
/* .free_size = */ 4
|
||||
};
|
||||
|
||||
static mps_pool_debug_option_s bothOptions16 = {
|
||||
/* .fence_template = */ (void *)"postpostpostpost",
|
||||
/* .fence_template = */ (const void *)"postpostpostpost",
|
||||
/* .fence_size = */ 16,
|
||||
/* .free_template = */ (void *)"DEAD",
|
||||
/* .free_template = */ (const void *)"DEAD",
|
||||
/* .free_size = */ 4
|
||||
};
|
||||
|
||||
static mps_pool_debug_option_s fenceOptions = {
|
||||
/* .fence_template = */ (void *)"\0XXX ''\"\"'' XXX\0",
|
||||
/* .fence_template = */ (const void *)"\0XXX ''\"\"'' XXX\0",
|
||||
/* .fence_size = */ 16,
|
||||
/* .free_template = */ NULL,
|
||||
/* .free_size = */ 0
|
||||
|
|
@ -159,7 +159,7 @@ static int testInArena(mps_arena_t arena, mps_pool_debug_option_s *options)
|
|||
/* cross-segment allocation (possibly MVFF ought not to). */
|
||||
printf("MVFF\n");
|
||||
die(stress(mps_class_mvff(), randomSize8, arena,
|
||||
(size_t)65536, (size_t)32, sizeof(void *), TRUE, TRUE, TRUE),
|
||||
(size_t)65536, (size_t)32, (mps_align_t)MPS_PF_ALIGN, TRUE, TRUE, TRUE),
|
||||
"stress MVFF");
|
||||
printf("MV debug\n");
|
||||
die(stress(mps_class_mv_debug(), randomSize, arena,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* mpmst.h: MEMORY POOL MANAGER DATA STRUCTURES
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2003, 2006 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (C) 2001 Global Graphics Software.
|
||||
*
|
||||
* .design: This header file crosses module boundaries. The relevant
|
||||
|
|
@ -73,6 +73,7 @@ typedef struct mps_class_s {
|
|||
PoolFramePushMethod framePush; /* push an allocation frame */
|
||||
PoolFramePopMethod framePop; /* pop an allocation frame */
|
||||
PoolFramePopPendingMethod framePopPending; /* notify pending pop */
|
||||
PoolAddrObjectMethod addrObject; /* find client pointer to object */
|
||||
PoolWalkMethod walk; /* walk over a segment */
|
||||
PoolFreeWalkMethod freewalk; /* walk over free blocks */
|
||||
PoolBufferClassMethod bufferClass; /* default BufferClass of pool */
|
||||
|
|
@ -532,7 +533,7 @@ typedef struct ChunkCacheEntryStruct {
|
|||
|
||||
typedef struct mps_arena_class_s {
|
||||
ProtocolClassStruct protocol;
|
||||
char *name; /* class name string */
|
||||
const char *name; /* class name string */
|
||||
size_t size; /* size of outer structure */
|
||||
size_t offset; /* offset of generic struct in outer struct */
|
||||
ArenaVarargsMethod varargs;
|
||||
|
|
@ -704,7 +705,7 @@ typedef struct AllocPatternStruct {
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2003, 2006, 2008 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -223,6 +223,8 @@ typedef Res (*PoolFramePopMethod)(Pool pool, Buffer buf,
|
|||
AllocFrame frame);
|
||||
typedef void (*PoolFramePopPendingMethod)(Pool pool, Buffer buf,
|
||||
AllocFrame frame);
|
||||
typedef Res (*PoolAddrObjectMethod)(Addr *pReturn,
|
||||
Pool pool, Seg seg, Addr addr);
|
||||
typedef void (*PoolWalkMethod)(Pool pool, Seg seg,
|
||||
FormattedObjectsStepMethod f,
|
||||
void *v, size_t s);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* mps.c: MEMORY POOL SYSTEM ALL-IN-ONE TRANSLATION UNIT
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (C) 2012 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (C) 2012-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .purpose: This file can be compiled to create the complete MPS library in
|
||||
* a single compilation, allowing the compiler to apply global optimizations
|
||||
|
|
@ -98,11 +98,12 @@
|
|||
#if defined(MPS_PF_XCI3LL) || defined(MPS_PF_XCI3GC)
|
||||
|
||||
#include "lockix.c" /* Posix locks */
|
||||
#include "than.c" /* generic single threading */
|
||||
#include "thxc.c" /* OS X Mach threading */
|
||||
#include "vmix.c" /* Posix virtual memory */
|
||||
#include "protix.c" /* Posix protection */
|
||||
#include "protsgix.c" /* Posix signal handling */
|
||||
#include "prmcan.c" /* generic mutator context */
|
||||
#include "protxc.c" /* OS X Mach exception handling */
|
||||
#include "proti3.c" /* 32-bit Intel mutator context decoding */
|
||||
#include "prmci3xc.c" /* 32-bit Intel for Mac OS X mutator context */
|
||||
#include "span.c" /* generic stack probe */
|
||||
#include "ssixi3.c" /* Posix on 32-bit Intel stack scan */
|
||||
|
||||
|
|
@ -111,11 +112,12 @@
|
|||
#elif defined(MPS_PF_XCI6LL) || defined(MPS_PF_XCI6GC)
|
||||
|
||||
#include "lockix.c" /* Posix locks */
|
||||
#include "than.c" /* generic single threading */
|
||||
#include "thxc.c" /* OS X Mach threading */
|
||||
#include "vmix.c" /* Posix virtual memory */
|
||||
#include "protix.c" /* Posix protection */
|
||||
#include "protsgix.c" /* Posix signal handling */
|
||||
#include "prmcan.c" /* generic mutator context */
|
||||
#include "protxc.c" /* OS X Mach exception handling */
|
||||
#include "proti6.c" /* 64-bit Intel mutator context decoding */
|
||||
#include "prmci6xc.c" /* 64-bit Intel for Mac OS X mutator context */
|
||||
#include "span.c" /* generic stack probe */
|
||||
#include "ssixi6.c" /* Posix on 64-bit Intel stack scan */
|
||||
|
||||
|
|
@ -164,9 +166,9 @@
|
|||
#include "span.c" /* generic stack probe */
|
||||
#include "ssixi3.c" /* Posix on 32-bit Intel stack scan */
|
||||
|
||||
/* Linux on 64-bit Intel with GCC */
|
||||
/* Linux on 64-bit Intel with GCC or Clang */
|
||||
|
||||
#elif defined(MPS_PF_LII6GC)
|
||||
#elif defined(MPS_PF_LII6GC) || defined(MPS_PF_LII6LL)
|
||||
|
||||
#include "lockli.c" /* Linux locks */
|
||||
#include "thix.c" /* Posix threading */
|
||||
|
|
@ -191,7 +193,7 @@
|
|||
#include "proti3.c" /* 32-bit Intel mutator context decoding */
|
||||
#include "prmci3w3.c" /* Windows on 32-bit Intel mutator context */
|
||||
#include "ssw3i3mv.c" /* Windows on 32-bit stack scan for Microsoft C */
|
||||
#include "spi3.c" /* Intel stack probe */
|
||||
#include "spw3i3mv.c" /* Windows on 32-bit stack probe for Microsoft C */
|
||||
#include "mpsiw3.c" /* Windows interface layer extras */
|
||||
|
||||
/* Windows on 64-bit Intel with Microsoft Visual Studio */
|
||||
|
|
@ -207,7 +209,7 @@
|
|||
#include "proti6.c" /* 64-bit Intel mutator context decoding */
|
||||
#include "prmci6w3.c" /* Windows on 64-bit Intel mutator context */
|
||||
#include "ssw3i6mv.c" /* Windows on 64-bit stack scan for Microsoft C */
|
||||
#include "span.c" /* generic stack probe FIXME: Is this correct? */
|
||||
#include "spw3i6mv.c" /* Windows on 64-bit stack probe for Microsoft C */
|
||||
#include "mpsiw3.c" /* Windows interface layer extras */
|
||||
|
||||
#else
|
||||
|
|
@ -220,7 +222,7 @@
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2012 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2012-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -661,6 +661,7 @@ extern void mps_ld_reset(mps_ld_t, mps_arena_t);
|
|||
extern void mps_ld_add(mps_ld_t, mps_arena_t, mps_addr_t);
|
||||
extern void mps_ld_merge(mps_ld_t, mps_arena_t, mps_ld_t);
|
||||
extern mps_bool_t mps_ld_isstale(mps_ld_t, mps_arena_t, mps_addr_t);
|
||||
extern mps_bool_t mps_ld_isstale_any(mps_ld_t, mps_arena_t);
|
||||
|
||||
extern mps_word_t mps_collections(mps_arena_t);
|
||||
|
||||
|
|
@ -736,15 +737,15 @@ extern void mps_arena_roots_walk(mps_arena_t,
|
|||
|
||||
|
||||
typedef struct mps_pool_debug_option_s {
|
||||
void* fence_template;
|
||||
const void *fence_template;
|
||||
size_t fence_size;
|
||||
void* free_template;
|
||||
const void *free_template;
|
||||
size_t free_size;
|
||||
} mps_pool_debug_option_s;
|
||||
|
||||
extern const struct mps_key_s _mps_key_pool_debug_options;
|
||||
#define MPS_KEY_POOL_DEBUG_OPTIONS (&_mps_key_pool_debug_options)
|
||||
#define MPS_KEY_VAL_POOL_DEBUG_OPTIONS pool_debug_options
|
||||
#define MPS_KEY_POOL_DEBUG_OPTIONS_FIELD pool_debug_options
|
||||
|
||||
extern void mps_pool_check_fenceposts(mps_pool_t);
|
||||
extern void mps_pool_check_free_space(mps_pool_t);
|
||||
|
|
|
|||
|
|
@ -184,7 +184,6 @@
|
|||
3114A6C1156E97B8001E0AA3 /* fmtno.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CACC156BE4C200753214 /* fmtno.c */; };
|
||||
3114A6D1156E9829001E0AA3 /* eventcnv.c in Sources */ = {isa = PBXBuildFile; fileRef = 3114A6D0156E9829001E0AA3 /* eventcnv.c */; };
|
||||
3114A6D7156E9923001E0AA3 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; };
|
||||
3114A6DA156E9950001E0AA3 /* eventpro.c in Sources */ = {isa = PBXBuildFile; fileRef = 3114A6D9156E9950001E0AA3 /* eventpro.c */; };
|
||||
3114A6DD156E9A0F001E0AA3 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; };
|
||||
3124CAC3156BE40100753214 /* awlut.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC2156BE40100753214 /* awlut.c */; };
|
||||
3124CAC4156BE40D00753214 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; };
|
||||
|
|
@ -209,7 +208,6 @@
|
|||
3137949E176CC3B100BCFAEC /* djbench.c in Sources */ = {isa = PBXBuildFile; fileRef = 3137949D176CC3B100BCFAEC /* djbench.c */; };
|
||||
3137949F176CD02700BCFAEC /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; };
|
||||
3150AE53156ABA2500A6E22A /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; };
|
||||
317B3C2B1731830100F9A469 /* arg.c in Sources */ = {isa = PBXBuildFile; fileRef = 317B3C2A1731830100F9A469 /* arg.c */; };
|
||||
31A47BA4156C1E130039B1C2 /* mps.c in Sources */ = {isa = PBXBuildFile; fileRef = 31A47BA3156C1E130039B1C2 /* mps.c */; };
|
||||
31D60007156D3C6200337B26 /* segsmss.c in Sources */ = {isa = PBXBuildFile; fileRef = 31D60006156D3C5F00337B26 /* segsmss.c */; };
|
||||
31D60008156D3C7400337B26 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; };
|
||||
|
|
@ -1206,7 +1204,11 @@
|
|||
3114A6BA156E9768001E0AA3 /* walkt0.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = walkt0.c; sourceTree = "<group>"; };
|
||||
3114A6C6156E9815001E0AA3 /* mpseventcnv */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mpseventcnv; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3114A6D0156E9829001E0AA3 /* eventcnv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = eventcnv.c; sourceTree = "<group>"; };
|
||||
3114A6D9156E9950001E0AA3 /* eventpro.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = eventpro.c; sourceTree = "<group>"; };
|
||||
31172ABA17750F9D009488E5 /* thxc.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = thxc.c; sourceTree = "<group>"; };
|
||||
31172ABB177512F6009488E5 /* prmci3xc.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = prmci3xc.c; sourceTree = "<group>"; };
|
||||
31172ABC1775131C009488E5 /* prmci6xc.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = prmci6xc.c; sourceTree = "<group>"; };
|
||||
31172ABE1775164F009488E5 /* prmcxc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = prmcxc.h; sourceTree = "<group>"; };
|
||||
31172AC017752253009488E5 /* protxc.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = protxc.c; sourceTree = "<group>"; };
|
||||
311F2F5017398AD500C15B6A /* boot.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = boot.h; sourceTree = "<group>"; };
|
||||
311F2F5117398AE900C15B6A /* bt.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bt.h; sourceTree = "<group>"; };
|
||||
311F2F5217398AE900C15B6A /* cbs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = cbs.h; sourceTree = "<group>"; };
|
||||
|
|
@ -1218,7 +1220,6 @@
|
|||
311F2F5817398AE900C15B6A /* event.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = event.h; sourceTree = "<group>"; };
|
||||
311F2F5917398AE900C15B6A /* eventcom.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = eventcom.h; sourceTree = "<group>"; };
|
||||
311F2F5A17398AE900C15B6A /* eventdef.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = eventdef.h; sourceTree = "<group>"; };
|
||||
311F2F5B17398AE900C15B6A /* eventpro.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = eventpro.h; sourceTree = "<group>"; };
|
||||
311F2F5C17398AE900C15B6A /* eventrep.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = eventrep.h; sourceTree = "<group>"; };
|
||||
311F2F5D17398B0400C15B6A /* lo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = lo.h; sourceTree = "<group>"; };
|
||||
311F2F5E17398B0E00C15B6A /* lock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = lock.h; sourceTree = "<group>"; };
|
||||
|
|
@ -1266,9 +1267,12 @@
|
|||
3124CAF5156BE81100753214 /* amcss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = amcss.c; sourceTree = "<group>"; };
|
||||
31379493176CC34D00BCFAEC /* djbench */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = djbench; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3137949D176CC3B100BCFAEC /* djbench.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = djbench.c; sourceTree = "<group>"; };
|
||||
315B7AFC17834FDB00B097C4 /* proti3.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = proti3.c; sourceTree = "<group>"; };
|
||||
315B7AFD17834FDB00B097C4 /* proti6.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = proti6.c; sourceTree = "<group>"; };
|
||||
317B3C2A1731830100F9A469 /* arg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = arg.c; sourceTree = "<group>"; };
|
||||
31A47BA3156C1E130039B1C2 /* mps.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mps.c; sourceTree = "<group>"; };
|
||||
31A47BA5156C1E5E0039B1C2 /* ssixi3.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ssixi3.c; sourceTree = "<group>"; };
|
||||
31C83ADD1786281C0031A0DB /* protxc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = protxc.h; sourceTree = "<group>"; };
|
||||
31CD33BB173A9F1500524741 /* mpscams.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = mpscams.h; sourceTree = "<group>"; };
|
||||
31CD33BC173A9F1500524741 /* poolams.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = poolams.c; sourceTree = "<group>"; };
|
||||
31CD33BD173A9F1500524741 /* poolams.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = poolams.h; sourceTree = "<group>"; };
|
||||
|
|
@ -1325,10 +1329,7 @@
|
|||
31EEAC43156AB32500714D05 /* splay.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = splay.c; sourceTree = "<group>"; };
|
||||
31EEAC44156AB32500714D05 /* version.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = version.c; sourceTree = "<group>"; };
|
||||
31EEAC4C156AB3B000714D05 /* lockix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lockix.c; sourceTree = "<group>"; };
|
||||
31EEAC4E156AB3E300714D05 /* prmcan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = prmcan.c; sourceTree = "<group>"; };
|
||||
31EEAC4F156AB3E300714D05 /* protix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = protix.c; sourceTree = "<group>"; };
|
||||
31EEAC50156AB3E300714D05 /* protsgix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = protsgix.c; sourceTree = "<group>"; };
|
||||
31EEAC52156AB3E300714D05 /* than.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = than.c; sourceTree = "<group>"; };
|
||||
31EEAC53156AB3E300714D05 /* vmix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vmix.c; sourceTree = "<group>"; };
|
||||
31EEAC5B156AB41900714D05 /* poolamc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = poolamc.c; sourceTree = "<group>"; };
|
||||
31EEAC5D156AB43F00714D05 /* poolsnc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = poolsnc.c; sourceTree = "<group>"; };
|
||||
|
|
@ -1700,7 +1701,6 @@
|
|||
3114A6D8156E9942001E0AA3 /* mpseventcnv */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3114A6D9156E9950001E0AA3 /* eventpro.c */,
|
||||
3114A6D0156E9829001E0AA3 /* eventcnv.c */,
|
||||
);
|
||||
name = mpseventcnv;
|
||||
|
|
@ -1763,22 +1763,6 @@
|
|||
name = Benchmarks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
31A47BA6156C1E620039B1C2 /* I3 */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
31A47BA5156C1E5E0039B1C2 /* ssixi3.c */,
|
||||
);
|
||||
name = I3;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
31A47BA7156C1E6E0039B1C2 /* I6 */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3104AFA5156D27E7000A585A /* ssixi6.c */,
|
||||
);
|
||||
name = I6;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
31A47BA8156C1E930039B1C2 /* MPS */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
|
@ -1879,7 +1863,6 @@
|
|||
311F2F5817398AE900C15B6A /* event.h */,
|
||||
311F2F5917398AE900C15B6A /* eventcom.h */,
|
||||
311F2F5A17398AE900C15B6A /* eventdef.h */,
|
||||
311F2F5B17398AE900C15B6A /* eventpro.h */,
|
||||
311F2F5C17398AE900C15B6A /* eventrep.h */,
|
||||
31EEAC1A156AB2B200714D05 /* format.c */,
|
||||
2291A5EE175CB768001D4920 /* freelist.c */,
|
||||
|
|
@ -1950,14 +1933,19 @@
|
|||
31EEAC4B156AB39C00714D05 /* Platform */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
31A47BA7156C1E6E0039B1C2 /* I6 */,
|
||||
31A47BA6156C1E620039B1C2 /* I3 */,
|
||||
315B7AFC17834FDB00B097C4 /* proti3.c */,
|
||||
315B7AFD17834FDB00B097C4 /* proti6.c */,
|
||||
31EEAC4C156AB3B000714D05 /* lockix.c */,
|
||||
31EEAC4E156AB3E300714D05 /* prmcan.c */,
|
||||
31172ABB177512F6009488E5 /* prmci3xc.c */,
|
||||
31172ABC1775131C009488E5 /* prmci6xc.c */,
|
||||
31172ABE1775164F009488E5 /* prmcxc.h */,
|
||||
31EEAC4F156AB3E300714D05 /* protix.c */,
|
||||
31EEAC50156AB3E300714D05 /* protsgix.c */,
|
||||
31C83ADD1786281C0031A0DB /* protxc.h */,
|
||||
31172AC017752253009488E5 /* protxc.c */,
|
||||
31EEACA7156AB79800714D05 /* span.c */,
|
||||
31EEAC52156AB3E300714D05 /* than.c */,
|
||||
31A47BA5156C1E5E0039B1C2 /* ssixi3.c */,
|
||||
3104AFA5156D27E7000A585A /* ssixi6.c */,
|
||||
31172ABA17750F9D009488E5 /* thxc.c */,
|
||||
31EEAC53156AB3E300714D05 /* vmix.c */,
|
||||
);
|
||||
name = Platform;
|
||||
|
|
@ -2809,7 +2797,7 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "# Not listed here:\n# awlutth -- fails (job003506).\n# bttest and teletest -- interactive and so cannot be run unattended.\n# zcoll -- takes too long to be useful as a regularly run smoke test.\nTESTCASES=\"abqtest amcss amcsshe amcssth amsss amssshe apss arenacv \\\n awlut awluthe btcv expt825 exposet0 fbmtest finalcv \\\n finaltest fotest lockcov locv messtest mpmss mpsicv mv2test \\\n poolncv qs sacss segsmss steptest walkt0 zmess\"\n\n../tool/testrun.sh $(for TEST in $TESTCASES; do echo $TARGET_BUILD_DIR/$TEST; done)\n\n# Coverage\nif [ \"$CONFIGURATION\" == \"Debug\" ]; then\n (cd xc/$PROJECT.build/$CONFIGURATION/$PROJECT.build/Objects-normal/x86_64 &&\n gcov mps.c 2> /dev/null) | ../tool/gcovfmt.py\nfi";
|
||||
shellScript = "# Not listed here:\n# awlutth -- fails (job003506).\n# bttest and teletest -- interactive and so cannot be run unattended.\n# zcoll -- takes too long to be useful as a regularly run smoke test.\nTESTCASES=\"abqtest amcss amcsshe amcssth amsss amssshe apss arenacv \\\n awlut awlutth awluthe btcv expt825 exposet0 fbmtest finalcv \\\n finaltest fotest lockcov locv messtest mpmss mpsicv mv2test \\\n poolncv qs sacss segsmss steptest walkt0 zmess\"\n\n../tool/testrun.sh $(for TEST in $TESTCASES; do echo $TARGET_BUILD_DIR/$TEST; done)\n\n# Coverage\nif [ \"$CONFIGURATION\" == \"Debug\" ]; then\n (cd xc/$PROJECT.build/$CONFIGURATION/$PROJECT.build/Objects-normal/x86_64 &&\n gcov mps.c 2> /dev/null) | ../tool/gcovfmt.py\nfi";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
|
@ -3089,7 +3077,6 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
3114A6D1156E9829001E0AA3 /* eventcnv.c in Sources */,
|
||||
3114A6DA156E9950001E0AA3 /* eventpro.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
@ -3214,7 +3201,6 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
31A47BA4156C1E130039B1C2 /* mps.c in Sources */,
|
||||
317B3C2B1731830100F9A469 /* arg.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
@ -4263,6 +4249,7 @@
|
|||
CONFIG_PROD_EPCORE,
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_TREAT_WARNINGS_AS_ERRORS = NO;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
|
|
@ -4274,6 +4261,7 @@
|
|||
CONFIG_VAR_HOT,
|
||||
MPS_PROD_EPCORE,
|
||||
);
|
||||
GCC_TREAT_WARNINGS_AS_ERRORS = NO;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
|
|
@ -4324,6 +4312,8 @@
|
|||
OTHER_CFLAGS = (
|
||||
"-pedantic",
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Wwrite-strings",
|
||||
"-Wno-extended-offsetof",
|
||||
);
|
||||
SDKROOT = macosx;
|
||||
|
|
@ -4339,6 +4329,8 @@
|
|||
"-Wcast-qual",
|
||||
"-Wshadow",
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Wwrite-strings",
|
||||
"-Wno-extended-offsetof",
|
||||
);
|
||||
};
|
||||
|
|
@ -4773,6 +4765,8 @@
|
|||
OTHER_CFLAGS = (
|
||||
"-pedantic",
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Wwrite-strings",
|
||||
"-Wno-extended-offsetof",
|
||||
);
|
||||
SDKROOT = macosx;
|
||||
|
|
@ -4788,6 +4782,8 @@
|
|||
"-Wcast-qual",
|
||||
"-Wshadow",
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Wwrite-strings",
|
||||
"-Wno-extended-offsetof",
|
||||
);
|
||||
};
|
||||
|
|
@ -4827,6 +4823,8 @@
|
|||
OTHER_CFLAGS = (
|
||||
"-pedantic",
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Wwrite-strings",
|
||||
"-Wno-extended-offsetof",
|
||||
);
|
||||
SDKROOT = macosx;
|
||||
|
|
@ -4842,6 +4840,8 @@
|
|||
"-Wcast-qual",
|
||||
"-Wshadow",
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Wwrite-strings",
|
||||
"-Wno-extended-offsetof",
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* mpsi.c: MEMORY POOL SYSTEM C INTERFACE LAYER
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2003, 2006 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (c) 2002 Global Graphics Software.
|
||||
*
|
||||
* .purpose: This code bridges between the MPS interface to C,
|
||||
|
|
@ -753,7 +753,6 @@ void mps_free(mps_pool_t pool, mps_addr_t p, size_t size)
|
|||
ArenaEnter(arena);
|
||||
|
||||
AVERT(Pool, pool);
|
||||
AVER(PoolHasRange(pool, p, AddrAdd(p, size)));
|
||||
AVER(size > 0);
|
||||
/* Note: class may allow unaligned size, see */
|
||||
/* <design/class-interface/#alloc.size.align>. */
|
||||
|
|
@ -1481,6 +1480,15 @@ mps_bool_t mps_ld_isstale(mps_ld_t ld, mps_arena_t arena,
|
|||
return (mps_bool_t)b;
|
||||
}
|
||||
|
||||
mps_bool_t mps_ld_isstale_any(mps_ld_t ld, mps_arena_t arena)
|
||||
{
|
||||
Bool b;
|
||||
|
||||
b = LDIsStaleAny(ld, arena);
|
||||
|
||||
return (mps_bool_t)b;
|
||||
}
|
||||
|
||||
mps_res_t mps_fix(mps_ss_t mps_ss, mps_addr_t *ref_io)
|
||||
{
|
||||
mps_res_t res;
|
||||
|
|
@ -1942,7 +1950,7 @@ void mps_chain_destroy(mps_chain_t chain)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2003, 2006, 2008 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -468,6 +468,7 @@ static void *test(void *arg, size_t s)
|
|||
mps_ld_add(&ld, arena, obj);
|
||||
|
||||
if (mps_ld_isstale(&ld, arena, obj)) {
|
||||
cdie(mps_ld_isstale_any(&ld, arena), "mps_ld_isstale_any");
|
||||
mps_ld_reset(&ld, arena);
|
||||
mps_ld_add(&ld, arena, obj);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* mpsioan.c: RAVENBROOK MEMORY POOL SYSTEM I/O IMPLEMENTATION (ANSI)
|
||||
*
|
||||
* $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.
|
||||
*
|
||||
* .readership: For MPS client application developers and MPS developers.
|
||||
* .sources: <design/io/>
|
||||
|
|
@ -21,14 +21,10 @@
|
|||
* instead.
|
||||
*/
|
||||
#include "check.h"
|
||||
|
||||
#ifdef MPS_OS_XC
|
||||
#include "osxc.h"
|
||||
#endif
|
||||
#include "config.h" /* to get platform configurations */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "config.h" /* to get platform configurations */
|
||||
|
||||
|
||||
static FILE *ioFile = NULL;
|
||||
|
|
@ -42,7 +38,7 @@ static FILE *ioFile = NULL;
|
|||
mps_res_t mps_io_create(mps_io_t *mps_io_r)
|
||||
{
|
||||
FILE *f;
|
||||
char *filename;
|
||||
const char *filename;
|
||||
|
||||
if(ioFile != NULL) /* See <code/event.c#trans.log> */
|
||||
return MPS_RES_LIMIT; /* Cannot currently open more than one log */
|
||||
|
|
@ -104,7 +100,7 @@ mps_res_t mps_io_flush(mps_io_t mps_io)
|
|||
|
||||
/* 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 @@
|
|||
/* mpsliban.c: RAVENBROOK MEMORY POOL SYSTEM LIBRARY INTERFACE (ANSI)
|
||||
*
|
||||
* $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: The purpose of this code is
|
||||
|
|
@ -27,12 +27,7 @@
|
|||
#include "mpstd.h"
|
||||
#include "event.h"
|
||||
|
||||
#ifdef MPS_OS_XC
|
||||
#include "osxc.h"
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
|
@ -172,7 +167,7 @@ unsigned long mps_lib_telemetry_control(void)
|
|||
unsigned long mask;
|
||||
char buf[256];
|
||||
char *word;
|
||||
char *sep = " ";
|
||||
const char *sep = " ";
|
||||
|
||||
s = getenv("MPS_TELEMETRY_CONTROL");
|
||||
if (s == NULL)
|
||||
|
|
@ -207,7 +202,7 @@ unsigned long mps_lib_telemetry_control(void)
|
|||
|
||||
/* 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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -139,9 +139,12 @@
|
|||
/* GCC 2.6.3, gcc -E -dM
|
||||
* The actual granularity of GNU malloc is 8, but field alignments are
|
||||
* all 4.
|
||||
* Note that Clang also defines __GNUC__ since it's generally GCC compatible,
|
||||
* but that doesn't fit our system so we exclude Clang here.
|
||||
*/
|
||||
|
||||
#elif defined(__linux__) && defined(__i386__) && defined(__GNUC__)
|
||||
#elif defined(__linux__) && defined(__i386__) && defined(__GNUC__) \
|
||||
&& !defined(__clang__)
|
||||
#if defined(CONFIG_PF_STRING) && ! defined(CONFIG_PF_LII3GC)
|
||||
#error "specified CONFIG_PF_... inconsistent with detected lii3gc"
|
||||
#endif
|
||||
|
|
@ -159,7 +162,8 @@
|
|||
|
||||
/* GCC 4.6.3, gcc -E -dM */
|
||||
|
||||
#elif defined(__linux__) && defined(__x86_64) && defined(__GNUC__)
|
||||
#elif defined(__linux__) && defined(__x86_64) && defined(__GNUC__) \
|
||||
&& !defined(__clang__)
|
||||
#if defined(CONFIG_PF_STRING) && ! defined(CONFIG_PF_LII6GC)
|
||||
#error "specified CONFIG_PF_... inconsistent with detected lii6gc"
|
||||
#endif
|
||||
|
|
@ -175,9 +179,29 @@
|
|||
#define MPS_PF_ALIGN 8
|
||||
|
||||
|
||||
/* Clang/LLVM 3.0, clang -E -dM */
|
||||
|
||||
#elif defined(__linux__) && defined(__x86_64) && defined(__GNUC__) \
|
||||
&& defined(__clang__)
|
||||
#if defined(CONFIG_PF_STRING) && ! defined(CONFIG_PF_LII6LL)
|
||||
#error "specified CONFIG_PF_... inconsistent with detected lii6ll"
|
||||
#endif
|
||||
#define MPS_PF_LII6LL
|
||||
#define MPS_PF_STRING "lii6ll"
|
||||
#define MPS_OS_LI
|
||||
#define MPS_ARCH_I6
|
||||
#define MPS_BUILD_LL
|
||||
#define MPS_T_WORD unsigned long
|
||||
#define MPS_T_ULONGEST unsigned long
|
||||
#define MPS_WORD_WIDTH 64
|
||||
#define MPS_WORD_SHIFT 6
|
||||
#define MPS_PF_ALIGN 8
|
||||
|
||||
|
||||
/* GCC 2.95.3, gcc -E -dM */
|
||||
|
||||
#elif defined(__FreeBSD__) && defined (__i386__) && defined (__GNUC__)
|
||||
#elif defined(__FreeBSD__) && defined (__i386__) && defined (__GNUC__) \
|
||||
&& !defined(__clang__)
|
||||
#if defined(CONFIG_PF_STRING) && ! defined(CONFIG_PF_FRI3GC)
|
||||
#error "specified CONFIG_PF_... inconsistent with detected fri3gc"
|
||||
#endif
|
||||
|
|
@ -193,7 +217,8 @@
|
|||
#define MPS_PF_ALIGN 4
|
||||
|
||||
|
||||
#elif defined(__FreeBSD__) && defined (__x86_64__) && defined (__GNUC__)
|
||||
#elif defined(__FreeBSD__) && defined (__x86_64__) && defined (__GNUC__) \
|
||||
&& !defined(__clang__)
|
||||
#if defined(CONFIG_PF_STRING) && ! defined(CONFIG_PF_FRI6GC)
|
||||
#error "specified CONFIG_PF_... inconsistent with detected fri6gc"
|
||||
#endif
|
||||
|
|
@ -219,7 +244,7 @@
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002,2008 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2013 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 @@
|
|||
/* pool.c: POOL IMPLEMENTATION
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (C) 2001 Global Graphics Software.
|
||||
*
|
||||
* DESIGN
|
||||
|
|
@ -68,6 +68,7 @@ Bool PoolClassCheck(PoolClass class)
|
|||
CHECKL(FUNCHECK(class->framePush));
|
||||
CHECKL(FUNCHECK(class->framePop));
|
||||
CHECKL(FUNCHECK(class->framePopPending));
|
||||
CHECKL(FUNCHECK(class->addrObject));
|
||||
CHECKL(FUNCHECK(class->walk));
|
||||
CHECKL(FUNCHECK(class->freewalk));
|
||||
CHECKL(FUNCHECK(class->bufferClass));
|
||||
|
|
@ -320,6 +321,8 @@ void PoolFree(Pool pool, Addr old, Size size)
|
|||
AVER(old != NULL);
|
||||
/* The pool methods should check that old is in pool. */
|
||||
AVER(size > 0);
|
||||
AVER(PoolHasRange(pool, old, AddrAdd(old, size)));
|
||||
|
||||
(*pool->class->free)(pool, old, size);
|
||||
|
||||
EVENT3(PoolFree, pool, old, size);
|
||||
|
|
@ -472,6 +475,23 @@ void PoolTraceEnd(Pool pool, Trace trace)
|
|||
}
|
||||
|
||||
|
||||
/* PoolAddrObject -- find client pointer to object containing addr
|
||||
* See user documentation for mps_addr_object.
|
||||
* addr is known to belong to seg, which belongs to pool.
|
||||
* See job003589.
|
||||
*/
|
||||
|
||||
Res PoolAddrObject(Addr *pReturn, Pool pool, Seg seg, Addr addr)
|
||||
{
|
||||
AVER(pReturn != NULL);
|
||||
AVERT(Pool, pool);
|
||||
AVERT(Seg, seg);
|
||||
AVER(pool == SegPool(seg));
|
||||
AVER(SegBase(seg) <= addr && addr < SegLimit(seg));
|
||||
return (*pool->class->addrObject)(pReturn, pool, seg, addr);
|
||||
}
|
||||
|
||||
|
||||
/* PoolWalk -- walk objects in this segment */
|
||||
|
||||
void PoolWalk(Pool pool, Seg seg, FormattedObjectsStepMethod f,
|
||||
|
|
@ -663,7 +683,7 @@ Bool PoolHasRange(Pool pool, Addr base, Addr limit)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -143,6 +143,7 @@ DEFINE_CLASS(AbstractPoolClass, class)
|
|||
class->framePush = PoolNoFramePush;
|
||||
class->framePop = PoolNoFramePop;
|
||||
class->framePopPending = PoolNoFramePopPending;
|
||||
class->addrObject = PoolNoAddrObject;
|
||||
class->walk = PoolNoWalk;
|
||||
class->freewalk = PoolNoFreeWalk;
|
||||
class->bufferClass = PoolNoBufferClass;
|
||||
|
|
@ -631,6 +632,16 @@ Res PoolTrivFramePop(Pool pool, Buffer buf, AllocFrame frame)
|
|||
}
|
||||
|
||||
|
||||
Res PoolNoAddrObject(Addr *pReturn, Pool pool, Seg seg, Addr addr)
|
||||
{
|
||||
AVER(pReturn != NULL);
|
||||
AVERT(Pool, pool);
|
||||
AVERT(Seg, seg);
|
||||
AVER(SegPool(seg) == pool);
|
||||
AVER(SegBase(seg) <= addr && addr < SegLimit(seg));
|
||||
return ResUNIMPL;
|
||||
}
|
||||
|
||||
void PoolNoWalk(Pool pool, Seg seg,
|
||||
FormattedObjectsStepMethod f, void *p, size_t s)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* poolamc.c: AUTOMATIC MOSTLY-COPYING MEMORY POOL CLASS
|
||||
*
|
||||
* $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) 2002 Global Graphics Software.
|
||||
*
|
||||
* .sources: <design/poolamc/>.
|
||||
|
|
@ -100,12 +100,12 @@ typedef struct amcNailboardStruct {
|
|||
* additional parameter (the address of the segment's generation) to
|
||||
* SegAlloc. See <design/poolamc/#fix.nail.distinguish>.
|
||||
*
|
||||
* .seg-ramp-new: "new" (if true) means this segment was allocated by
|
||||
* AMCBufferFill while amc->rampMode == RampRAMPING, and therefore
|
||||
* (I think) the contribution it *should* make to gen->pgen.newSize
|
||||
* is being deferred until the ramping is over. "new" is set to FALSE
|
||||
* in all other (ie. normal) circumstances. (The original comment for
|
||||
* this struct member was "allocated since last GC"). RHSK 2009-04-15.
|
||||
* .seg-ramp-new: The "new" flag is usually true, and indicates that the
|
||||
* segment has been counted towards the pool generation's newSize. It is
|
||||
* set to FALSE otherwise. This is used by both ramping and hash array
|
||||
* allocations. TODO: The code for this is scrappy and needs refactoring,
|
||||
* and the *reasons* for setting these flags need properly documenting.
|
||||
* RB 2013-07-17
|
||||
*/
|
||||
|
||||
typedef struct amcSegStruct *amcSeg;
|
||||
|
|
@ -563,13 +563,20 @@ typedef struct amcBufStruct *amcBuf;
|
|||
typedef struct amcBufStruct {
|
||||
SegBufStruct segbufStruct; /* superclass fields must come first */
|
||||
amcGen gen; /* The AMC generation */
|
||||
Bool forHashArrays; /* allocates hash table arrays, see AMCBufferFill */
|
||||
Sig sig; /* <design/sig/> */
|
||||
} amcBufStruct;
|
||||
|
||||
|
||||
/* Buffer2amcBuf -- convert generic Buffer to an amcBuf */
|
||||
|
||||
#define Buffer2amcBuf(buffer) ((amcBuf)(buffer))
|
||||
#define Buffer2amcBuf(buffer) \
|
||||
PARENT(amcBufStruct, segbufStruct, \
|
||||
PARENT(SegBufStruct, bufferStruct, buffer))
|
||||
|
||||
/* amcBuf2Buffer -- convert amcBuf to generic Buffer */
|
||||
|
||||
#define amcBuf2Buffer(amcbuf) (&(amcbuf)->segbufStruct.bufferStruct)
|
||||
|
||||
|
||||
|
||||
|
|
@ -577,13 +584,13 @@ typedef struct amcBufStruct {
|
|||
|
||||
static Bool amcBufCheck(amcBuf amcbuf)
|
||||
{
|
||||
SegBuf segbuf;
|
||||
|
||||
CHECKS(amcBuf, amcbuf);
|
||||
segbuf = &amcbuf->segbufStruct;
|
||||
CHECKL(SegBufCheck(segbuf));
|
||||
CHECKL(SegBufCheck(&amcbuf->segbufStruct));
|
||||
if(amcbuf->gen != NULL)
|
||||
CHECKD(amcGen, amcbuf->gen);
|
||||
CHECKL(BoolCheck(amcbuf->forHashArrays));
|
||||
/* hash array buffers only created by mutator */
|
||||
CHECKL(BufferIsMutator(amcBuf2Buffer(amcbuf)) || !amcbuf->forHashArrays);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -609,6 +616,10 @@ static void amcBufSetGen(Buffer buffer, amcGen gen)
|
|||
}
|
||||
|
||||
|
||||
ARG_DEFINE_KEY(ap_hash_arrays, Bool);
|
||||
|
||||
#define amcKeyAPHashArrays (&_mps_key_ap_hash_arrays)
|
||||
|
||||
/* AMCBufInit -- Initialize an amcBuf */
|
||||
|
||||
static Res AMCBufInit(Buffer buffer, Pool pool, ArgList args)
|
||||
|
|
@ -617,12 +628,17 @@ static Res AMCBufInit(Buffer buffer, Pool pool, ArgList args)
|
|||
amcBuf amcbuf;
|
||||
BufferClass superclass;
|
||||
Res res;
|
||||
Bool forHashArrays = FALSE;
|
||||
ArgStruct arg;
|
||||
|
||||
AVERT(Buffer, buffer);
|
||||
AVERT(Pool, pool);
|
||||
amc = Pool2AMC(pool);
|
||||
AVERT(AMC, amc);
|
||||
|
||||
if (ArgPick(&arg, args, amcKeyAPHashArrays))
|
||||
forHashArrays = arg.val.b;
|
||||
|
||||
/* call next method */
|
||||
superclass = BUFFER_SUPERCLASS(amcBufClass);
|
||||
res = (*superclass->init)(buffer, pool, args);
|
||||
|
|
@ -637,6 +653,7 @@ static Res AMCBufInit(Buffer buffer, Pool pool, ArgList args)
|
|||
/* No gen yet -- see <design/poolamc/#gen.forward>. */
|
||||
amcbuf->gen = NULL;
|
||||
}
|
||||
amcbuf->forHashArrays = forHashArrays;
|
||||
amcbuf->sig = amcBufSig;
|
||||
AVERT(amcBuf, amcbuf);
|
||||
|
||||
|
|
@ -1147,6 +1164,8 @@ static Res AMCBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
Serial genNr;
|
||||
SegPrefStruct segPrefStruct;
|
||||
PoolGen pgen;
|
||||
amcBuf amcbuf;
|
||||
Bool isRamping;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
amc = Pool2AMC(pool);
|
||||
|
|
@ -1164,6 +1183,9 @@ static Res AMCBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
|
||||
pgen = &gen->pgen;
|
||||
|
||||
amcbuf = Buffer2amcBuf(buffer);
|
||||
AVERT(amcBuf, amcbuf);
|
||||
|
||||
/* Create and attach segment. The location of this segment is */
|
||||
/* expressed as a generation number. We rely on the arena to */
|
||||
/* organize locations appropriately. */
|
||||
|
|
@ -1193,21 +1215,15 @@ static Res AMCBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
++gen->segs;
|
||||
pgen->totalSize += alignedSize;
|
||||
|
||||
/* If ramping, or if the buffer is a large proportion of the
|
||||
* generation size, don't count it towards newSize. */
|
||||
|
||||
/* TODO: Find a better hack for this, which is really a work-around
|
||||
* for a nasty problem in the collection scheduling strategy.
|
||||
* See job003435. NB 2013-03-07. */
|
||||
|
||||
if((size < (pgen->chain->gens[genNr].capacity * 1024.0 / 4.0)) &&
|
||||
(amc->rampMode != RampRAMPING
|
||||
|| buffer != amc->rampGen->forward
|
||||
|| gen != amc->rampGen))
|
||||
{
|
||||
pgen->newSize += alignedSize;
|
||||
} else {
|
||||
/* If ramping, or if the buffer is intended for allocating
|
||||
hash table arrays, don't count it towards newSize. */
|
||||
isRamping = (amc->rampMode == RampRAMPING &&
|
||||
buffer == amc->rampGen->forward &&
|
||||
gen == amc->rampGen);
|
||||
if (isRamping || amcbuf->forHashArrays) {
|
||||
Seg2amcSeg(seg)->new = FALSE;
|
||||
} else {
|
||||
pgen->newSize += alignedSize;
|
||||
}
|
||||
PoolGenUpdateZones(pgen, seg);
|
||||
|
||||
|
|
@ -2081,23 +2097,26 @@ static void amcReclaimNailed(Pool pool, Trace trace, Seg seg)
|
|||
while(p < limit) {
|
||||
Addr q;
|
||||
Size length;
|
||||
Bool preserve;
|
||||
q = (*format->skip)(p);
|
||||
length = AddrOffset(p, q);
|
||||
if(amcSegHasNailboard(seg)
|
||||
? !amcNailGetMark(seg, p)
|
||||
/* If there's no mark table, retain all that hasn't been */
|
||||
/* forwarded. In this case, preservedInPlace* become */
|
||||
/* somewhat overstated. */
|
||||
: (*format->isMoved)(p) != NULL)
|
||||
{
|
||||
/* Replace forwarding pointer / unreachable object with pad */
|
||||
(*format->pad)(AddrSub(p, headerSize), length);
|
||||
bytesReclaimed += length;
|
||||
if(amcSegHasNailboard(seg)) {
|
||||
preserve = amcNailGetMark(seg, p);
|
||||
} else {
|
||||
/* There's no nailboard, so preserve everything that hasn't been
|
||||
* forwarded. In this case, preservedInPlace* become somewhat
|
||||
* overstated. */
|
||||
preserve = !(*format->isMoved)(p);
|
||||
}
|
||||
if(preserve) {
|
||||
++preservedInPlaceCount;
|
||||
preservedInPlaceSize += length;
|
||||
if(p == p1)
|
||||
obj1pip = TRUE;
|
||||
} else {
|
||||
/* Replace forwarding pointer / unreachable object with pad. */
|
||||
(*format->pad)(AddrSub(p, headerSize), length);
|
||||
bytesReclaimed += length;
|
||||
}
|
||||
|
||||
AVER(p < q);
|
||||
|
|
@ -2319,6 +2338,85 @@ static void amcWalkAll(Pool pool, FormattedObjectsStepMethod f,
|
|||
}
|
||||
|
||||
|
||||
/* amcAddrObjectSearch -- skip over objects (belonging to pool)
|
||||
* starting at objBase until we reach one of the following cases:
|
||||
* 1. addr is found (and not moved): set *pReturn to the client
|
||||
* pointer to the object containing addr and return ResOK;
|
||||
* 2. addr is found, but it moved: return ResFAIL;
|
||||
* 3. we reach searchLimit: return ResFAIL.
|
||||
*/
|
||||
static Res amcAddrObjectSearch(Addr *pReturn, Pool pool, Addr objBase,
|
||||
Addr searchLimit, Addr addr)
|
||||
{
|
||||
Format format;
|
||||
Size hdrSize;
|
||||
|
||||
AVER(pReturn != NULL);
|
||||
AVERT(Pool, pool);
|
||||
AVER(objBase <= searchLimit);
|
||||
|
||||
format = pool->format;
|
||||
hdrSize = format->headerSize;
|
||||
while (objBase < searchLimit) {
|
||||
Addr objRef = AddrAdd(objBase, hdrSize);
|
||||
Addr objLimit = AddrSub((*format->skip)(objRef), hdrSize);
|
||||
AVER(objBase < objLimit);
|
||||
if (addr < objLimit) {
|
||||
AVER(objBase <= addr && addr < objLimit); /* the point */
|
||||
if (!(*format->isMoved)(objRef)) {
|
||||
*pReturn = objRef;
|
||||
return ResOK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
objBase = objLimit;
|
||||
}
|
||||
return ResFAIL;
|
||||
}
|
||||
|
||||
|
||||
/* AMCAddrObject -- find client pointer to object containing addr.
|
||||
* addr is known to belong to seg, which belongs to pool.
|
||||
* See job003589.
|
||||
*/
|
||||
static Res AMCAddrObject(Addr *pReturn, Pool pool, Seg seg, Addr addr)
|
||||
{
|
||||
Res res;
|
||||
Arena arena;
|
||||
Addr base, limit; /* range of objects on segment */
|
||||
|
||||
AVER(pReturn != NULL);
|
||||
AVERT(Pool, pool);
|
||||
AVERT(Seg, seg);
|
||||
AVER(SegPool(seg) == pool);
|
||||
AVER(SegBase(seg) <= addr && addr < SegLimit(seg));
|
||||
|
||||
arena = PoolArena(pool);
|
||||
base = SegBase(seg);
|
||||
if (SegBuffer(seg) != NULL) {
|
||||
/* We use BufferGetInit here (and not BufferScanLimit) because we
|
||||
* want to be able to find objects that have been allocated and
|
||||
* committed since the last flip. These objects lie between the
|
||||
* addresses returned by BufferScanLimit (which returns the value
|
||||
* of init at the last flip) and BufferGetInit.
|
||||
*
|
||||
* Strictly speaking we only need a limit that is at least the
|
||||
* maximum of the objects on the segments. This is because addr
|
||||
* *must* point inside a live object and we stop skipping once we
|
||||
* have found it. The init pointer serves this purpose.
|
||||
*/
|
||||
limit = BufferGetInit(SegBuffer(seg));
|
||||
} else {
|
||||
limit = SegLimit(seg);
|
||||
}
|
||||
|
||||
ShieldExpose(arena, seg);
|
||||
res = amcAddrObjectSearch(pReturn, pool, base, limit, addr);
|
||||
ShieldCover(arena, seg);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* AMCDescribe -- describe the contents of the AMC pool
|
||||
*
|
||||
* See <design/poolamc/#describe>.
|
||||
|
|
@ -2328,7 +2426,7 @@ static Res AMCDescribe(Pool pool, mps_lib_FILE *stream)
|
|||
Res res;
|
||||
AMC amc;
|
||||
Ring node, nextNode;
|
||||
char *rampmode;
|
||||
const char *rampmode;
|
||||
|
||||
if(!TESTT(Pool, pool))
|
||||
return ResFAIL;
|
||||
|
|
@ -2415,6 +2513,7 @@ DEFINE_POOL_CLASS(AMCPoolClass, this)
|
|||
this->traceEnd = AMCTraceEnd;
|
||||
this->rampBegin = AMCRampBegin;
|
||||
this->rampEnd = AMCRampEnd;
|
||||
this->addrObject = AMCAddrObject;
|
||||
this->walk = AMCWalk;
|
||||
this->bufferClass = amcBufClassGet;
|
||||
this->describe = AMCDescribe;
|
||||
|
|
@ -2535,7 +2634,7 @@ static Bool AMCCheck(AMC amc)
|
|||
|
||||
/* 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 @@
|
|||
/* poolams.c: AUTOMATIC MARK & SWEEP POOL CLASS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (c) 2002 Global Graphics Software.
|
||||
*
|
||||
*
|
||||
|
|
@ -763,7 +763,7 @@ static Res AMSInit(Pool pool, ArgList args)
|
|||
Res res;
|
||||
Format format;
|
||||
Chain chain;
|
||||
Bool supportAmbiguous;
|
||||
Bool supportAmbiguous = AMS_SUPPORT_AMBIGUOUS_DEFAULT;
|
||||
ArgStruct arg;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
|
|
@ -773,7 +773,7 @@ static Res AMSInit(Pool pool, ArgList args)
|
|||
chain = arg.val.chain;
|
||||
ArgRequire(&arg, args, MPS_KEY_FORMAT);
|
||||
format = arg.val.format;
|
||||
ArgRequire(&arg, args, MPS_KEY_AMS_SUPPORT_AMBIGUOUS);
|
||||
if (ArgPick(&arg, args, MPS_KEY_AMS_SUPPORT_AMBIGUOUS))
|
||||
supportAmbiguous = arg.val.b;
|
||||
|
||||
/* .ambiguous.noshare: If the pool is required to support ambiguous */
|
||||
|
|
@ -1741,7 +1741,7 @@ Bool AMSCheck(AMS ams)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1304,8 +1304,8 @@ static Bool AWLCheck(AWL awl)
|
|||
CHECKL(awl->poolStruct.class == AWLPoolClassGet());
|
||||
CHECKL((Align)1 << awl->alignShift == awl->poolStruct.alignment);
|
||||
CHECKD(Chain, awl->chain);
|
||||
CHECKL(NONNEGATIVE(awl->gen));
|
||||
/* 30 is just a sanity check really, not a constraint. */
|
||||
CHECKL(0 <= awl->gen);
|
||||
CHECKL(awl->gen <= 30);
|
||||
/* Nothing to check about succAccesses. */
|
||||
CHECKL(FUNCHECK(awl->findDependent));
|
||||
|
|
|
|||
|
|
@ -50,17 +50,17 @@ enum {
|
|||
typedef struct LinkStruct *Link;
|
||||
typedef struct LinkStruct {
|
||||
int state; /* Free, Prefinal, Final */
|
||||
union {
|
||||
union LinkStructUnion {
|
||||
MessageStruct messageStruct; /* state = Final */
|
||||
RingStruct linkRing; /* state one of {Free, Prefinal} */
|
||||
} the;
|
||||
} LinkStruct;
|
||||
|
||||
#define linkOfMessage(message) \
|
||||
PARENT(LinkStruct, the.messageStruct, (message))
|
||||
PARENT(LinkStruct, the, PARENT(union LinkStructUnion, messageStruct, (message)))
|
||||
|
||||
#define linkOfRing(ring) \
|
||||
PARENT(LinkStruct, the.linkRing, (ring))
|
||||
PARENT(LinkStruct, the, PARENT(union LinkStructUnion, linkRing, (ring)))
|
||||
|
||||
|
||||
/* RefPart -- Protectable part of guardian
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* poolmv2.c: MANUAL VARIABLE-SIZED TEMPORAL POOL
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .purpose: A manual-variable pool designed to take advantage of
|
||||
* placement according to predicted deathtime.
|
||||
|
|
@ -39,14 +39,14 @@ static Res MVTBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
static void MVTBufferEmpty(Pool pool, Buffer buffer, Addr base, Addr limit);
|
||||
static void MVTFree(Pool pool, Addr base, Size size);
|
||||
static Res MVTDescribe(Pool pool, mps_lib_FILE *stream);
|
||||
static Res MVTSegAlloc(Seg *segReturn, MVT mvt, Size size, Pool pool,
|
||||
static Res MVTSegAlloc(Seg *segReturn, MVT mvt, Size size,
|
||||
Bool withReservoirPermit);
|
||||
|
||||
static void MVTSegFree(MVT mvt, Seg seg);
|
||||
static Bool MVTReturnSegs(MVT mvt, Range range, Arena arena);
|
||||
static Res MVTInsert(MVT mvt, Addr base, Addr limit);
|
||||
static Res MVTDelete(MVT mvt, Addr base, Addr limit);
|
||||
static void MVTRefillIfNecessary(MVT mvt, Size size);
|
||||
static void MVTRefillABQIfEmpty(MVT mvt, Size size);
|
||||
static Res MVTContingencySearch(Addr *baseReturn, Addr *limitReturn,
|
||||
MVT mvt, Size min);
|
||||
static Bool MVTCheckFit(Addr base, Addr limit, Size min, Arena arena);
|
||||
|
|
@ -425,7 +425,10 @@ static void MVTFinish(Pool pool)
|
|||
/* Free the segments in the pool */
|
||||
ring = PoolSegRing(pool);
|
||||
RING_FOR(node, ring, nextNode) {
|
||||
MVTSegFree(mvt, SegOfPoolRing(node));
|
||||
/* We mustn't call MVTSegFree, because we don't know whether or not
|
||||
* there was any fragmented (unavailable) space in this segment,
|
||||
* and so we can't keep the accounting correct. */
|
||||
SegFree(SegOfPoolRing(node));
|
||||
}
|
||||
|
||||
/* Finish the Freelist, ABQ and CBS structures */
|
||||
|
|
@ -435,6 +438,247 @@ static void MVTFinish(Pool pool)
|
|||
}
|
||||
|
||||
|
||||
/* SURELY(expr) -- evaluate expr and AVER that the result is true */
|
||||
|
||||
#define SURELY(expr) \
|
||||
BEGIN \
|
||||
Bool _b = (expr); \
|
||||
AVER(_b); \
|
||||
UNUSED(_b); \
|
||||
END
|
||||
|
||||
|
||||
/* MUST(expr) -- evaluate expr and AVER that the result is ResOK */
|
||||
|
||||
#define MUST(expr) \
|
||||
BEGIN \
|
||||
Res _res = (expr); \
|
||||
AVER(_res == ResOK); \
|
||||
UNUSED(_res); \
|
||||
END
|
||||
|
||||
|
||||
/* MVTNoteFill -- record that a buffer fill has occurred */
|
||||
|
||||
static void MVTNoteFill(MVT mvt, Addr base, Addr limit, Size minSize) {
|
||||
mvt->available -= AddrOffset(base, limit);
|
||||
mvt->allocated += AddrOffset(base, limit);
|
||||
AVER(mvt->size == mvt->allocated + mvt->available + mvt->unavailable);
|
||||
METER_ACC(mvt->poolUtilization, mvt->allocated * 100 / mvt->size);
|
||||
METER_ACC(mvt->poolUnavailable, mvt->unavailable);
|
||||
METER_ACC(mvt->poolAvailable, mvt->available);
|
||||
METER_ACC(mvt->poolAllocated, mvt->allocated);
|
||||
METER_ACC(mvt->poolSize, mvt->size);
|
||||
METER_ACC(mvt->bufferFills, AddrOffset(base, limit));
|
||||
AVER(AddrOffset(base, limit) >= minSize);
|
||||
}
|
||||
|
||||
|
||||
/* MVTOversizeFill -- try to fill a request for a large object
|
||||
*
|
||||
* When a request exceeds mvt->fillSize, we allocate it on a segment of
|
||||
* its own.
|
||||
*/
|
||||
static Res MVTOversizeFill(Addr *baseReturn,
|
||||
Addr *limitReturn,
|
||||
MVT mvt,
|
||||
Size minSize,
|
||||
Bool withReservoirPermit)
|
||||
{
|
||||
Res res;
|
||||
Seg seg;
|
||||
Addr base, limit;
|
||||
Size alignedSize;
|
||||
|
||||
alignedSize = SizeAlignUp(minSize, ArenaAlign(PoolArena(MVT2Pool(mvt))));
|
||||
|
||||
res = MVTSegAlloc(&seg, mvt, alignedSize, withReservoirPermit);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
/* Just exactly fill the buffer so that only this allocation comes from
|
||||
the segment. */
|
||||
base = SegBase(seg);
|
||||
limit = AddrAdd(SegBase(seg), minSize);
|
||||
|
||||
/* The rest of the segment was lost to fragmentation, so transfer it
|
||||
* to the unavailable total. (We deliberately lose these fragments
|
||||
* now so as to avoid the more severe fragmentation that we believe
|
||||
* would result if we used these for allocation. See
|
||||
* design.mps.poolmvt.arch.fragmentation.internal and
|
||||
* design.mps.poolmvt.anal.policy.size.)
|
||||
*/
|
||||
mvt->available -= alignedSize - minSize;
|
||||
mvt->unavailable += alignedSize - minSize;
|
||||
|
||||
METER_ACC(mvt->exceptions, minSize);
|
||||
METER_ACC(mvt->exceptionSplinters, alignedSize - minSize);
|
||||
|
||||
MVTNoteFill(mvt, base, limit, minSize);
|
||||
*baseReturn = base;
|
||||
*limitReturn = limit;
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
||||
/* MVTSplinterFill -- try to fill a request from the splinter */
|
||||
|
||||
static Bool MVTSplinterFill(Addr *baseReturn, Addr *limitReturn,
|
||||
MVT mvt, Size minSize)
|
||||
{
|
||||
Addr base, limit;
|
||||
|
||||
if (!mvt->splinter ||
|
||||
AddrOffset(mvt->splinterBase, mvt->splinterLimit) < minSize)
|
||||
return FALSE;
|
||||
|
||||
base = mvt->splinterBase;
|
||||
limit = mvt->splinterLimit;
|
||||
mvt->splinter = FALSE;
|
||||
|
||||
METER_ACC(mvt->splintersUsed, AddrOffset(base, limit));
|
||||
|
||||
MVTNoteFill(mvt, base, limit, minSize);
|
||||
*baseReturn = base;
|
||||
*limitReturn = limit;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* MVTOneSegOnly -- restrict a buffer fill to a single segment
|
||||
*
|
||||
* After a block has been found, this is applied so that the block
|
||||
* used to fill the buffer does not span multiple segments. (This
|
||||
* makes it more likely that when we free the objects that were
|
||||
* allocated from the block, that this will free the whole segment,
|
||||
* and so we'll be able to return the segment to the arena. A block
|
||||
* that spanned two segments would keep both segments allocated,
|
||||
* possibly unnecessarily.)
|
||||
*/
|
||||
static void MVTOneSegOnly(Addr *baseIO, Addr *limitIO, MVT mvt, Size minSize)
|
||||
{
|
||||
Addr base, limit, segLimit;
|
||||
Seg seg;
|
||||
Arena arena;
|
||||
|
||||
base = *baseIO;
|
||||
limit = *limitIO;
|
||||
|
||||
arena = PoolArena(MVT2Pool(mvt));
|
||||
|
||||
SURELY(SegOfAddr(&seg, arena, base));
|
||||
segLimit = SegLimit(seg);
|
||||
if (limit <= segLimit) {
|
||||
/* perfect fit */
|
||||
METER_ACC(mvt->perfectFits, AddrOffset(base, limit));
|
||||
} else if (AddrOffset(base, segLimit) >= minSize) {
|
||||
/* fit in 1st segment */
|
||||
limit = segLimit;
|
||||
METER_ACC(mvt->firstFits, AddrOffset(base, limit));
|
||||
} else {
|
||||
/* fit in 2nd segment */
|
||||
base = segLimit;
|
||||
SURELY(SegOfAddr(&seg, arena, base));
|
||||
segLimit = SegLimit(seg);
|
||||
if (limit > segLimit)
|
||||
limit = segLimit;
|
||||
METER_ACC(mvt->secondFits, AddrOffset(base, limit));
|
||||
}
|
||||
|
||||
*baseIO = base;
|
||||
*limitIO = limit;
|
||||
}
|
||||
|
||||
|
||||
/* MVTABQFill -- try to fill a request from the available block queue */
|
||||
|
||||
static Bool MVTABQFill(Addr *baseReturn, Addr *limitReturn,
|
||||
MVT mvt, Size minSize)
|
||||
{
|
||||
Addr base, limit;
|
||||
RangeStruct range;
|
||||
Res res;
|
||||
|
||||
MVTRefillABQIfEmpty(mvt, minSize);
|
||||
|
||||
if (!ABQPeek(MVTABQ(mvt), &range))
|
||||
return FALSE;
|
||||
/* Check that the range was stored and retrieved correctly by the ABQ. */
|
||||
AVERT(Range, &range);
|
||||
|
||||
base = RangeBase(&range);
|
||||
limit = RangeLimit(&range);
|
||||
MVTOneSegOnly(&base, &limit, mvt, minSize);
|
||||
|
||||
METER_ACC(mvt->finds, minSize);
|
||||
|
||||
res = MVTDelete(mvt, base, limit);
|
||||
if (res != ResOK) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
MVTNoteFill(mvt, base, limit, minSize);
|
||||
*baseReturn = base;
|
||||
*limitReturn = limit;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* MVTContingencyFill -- try to fill a request from the CBS or Freelist
|
||||
*
|
||||
* (The CBS and Freelist are lumped together under the heading of
|
||||
* "contingency" for historical reasons: the Freelist used to be part
|
||||
* of the CBS. There is no principled reason why these two are
|
||||
* searched at the same time: if it should prove convenient to
|
||||
* separate them, go ahead.)
|
||||
*/
|
||||
static Bool MVTContingencyFill(Addr *baseReturn, Addr *limitReturn,
|
||||
MVT mvt, Size minSize)
|
||||
{
|
||||
Res res;
|
||||
Addr base, limit;
|
||||
|
||||
if (!MVTContingencySearch(&base, &limit, mvt, minSize))
|
||||
return FALSE;
|
||||
|
||||
MVTOneSegOnly(&base, &limit, mvt, minSize);
|
||||
|
||||
res = MVTDelete(mvt, base, limit);
|
||||
if (res != ResOK)
|
||||
return FALSE;
|
||||
|
||||
MVTNoteFill(mvt, base, limit, minSize);
|
||||
*baseReturn = base;
|
||||
*limitReturn = limit;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* MVTSegFill -- try to fill a request with a new segment */
|
||||
|
||||
static Res MVTSegFill(Addr *baseReturn, Addr *limitReturn,
|
||||
MVT mvt, Size fillSize,
|
||||
Size minSize,
|
||||
Bool withReservoirPermit)
|
||||
{
|
||||
Res res;
|
||||
Seg seg;
|
||||
Addr base, limit;
|
||||
|
||||
res = MVTSegAlloc(&seg, mvt, fillSize, withReservoirPermit);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
base = SegBase(seg);
|
||||
limit = SegLimit(seg);
|
||||
|
||||
MVTNoteFill(mvt, base, limit, minSize);
|
||||
*baseReturn = base;
|
||||
*limitReturn = limit;
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
||||
/* MVTBufferFill -- refill an allocation buffer from an MVT pool
|
||||
*
|
||||
* See <design/poolmvt/#impl.c.ap.fill>
|
||||
|
|
@ -443,13 +687,8 @@ static Res MVTBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
Pool pool, Buffer buffer, Size minSize,
|
||||
Bool withReservoirPermit)
|
||||
{
|
||||
Seg seg;
|
||||
MVT mvt;
|
||||
Res res;
|
||||
Addr base = NULL, limit = NULL;
|
||||
Arena arena;
|
||||
Size alignedSize, fillSize;
|
||||
RangeStruct range;
|
||||
|
||||
AVER(baseReturn != NULL);
|
||||
AVER(limitReturn != NULL);
|
||||
|
|
@ -462,136 +701,51 @@ static Res MVTBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
AVER(SizeIsAligned(minSize, pool->alignment));
|
||||
AVER(BoolCheck(withReservoirPermit));
|
||||
|
||||
arena = PoolArena(pool);
|
||||
fillSize = mvt->fillSize;
|
||||
alignedSize = SizeAlignUp(minSize, ArenaAlign(arena));
|
||||
|
||||
/* <design/poolmvt/#arch.ap.no-fit.oversize> */
|
||||
/* Allocate oversize blocks exactly, directly from the arena */
|
||||
if (minSize > fillSize) {
|
||||
res = MVTSegAlloc(&seg, mvt, alignedSize, pool, withReservoirPermit);
|
||||
if (res == ResOK) {
|
||||
base = SegBase(seg);
|
||||
/* only allocate this block in the segment */
|
||||
limit = AddrAdd(base, minSize);
|
||||
mvt->available -= alignedSize - minSize;
|
||||
mvt->unavailable += alignedSize - minSize;
|
||||
AVER(mvt->size == mvt->allocated + mvt->available +
|
||||
mvt->unavailable);
|
||||
METER_ACC(mvt->exceptions, minSize);
|
||||
METER_ACC(mvt->exceptionSplinters, alignedSize - minSize);
|
||||
goto done;
|
||||
}
|
||||
/* --- There cannot be a segment big enough to hold this object in
|
||||
the free list, although there may be segments that could be
|
||||
coalesced to do so. */
|
||||
AVER(res != ResOK);
|
||||
return res;
|
||||
/* Allocate oversize blocks exactly, directly from the arena.
|
||||
<design/poolmvt/#arch.ap.no-fit.oversize> */
|
||||
if (minSize > mvt->fillSize) {
|
||||
return MVTOversizeFill(baseReturn, limitReturn, mvt,
|
||||
minSize, withReservoirPermit);
|
||||
}
|
||||
|
||||
/* <design/poolmvt/#arch.ap.no-fit.return> */
|
||||
/* Use any splinter, if available */
|
||||
if (mvt->splinter) {
|
||||
base = mvt->splinterBase;
|
||||
limit = mvt->splinterLimit;
|
||||
if(AddrOffset(base, limit) >= minSize) {
|
||||
seg = mvt->splinterSeg;
|
||||
mvt->splinter = FALSE;
|
||||
METER_ACC(mvt->splintersUsed, AddrOffset(base, limit));
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
/* Use any splinter, if available.
|
||||
<design/poolmvt/#arch.ap.no-fit.return> */
|
||||
if (MVTSplinterFill(baseReturn, limitReturn, mvt, minSize))
|
||||
return ResOK;
|
||||
|
||||
/* Attempt to retrieve a free block from the ABQ. */
|
||||
if (MVTABQFill(baseReturn, limitReturn, mvt, minSize))
|
||||
return ResOK;
|
||||
|
||||
/* Attempt to retrieve a free block from the ABQ */
|
||||
MVTRefillIfNecessary(mvt, minSize);
|
||||
res = ABQPeek(MVTABQ(mvt), &range);
|
||||
if (res != ResOK) {
|
||||
METER_ACC(mvt->underflows, minSize);
|
||||
/* <design/poolmvt/#arch.contingency.fragmentation-limit> */
|
||||
|
||||
/* If fragmentation is acceptable, attempt to find a free block from
|
||||
the CBS or Freelist.
|
||||
<design/poolmvt/#arch.contingency.fragmentation-limit> */
|
||||
if (mvt->available >= mvt->availLimit) {
|
||||
METER_ACC(mvt->fragLimitContingencies, minSize);
|
||||
res = MVTContingencySearch(&base, &limit, mvt, minSize);
|
||||
}
|
||||
} else {
|
||||
AVERT(Range, &range);
|
||||
base = RangeBase(&range);
|
||||
limit = RangeLimit(&range);
|
||||
METER_ACC(mvt->finds, minSize);
|
||||
}
|
||||
found:
|
||||
if (res == ResOK) {
|
||||
{
|
||||
Bool b = SegOfAddr(&seg, arena, base);
|
||||
AVER(b);
|
||||
UNUSED(b); /* <code/mpm.c#check.unused> */
|
||||
}
|
||||
/* Only pass out segments - may not be the best long-term policy. */
|
||||
{
|
||||
Addr segLimit = SegLimit(seg);
|
||||
|
||||
if (limit <= segLimit) {
|
||||
/* perfect fit */
|
||||
METER_ACC(mvt->perfectFits, AddrOffset(base, limit));
|
||||
} else if (AddrOffset(base, segLimit) >= minSize) {
|
||||
/* fit in 1st segment */
|
||||
limit = segLimit;
|
||||
METER_ACC(mvt->firstFits, AddrOffset(base, limit));
|
||||
} else {
|
||||
/* fit in 2nd second segment */
|
||||
base = segLimit;
|
||||
{
|
||||
Bool b = SegOfAddr(&seg, arena, base);
|
||||
AVER(b);
|
||||
UNUSED(b); /* <code/mpm.c#check.unused> */
|
||||
}
|
||||
segLimit = SegLimit(seg);
|
||||
if (limit > segLimit)
|
||||
limit = segLimit;
|
||||
METER_ACC(mvt->secondFits, AddrOffset(base, limit));
|
||||
}
|
||||
}
|
||||
{
|
||||
Res r = MVTDelete(mvt, base, limit);
|
||||
AVER(r == ResOK);
|
||||
UNUSED(r); /* <code/mpm.c#check.unused> */
|
||||
}
|
||||
goto done;
|
||||
if (MVTContingencyFill(baseReturn, limitReturn, mvt, minSize))
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
/* Attempt to request a block from the arena */
|
||||
/* see <design/poolmvt/#impl.c.free.merge.segment> */
|
||||
res = MVTSegAlloc(&seg, mvt, fillSize, pool, withReservoirPermit);
|
||||
if (res == ResOK) {
|
||||
base = SegBase(seg);
|
||||
limit = SegLimit(seg);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Try contingency */
|
||||
METER_ACC(mvt->emergencyContingencies, minSize);
|
||||
res = MVTContingencySearch(&base, &limit, mvt, minSize);
|
||||
/* Attempt to request a block from the arena.
|
||||
<design/poolmvt/#impl.c.free.merge.segment> */
|
||||
res = MVTSegFill(baseReturn, limitReturn,
|
||||
mvt, mvt->fillSize, minSize, withReservoirPermit);
|
||||
if (res == ResOK)
|
||||
goto found;
|
||||
return ResOK;
|
||||
|
||||
/* Things are looking pretty desperate. Try the contingencies again,
|
||||
disregarding fragmentation limits. */
|
||||
if (ResIsAllocFailure(res)) {
|
||||
METER_ACC(mvt->emergencyContingencies, minSize);
|
||||
if (MVTContingencyFill(baseReturn, limitReturn, mvt, minSize))
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
METER_ACC(mvt->failures, minSize);
|
||||
AVER(res != ResOK);
|
||||
return res;
|
||||
|
||||
done:
|
||||
*baseReturn = base;
|
||||
*limitReturn = limit;
|
||||
mvt->available -= AddrOffset(base, limit);
|
||||
mvt->allocated += AddrOffset(base, limit);
|
||||
AVER(mvt->size == mvt->allocated + mvt->available +
|
||||
mvt->unavailable);
|
||||
METER_ACC(mvt->poolUtilization, mvt->allocated * 100 / mvt->size);
|
||||
METER_ACC(mvt->poolUnavailable, mvt->unavailable);
|
||||
METER_ACC(mvt->poolAvailable, mvt->available);
|
||||
METER_ACC(mvt->poolAllocated, mvt->allocated);
|
||||
METER_ACC(mvt->poolSize, mvt->size);
|
||||
METER_ACC(mvt->bufferFills, AddrOffset(base, limit));
|
||||
AVER(AddrOffset(base, limit) >= minSize);
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -623,25 +777,22 @@ static Bool MVTDeleteOverlapping(Bool *deleteReturn, void *element,
|
|||
*/
|
||||
static Res MVTReserve(MVT mvt, Range range)
|
||||
{
|
||||
Res res;
|
||||
AVERT(MVT, mvt);
|
||||
AVERT(Range, range);
|
||||
AVER(RangeSize(range) >= mvt->reuseSize);
|
||||
|
||||
res = ABQPush(MVTABQ(mvt), range);
|
||||
|
||||
/* See <design/poolmvt/#impl.c.free.merge> */
|
||||
if (res != ResOK) {
|
||||
if (!ABQPush(MVTABQ(mvt), range)) {
|
||||
Arena arena = PoolArena(MVT2Pool(mvt));
|
||||
RangeStruct oldRange;
|
||||
res = ABQPeek(MVTABQ(mvt), &oldRange);
|
||||
AVER(res == ResOK);
|
||||
/* We just failed to push, so the ABQ must be full, and so surely
|
||||
* the peek will succeed. */
|
||||
SURELY(ABQPeek(MVTABQ(mvt), &oldRange));
|
||||
AVERT(Range, &oldRange);
|
||||
if (!MVTReturnSegs(mvt, &oldRange, arena))
|
||||
goto failOverflow;
|
||||
METER_ACC(mvt->returns, RangeSize(&oldRange));
|
||||
res = ABQPush(MVTABQ(mvt), range);
|
||||
if (res != ResOK)
|
||||
if (!ABQPush(MVTABQ(mvt), range))
|
||||
goto failOverflow;
|
||||
}
|
||||
|
||||
|
|
@ -851,11 +1002,7 @@ static void MVTFree(Pool pool, Addr base, Size size)
|
|||
/* Return exceptional blocks directly to arena */
|
||||
if (size > mvt->fillSize) {
|
||||
Seg seg;
|
||||
{
|
||||
Bool b = SegOfAddr(&seg, PoolArena(pool), base);
|
||||
AVER(b);
|
||||
UNUSED(b); /* <code/mpm.c#check.unused> */
|
||||
}
|
||||
SURELY(SegOfAddr(&seg, PoolArena(pool), base));
|
||||
AVER(base == SegBase(seg));
|
||||
AVER(limit <= SegLimit(seg));
|
||||
mvt->available += SegSize(seg) - size;
|
||||
|
|
@ -869,11 +1016,7 @@ static void MVTFree(Pool pool, Addr base, Size size)
|
|||
return;
|
||||
}
|
||||
|
||||
{
|
||||
Res res = MVTInsert(mvt, base, limit);
|
||||
AVER(res == ResOK);
|
||||
UNUSED(res); /* <code/mpm.c#check.unused> */
|
||||
}
|
||||
MUST(MVTInsert(mvt, base, limit));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1054,12 +1197,12 @@ size_t mps_mvt_free_size(mps_pool_t mps_pool)
|
|||
* metering
|
||||
*/
|
||||
static Res MVTSegAlloc(Seg *segReturn, MVT mvt, Size size,
|
||||
Pool pool, Bool withReservoirPermit)
|
||||
Bool withReservoirPermit)
|
||||
{
|
||||
/* Can't use plain old SegClass here because we need to call
|
||||
* SegBuffer() in MVTFree(). */
|
||||
Res res = SegAlloc(segReturn, GCSegClassGet(),
|
||||
MVTSegPref(mvt), size, pool, withReservoirPermit,
|
||||
MVTSegPref(mvt), size, MVT2Pool(mvt), withReservoirPermit,
|
||||
argsNone);
|
||||
|
||||
if (res == ResOK) {
|
||||
|
|
@ -1083,6 +1226,7 @@ static Res MVTSegAlloc(Seg *segReturn, MVT mvt, Size size,
|
|||
static void MVTSegFree(MVT mvt, Seg seg)
|
||||
{
|
||||
Size size = SegSize(seg);
|
||||
AVER(mvt->available >= size);
|
||||
|
||||
mvt->available -= size;
|
||||
mvt->size -= size;
|
||||
|
|
@ -1107,18 +1251,11 @@ static Bool MVTReturnSegs(MVT mvt, Range range, Arena arena)
|
|||
Seg seg;
|
||||
Addr segBase, segLimit;
|
||||
|
||||
{
|
||||
Bool b = SegOfAddr(&seg, arena, base);
|
||||
AVER(b);
|
||||
UNUSED(b); /* <code/mpm.c#check.unused> */
|
||||
}
|
||||
SURELY(SegOfAddr(&seg, arena, base));
|
||||
segBase = SegBase(seg);
|
||||
segLimit = SegLimit(seg);
|
||||
if (base <= segBase && limit >= segLimit) {
|
||||
Res r = MVTDelete(mvt, segBase, segLimit);
|
||||
|
||||
AVER(r == ResOK);
|
||||
UNUSED(r); /* <code/mpm.c#check.unused> */
|
||||
MUST(MVTDelete(mvt, segBase, segLimit));
|
||||
MVTSegFree(mvt, seg);
|
||||
success = TRUE;
|
||||
}
|
||||
|
|
@ -1130,7 +1267,7 @@ static Bool MVTReturnSegs(MVT mvt, Range range, Arena arena)
|
|||
|
||||
|
||||
/* MVTRefillCallback -- called from CBSIterate or FreelistIterate at
|
||||
* the behest of MVTRefillIfNecessary
|
||||
* the behest of MVTRefillABQIfEmpty
|
||||
*/
|
||||
static Bool MVTRefillCallback(MVT mvt, Range range)
|
||||
{
|
||||
|
|
@ -1173,14 +1310,19 @@ static Bool MVTFreelistRefillCallback(Bool *deleteReturn, Range range,
|
|||
return MVTRefillCallback(mvt, range);
|
||||
}
|
||||
|
||||
/* MVTRefillIfNecessary -- refill the ABQ from the CBS and the
|
||||
* Freelist if it had overflowed and is now empty.
|
||||
/* MVTRefillABQIfEmpty -- refill the ABQ from the CBS and the Freelist if
|
||||
* it is empty
|
||||
*/
|
||||
static void MVTRefillIfNecessary(MVT mvt, Size size)
|
||||
static void MVTRefillABQIfEmpty(MVT mvt, Size size)
|
||||
{
|
||||
AVERT(MVT, mvt);
|
||||
AVER(size > 0);
|
||||
|
||||
/* If there have never been any overflows from the ABQ back to the
|
||||
* CBS/Freelist, then there cannot be any blocks in the CBS/Freelist
|
||||
* that are worth adding to the ABQ. So as an optimization, we don't
|
||||
* bother to look.
|
||||
*/
|
||||
if (mvt->abqOverflow && ABQIsEmpty(MVTABQ(mvt))) {
|
||||
mvt->abqOverflow = FALSE;
|
||||
METER_ACC(mvt->refills, size);
|
||||
|
|
@ -1269,7 +1411,7 @@ static Bool MVTFreelistContingencyCallback(Bool *deleteReturn, Range range,
|
|||
/* MVTContingencySearch -- search the CBS and the Freelist for a block
|
||||
* of size min */
|
||||
|
||||
static Res MVTContingencySearch(Addr *baseReturn, Addr *limitReturn,
|
||||
static Bool MVTContingencySearch(Addr *baseReturn, Addr *limitReturn,
|
||||
MVT mvt, Size min)
|
||||
{
|
||||
MVTContigencyStruct cls;
|
||||
|
|
@ -1286,7 +1428,9 @@ static Res MVTContingencySearch(Addr *baseReturn, Addr *limitReturn,
|
|||
CBSIterate(MVTCBS(mvt), MVTCBSContingencyCallback, (void *)&cls, 0);
|
||||
FreelistIterate(MVTFreelist(mvt), MVTFreelistContingencyCallback,
|
||||
(void *)&cls, 0);
|
||||
if (cls.found) {
|
||||
if (!cls.found)
|
||||
return FALSE;
|
||||
|
||||
AVER(RangeSize(&cls.range) >= min);
|
||||
METER_ACC(mvt->contingencySearches, cls.steps);
|
||||
if (cls.hardSteps) {
|
||||
|
|
@ -1294,10 +1438,7 @@ static Res MVTContingencySearch(Addr *baseReturn, Addr *limitReturn,
|
|||
}
|
||||
*baseReturn = RangeBase(&cls.range);
|
||||
*limitReturn = RangeLimit(&cls.range);
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
return ResFAIL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1309,11 +1450,7 @@ static Bool MVTCheckFit(Addr base, Addr limit, Size min, Arena arena)
|
|||
Seg seg;
|
||||
Addr segLimit;
|
||||
|
||||
{
|
||||
Bool b = SegOfAddr(&seg, arena, base);
|
||||
AVER(b);
|
||||
UNUSED(b); /* <code/mpm.c#check.unused> */
|
||||
}
|
||||
SURELY(SegOfAddr(&seg, arena, base));
|
||||
segLimit = SegLimit(seg);
|
||||
|
||||
if (limit <= segLimit) {
|
||||
|
|
@ -1325,11 +1462,7 @@ static Bool MVTCheckFit(Addr base, Addr limit, Size min, Arena arena)
|
|||
return TRUE;
|
||||
|
||||
base = segLimit;
|
||||
{
|
||||
Bool b = SegOfAddr(&seg, arena, base);
|
||||
AVER(b);
|
||||
UNUSED(b); /* <code/mpm.c#check.unused> */
|
||||
}
|
||||
SURELY(SegOfAddr(&seg, arena, base));
|
||||
segLimit = SegLimit(seg);
|
||||
|
||||
if (AddrOffset(base, limit < segLimit ? limit : segLimit) >= min)
|
||||
|
|
@ -1357,7 +1490,7 @@ CBS _mps_mvt_cbs(mps_pool_t mps_pool) {
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -36,8 +36,8 @@ SRCID(prmci3li, "$Id$");
|
|||
|
||||
MRef Prmci3AddressHoldingReg(MutatorFaultContext mfc, unsigned int regnum)
|
||||
{
|
||||
AVER(NONNEGATIVE(regnum));
|
||||
AVER(regnum <= 7);
|
||||
AVER(regnum >= 0);
|
||||
|
||||
/* .source.i486 */
|
||||
/* .assume.regref */
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* prmci3w3.c: PROTECTION MUTATOR CONTEXT INTEL 386 (Win32)
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* PURPOSE
|
||||
*
|
||||
|
|
@ -32,8 +32,8 @@ MRef Prmci3AddressHoldingReg(MutatorFaultContext context, unsigned int regnum)
|
|||
{
|
||||
PCONTEXT wincont;
|
||||
|
||||
AVER(NONNEGATIVE(regnum));
|
||||
AVER(regnum <= 7);
|
||||
AVER(regnum >= 0);
|
||||
|
||||
wincont = context->ep->ContextRecord;
|
||||
|
||||
|
|
@ -80,7 +80,7 @@ void Prmci3StepOverIns(MutatorFaultContext context, Size inslen)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
144
mps/code/prmci3xc.c
Normal file
144
mps/code/prmci3xc.c
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
/* prmci3xc.c: PROTECTION MUTATOR CONTEXT INTEL 386 (MAC OS X)
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .purpose: This module implements the part of the protection module
|
||||
* that decodes the MutatorFaultContext.
|
||||
*
|
||||
*
|
||||
* SOURCES
|
||||
*
|
||||
* .source.i486: Intel486 Microprocessor Family Programmer's
|
||||
* Reference Manual
|
||||
*
|
||||
* .source.linux.kernel: Linux kernel source files.
|
||||
*
|
||||
*
|
||||
* ASSUMPTIONS
|
||||
*
|
||||
* .context.regroots: The root regs are assumed to be recorded in the context
|
||||
* at pointer-aligned boundaries.
|
||||
*
|
||||
* .assume.regref: The resisters in the context can be modified by
|
||||
* storing into an MRef pointer.
|
||||
*/
|
||||
|
||||
#include "prmcxc.h"
|
||||
#include "prmci3.h"
|
||||
|
||||
SRCID(prmci3li, "$Id$");
|
||||
|
||||
|
||||
/* Prmci3AddressHoldingReg -- return an address of a register in a context */
|
||||
|
||||
MRef Prmci3AddressHoldingReg(MutatorFaultContext mfc, unsigned int regnum)
|
||||
{
|
||||
AVER(NONNEGATIVE(regnum));
|
||||
AVER(regnum <= 7);
|
||||
|
||||
/* .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->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);
|
||||
}
|
||||
NOTREACHED;
|
||||
return (MRef)NULL; /* Avoids compiler warning. */
|
||||
}
|
||||
|
||||
|
||||
/* Prmci3DecodeFaultContext -- decode fault to find faulting address and IP */
|
||||
|
||||
void Prmci3DecodeFaultContext(MRef *faultmemReturn,
|
||||
Byte **insvecReturn,
|
||||
MutatorFaultContext mfc)
|
||||
{
|
||||
*faultmemReturn = (MRef)mfc->address;
|
||||
*insvecReturn = (Byte*)mfc->threadState->__eip;
|
||||
}
|
||||
|
||||
|
||||
/* Prmci3StepOverIns -- modify context to step over instruction */
|
||||
|
||||
void Prmci3StepOverIns(MutatorFaultContext mfc, Size inslen)
|
||||
{
|
||||
mfc->threadState->__eip += (Word)inslen;
|
||||
}
|
||||
|
||||
|
||||
Addr MutatorFaultContextSP(MutatorFaultContext mfc)
|
||||
{
|
||||
return (Addr)mfc->threadState->__esp;
|
||||
}
|
||||
|
||||
|
||||
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
|
||||
{
|
||||
x86_thread_state32_t *mc;
|
||||
Res res;
|
||||
|
||||
/* This scans the root registers (.context.regroots). It also
|
||||
unnecessarily scans the rest of the context. The optimisation
|
||||
to scan only relevant parts would be machine dependent. */
|
||||
mc = mfc->threadState;
|
||||
res = TraceScanAreaTagged(ss,
|
||||
(Addr *)mc,
|
||||
(Addr *)((char *)mc + sizeof(*mc)));
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 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.
|
||||
*/
|
||||
|
|
@ -35,8 +35,8 @@ MRef Prmci6AddressHoldingReg(MutatorFaultContext mfc, unsigned int regnum)
|
|||
{
|
||||
Word *gregs;
|
||||
|
||||
AVER(NONNEGATIVE(regnum));
|
||||
AVER(regnum <= 15);
|
||||
AVER(regnum >= 0);
|
||||
|
||||
gregs = (Word *)&mfc->ucontext->uc_mcontext.gregs;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* prmci6w3.c: PROTECTION MUTATOR CONTEXT INTEL 386 (Win32)
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* PURPOSE
|
||||
*
|
||||
|
|
@ -30,8 +30,8 @@ MRef Prmci6AddressHoldingReg(MutatorFaultContext context, unsigned int regnum)
|
|||
{
|
||||
PCONTEXT wincont;
|
||||
|
||||
AVER(NONNEGATIVE(regnum));
|
||||
AVER(regnum <= 16);
|
||||
AVER(regnum >= 0);
|
||||
|
||||
wincont = context->ep->ContextRecord;
|
||||
|
||||
|
|
@ -86,7 +86,7 @@ void Prmci6StepOverIns(MutatorFaultContext context, Size inslen)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
147
mps/code/prmci6xc.c
Normal file
147
mps/code/prmci6xc.c
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
/* prmci6xc.c: PROTECTION MUTATOR CONTEXT x64 (MAC OS X)
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .purpose: This module implements the part of the protection module
|
||||
* that decodes the MutatorFaultContext.
|
||||
*
|
||||
*
|
||||
* SOURCES
|
||||
*
|
||||
* .source.linux.kernel: Linux kernel source files.
|
||||
*
|
||||
*
|
||||
* ASSUMPTIONS
|
||||
*
|
||||
* .context.regroots: The root regs are assumed to be recorded in the context
|
||||
* at pointer-aligned boundaries.
|
||||
*
|
||||
* .assume.regref: The resisters in the context can be modified by
|
||||
* storing into an MRef pointer.
|
||||
*/
|
||||
|
||||
#include "prmcxc.h"
|
||||
#include "prmci6.h"
|
||||
|
||||
SRCID(prmci6li, "$Id$");
|
||||
|
||||
|
||||
/* Prmci6AddressHoldingReg -- return an address of a register in a context */
|
||||
|
||||
MRef Prmci6AddressHoldingReg(MutatorFaultContext mfc, unsigned int regnum)
|
||||
{
|
||||
AVER(NONNEGATIVE(regnum));
|
||||
AVER(regnum <= 15);
|
||||
|
||||
/* .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 *) */
|
||||
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);
|
||||
}
|
||||
NOTREACHED;
|
||||
return (MRef)NULL; /* Avoids compiler warning. */
|
||||
}
|
||||
|
||||
|
||||
/* Prmci3DecodeFaultContext -- decode fault to find faulting address and IP */
|
||||
|
||||
void Prmci6DecodeFaultContext(MRef *faultmemReturn,
|
||||
Byte **insvecReturn,
|
||||
MutatorFaultContext mfc)
|
||||
{
|
||||
*faultmemReturn = (MRef)mfc->address;
|
||||
*insvecReturn = (Byte*)mfc->threadState->__rip;
|
||||
}
|
||||
|
||||
|
||||
/* Prmci3StepOverIns -- modify context to step over instruction */
|
||||
|
||||
void Prmci6StepOverIns(MutatorFaultContext mfc, Size inslen)
|
||||
{
|
||||
mfc->threadState->__rip += (Word)inslen;
|
||||
}
|
||||
|
||||
|
||||
Addr MutatorFaultContextSP(MutatorFaultContext mfc)
|
||||
{
|
||||
return (Addr)mfc->threadState->__rsp;
|
||||
}
|
||||
|
||||
|
||||
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
|
||||
{
|
||||
x86_thread_state64_t *mc;
|
||||
Res res;
|
||||
|
||||
/* This scans the root registers (.context.regroots). It also
|
||||
unnecessarily scans the rest of the context. The optimisation
|
||||
to scan only relevant parts would be machine dependent. */
|
||||
mc = mfc->threadState;
|
||||
res = TraceScanAreaTagged(ss,
|
||||
(Addr *)mc,
|
||||
(Addr *)((char *)mc + sizeof(*mc)));
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 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,47 +1,33 @@
|
|||
/* eventpro.h: Interface for event processing routines
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
/* prmcxc.h: PROTECTION MUTATOR CONTEXT FOR OS X MACH
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .readership: MPS developers.
|
||||
*/
|
||||
|
||||
#ifndef eventpro_h
|
||||
#define eventpro_h
|
||||
#ifndef prmcxc_h
|
||||
#define prmcxc_h
|
||||
|
||||
#include "config.h"
|
||||
#include "mpm.h"
|
||||
|
||||
#include "eventcom.h"
|
||||
#include "mpmtypes.h"
|
||||
#include <mach/mach_types.h>
|
||||
#include <mach/i386/thread_status.h>
|
||||
|
||||
typedef struct MutatorFaultContextStruct { /* Protection fault context data */
|
||||
Addr address;
|
||||
THREAD_STATE_S *threadState;
|
||||
/* FIXME: Might need to get the floats in case the compiler stashes
|
||||
intermediate values in them. */
|
||||
} MutatorFaultContextStruct;
|
||||
|
||||
|
||||
typedef struct EventProcStruct *EventProc;
|
||||
typedef Res (*EventProcReader)(void *, void *, size_t);
|
||||
|
||||
|
||||
extern EventCode EventName2Code(char *name);
|
||||
extern char *EventCode2Name(EventCode code);
|
||||
extern char *EventCode2Format(EventCode code);
|
||||
extern Bool EventCodeIsValid(EventCode code);
|
||||
|
||||
extern Word AddrLabel(EventProc proc, Addr addr);
|
||||
extern char *LabelText(EventProc proc, Word label);
|
||||
|
||||
extern Res EventRead(Event *eventReturn, EventProc proc);
|
||||
extern void EventDestroy(EventProc proc, Event event);
|
||||
|
||||
extern Res EventRecord(EventProc proc, Event event, EventClock etime);
|
||||
|
||||
extern Res EventProcCreate(EventProc *procReturn,
|
||||
EventProcReader reader,
|
||||
void *readerP);
|
||||
extern void EventProcDestroy(EventProc proc);
|
||||
|
||||
|
||||
#endif /* eventpro_h */
|
||||
#endif /* prmcxc_h */
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
443
mps/code/protxc.c
Normal file
443
mps/code/protxc.c
Normal file
|
|
@ -0,0 +1,443 @@
|
|||
/* protxc.c: PROTECTION EXCEPTION HANDLER FOR OS X MACH
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2013 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* This is the protection exception handling code for OS X using the
|
||||
* Mach interface (not pthreads).
|
||||
*
|
||||
* In Mach, a thread that hits protected memory is suspended, and a message
|
||||
* is sent to a separate handler thread.
|
||||
*
|
||||
* The handler thread can fix things up and continue the suspended thread by
|
||||
* sending back a "success" reply. It can forward the message to another
|
||||
* handler of the same kind, or it can forward the message to another handler
|
||||
* at the next level out (the levels are thread, task, host) by sending a
|
||||
* "fail" reply.
|
||||
*
|
||||
* In OS X, pthreads are implemented by Mach threads. (The implementation is
|
||||
* part of the XNU source code at opensource.apple.com. [copy to import?]) So
|
||||
* we can use some pthread interfaces (pthread_create, pthread_once) for
|
||||
* convenience in setting up threads.
|
||||
*
|
||||
* This module sets up an exception handling thread for the EXC_BAD_ACCESS
|
||||
* exceptions that will be caused by the MPS shield (read/write barriers).
|
||||
* That thread calls the MPS to resolve the condition and allow the mutator
|
||||
* thread to progress.
|
||||
*
|
||||
*
|
||||
* REFERENCES
|
||||
*
|
||||
* [Fuller_2013] "Mach Exception Handlers"; Landon Fuller;
|
||||
* <http://www.mikeash.com/pyblog/friday-qa-2013-01-11-mach-exception-handlers.html>.
|
||||
*
|
||||
* [XNU] "xnu-2050.22.13" source code;
|
||||
* Apple Computer;
|
||||
* <http://www.opensource.apple.com/source/xnu/xnu-2050.22.13/>.
|
||||
*
|
||||
* [Mach_man] Mach man pages within XNU;
|
||||
* Apple Computer;
|
||||
* <http://www.opensource.apple.com/source/xnu/xnu-2050.22.13/osfmk/man/>.
|
||||
*
|
||||
* [Libc] "Libc-825.26" source code;
|
||||
* Apple Computer;
|
||||
* <http://www.opensource.apple.com/source/Libc/Libc-825.26/>.
|
||||
*
|
||||
*
|
||||
* TRANSGRESSIONS
|
||||
*
|
||||
* .trans.stdlib: It's OK to use the C library from here because we know
|
||||
* we're on OS X and not freestanding. In particular, we use memcpy.
|
||||
*
|
||||
* .trans.must: Various OS calls are asserted to succeed, since there isn't
|
||||
* really a dynamic reason they should fail, so it must be a static error.
|
||||
* In a RASH build, they don't stop the program, just in case it's able to
|
||||
* limp along.
|
||||
*/
|
||||
|
||||
#include "mpm.h"
|
||||
#include "prmcxc.h"
|
||||
#include "protxc.h"
|
||||
|
||||
#include <stdlib.h> /* see .trans.stdlib */
|
||||
#include <stdio.h> /* see .trans.stdlib */
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include <mach/mach_port.h>
|
||||
#include <mach/mach_init.h>
|
||||
#include <mach/task.h>
|
||||
#include <mach/thread_act.h>
|
||||
#include <mach/thread_status.h>
|
||||
#include <mach/mach_error.h>
|
||||
#include <mach/i386/thread_status.h>
|
||||
#include <mach/exc.h>
|
||||
|
||||
#if !defined(MPS_OS_XC)
|
||||
#error "protxc.c is OS X specific"
|
||||
#endif
|
||||
#if !defined(PROTECTION)
|
||||
#error "protxc.c implements protection, but PROTECTION is not defined"
|
||||
#endif
|
||||
|
||||
SRCID(protxc, "$Id$");
|
||||
|
||||
|
||||
/* Exception request message structure
|
||||
*
|
||||
* The following declaration is extracted by running the Mach Interface
|
||||
* Generator like this:
|
||||
*
|
||||
* mig /usr/include/mach/mach_exc.defs
|
||||
*
|
||||
* then copying it from the resulting mach_exc.h file. This gets the
|
||||
* structure with 64-bit code fields, corresponding to the exception
|
||||
* behaviour EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES. Only the
|
||||
* 32-bit structures are available in /usr/include/mach. Note that these
|
||||
* 32- and 64-bit message structures are independent of the architecture
|
||||
* word width, so we choose to use 64-bit on both I3 and I6.
|
||||
*/
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
/* start of the kernel processed data */
|
||||
mach_msg_body_t msgh_body;
|
||||
mach_msg_port_descriptor_t thread;
|
||||
mach_msg_port_descriptor_t task;
|
||||
/* end of the kernel processed data */
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
int64_t code[2];
|
||||
int flavor;
|
||||
mach_msg_type_number_t old_stateCnt;
|
||||
natural_t old_state[224];
|
||||
} __Request__mach_exception_raise_state_identity_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
|
||||
/* Local short names, for convenience. */
|
||||
typedef __Request__mach_exception_raise_state_identity_t protRequestStruct;
|
||||
typedef __Reply__exception_raise_state_identity_t protReplyStruct;
|
||||
|
||||
|
||||
/* protExcPort -- exception message receiving Mach port
|
||||
*
|
||||
* This will be the port that will receive messages for our exception
|
||||
* handler, initialized by protSetupInner.
|
||||
*/
|
||||
|
||||
static mach_port_name_t protExcPort = MACH_PORT_NULL;
|
||||
|
||||
|
||||
/* protBuildReply -- build a reply message based on a request. */
|
||||
|
||||
static void protBuildReply(protReplyStruct *reply,
|
||||
protRequestStruct *request,
|
||||
kern_return_t ret_code)
|
||||
{
|
||||
mach_msg_size_t state_size;
|
||||
reply->Head.msgh_bits =
|
||||
MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(request->Head.msgh_bits), 0);
|
||||
reply->Head.msgh_remote_port = request->Head.msgh_remote_port;
|
||||
reply->Head.msgh_local_port = MACH_PORT_NULL;
|
||||
reply->Head.msgh_reserved = 0;
|
||||
reply->Head.msgh_id = request->Head.msgh_id + 100;
|
||||
reply->NDR = request->NDR;
|
||||
reply->RetCode = ret_code;
|
||||
reply->flavor = request->flavor;
|
||||
reply->new_stateCnt = request->old_stateCnt;
|
||||
state_size = reply->new_stateCnt * sizeof(natural_t);
|
||||
AVER(sizeof(reply->new_state) >= state_size);
|
||||
memcpy(reply->new_state, request->old_state, state_size);
|
||||
/* If you use sizeof(reply) for reply->Head.msgh_size then the state
|
||||
gets ignored. */
|
||||
reply->Head.msgh_size = offsetof(protReplyStruct, new_state) + state_size;
|
||||
}
|
||||
|
||||
|
||||
/* protMustSend -- send a Mach message without fail, probably */
|
||||
|
||||
static void protMustSend(mach_msg_header_t *head)
|
||||
{
|
||||
kern_return_t kr;
|
||||
kr = mach_msg(head,
|
||||
MACH_SEND_MSG,
|
||||
head->msgh_size,
|
||||
/* recv_size */ 0,
|
||||
MACH_PORT_NULL,
|
||||
MACH_MSG_TIMEOUT_NONE,
|
||||
MACH_PORT_NULL);
|
||||
AVER(kr == KERN_SUCCESS);
|
||||
if (kr != KERN_SUCCESS)
|
||||
mach_error("ERROR: MPS mach_msg send", kr); /* .trans.must */
|
||||
}
|
||||
|
||||
|
||||
/* protCatchOne -- catch one EXC_BAD_ACCESS exception message.
|
||||
*
|
||||
* OS X provides a function exc_server (in
|
||||
* /usr/lib/system/libsystem_kernel.dylib) that's documented in the XNU
|
||||
* sources <http://www.opensource.apple.com/source/xnu/xnu-2050.22.13/osfmk/man/exc_server.html>
|
||||
* and generated by the Mach Interface Generator (mig). It unpacks
|
||||
* an exception message structure and calls one of several handler functions.
|
||||
* We can't use it because:
|
||||
*
|
||||
* 1. It's hard-wired to call certain functions by name. The MPS can't
|
||||
* steal those names in case the client program is using them too.
|
||||
*
|
||||
* 2. It fails anyway in Xcode's default "Release" build with hidden
|
||||
* symbols, because it uses dlsym to find those handler functions, and
|
||||
* dlsym can't find them.
|
||||
*
|
||||
* So instead this function duplicates the work of exc_server, and is shorter
|
||||
* because it's specialised for protection exceptions of a single behaviour
|
||||
* and flavour. It is also more flexible and can dispatch to any function
|
||||
* we want. The downside is that it depends on various unpublished stuff
|
||||
* like the code numbers for certain messages.
|
||||
*/
|
||||
|
||||
static void protCatchOne(void)
|
||||
{
|
||||
protRequestStruct request;
|
||||
mach_msg_return_t mr;
|
||||
protReplyStruct reply;
|
||||
|
||||
AVER(MACH_PORT_VALID(protExcPort));
|
||||
mr = mach_msg(&request.Head,
|
||||
/* option */ MACH_RCV_MSG,
|
||||
/* send_size */ 0,
|
||||
/* receive_limit */ sizeof(request),
|
||||
/* receive_name */ protExcPort,
|
||||
/* timeout */ MACH_MSG_TIMEOUT_NONE,
|
||||
/* notify */ MACH_PORT_NULL);
|
||||
AVER(mr == MACH_MSG_SUCCESS);
|
||||
if (mr != MACH_MSG_SUCCESS)
|
||||
mach_error("ERROR: MPS mach_msg recv\n", mr); /* .trans.must */
|
||||
|
||||
/* 2407 is the id for the 64-bit exception requests we asked for in
|
||||
ProtThreadRegister, with state and identity
|
||||
information, determined by experimentation and confirmed by
|
||||
running mig on /usr/include/mach/mach_exc.defs */
|
||||
AVER(request.Head.msgh_id == 2407);
|
||||
AVER(request.Head.msgh_local_port == protExcPort);
|
||||
AVER(request.task.name == mach_task_self());
|
||||
AVER(request.exception == EXC_BAD_ACCESS);
|
||||
AVER(request.codeCnt == 2);
|
||||
AVER(request.old_stateCnt == THREAD_STATE_COUNT);
|
||||
AVER(request.flavor == THREAD_STATE_FLAVOR);
|
||||
|
||||
/* TODO: This could dispatch to separate worker threads, in order to
|
||||
spread scanning work across several cores once the MPS can be
|
||||
re-entered. */
|
||||
|
||||
if (request.code[0] == KERN_PROTECTION_FAILURE) {
|
||||
MutatorFaultContextStruct mfcStruct;
|
||||
|
||||
/* The cast via Word suppresses "cast to pointer from integer of
|
||||
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;
|
||||
|
||||
if (ArenaAccess(mfcStruct.address,
|
||||
AccessREAD | AccessWRITE,
|
||||
&mfcStruct)) {
|
||||
/* Send a reply that will cause the thread to continue.
|
||||
Note that ArenaAccess may have updated request.old_state
|
||||
via mfcStruct.thread_state, and that will get copied to the
|
||||
reply and affect the state the thread resumes in. */
|
||||
protBuildReply(&reply, &request, KERN_SUCCESS);
|
||||
protMustSend(&reply.Head);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* We didn't handle the exception -- it wasn't one of ours. */
|
||||
|
||||
/* .assume.only-port: We assume that there was no previously installed
|
||||
exception port. This is checked in ProtThreadRegister, and we don't
|
||||
check it again here to avoid the extra system call. If there
|
||||
were, we must arrange to forward the exception message to the
|
||||
previous port. This module used to do that because it installed a
|
||||
task-wide exception handler, but the code is pretty hairy and not
|
||||
necessary as long as the MPS is registering threads individually.
|
||||
If we ever need to reinstate that code, look at
|
||||
https://info.ravenbrook.com/project/mps/prototype/2013-06-24/machtest */
|
||||
|
||||
protBuildReply(&reply, &request, KERN_FAILURE);
|
||||
protMustSend(&reply.Head);
|
||||
}
|
||||
|
||||
|
||||
/* protCatchThread -- exception handler thread loop.
|
||||
*
|
||||
* Note that this thread does *not* have a thread-specific exception handler
|
||||
* installed. This means that an exception-causing bug in the exception
|
||||
* handler won't cause a deadlock.
|
||||
*/
|
||||
|
||||
static void *protCatchThread(void *p) {
|
||||
for (;;)
|
||||
protCatchOne();
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/* ProtThreadRegister -- register a thread for protection exception handling */
|
||||
|
||||
extern void ProtThreadRegister(Bool setup)
|
||||
{
|
||||
kern_return_t kr;
|
||||
mach_msg_type_number_t old_exception_count;
|
||||
exception_mask_t old_exception_masks;
|
||||
exception_behavior_t behavior;
|
||||
mach_port_t old_exception_ports;
|
||||
exception_behavior_t old_behaviors;
|
||||
thread_state_flavor_t old_flavors;
|
||||
mach_port_t self;
|
||||
static mach_port_t setupThread = MACH_PORT_NULL;
|
||||
|
||||
self = mach_thread_self();
|
||||
AVER(MACH_PORT_VALID(self));
|
||||
|
||||
/* Avoid setting up the exception handler for the thread that calls
|
||||
ProtSetup twice, in the case where the mutator registers that thread
|
||||
explicitly. We need a special case because we don't require thread
|
||||
registration of the sole thread of a single-threaded mutator. */
|
||||
if (setup) {
|
||||
AVER(setupThread == MACH_PORT_NULL);
|
||||
setupThread = self;
|
||||
} else {
|
||||
AVER(setupThread != MACH_PORT_NULL);
|
||||
if (self == setupThread)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ask to receive EXC_BAD_ACCESS exceptions on our port, complete
|
||||
with thread state and identity information in the message.
|
||||
The MACH_EXCEPTION_CODES flag causes the code fields to be
|
||||
passed 64-bits wide, matching protRequestStruct [Fuller_2013]. */
|
||||
behavior = (exception_behavior_t)(EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES);
|
||||
AVER(MACH_PORT_VALID(protExcPort));
|
||||
kr = thread_swap_exception_ports(self,
|
||||
EXC_MASK_BAD_ACCESS,
|
||||
protExcPort,
|
||||
behavior,
|
||||
THREAD_STATE_FLAVOR,
|
||||
&old_exception_masks,
|
||||
&old_exception_count,
|
||||
&old_exception_ports,
|
||||
&old_behaviors,
|
||||
&old_flavors);
|
||||
AVER(kr == KERN_SUCCESS);
|
||||
if (kr != KERN_SUCCESS)
|
||||
mach_error("ERROR: MPS thread_swap_exception_ports", kr); /* .trans.must */
|
||||
AVER(old_exception_masks == EXC_MASK_BAD_ACCESS);
|
||||
AVER(old_exception_count == 1);
|
||||
AVER(old_exception_ports == MACH_PORT_NULL); /* .assume.only-port */
|
||||
}
|
||||
|
||||
|
||||
/* ProtSetup -- set up protection exception handling */
|
||||
|
||||
static void protSetupInner(void)
|
||||
{
|
||||
kern_return_t kr;
|
||||
int pr;
|
||||
pthread_t excThread;
|
||||
mach_port_t self;
|
||||
|
||||
/* Create a port to send and receive exceptions. */
|
||||
self = mach_task_self();
|
||||
AVER(MACH_PORT_VALID(self));
|
||||
kr = mach_port_allocate(self,
|
||||
MACH_PORT_RIGHT_RECEIVE,
|
||||
&protExcPort);
|
||||
AVER(kr == KERN_SUCCESS);
|
||||
if (kr != KERN_SUCCESS)
|
||||
mach_error("ERROR: MPS mach_port_allocate", kr); /* .trans.must */
|
||||
AVER(MACH_PORT_VALID(protExcPort));
|
||||
|
||||
/* Allow me to send exceptions on this port. */
|
||||
/* TODO: Find out why this is necessary. */
|
||||
self = mach_task_self();
|
||||
AVER(MACH_PORT_VALID(self));
|
||||
kr = mach_port_insert_right(self,
|
||||
protExcPort, protExcPort,
|
||||
MACH_MSG_TYPE_MAKE_SEND);
|
||||
AVER(kr == KERN_SUCCESS);
|
||||
if (kr != KERN_SUCCESS)
|
||||
mach_error("ERROR: MPS mach_port_insert_right", kr); /* .trans.must */
|
||||
|
||||
ProtThreadRegister(TRUE);
|
||||
|
||||
/* Launch the exception handling thread. We use pthread_create because
|
||||
it's much simpler than setting up a thread from scratch using Mach,
|
||||
and that's basically what it does. See [Libc]
|
||||
<http://www.opensource.apple.com/source/Libc/Libc-825.26/pthreads/pthread.c> */
|
||||
pr = pthread_create(&excThread, NULL, protCatchThread, NULL);
|
||||
AVER(pr == 0);
|
||||
if (pr != 0)
|
||||
fprintf(stderr, "ERROR: MPS pthread_create: %d\n", pr); /* .trans.must */
|
||||
}
|
||||
|
||||
void ProtSetup(void)
|
||||
{
|
||||
int pr;
|
||||
static pthread_once_t prot_setup_once = PTHREAD_ONCE_INIT;
|
||||
|
||||
/* ProtSetup may be called several times if the client creates more than
|
||||
one arena, but we still only want one exception handling thread. */
|
||||
pr = pthread_once(&prot_setup_once, protSetupInner);
|
||||
AVER(pr == 0);
|
||||
if (pr != 0)
|
||||
fprintf(stderr, "ERROR: MPS pthread_once: %d\n", pr); /* .trans.must */
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2013 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,25 +1,19 @@
|
|||
/* osxc.h: MacOS X (Carbon-compatible) system header hacks
|
||||
/* protxc.h: PROTECTION EXCPETION HANDLER FOR OS X MACH
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2005 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .purpose: This header fixes bugs in the system headers.
|
||||
* Copyright (c) 2013 Ravenbrook Limited. See end of file for license.
|
||||
*/
|
||||
|
||||
#ifndef protxc_h
|
||||
#define protxc_h
|
||||
|
||||
#ifndef osxc_h
|
||||
#define osxc_h
|
||||
|
||||
|
||||
/* There's nothing to fix. */
|
||||
|
||||
|
||||
#endif /* osxc_h */
|
||||
extern void ProtThreadRegister(Bool setup);
|
||||
|
||||
#endif /* protxc_h */
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2005 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
@ -85,6 +85,7 @@ static void suspendSignalHandler(int sig,
|
|||
|
||||
AVER(sig == PTHREADEXT_SIGSUSPEND);
|
||||
UNUSED(sig);
|
||||
UNUSED(info);
|
||||
|
||||
AVER(suspendingVictim != NULL);
|
||||
/* copy the ucontext structure so we definitely have it on our stack,
|
||||
|
|
|
|||
|
|
@ -144,16 +144,16 @@ static size_t randomSize8(int i)
|
|||
/* testInArena -- test all the pool classes in the given arena */
|
||||
|
||||
static mps_pool_debug_option_s debugOptions8 = {
|
||||
/* .fence_template = */ (void *)"postpost",
|
||||
/* .fence_template = */ (const void *)"postpost",
|
||||
/* .fence_size = */ 8,
|
||||
/* .free_template = */ (void *)"DEAD",
|
||||
/* .free_template = */ (const void *)"DEAD",
|
||||
/* .free_size = */ 4
|
||||
};
|
||||
|
||||
static mps_pool_debug_option_s debugOptions16 = {
|
||||
/* .fence_template = */ (void *)"postpostpostpost",
|
||||
/* .fence_template = */ (const void *)"postpostpostpost",
|
||||
/* .fence_size = */ 16,
|
||||
/* .free_template = */ (void *)"DEAD",
|
||||
/* .free_template = */ (const void *)"DEAD",
|
||||
/* .free_size = */ 4
|
||||
};
|
||||
|
||||
|
|
@ -173,7 +173,7 @@ static int testInArena(mps_arena_t arena)
|
|||
|
||||
printf("MVFF\n\n");
|
||||
die(stress(mps_class_mvff(), classCOUNT, classes, randomSize8, arena,
|
||||
(size_t)65536, (size_t)32, sizeof(void *), TRUE, TRUE, TRUE),
|
||||
(size_t)65536, (size_t)32, (mps_align_t)MPS_PF_ALIGN, TRUE, TRUE, TRUE),
|
||||
"stress MVFF");
|
||||
printf("MV debug\n\n");
|
||||
die(stress(mps_class_mv_debug(), classCOUNT, classes, randomSize8, arena,
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ typedef struct AMSTStruct {
|
|||
|
||||
typedef struct AMSTStruct *AMST;
|
||||
|
||||
#define Pool2AMST(pool) PARENT(AMSTStruct, amsStruct.poolStruct, (pool))
|
||||
#define Pool2AMST(pool) PARENT(AMSTStruct, amsStruct, PARENT(AMSStruct, poolStruct, (pool)))
|
||||
#define AMST2AMS(amst) (&(amst)->amsStruct)
|
||||
|
||||
|
||||
|
|
@ -670,7 +670,7 @@ DEFINE_POOL_CLASS(AMSTPoolClass, this)
|
|||
INHERIT_CLASS(this, AMSPoolClass);
|
||||
this->name = "AMST";
|
||||
this->size = sizeof(AMSTStruct);
|
||||
this->offset = offsetof(AMSTStruct, amsStruct.poolStruct);
|
||||
this->offset = offsetof(AMSTStruct, amsStruct) + offsetof(AMSStruct, poolStruct);
|
||||
this->init = AMSTInit;
|
||||
this->finish = AMSTFinish;
|
||||
this->bufferFill = AMSTBufferFill;
|
||||
|
|
@ -758,7 +758,7 @@ static void *test(void *arg, size_t s)
|
|||
unsigned long objs;
|
||||
mps_ap_t busy_ap;
|
||||
mps_addr_t busy_init;
|
||||
char *indent = " ";
|
||||
const char *indent = " ";
|
||||
|
||||
arena = (mps_arena_t)arg;
|
||||
(void)s; /* unused */
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
/* spi3.c: STACK PROBE
|
||||
/* spw3i3mv.c: STACK PROBE FOR 32-BIT WINDOWS
|
||||
*
|
||||
* $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.
|
||||
*
|
||||
* This function reads a location that is probeDepth words beyond
|
||||
* the current stack pointer. On intel platforms the stack grows
|
||||
* downwards so this means reading from a location with a lesser address.
|
||||
* This function reads a location that is depth words beyond the
|
||||
* current stack pointer. On Intel platforms, the stack grows
|
||||
* downwards, so this means reading from a location with a lesser
|
||||
* address.
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -25,7 +26,7 @@ void StackProbe(Size depth)
|
|||
|
||||
/* 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,73 +1,33 @@
|
|||
/* libcbt: MPS LIBRARY CALLBACK TEST
|
||||
/* spw3i6mv.c: STACK PROBE FOR 64-BIT WINDOWS
|
||||
*
|
||||
* $Header$
|
||||
* Copyright (C) 2005 Ravenbrook Limited. See end of file for license.
|
||||
* $Id$
|
||||
* Copyright (c) 2013 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* This is a simple test of the MPS Library Callback interface
|
||||
* (mpslibcb.h). */
|
||||
* The function StackProbe ensures that the stack has at least depth
|
||||
* words available. It achieves this by exploiting an obscure but
|
||||
* documented feature of Microsoft's function _alloca: "A stack
|
||||
* overflow exception is generated if the space cannot be allocated."
|
||||
* _alloca: http://msdn.microsoft.com/en-us/library/wb1s57t5.aspx
|
||||
*
|
||||
* The purpose of this function to ensure that the stack overflow
|
||||
* exception is generated here (before taking the arena lock) where it
|
||||
* can be handled safely rather than at some later point where the
|
||||
* arena lock is held and so handling the exception may cause the MPS
|
||||
* to be entered recursively.
|
||||
*/
|
||||
|
||||
#include "mps.h"
|
||||
#include "mpsavm.h"
|
||||
#include "mpslib.h"
|
||||
#include "mpslibcb.h"
|
||||
#include "mpm.h"
|
||||
#include <malloc.h>
|
||||
|
||||
#include "testlib.h"
|
||||
#include "mpslib.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void libcbt_assert_fail(const char *);
|
||||
mps_clock_t libcbt_clock(void);
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
void StackProbe(Size depth)
|
||||
{
|
||||
int res;
|
||||
mps_arena_t arena;
|
||||
|
||||
res = mps_lib_callback_register("not a callback", (void(*)(void))0);
|
||||
if(MPS_RES_OK == res) {
|
||||
error("mps_lib_callback_register claims to successfully register\n"
|
||||
"an interface that does not exist.\n");
|
||||
}
|
||||
die(mps_lib_callback_register("mps_lib_assert_fail",
|
||||
(void(*)(void))libcbt_assert_fail),
|
||||
"register assert_fail");
|
||||
/* The following functions are registered in the order that you get by
|
||||
* providing no functions and then providing functions as they are
|
||||
* required by assertionn failures.
|
||||
* Interestingly, for this very simple test, only mps_clock is
|
||||
* required. */
|
||||
die(mps_lib_callback_register("mps_clock",
|
||||
(mps_lib_function_t)libcbt_clock),
|
||||
"register clock");
|
||||
die(mps_arena_create(&arena, mps_arena_class_vm(), (size_t)1000*1000),
|
||||
"mps_arena_create");
|
||||
|
||||
printf("%s: Conclusion: Failed to find any defects.\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void libcbt_assert_fail(const char *message)
|
||||
{
|
||||
fflush(stdout);
|
||||
fprintf(stderr, "\nMPS ASSERTION FAILURE (TEST): %s\n", message);
|
||||
fflush(stderr);
|
||||
abort();
|
||||
}
|
||||
|
||||
mps_clock_t libcbt_clock(void)
|
||||
{
|
||||
static mps_clock_t c = 0;
|
||||
|
||||
++ c;
|
||||
return c;
|
||||
_alloca(depth*sizeof(Word));
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (c) 2005-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
@ -204,7 +204,7 @@ static double time_since(double t)
|
|||
#define MAXPRINTABLE 100.0
|
||||
#define MINPRINTABLE (MAXPRINTABLE / 1000.0)
|
||||
|
||||
static void print_time(char *before, double t, char *after)
|
||||
static void print_time(const char *before, double t, const char *after)
|
||||
{
|
||||
char prefixes[] = "\0munpfazy"; /* don't print "ks" etc */
|
||||
char *x = prefixes+2; /* start at micro */
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* teletest.c: TELEMETRY TEST
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .source: The command parser here was taken and adapted from bttest.c.
|
||||
*/
|
||||
|
|
@ -121,7 +121,7 @@ static void doHelp(void)
|
|||
|
||||
|
||||
static struct commandShapeStruct {
|
||||
char *name;
|
||||
const char *name;
|
||||
Count int_args;
|
||||
mps_bool_t string_arg;
|
||||
void (*fun)(void);
|
||||
|
|
@ -147,7 +147,7 @@ static void obeyCommand(char *command)
|
|||
{
|
||||
commandShape shape = commandShapes;
|
||||
while(shape->name != NULL) {
|
||||
char *csp = shape->name;
|
||||
const char *csp = shape->name;
|
||||
char *p = command;
|
||||
while (*csp == *p) {
|
||||
csp++;
|
||||
|
|
@ -223,7 +223,7 @@ extern int main(int argc, char *argv[])
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -334,8 +334,17 @@ void verror(const char *format, va_list args)
|
|||
vfprintf(stderr, format, args);
|
||||
fprintf(stderr, "\n");
|
||||
fflush(stderr); /* make sure the message is output */
|
||||
/* On Windows, the abort signal pops up a dialog box. This suspends
|
||||
* the test suite until a button is pressed, which is not acceptable
|
||||
* for offline testing, so if the MPS_TESTLIB_NOABORT environment
|
||||
* variable is set, then the test case exits instead of aborting.
|
||||
*/
|
||||
if (getenv("MPS_TESTLIB_NOABORT")) {
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* error -- die with message */
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* testlib.h: TEST LIBRARY 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) 2002 Global Graphics Software.
|
||||
*
|
||||
* .purpose: A library of functions that may be of use to unit tests.
|
||||
|
|
@ -18,9 +18,6 @@
|
|||
#ifdef MPS_OS_W3
|
||||
#include "mpswin.h"
|
||||
#endif
|
||||
#ifdef MPS_OS_XC
|
||||
#include "osxc.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
|
@ -235,7 +232,7 @@ extern void randomize(int argc, char *argv[]);
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002, 2008 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.
|
||||
*
|
||||
|
|
|
|||
307
mps/code/thxc.c
Normal file
307
mps/code/thxc.c
Normal file
|
|
@ -0,0 +1,307 @@
|
|||
/* thxc.c: OS X MACH THREADS MANAGER
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .design: See <design/thread-manager/>.
|
||||
*
|
||||
*
|
||||
* TODO
|
||||
*
|
||||
* Too much code in common with than.c, thix.c. Consider how to reduce
|
||||
* redundancy without making the code obscure.
|
||||
*
|
||||
*
|
||||
* REFERENCES
|
||||
*
|
||||
* [Mach_man] Mach man pages within XNU;
|
||||
* Apple Computer;
|
||||
* <http://www.opensource.apple.com/source/xnu/xnu-2050.22.13/osfmk/man/>.
|
||||
*/
|
||||
|
||||
#include "mpm.h"
|
||||
#include "protxc.h"
|
||||
|
||||
#include <mach/mach_init.h>
|
||||
#include <mach/task.h>
|
||||
#include <mach/thread_act.h>
|
||||
#include <mach/thread_status.h>
|
||||
|
||||
|
||||
SRCID(thxc, "$Id$");
|
||||
|
||||
|
||||
typedef struct mps_thr_s { /* OS X / Mach thread structure */
|
||||
Sig sig; /* <design/sig/> */
|
||||
Serial serial; /* from arena->threadSerial */
|
||||
Arena arena; /* owning arena */
|
||||
RingStruct arenaRing; /* attaches to arena */
|
||||
thread_port_t port; /* thread kernel port */
|
||||
} ThreadStruct;
|
||||
|
||||
|
||||
Bool ThreadCheck(Thread thread)
|
||||
{
|
||||
CHECKS(Thread, thread);
|
||||
CHECKU(Arena, thread->arena);
|
||||
CHECKL(thread->serial < thread->arena->threadSerial);
|
||||
CHECKL(RingCheck(&thread->arenaRing));
|
||||
CHECKL(MACH_PORT_VALID(thread->port));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
Bool ThreadCheckSimple(Thread thread)
|
||||
{
|
||||
CHECKS(Thread, thread);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
Res ThreadRegister(Thread *threadReturn, Arena arena)
|
||||
{
|
||||
Res res;
|
||||
Thread thread;
|
||||
Ring ring;
|
||||
void *p;
|
||||
|
||||
AVER(threadReturn != NULL);
|
||||
|
||||
res = ControlAlloc(&p, arena, sizeof(ThreadStruct),
|
||||
/* withReservoirPermit */ FALSE);
|
||||
if(res != ResOK) return res;
|
||||
thread = (Thread)p;
|
||||
|
||||
thread->arena = arena;
|
||||
RingInit(&thread->arenaRing);
|
||||
|
||||
thread->serial = arena->threadSerial;
|
||||
++arena->threadSerial;
|
||||
thread->port = mach_thread_self();
|
||||
thread->sig = ThreadSig;
|
||||
AVERT(Thread, thread);
|
||||
|
||||
ProtThreadRegister(FALSE);
|
||||
|
||||
ring = ArenaThreadRing(arena);
|
||||
|
||||
RingAppend(ring, &thread->arenaRing);
|
||||
|
||||
*threadReturn = thread;
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
||||
void ThreadDeregister(Thread thread, Arena arena)
|
||||
{
|
||||
AVERT(Thread, thread);
|
||||
AVERT(Arena, arena);
|
||||
|
||||
RingRemove(&thread->arenaRing);
|
||||
|
||||
thread->sig = SigInvalid;
|
||||
|
||||
RingFinish(&thread->arenaRing);
|
||||
|
||||
ControlFree(arena, thread, sizeof(ThreadStruct));
|
||||
}
|
||||
|
||||
|
||||
/* mapThreadRing -- map over threads on ring calling a function on each one
|
||||
* except the current thread
|
||||
*/
|
||||
|
||||
static void mapThreadRing(Ring threadRing, void (*func)(Thread))
|
||||
{
|
||||
Ring node, next;
|
||||
mach_port_t self;
|
||||
|
||||
AVERT(Ring, threadRing);
|
||||
|
||||
self = mach_thread_self();
|
||||
AVER(MACH_PORT_VALID(self));
|
||||
RING_FOR(node, threadRing, next) {
|
||||
Thread thread = RING_ELT(Thread, arenaRing, node);
|
||||
AVERT(Thread, thread);
|
||||
if(thread->port != self)
|
||||
(*func)(thread);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void threadSuspend(Thread thread)
|
||||
{
|
||||
kern_return_t kern_return;
|
||||
kern_return = thread_suspend(thread->port);
|
||||
/* No rendezvous is necessary: thread_suspend "prevents the thread
|
||||
* from executing any more user-level instructions" */
|
||||
AVER(kern_return == KERN_SUCCESS);
|
||||
}
|
||||
|
||||
static void threadResume(Thread thread)
|
||||
{
|
||||
kern_return_t kern_return;
|
||||
kern_return = thread_resume(thread->port);
|
||||
/* Mach has no equivalent of EAGAIN. */
|
||||
AVER(kern_return == KERN_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
/* ThreadRingSuspend -- suspend all threads on a ring, except the
|
||||
* current one.
|
||||
*/
|
||||
void ThreadRingSuspend(Ring threadRing)
|
||||
{
|
||||
AVERT(Ring, threadRing);
|
||||
mapThreadRing(threadRing, threadSuspend);
|
||||
}
|
||||
|
||||
/* ThreadRingResume -- resume all threads on a ring, except the
|
||||
* current one.
|
||||
*/
|
||||
void ThreadRingResume(Ring threadRing)
|
||||
{
|
||||
AVERT(Ring, threadRing);
|
||||
mapThreadRing(threadRing, threadResume);
|
||||
}
|
||||
|
||||
Thread ThreadRingThread(Ring threadRing)
|
||||
{
|
||||
Thread thread;
|
||||
AVERT(Ring, threadRing);
|
||||
thread = RING_ELT(Thread, arenaRing, threadRing);
|
||||
AVERT(Thread, thread);
|
||||
return thread;
|
||||
}
|
||||
|
||||
|
||||
/* Must be thread-safe. See <design/interface-c/#thread-safety>. */
|
||||
Arena ThreadArena(Thread thread)
|
||||
{
|
||||
/* Can't AVER thread as that would not be thread-safe */
|
||||
/* AVERT(Thread, thread); */
|
||||
return thread->arena;
|
||||
}
|
||||
|
||||
|
||||
/* ThreadScan -- scan the state of a thread (stack and regs) */
|
||||
|
||||
#include "prmcxc.h"
|
||||
|
||||
Res ThreadScan(ScanState ss, Thread thread, void *stackBot)
|
||||
{
|
||||
mach_port_t self;
|
||||
Res res;
|
||||
|
||||
AVERT(Thread, thread);
|
||||
self = mach_thread_self();
|
||||
AVER(MACH_PORT_VALID(self));
|
||||
if (thread->port == self) {
|
||||
/* scan this thread's stack */
|
||||
res = StackScan(ss, stackBot);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
} else {
|
||||
MutatorFaultContextStruct mfcStruct;
|
||||
THREAD_STATE_S threadState;
|
||||
Addr *stackBase, *stackLimit, stackPtr;
|
||||
mach_msg_type_number_t count;
|
||||
kern_return_t kern_return;
|
||||
|
||||
/* Note: We could get the thread state and check the suspend cound in
|
||||
order to assert that the thread is suspended, but it's probably
|
||||
unnecessary and is a lot of work to check a static condition. */
|
||||
|
||||
mfcStruct.address = NULL;
|
||||
mfcStruct.threadState = &threadState;
|
||||
|
||||
count = THREAD_STATE_COUNT;
|
||||
AVER(sizeof(*mfcStruct.threadState) == count * sizeof(natural_t));
|
||||
kern_return = thread_get_state(thread->port,
|
||||
THREAD_STATE_FLAVOR,
|
||||
(thread_state_t)mfcStruct.threadState,
|
||||
&count);
|
||||
AVER(kern_return == KERN_SUCCESS);
|
||||
AVER(count == THREAD_STATE_COUNT);
|
||||
|
||||
stackPtr = MutatorFaultContextSP(&mfcStruct);
|
||||
/* .stack.align */
|
||||
stackBase = (Addr *)AddrAlignUp(stackPtr, sizeof(Addr));
|
||||
stackLimit = (Addr *)stackBot;
|
||||
if (stackBase >= stackLimit)
|
||||
return ResOK; /* .stack.below-bottom */
|
||||
|
||||
/* scan stack inclusive of current sp and exclusive of
|
||||
* stackBot (.stack.full-descend)
|
||||
*/
|
||||
res = TraceScanAreaTagged(ss, stackBase, stackLimit);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
|
||||
/* scan the registers in the mutator fault context */
|
||||
res = MutatorFaultContextScan(ss, &mfcStruct);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
}
|
||||
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
||||
Res ThreadDescribe(Thread thread, mps_lib_FILE *stream)
|
||||
{
|
||||
Res res;
|
||||
|
||||
res = WriteF(stream,
|
||||
"Thread $P ($U) {\n", (WriteFP)thread, (WriteFU)thread->serial,
|
||||
" arena $P ($U)\n",
|
||||
(WriteFP)thread->arena, (WriteFU)thread->arena->serial,
|
||||
" port $U\n", (WriteFU)thread->port,
|
||||
"} Thread $P ($U)\n", (WriteFP)thread, (WriteFU)thread->serial,
|
||||
NULL);
|
||||
if(res != ResOK) return res;
|
||||
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 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.
|
||||
*/
|
||||
|
|
@ -421,6 +421,8 @@ Res TraceCondemnZones(Trace trace, ZoneSet condemnedSet)
|
|||
} while (SegNext(&seg, arena, base));
|
||||
}
|
||||
|
||||
EVENT3(TraceCondemnZones, trace, condemnedSet, trace->white);
|
||||
|
||||
/* The trace's white set must be a subset of the condemned set */
|
||||
AVER(ZoneSetSuper(condemnedSet, trace->white));
|
||||
|
||||
|
|
@ -810,14 +812,21 @@ static void traceReclaim(Trace trace)
|
|||
Arena arena;
|
||||
Seg seg;
|
||||
Ring node, nextNode;
|
||||
Size reclaimed = 0;
|
||||
|
||||
AVER(trace->state == TraceRECLAIM);
|
||||
/* FIXME: These should be enabled and we shouldn't reach here with an
|
||||
empty trace.
|
||||
AVER(trace->white != 0);
|
||||
AVER(trace->condemned != 0);
|
||||
*/
|
||||
|
||||
EVENT1(TraceReclaim, trace);
|
||||
arena = trace->arena;
|
||||
if(SegFirst(&seg, arena)) {
|
||||
if(reclaimed < trace->condemned && SegFirst(&seg, arena)) {
|
||||
Addr base;
|
||||
do {
|
||||
reclaimed += SegSize(seg);
|
||||
base = SegBase(seg);
|
||||
/* There shouldn't be any grey stuff left for this trace. */
|
||||
AVER_CRITICAL(!TraceSetIsMember(SegGrey(seg), trace));
|
||||
|
|
@ -841,7 +850,7 @@ static void traceReclaim(Trace trace)
|
|||
UNUSED(nonWhiteSeg); /* <code/mpm.c#check.unused> */
|
||||
}
|
||||
}
|
||||
} while(SegNext(&seg, arena, base));
|
||||
} while(reclaimed < trace->condemned && SegNext(&seg, arena, base));
|
||||
}
|
||||
|
||||
trace->state = TraceFINISHED;
|
||||
|
|
@ -1810,6 +1819,8 @@ Size TracePoll(Globals globals)
|
|||
AVERT(Globals, globals);
|
||||
arena = GlobalsArena(globals);
|
||||
|
||||
if (RingIsSingle(&arena->chainRing)) return 0;
|
||||
|
||||
scannedSize = (Size)0;
|
||||
if(arena->busyTraces == TraceSetEMPTY) {
|
||||
/* If no traces are going on, see if we need to start one. */
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* tract.c: PAGE TABLES
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .ullagepages: Pages whose page index is < allocBase are recorded as
|
||||
* free but never allocated as alloc starts searching after the tables.
|
||||
|
|
@ -142,8 +142,8 @@ Bool ChunkCheck(Chunk chunk)
|
|||
CHECKL((Addr)chunk->pageTable >= chunk->base);
|
||||
CHECKL((Addr)&chunk->pageTable[chunk->pageTablePages]
|
||||
<= PageIndexBase(chunk, chunk->allocBase));
|
||||
CHECKL(NONNEGATIVE(INDEX_OF_ADDR(chunk, (Addr)chunk->pageTable)));
|
||||
/* check there's enough space in the page table */
|
||||
CHECKL(INDEX_OF_ADDR(chunk, (Addr)chunk->pageTable) >= 0);
|
||||
CHECKL(INDEX_OF_ADDR(chunk, AddrSub(chunk->limit, 1)) < chunk->pages);
|
||||
CHECKL(chunk->pageTablePages < chunk->pages);
|
||||
|
||||
|
|
@ -649,7 +649,7 @@ void PageFree(Chunk chunk, Index pi)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ extern void TractFinish(Tract tract);
|
|||
enum {PageTypeSpare=1, PageTypeFree};
|
||||
|
||||
typedef struct PageStruct { /* page structure */
|
||||
union {
|
||||
union PageStructUnion {
|
||||
TractStruct tractStruct; /* allocated tract */
|
||||
struct {
|
||||
Pool pool; /* NULL, must be first field (.page) */
|
||||
|
|
@ -111,7 +111,7 @@ typedef struct PageStruct { /* page structure */
|
|||
|
||||
/* PageOfTract -- VM page descriptor from arena tract */
|
||||
|
||||
#define PageOfTract(tract) PARENT(PageStruct, the.tractStruct, (tract))
|
||||
#define PageOfTract(tract) PARENT(PageStruct, the, PARENT(union PageStructUnion, tractStruct, (tract)))
|
||||
|
||||
/* PagePool -- pool field of a page */
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* version.c: VERSION INSPECTION
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2002, 2006-2010 Ravenbrook Limited.
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited.
|
||||
* See end of file for license.
|
||||
*
|
||||
* PURPOSE
|
||||
|
|
@ -29,7 +29,7 @@ SRCID(version, "$Id$");
|
|||
* (Note: before 2006-02-01 the style was "release.epcore.chub")
|
||||
*/
|
||||
|
||||
#define MPS_RELEASE "release/1.111.0"
|
||||
#define MPS_RELEASE "release/1.112.0"
|
||||
|
||||
|
||||
/* MPSCopyrightNotice -- copyright notice for the binary
|
||||
|
|
@ -39,7 +39,7 @@ SRCID(version, "$Id$");
|
|||
*/
|
||||
|
||||
char MPSCopyrightNotice[] =
|
||||
"Portions copyright (c) 2010 Ravenbrook Limited and Global Graphics Software.";
|
||||
"Portions copyright (c) 2010-2013 Ravenbrook Limited and Global Graphics Software.";
|
||||
|
||||
|
||||
/* MPSVersion -- return version string
|
||||
|
|
@ -63,7 +63,7 @@ char *MPSVersion(void)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002, 2006-2010 Ravenbrook Limited
|
||||
* Copyright (C) 2001-2013 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 @@
|
|||
# w3i3mv.nmk: WINDOWS (IA-32) NMAKE FILE -*- 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.
|
||||
|
||||
PFM = w3i3mv
|
||||
|
||||
|
|
@ -14,7 +14,7 @@ PFMDEFS = /DCONFIG_PF_STRING="w3i3mv" /DCONFIG_PF_W3I3MV \
|
|||
!INCLUDE commpre.nmk
|
||||
|
||||
# MPM sources: core plus platform-specific.
|
||||
MPM = $(MPMCOMMON) <proti3> <prmci3w3> <spi3> <ssw3i3mv> <thw3i3>
|
||||
MPM = $(MPMCOMMON) <proti3> <prmci3w3> <spw3i3mv> <ssw3i3mv> <thw3i3>
|
||||
|
||||
|
||||
|
||||
|
|
@ -132,7 +132,7 @@ TESTLIBOBJ = $(TESTLIBOBJ0:>=.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.
|
||||
#
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ PFMDEFS = /DCONFIG_PF_STRING="w3i6mv" /DCONFIG_PF_W3I6MV \
|
|||
MASM = ml64
|
||||
|
||||
# MPM sources: core plus platform-specific.
|
||||
MPM = $(MPMCOMMON) <prmci6w3> <span> <ssw3i6mv> <thw3i6>
|
||||
MPM = $(MPMCOMMON) <proti6> <prmci6w3> <spw3i6mv> <ssw3i6mv> <thw3i6>
|
||||
|
||||
|
||||
!INCLUDE commpre.nmk
|
||||
|
|
|
|||
|
|
@ -136,7 +136,6 @@
|
|||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\eventcnv.c" />
|
||||
<ClCompile Include="..\..\eventpro.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\mps\mps.vcxproj">
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@
|
|||
|
||||
PFM = xci3gc
|
||||
|
||||
MPMPF = lockix.c than.c vmix.c \
|
||||
protix.c protsgix.c prmcan.c span.c ssixi3.c
|
||||
MPMPF = lockix.c thxc.c vmix.c protix.c proti3.c prmci3xc.c span.c ssixi3.c \
|
||||
protxc.c
|
||||
|
||||
LIBS =
|
||||
|
||||
|
|
|
|||
746
mps/configure
vendored
746
mps/configure
vendored
|
|
@ -1,11 +1,13 @@
|
|||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for Memory Pool System Kit master.
|
||||
# Generated by GNU Autoconf 2.68 for Memory Pool System Kit master.
|
||||
#
|
||||
# Report bugs to <mps-questions@ravenbrook.com>.
|
||||
#
|
||||
#
|
||||
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
|
||||
# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
|
||||
# Foundation, Inc.
|
||||
#
|
||||
#
|
||||
# This configure script is free software; the Free Software Foundation
|
||||
|
|
@ -134,31 +136,6 @@ export LANGUAGE
|
|||
# CDPATH.
|
||||
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
|
||||
|
||||
# Use a proper internal environment variable to ensure we don't fall
|
||||
# into an infinite loop, continuously re-executing ourselves.
|
||||
if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
|
||||
_as_can_reexec=no; export _as_can_reexec;
|
||||
# We cannot yet assume a decent shell, so we have to provide a
|
||||
# neutralization value for shells without unset; and this also
|
||||
# works around shells that cannot unset nonexistent variables.
|
||||
# Preserve -v and -x to the replacement shell.
|
||||
BASH_ENV=/dev/null
|
||||
ENV=/dev/null
|
||||
(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
|
||||
case $- in # ((((
|
||||
*v*x* | *x*v* ) as_opts=-vx ;;
|
||||
*v* ) as_opts=-v ;;
|
||||
*x* ) as_opts=-x ;;
|
||||
* ) as_opts= ;;
|
||||
esac
|
||||
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
|
||||
# Admittedly, this is quite paranoid, since all the known shells bail
|
||||
# out after a failed `exec'.
|
||||
$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
|
||||
as_fn_exit 255
|
||||
fi
|
||||
# We don't want this to propagate to other subprocesses.
|
||||
{ _as_can_reexec=; unset _as_can_reexec;}
|
||||
if test "x$CONFIG_SHELL" = x; then
|
||||
as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
|
||||
emulate sh
|
||||
|
|
@ -192,8 +169,7 @@ if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
|
|||
else
|
||||
exitcode=1; echo positional parameters were not saved.
|
||||
fi
|
||||
test x\$exitcode = x0 || exit 1
|
||||
test -x / || exit 1"
|
||||
test x\$exitcode = x0 || exit 1"
|
||||
as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
|
||||
as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
|
||||
eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
|
||||
|
|
@ -238,7 +214,6 @@ IFS=$as_save_IFS
|
|||
|
||||
|
||||
if test "x$CONFIG_SHELL" != x; then :
|
||||
export CONFIG_SHELL
|
||||
# We cannot yet assume a decent shell, so we have to provide a
|
||||
# neutralization value for shells without unset; and this also
|
||||
# works around shells that cannot unset nonexistent variables.
|
||||
|
|
@ -246,17 +221,14 @@ IFS=$as_save_IFS
|
|||
BASH_ENV=/dev/null
|
||||
ENV=/dev/null
|
||||
(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
|
||||
export CONFIG_SHELL
|
||||
case $- in # ((((
|
||||
*v*x* | *x*v* ) as_opts=-vx ;;
|
||||
*v* ) as_opts=-v ;;
|
||||
*x* ) as_opts=-x ;;
|
||||
* ) as_opts= ;;
|
||||
esac
|
||||
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
|
||||
# Admittedly, this is quite paranoid, since all the known shells bail
|
||||
# out after a failed `exec'.
|
||||
$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
|
||||
exit 255
|
||||
exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"}
|
||||
fi
|
||||
|
||||
if test x$as_have_required = xno; then :
|
||||
|
|
@ -359,14 +331,6 @@ $as_echo X"$as_dir" |
|
|||
|
||||
|
||||
} # as_fn_mkdir_p
|
||||
|
||||
# as_fn_executable_p FILE
|
||||
# -----------------------
|
||||
# Test if FILE is an executable regular file.
|
||||
as_fn_executable_p ()
|
||||
{
|
||||
test -f "$1" && test -x "$1"
|
||||
} # as_fn_executable_p
|
||||
# as_fn_append VAR VALUE
|
||||
# ----------------------
|
||||
# Append the text in VALUE to the end of the definition contained in VAR. Take
|
||||
|
|
@ -488,10 +452,6 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
|
|||
chmod +x "$as_me.lineno" ||
|
||||
{ $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
|
||||
|
||||
# If we had to re-execute with $CONFIG_SHELL, we're ensured to have
|
||||
# already done that, so ensure we don't try to do so again and fall
|
||||
# in an infinite loop. This has already happened in practice.
|
||||
_as_can_reexec=no; export _as_can_reexec
|
||||
# Don't try to exec as it changes $[0], causing all sort of problems
|
||||
# (the dirname of $[0] is not the place where we might find the
|
||||
# original and so on. Autoconf is especially sensitive to this).
|
||||
|
|
@ -526,16 +486,16 @@ if (echo >conf$$.file) 2>/dev/null; then
|
|||
# ... but there are two gotchas:
|
||||
# 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
|
||||
# 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
|
||||
# In both cases, we have to default to `cp -pR'.
|
||||
# In both cases, we have to default to `cp -p'.
|
||||
ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
|
||||
as_ln_s='cp -pR'
|
||||
as_ln_s='cp -p'
|
||||
elif ln conf$$.file conf$$ 2>/dev/null; then
|
||||
as_ln_s=ln
|
||||
else
|
||||
as_ln_s='cp -pR'
|
||||
as_ln_s='cp -p'
|
||||
fi
|
||||
else
|
||||
as_ln_s='cp -pR'
|
||||
as_ln_s='cp -p'
|
||||
fi
|
||||
rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
|
||||
rmdir conf$$.dir 2>/dev/null
|
||||
|
|
@ -547,8 +507,28 @@ else
|
|||
as_mkdir_p=false
|
||||
fi
|
||||
|
||||
if test -x / >/dev/null 2>&1; then
|
||||
as_test_x='test -x'
|
||||
as_executable_p=as_fn_executable_p
|
||||
else
|
||||
if ls -dL / >/dev/null 2>&1; then
|
||||
as_ls_L_option=L
|
||||
else
|
||||
as_ls_L_option=
|
||||
fi
|
||||
as_test_x='
|
||||
eval sh -c '\''
|
||||
if test -d "$1"; then
|
||||
test -d "$1/.";
|
||||
else
|
||||
case $1 in #(
|
||||
-*)set "./$1";;
|
||||
esac;
|
||||
case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
|
||||
???[sx]*):;;*)false;;esac;fi
|
||||
'\'' sh
|
||||
'
|
||||
fi
|
||||
as_executable_p=$as_test_x
|
||||
|
||||
# Sed expression to map a string onto a valid CPP name.
|
||||
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
|
||||
|
|
@ -630,9 +610,6 @@ INSTALL_TARGET
|
|||
CLEAN_TARGET
|
||||
BUILD_TARGET
|
||||
MPS_TARGET_NAME
|
||||
EGREP
|
||||
GREP
|
||||
CPP
|
||||
MAKE
|
||||
host_os
|
||||
host_vendor
|
||||
|
|
@ -642,6 +619,9 @@ build_os
|
|||
build_vendor
|
||||
build_cpu
|
||||
build
|
||||
EGREP
|
||||
GREP
|
||||
CPP
|
||||
INSTALL_DATA
|
||||
INSTALL_SCRIPT
|
||||
INSTALL_PROGRAM
|
||||
|
|
@ -1158,6 +1138,8 @@ target=$target_alias
|
|||
if test "x$host_alias" != x; then
|
||||
if test "x$build_alias" = x; then
|
||||
cross_compiling=maybe
|
||||
$as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host.
|
||||
If a cross compiler is detected then cross compile mode will be used" >&2
|
||||
elif test "x$build_alias" != "x$host_alias"; then
|
||||
cross_compiling=yes
|
||||
fi
|
||||
|
|
@ -1390,9 +1372,9 @@ test -n "$ac_init_help" && exit $ac_status
|
|||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
Memory Pool System Kit configure master
|
||||
generated by GNU Autoconf 2.69
|
||||
generated by GNU Autoconf 2.68
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
This configure script is free software; the Free Software Foundation
|
||||
gives unlimited permission to copy, distribute and modify it.
|
||||
_ACEOF
|
||||
|
|
@ -1441,6 +1423,52 @@ fi
|
|||
|
||||
} # ac_fn_c_try_compile
|
||||
|
||||
# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
|
||||
# ---------------------------------------------
|
||||
# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
|
||||
# accordingly.
|
||||
ac_fn_c_check_decl ()
|
||||
{
|
||||
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
|
||||
as_decl_name=`echo $2|sed 's/ *(.*//'`
|
||||
as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
|
||||
$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
|
||||
if eval \${$3+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
$4
|
||||
int
|
||||
main ()
|
||||
{
|
||||
#ifndef $as_decl_name
|
||||
#ifdef __cplusplus
|
||||
(void) $as_decl_use;
|
||||
#else
|
||||
(void) $as_decl_name;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"; then :
|
||||
eval "$3=yes"
|
||||
else
|
||||
eval "$3=no"
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
fi
|
||||
eval ac_res=\$$3
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
|
||||
$as_echo "$ac_res" >&6; }
|
||||
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
|
||||
|
||||
} # ac_fn_c_check_decl
|
||||
|
||||
# ac_fn_c_try_cpp LINENO
|
||||
# ----------------------
|
||||
# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
|
||||
|
|
@ -1478,6 +1506,79 @@ fi
|
|||
|
||||
} # ac_fn_c_try_cpp
|
||||
|
||||
# ac_fn_c_try_run LINENO
|
||||
# ----------------------
|
||||
# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
|
||||
# that executables *can* be run.
|
||||
ac_fn_c_try_run ()
|
||||
{
|
||||
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
|
||||
if { { ac_try="$ac_link"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
|
||||
$as_echo "$ac_try_echo"; } >&5
|
||||
(eval "$ac_link") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
|
||||
{ { case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
|
||||
$as_echo "$ac_try_echo"; } >&5
|
||||
(eval "$ac_try") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; }; then :
|
||||
ac_retval=0
|
||||
else
|
||||
$as_echo "$as_me: program exited with status $ac_status" >&5
|
||||
$as_echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
ac_retval=$ac_status
|
||||
fi
|
||||
rm -rf conftest.dSYM conftest_ipa8_conftest.oo
|
||||
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
|
||||
as_fn_set_status $ac_retval
|
||||
|
||||
} # ac_fn_c_try_run
|
||||
|
||||
# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
|
||||
# -------------------------------------------------------
|
||||
# Tests whether HEADER exists and can be compiled using the include files in
|
||||
# INCLUDES, setting the cache variable VAR accordingly.
|
||||
ac_fn_c_check_header_compile ()
|
||||
{
|
||||
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
|
||||
$as_echo_n "checking for $2... " >&6; }
|
||||
if eval \${$3+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
$4
|
||||
#include <$2>
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"; then :
|
||||
eval "$3=yes"
|
||||
else
|
||||
eval "$3=no"
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
fi
|
||||
eval ac_res=\$$3
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
|
||||
$as_echo "$ac_res" >&6; }
|
||||
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
|
||||
|
||||
} # ac_fn_c_check_header_compile
|
||||
|
||||
# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
|
||||
# -------------------------------------------------------
|
||||
# Tests whether HEADER exists, giving a warning if it cannot be compiled using
|
||||
|
|
@ -1568,85 +1669,12 @@ fi
|
|||
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
|
||||
|
||||
} # ac_fn_c_check_header_mongrel
|
||||
|
||||
# ac_fn_c_try_run LINENO
|
||||
# ----------------------
|
||||
# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
|
||||
# that executables *can* be run.
|
||||
ac_fn_c_try_run ()
|
||||
{
|
||||
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
|
||||
if { { ac_try="$ac_link"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
|
||||
$as_echo "$ac_try_echo"; } >&5
|
||||
(eval "$ac_link") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
|
||||
{ { case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
|
||||
$as_echo "$ac_try_echo"; } >&5
|
||||
(eval "$ac_try") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; }; then :
|
||||
ac_retval=0
|
||||
else
|
||||
$as_echo "$as_me: program exited with status $ac_status" >&5
|
||||
$as_echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
ac_retval=$ac_status
|
||||
fi
|
||||
rm -rf conftest.dSYM conftest_ipa8_conftest.oo
|
||||
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
|
||||
as_fn_set_status $ac_retval
|
||||
|
||||
} # ac_fn_c_try_run
|
||||
|
||||
# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
|
||||
# -------------------------------------------------------
|
||||
# Tests whether HEADER exists and can be compiled using the include files in
|
||||
# INCLUDES, setting the cache variable VAR accordingly.
|
||||
ac_fn_c_check_header_compile ()
|
||||
{
|
||||
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
|
||||
$as_echo_n "checking for $2... " >&6; }
|
||||
if eval \${$3+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
$4
|
||||
#include <$2>
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"; then :
|
||||
eval "$3=yes"
|
||||
else
|
||||
eval "$3=no"
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
fi
|
||||
eval ac_res=\$$3
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
|
||||
$as_echo "$ac_res" >&6; }
|
||||
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
|
||||
|
||||
} # ac_fn_c_check_header_compile
|
||||
cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by Memory Pool System Kit $as_me master, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
generated by GNU Autoconf 2.68. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
|
||||
|
|
@ -2047,7 +2075,7 @@ do
|
|||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
ac_cv_prog_CC="${ac_tool_prefix}gcc"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
|
|
@ -2087,7 +2115,7 @@ do
|
|||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
ac_cv_prog_ac_ct_CC="gcc"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
|
|
@ -2140,7 +2168,7 @@ do
|
|||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
ac_cv_prog_CC="${ac_tool_prefix}cc"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
|
|
@ -2181,7 +2209,7 @@ do
|
|||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
|
||||
ac_prog_rejected=yes
|
||||
continue
|
||||
|
|
@ -2239,7 +2267,7 @@ do
|
|||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
|
|
@ -2283,7 +2311,7 @@ do
|
|||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
ac_cv_prog_ac_ct_CC="$ac_prog"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
|
|
@ -2729,7 +2757,8 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
|||
/* end confdefs.h. */
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
struct stat;
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
|
||||
struct buf { int x; };
|
||||
FILE * (*rcsopen) (struct buf *, struct stat *, int);
|
||||
|
|
@ -2857,7 +2886,7 @@ case $as_dir/ in #((
|
|||
# by default.
|
||||
for ac_prog in ginstall scoinst install; do
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
|
||||
if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
|
||||
if test $ac_prog = install &&
|
||||
grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
|
||||
# AIX install. It has an incompatible calling convention.
|
||||
|
|
@ -2914,193 +2943,7 @@ test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
|
|||
test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
|
||||
|
||||
|
||||
# These flags aren't used for building the MPS, but for sample programs.
|
||||
CFLAGS_GC="-ansi -pedantic -Wall -Werror -Wpointer-arith \
|
||||
-Wstrict-prototypes -Wmissing-prototypes \
|
||||
-Winline -Waggregate-return -Wnested-externs \
|
||||
-Wcast-qual -Wstrict-aliasing=2 -O -g3"
|
||||
CFLAGS_LL="$CFLAGS_GC -Wno-extended-offsetof"
|
||||
|
||||
# Make sure we can run config.sub.
|
||||
$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
|
||||
as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
|
||||
$as_echo_n "checking build system type... " >&6; }
|
||||
if ${ac_cv_build+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_build_alias=$build_alias
|
||||
test "x$ac_build_alias" = x &&
|
||||
ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
|
||||
test "x$ac_build_alias" = x &&
|
||||
as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
|
||||
ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
|
||||
as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
|
||||
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
|
||||
$as_echo "$ac_cv_build" >&6; }
|
||||
case $ac_cv_build in
|
||||
*-*-*) ;;
|
||||
*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
|
||||
esac
|
||||
build=$ac_cv_build
|
||||
ac_save_IFS=$IFS; IFS='-'
|
||||
set x $ac_cv_build
|
||||
shift
|
||||
build_cpu=$1
|
||||
build_vendor=$2
|
||||
shift; shift
|
||||
# Remember, the first character of IFS is used to create $*,
|
||||
# except with old shells:
|
||||
build_os=$*
|
||||
IFS=$ac_save_IFS
|
||||
case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
|
||||
$as_echo_n "checking host system type... " >&6; }
|
||||
if ${ac_cv_host+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
if test "x$host_alias" = x; then
|
||||
ac_cv_host=$ac_cv_build
|
||||
else
|
||||
ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
|
||||
as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
|
||||
fi
|
||||
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
|
||||
$as_echo "$ac_cv_host" >&6; }
|
||||
case $ac_cv_host in
|
||||
*-*-*) ;;
|
||||
*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
|
||||
esac
|
||||
host=$ac_cv_host
|
||||
ac_save_IFS=$IFS; IFS='-'
|
||||
set x $ac_cv_host
|
||||
shift
|
||||
host_cpu=$1
|
||||
host_vendor=$2
|
||||
shift; shift
|
||||
# Remember, the first character of IFS is used to create $*,
|
||||
# except with old shells:
|
||||
host_os=$*
|
||||
IFS=$ac_save_IFS
|
||||
case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target platform" >&5
|
||||
$as_echo_n "checking target platform... " >&6; }
|
||||
BUILD_TARGET=build-via-make
|
||||
CLEAN_TARGET=clean-make-build
|
||||
INSTALL_TARGET=install-make-build
|
||||
TEST_TARGET=test-make-build
|
||||
case $host in
|
||||
i*86-*-linux*)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Linux x86" >&5
|
||||
$as_echo "Linux x86" >&6; }
|
||||
MPS_TARGET_NAME=lii3gc
|
||||
PFMCFLAGS="$CFLAGS_GC"
|
||||
;;
|
||||
x86_64-*-linux*)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Linux x86_64" >&5
|
||||
$as_echo "Linux x86_64" >&6; }
|
||||
MPS_TARGET_NAME=lii6gc
|
||||
PFMCFLAGS="$CFLAGS_GC"
|
||||
;;
|
||||
i*86-*-darwin*)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Mac OS X x86" >&5
|
||||
$as_echo "Mac OS X x86" >&6; }
|
||||
MPS_TARGET_NAME=xci3ll
|
||||
BUILD_TARGET=build-via-xcode
|
||||
CLEAN_TARGET=clean-xcode-build
|
||||
INSTALL_TARGET=install-xcode-build
|
||||
TEST_TARGET=test-xcode-build
|
||||
PFMCFLAGS="$CFLAGS_LL"
|
||||
;;
|
||||
x86_64-apple-darwin*)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Mac OS X x86_64" >&5
|
||||
$as_echo "Mac OS X x86_64" >&6; }
|
||||
MPS_TARGET_NAME=xci6ll
|
||||
BUILD_TARGET=build-via-xcode
|
||||
CLEAN_TARGET=clean-xcode-build
|
||||
INSTALL_TARGET=install-xcode-build
|
||||
TEST_TARGET=test-xcode-build
|
||||
PFMCFLAGS="$CFLAGS_LL"
|
||||
;;
|
||||
i*86-*-freebsd*)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: FreeBSD x86" >&5
|
||||
$as_echo "FreeBSD x86" >&6; }
|
||||
MPS_TARGET_NAME=fri3gc
|
||||
# Need /usr/local/include in order to find sqlite3.h
|
||||
CFLAGS="-I/usr/local/include"
|
||||
CPP="$CC -I/usr/local/include -E"
|
||||
PFMCFLAGS="$CFLAGS_GC -pthread"
|
||||
;;
|
||||
amd64-*-freebsd* | x86_64-*-freebsd*)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: FreeBSD x86_64" >&5
|
||||
$as_echo "FreeBSD x86_64" >&6; }
|
||||
MPS_TARGET_NAME=fri6gc
|
||||
# Need /usr/local/include in order to find sqlite3.h
|
||||
CFLAGS="-I/usr/local/include"
|
||||
CPP="$CC -I/usr/local/include -E"
|
||||
PFMCFLAGS="$CFLAGS_GC -pthread"
|
||||
;;
|
||||
*)
|
||||
as_fn_error $? "MPS does not support this platform out of the box. See manual/build.txt" "$LINENO" 5
|
||||
esac
|
||||
|
||||
for ac_prog in gnumake gmake make
|
||||
do
|
||||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
$as_echo_n "checking for $ac_word... " >&6; }
|
||||
if ${ac_cv_prog_MAKE+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
if test -n "$MAKE"; then
|
||||
ac_cv_prog_MAKE="$MAKE" # Let the user override the test.
|
||||
else
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_MAKE="$ac_prog"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
|
||||
fi
|
||||
fi
|
||||
MAKE=$ac_cv_prog_MAKE
|
||||
if test -n "$MAKE"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAKE" >&5
|
||||
$as_echo "$MAKE" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
test -n "$MAKE" && break
|
||||
done
|
||||
test -n "$MAKE" || MAKE="as_fn_error $? "Unable to find a make program." "$LINENO" 5"
|
||||
|
||||
if ! $MAKE --version | grep -q "GNU" 2> /dev/null; then
|
||||
as_fn_error $? "MPS requires GNU make to build from configure, but see manual/build.txt" "$LINENO" 5
|
||||
fi
|
||||
|
||||
EXTRA_TARGETS="mpseventcnv mpseventtxt"
|
||||
# Check for Clang/LLVM.
|
||||
|
||||
ac_ext=c
|
||||
ac_cpp='$CPP $CPPFLAGS'
|
||||
|
|
@ -3256,7 +3099,7 @@ do
|
|||
for ac_prog in grep ggrep; do
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
|
||||
as_fn_executable_p "$ac_path_GREP" || continue
|
||||
{ test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
|
||||
# Check for GNU ac_path_GREP and select it if it is found.
|
||||
# Check for GNU $ac_path_GREP
|
||||
case `"$ac_path_GREP" --version 2>&1` in
|
||||
|
|
@ -3322,7 +3165,7 @@ do
|
|||
for ac_prog in egrep; do
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
|
||||
as_fn_executable_p "$ac_path_EGREP" || continue
|
||||
{ test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
|
||||
# Check for GNU ac_path_EGREP and select it if it is found.
|
||||
# Check for GNU $ac_path_EGREP
|
||||
case `"$ac_path_EGREP" --version 2>&1` in
|
||||
|
|
@ -3499,6 +3342,207 @@ fi
|
|||
done
|
||||
|
||||
|
||||
ac_fn_c_check_decl "$LINENO" "__clang__" "ac_cv_have_decl___clang__" "$ac_includes_default"
|
||||
if test "x$ac_cv_have_decl___clang__" = xyes; then :
|
||||
CLANG=yes
|
||||
else
|
||||
CLANG=no
|
||||
fi
|
||||
|
||||
|
||||
# These flags aren't used for building the MPS, but for sample programs.
|
||||
CFLAGS_GC="-ansi -pedantic -Wall -Werror -Wpointer-arith \
|
||||
-Wstrict-prototypes -Wmissing-prototypes \
|
||||
-Winline -Waggregate-return -Wnested-externs \
|
||||
-Wcast-qual -Wstrict-aliasing=2 -O -g3 -pthread"
|
||||
CFLAGS_LL="$CFLAGS_GC -Wno-extended-offsetof"
|
||||
|
||||
# Make sure we can run config.sub.
|
||||
$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
|
||||
as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
|
||||
$as_echo_n "checking build system type... " >&6; }
|
||||
if ${ac_cv_build+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_build_alias=$build_alias
|
||||
test "x$ac_build_alias" = x &&
|
||||
ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
|
||||
test "x$ac_build_alias" = x &&
|
||||
as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
|
||||
ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
|
||||
as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
|
||||
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
|
||||
$as_echo "$ac_cv_build" >&6; }
|
||||
case $ac_cv_build in
|
||||
*-*-*) ;;
|
||||
*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
|
||||
esac
|
||||
build=$ac_cv_build
|
||||
ac_save_IFS=$IFS; IFS='-'
|
||||
set x $ac_cv_build
|
||||
shift
|
||||
build_cpu=$1
|
||||
build_vendor=$2
|
||||
shift; shift
|
||||
# Remember, the first character of IFS is used to create $*,
|
||||
# except with old shells:
|
||||
build_os=$*
|
||||
IFS=$ac_save_IFS
|
||||
case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
|
||||
$as_echo_n "checking host system type... " >&6; }
|
||||
if ${ac_cv_host+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
if test "x$host_alias" = x; then
|
||||
ac_cv_host=$ac_cv_build
|
||||
else
|
||||
ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
|
||||
as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
|
||||
fi
|
||||
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
|
||||
$as_echo "$ac_cv_host" >&6; }
|
||||
case $ac_cv_host in
|
||||
*-*-*) ;;
|
||||
*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
|
||||
esac
|
||||
host=$ac_cv_host
|
||||
ac_save_IFS=$IFS; IFS='-'
|
||||
set x $ac_cv_host
|
||||
shift
|
||||
host_cpu=$1
|
||||
host_vendor=$2
|
||||
shift; shift
|
||||
# Remember, the first character of IFS is used to create $*,
|
||||
# except with old shells:
|
||||
host_os=$*
|
||||
IFS=$ac_save_IFS
|
||||
case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target platform" >&5
|
||||
$as_echo_n "checking target platform... " >&6; }
|
||||
BUILD_TARGET=build-via-make
|
||||
CLEAN_TARGET=clean-make-build
|
||||
INSTALL_TARGET=install-make-build
|
||||
TEST_TARGET=test-make-build
|
||||
case $host/$CLANG in
|
||||
i*86-*-linux*/no)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Linux x86" >&5
|
||||
$as_echo "Linux x86" >&6; }
|
||||
MPS_TARGET_NAME=lii3gc
|
||||
PFMCFLAGS="$CFLAGS_GC"
|
||||
;;
|
||||
x86_64-*-linux*/no)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Linux x86_64" >&5
|
||||
$as_echo "Linux x86_64" >&6; }
|
||||
MPS_TARGET_NAME=lii6gc
|
||||
PFMCFLAGS="$CFLAGS_GC"
|
||||
;;
|
||||
x86_64-*-linux*/yes)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Linux x86_64" >&5
|
||||
$as_echo "Linux x86_64" >&6; }
|
||||
MPS_TARGET_NAME=lii6ll
|
||||
PFMCFLAGS="$CFLAGS_LL"
|
||||
;;
|
||||
i*86-*-darwin*/*)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Mac OS X x86" >&5
|
||||
$as_echo "Mac OS X x86" >&6; }
|
||||
MPS_TARGET_NAME=xci3ll
|
||||
BUILD_TARGET=build-via-xcode
|
||||
CLEAN_TARGET=clean-xcode-build
|
||||
INSTALL_TARGET=install-xcode-build
|
||||
TEST_TARGET=test-xcode-build
|
||||
PFMCFLAGS="$CFLAGS_LL"
|
||||
;;
|
||||
x86_64-apple-darwin*/*)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Mac OS X x86_64" >&5
|
||||
$as_echo "Mac OS X x86_64" >&6; }
|
||||
MPS_TARGET_NAME=xci6ll
|
||||
BUILD_TARGET=build-via-xcode
|
||||
CLEAN_TARGET=clean-xcode-build
|
||||
INSTALL_TARGET=install-xcode-build
|
||||
TEST_TARGET=test-xcode-build
|
||||
PFMCFLAGS="$CFLAGS_LL"
|
||||
;;
|
||||
i*86-*-freebsd*/no)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: FreeBSD x86" >&5
|
||||
$as_echo "FreeBSD x86" >&6; }
|
||||
MPS_TARGET_NAME=fri3gc
|
||||
# Need /usr/local/include in order to find sqlite3.h
|
||||
CFLAGS="-I/usr/local/include"
|
||||
CPP="$CC -I/usr/local/include -E"
|
||||
PFMCFLAGS="$CFLAGS_GC"
|
||||
;;
|
||||
amd64-*-freebsd*/no | x86_64-*-freebsd*/no)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: FreeBSD x86_64" >&5
|
||||
$as_echo "FreeBSD x86_64" >&6; }
|
||||
MPS_TARGET_NAME=fri6gc
|
||||
# Need /usr/local/include in order to find sqlite3.h
|
||||
CFLAGS="-I/usr/local/include"
|
||||
CPP="$CC -I/usr/local/include -E"
|
||||
PFMCFLAGS="$CFLAGS_GC"
|
||||
;;
|
||||
*)
|
||||
as_fn_error $? "MPS does not support this platform out of the box. See manual/build.txt" "$LINENO" 5
|
||||
esac
|
||||
|
||||
for ac_prog in gnumake gmake make
|
||||
do
|
||||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
set dummy $ac_prog; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
$as_echo_n "checking for $ac_word... " >&6; }
|
||||
if ${ac_cv_prog_MAKE+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
if test -n "$MAKE"; then
|
||||
ac_cv_prog_MAKE="$MAKE" # Let the user override the test.
|
||||
else
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
ac_cv_prog_MAKE="$ac_prog"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
|
||||
fi
|
||||
fi
|
||||
MAKE=$ac_cv_prog_MAKE
|
||||
if test -n "$MAKE"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAKE" >&5
|
||||
$as_echo "$MAKE" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
test -n "$MAKE" && break
|
||||
done
|
||||
test -n "$MAKE" || MAKE="as_fn_error $? "Unable to find a make program." "$LINENO" 5"
|
||||
|
||||
if ! $MAKE --version | grep -q "GNU" 2> /dev/null; then
|
||||
as_fn_error $? "MPS requires GNU make to build from configure, but see manual/build.txt" "$LINENO" 5
|
||||
fi
|
||||
|
||||
EXTRA_TARGETS="mpseventcnv mpseventtxt"
|
||||
ac_fn_c_check_header_mongrel "$LINENO" "sqlite3.h" "ac_cv_header_sqlite3_h" "$ac_includes_default"
|
||||
if test "x$ac_cv_header_sqlite3_h" = xyes; then :
|
||||
EXTRA_TARGETS="$EXTRA_TARGETS mpseventsql"
|
||||
|
|
@ -3966,16 +4010,16 @@ if (echo >conf$$.file) 2>/dev/null; then
|
|||
# ... but there are two gotchas:
|
||||
# 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
|
||||
# 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
|
||||
# In both cases, we have to default to `cp -pR'.
|
||||
# In both cases, we have to default to `cp -p'.
|
||||
ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
|
||||
as_ln_s='cp -pR'
|
||||
as_ln_s='cp -p'
|
||||
elif ln conf$$.file conf$$ 2>/dev/null; then
|
||||
as_ln_s=ln
|
||||
else
|
||||
as_ln_s='cp -pR'
|
||||
as_ln_s='cp -p'
|
||||
fi
|
||||
else
|
||||
as_ln_s='cp -pR'
|
||||
as_ln_s='cp -p'
|
||||
fi
|
||||
rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
|
||||
rmdir conf$$.dir 2>/dev/null
|
||||
|
|
@ -4035,16 +4079,28 @@ else
|
|||
as_mkdir_p=false
|
||||
fi
|
||||
|
||||
|
||||
# as_fn_executable_p FILE
|
||||
# -----------------------
|
||||
# Test if FILE is an executable regular file.
|
||||
as_fn_executable_p ()
|
||||
{
|
||||
test -f "$1" && test -x "$1"
|
||||
} # as_fn_executable_p
|
||||
if test -x / >/dev/null 2>&1; then
|
||||
as_test_x='test -x'
|
||||
as_executable_p=as_fn_executable_p
|
||||
else
|
||||
if ls -dL / >/dev/null 2>&1; then
|
||||
as_ls_L_option=L
|
||||
else
|
||||
as_ls_L_option=
|
||||
fi
|
||||
as_test_x='
|
||||
eval sh -c '\''
|
||||
if test -d "$1"; then
|
||||
test -d "$1/.";
|
||||
else
|
||||
case $1 in #(
|
||||
-*)set "./$1";;
|
||||
esac;
|
||||
case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
|
||||
???[sx]*):;;*)false;;esac;fi
|
||||
'\'' sh
|
||||
'
|
||||
fi
|
||||
as_executable_p=$as_test_x
|
||||
|
||||
# Sed expression to map a string onto a valid CPP name.
|
||||
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
|
||||
|
|
@ -4066,7 +4122,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
|||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by Memory Pool System Kit $as_me master, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
generated by GNU Autoconf 2.68. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
CONFIG_HEADERS = $CONFIG_HEADERS
|
||||
|
|
@ -4120,10 +4176,10 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
|||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||
ac_cs_version="\\
|
||||
Memory Pool System Kit config.status master
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
configured by $0, generated by GNU Autoconf 2.68,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
This config.status script is free software; the Free Software Foundation
|
||||
gives unlimited permission to copy, distribute and modify it."
|
||||
|
||||
|
|
@ -4201,7 +4257,7 @@ fi
|
|||
_ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
if \$ac_cs_recheck; then
|
||||
set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
|
||||
set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
|
||||
shift
|
||||
\$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
|
||||
CONFIG_SHELL='$SHELL'
|
||||
|
|
|
|||
|
|
@ -28,6 +28,9 @@ AC_PROG_CC
|
|||
AC_LANG_C
|
||||
AC_PROG_INSTALL
|
||||
|
||||
# Check for Clang/LLVM.
|
||||
AC_CHECK_DECL([__clang__],[CLANG=yes],[CLANG=no])
|
||||
|
||||
# These flags aren't used for building the MPS, but for sample programs.
|
||||
CFLAGS_GC="-ansi -pedantic -Wall -Werror -Wpointer-arith \
|
||||
-Wstrict-prototypes -Wmissing-prototypes \
|
||||
|
|
@ -41,18 +44,23 @@ BUILD_TARGET=build-via-make
|
|||
CLEAN_TARGET=clean-make-build
|
||||
INSTALL_TARGET=install-make-build
|
||||
TEST_TARGET=test-make-build
|
||||
case $host in
|
||||
i*86-*-linux*)
|
||||
case $host/$CLANG in
|
||||
i*86-*-linux*/no)
|
||||
AC_MSG_RESULT([Linux x86])
|
||||
MPS_TARGET_NAME=lii3gc
|
||||
PFMCFLAGS="$CFLAGS_GC"
|
||||
;;
|
||||
x86_64-*-linux*)
|
||||
x86_64-*-linux*/no)
|
||||
AC_MSG_RESULT([Linux x86_64])
|
||||
MPS_TARGET_NAME=lii6gc
|
||||
PFMCFLAGS="$CFLAGS_GC"
|
||||
;;
|
||||
i*86-*-darwin*)
|
||||
x86_64-*-linux*/yes)
|
||||
AC_MSG_RESULT([Linux x86_64])
|
||||
MPS_TARGET_NAME=lii6ll
|
||||
PFMCFLAGS="$CFLAGS_LL"
|
||||
;;
|
||||
i*86-*-darwin*/*)
|
||||
AC_MSG_RESULT([Mac OS X x86])
|
||||
MPS_TARGET_NAME=xci3ll
|
||||
BUILD_TARGET=build-via-xcode
|
||||
|
|
@ -61,7 +69,7 @@ case $host in
|
|||
TEST_TARGET=test-xcode-build
|
||||
PFMCFLAGS="$CFLAGS_LL"
|
||||
;;
|
||||
x86_64-apple-darwin*)
|
||||
x86_64-apple-darwin*/*)
|
||||
AC_MSG_RESULT([Mac OS X x86_64])
|
||||
MPS_TARGET_NAME=xci6ll
|
||||
BUILD_TARGET=build-via-xcode
|
||||
|
|
@ -70,7 +78,7 @@ case $host in
|
|||
TEST_TARGET=test-xcode-build
|
||||
PFMCFLAGS="$CFLAGS_LL"
|
||||
;;
|
||||
i*86-*-freebsd*)
|
||||
i*86-*-freebsd*/no)
|
||||
AC_MSG_RESULT([FreeBSD x86])
|
||||
MPS_TARGET_NAME=fri3gc
|
||||
# Need /usr/local/include in order to find sqlite3.h
|
||||
|
|
@ -78,7 +86,7 @@ case $host in
|
|||
CPP="$CC -I/usr/local/include -E"
|
||||
PFMCFLAGS="$CFLAGS_GC"
|
||||
;;
|
||||
amd64-*-freebsd* | x86_64-*-freebsd*)
|
||||
amd64-*-freebsd*/no | x86_64-*-freebsd*/no)
|
||||
AC_MSG_RESULT([FreeBSD x86_64])
|
||||
MPS_TARGET_NAME=fri6gc
|
||||
# Need /usr/local/include in order to find sqlite3.h
|
||||
|
|
|
|||
51
mps/contributing.rst
Normal file
51
mps/contributing.rst
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
Contributing to the MPS
|
||||
=======================
|
||||
:author: Richard Brooksby
|
||||
:organization: Ravenbrook Limited
|
||||
:date: 2013-07-05
|
||||
:revision: $Id$
|
||||
:confidentiality: public
|
||||
|
||||
We are very happy to receive contributions to the Memory Pool System so
|
||||
that we can improve it for everyone.
|
||||
|
||||
|
||||
Review
|
||||
------
|
||||
The MPS is highly engineered and rigorously controlled in order to
|
||||
prevent defects. This approach has lead to an extremely small number of
|
||||
bugs in production since its first commercial use in 1997. There are a
|
||||
fairly large number of rules, both low- and high-level that your code
|
||||
must follow in order to be accepted. These rules are the result of
|
||||
continuous process improvement to prevent defects. Unfortunately, we do
|
||||
not have many of them published at present. We apologise if you find it
|
||||
frustrating that we do not accept your changes as they are.
|
||||
|
||||
The style guide in guide.impl.c.format_ contains basic rules for style.
|
||||
|
||||
.. _guide.impl.c.format: design/guide.impl.c.format.txt
|
||||
|
||||
|
||||
Licensing
|
||||
---------
|
||||
In order for us to accept your contribution, you must agree to the MPS
|
||||
contribution agreement, so that we can continue to commercially license the
|
||||
MPS and thereby fund future development.
|
||||
|
||||
I grant Ravenbrook Ltd an irrevocable, perpetual, worldwide,
|
||||
non-exclusive licence to do anything with [your contribution] that I
|
||||
would have the right to do. This includes (but is not limited to):
|
||||
|
||||
1. reproducing it and doing any other act that is restricted by
|
||||
copyright;
|
||||
|
||||
2. the right to sublicence to others the code and any derivative
|
||||
work.
|
||||
|
||||
A member of Ravenbrook staff may ask you to expressly (in writing) agree.
|
||||
You just need to reply with “I agree.” We apologise for the inconvenience.
|
||||
|
||||
|
||||
Thank you
|
||||
---------
|
||||
Finally, thank you for making the MPS more useful to everyone.
|
||||
|
|
@ -62,22 +62,22 @@ the queue; and ``elementSize`` is the size of each element.
|
|||
|
||||
Finish ``abq`` and free all resources associated with it.
|
||||
|
||||
``Res ABQPush(ABQ abq, void *element)``
|
||||
``Bool ABQPush(ABQ abq, void *element)``
|
||||
|
||||
If the queue is full, leave it unchanged and return ``ResFAIL``.
|
||||
Otherwise, push ``element`` on to the queue and return ``ResOK``.
|
||||
If the queue is full, leave it unchanged and return ``FALSE``.
|
||||
Otherwise, push ``element`` on to the queue and return ``TRUE``.
|
||||
|
||||
``Res ABQPop(ABQ abq, void *elementReturn)``
|
||||
``Bool ABQPop(ABQ abq, void *elementReturn)``
|
||||
|
||||
If the queue is empty, return ``ResFAIL``. Othwreise, copy the first
|
||||
If the queue is empty, return ``FALSE``. Otherwise, copy the first
|
||||
element on the queue into the memory pointed to by ``elementReturn``,
|
||||
remove the element from the queue, and return ``ResOK``.
|
||||
remove the element from the queue, and return ``TRUE``.
|
||||
|
||||
``Res ABQPeek(ABQ abq, void *elementReturn)``
|
||||
``Bool ABQPeek(ABQ abq, void *elementReturn)``
|
||||
|
||||
If the queue is empty, return ``ResFAIL``. Otherwise, copy the first
|
||||
If the queue is empty, return ``FALSE``. Otherwise, copy the first
|
||||
element on the queue into the memory pointed to by ``elementReturn``
|
||||
and return ``ResOK``. (This is the same as ``ABQPop()`` except that
|
||||
and return ``TRUE``. (This is the same as ``ABQPop()`` except that
|
||||
the queue is unchanged.)
|
||||
|
||||
``Bool ABQIsEmpty(ABQ abq)``
|
||||
|
|
@ -119,7 +119,7 @@ Document History
|
|||
Copyright and License
|
||||
---------------------
|
||||
|
||||
Copyright © 2013 Ravenbrook Limited. All rights reserved.
|
||||
Copyright © 2013-2014 Ravenbrook Limited. All rights reserved.
|
||||
<http://www.ravenbrook.com/>. This is an open source license. Contact
|
||||
Ravenbrook for commercial licensing options.
|
||||
|
||||
|
|
@ -127,14 +127,14 @@ 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
|
||||
#. 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
|
||||
#. 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
|
||||
#. 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
|
||||
|
|
|
|||
|
|
@ -473,7 +473,7 @@ Document History
|
|||
Copyright and License
|
||||
---------------------
|
||||
|
||||
Copyright © 2013 Ravenbrook Limited. All rights reserved.
|
||||
Copyright © 2013-2014 Ravenbrook Limited. All rights reserved.
|
||||
<http://www.ravenbrook.com/>. This is an open source license. Contact
|
||||
Ravenbrook for commercial licensing options.
|
||||
|
||||
|
|
@ -481,14 +481,14 @@ 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
|
||||
#. 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
|
||||
#. 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
|
||||
#. 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
|
||||
|
|
|
|||
|
|
@ -553,7 +553,7 @@ Document History
|
|||
Copyright and License
|
||||
---------------------
|
||||
|
||||
Copyright © 2001-2013 Ravenbrook Limited. All rights reserved.
|
||||
Copyright © 2001-2014 Ravenbrook Limited. All rights reserved.
|
||||
<http://www.ravenbrook.com/>. This is an open source license. Contact
|
||||
Ravenbrook for commercial licensing options.
|
||||
|
||||
|
|
@ -561,14 +561,14 @@ 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
|
||||
#. 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
|
||||
#. 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
|
||||
#. 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
|
||||
|
|
|
|||
|
|
@ -106,8 +106,8 @@ entries.
|
|||
|
||||
_`.idea.table.figure`: [missing figure]
|
||||
|
||||
_`.idea.map`: Store the pointers (`.req.fun.trans`_) in the table
|
||||
directly for every grain.
|
||||
_`.idea.map`: Store the pointers (design.arena.req.fun.trans) in the
|
||||
table directly for every grain.
|
||||
|
||||
_`.idea.zones`: Partition the managed address space into zones (see
|
||||
idea.zones) and provide the set approximation as a reference
|
||||
|
|
@ -141,8 +141,8 @@ overhead, and with 1 MiB active, it is a 300% overhead! The address
|
|||
space for the table should be reserved, but the pages for it mapped
|
||||
and unmapped on demand. By storing the table in a tract, the status of
|
||||
the table's pages can be determined by looking at it's own entries in
|
||||
itself, and thus the translation lookup (`.req.fun.trans`_) is slowed
|
||||
to two lookups rather than one.
|
||||
itself, and thus the translation lookup (design.arena.req.fun.trans)
|
||||
is slowed to two lookups rather than one.
|
||||
|
||||
_`.idea.pool`: Make the Arena Manager a pool class. Arena
|
||||
initialization becomes pool creation. Tract allocation becomes
|
||||
|
|
@ -222,7 +222,7 @@ Document History
|
|||
Copyright and License
|
||||
---------------------
|
||||
|
||||
Copyright © 2013 Ravenbrook Limited. All rights reserved.
|
||||
Copyright © 2013-2014 Ravenbrook Limited. All rights reserved.
|
||||
<http://www.ravenbrook.com/>. This is an open source license. Contact
|
||||
Ravenbrook for commercial licensing options.
|
||||
|
||||
|
|
@ -230,14 +230,14 @@ 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
|
||||
#. 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
|
||||
#. 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
|
||||
#. 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
|
||||
|
|
|
|||
|
|
@ -741,7 +741,7 @@ Document History
|
|||
Copyright and License
|
||||
---------------------
|
||||
|
||||
Copyright © 2013 Ravenbrook Limited. All rights reserved.
|
||||
Copyright © 2013-2014 Ravenbrook Limited. All rights reserved.
|
||||
<http://www.ravenbrook.com/>. This is an open source license. Contact
|
||||
Ravenbrook for commercial licensing options.
|
||||
|
||||
|
|
@ -749,14 +749,14 @@ 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
|
||||
#. 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
|
||||
#. 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
|
||||
#. 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
|
||||
|
|
|
|||
|
|
@ -186,7 +186,8 @@ changed.
|
|||
|
||||
_`.class.method`: Buffer classes provide the following methods (these
|
||||
should not be confused with the pool class methods related to the
|
||||
buffer protocol, described in `.method`_):
|
||||
buffer protocol, described in `.method.create`_ and following
|
||||
sections):
|
||||
|
||||
``typedef Res (*BufferInitMethod)(Buffer buffer, Pool pool, ArgList args)``
|
||||
|
||||
|
|
@ -706,7 +707,7 @@ Document History
|
|||
|
||||
- 2002-06-07 RB_ Converted from MMInfo database design document.
|
||||
|
||||
- 2007-03-22 RHSK_ Created Guide.
|
||||
- 2007-03-22 RHSK Created Guide.
|
||||
|
||||
- 2013-05-24 GDR_ Converted to reStructuredText; some tidying and
|
||||
modernizing (``BufferInit()`` takes keyword arguments;
|
||||
|
|
@ -722,7 +723,7 @@ Document History
|
|||
Copyright and License
|
||||
---------------------
|
||||
|
||||
Copyright © 2013 Ravenbrook Limited. All rights reserved.
|
||||
Copyright © 2013-2014 Ravenbrook Limited. All rights reserved.
|
||||
<http://www.ravenbrook.com/>. This is an open source license. Contact
|
||||
Ravenbrook for commercial licensing options.
|
||||
|
||||
|
|
@ -730,14 +731,14 @@ 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
|
||||
#. 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
|
||||
#. 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
|
||||
#. 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
|
||||
|
|
|
|||
|
|
@ -251,9 +251,9 @@ if there is no suitable block.
|
|||
_`.impl.find-largest`: ``CBSFindLargest()`` simply finds out the size
|
||||
of the largest block in the CBS from the root of the tree, using
|
||||
``SplayRoot()``, and does ``SplayFindFirst()`` for a block of that
|
||||
size. This is O(log *n*) in the size of the free list, so it's about
|
||||
the best you can do without maintaining a separate priority queue,
|
||||
just to do ``CBSFindLargest()``.
|
||||
size. This takes time proportional to the logarithm of the size of the
|
||||
free list, so it's about the best you can do without maintaining a
|
||||
separate priority queue, just to do ``CBSFindLargest()``.
|
||||
|
||||
|
||||
Low memory behaviour
|
||||
|
|
@ -366,7 +366,7 @@ Document History
|
|||
Copyright and License
|
||||
---------------------
|
||||
|
||||
Copyright © 1998-2013 Ravenbrook Limited. All rights reserved.
|
||||
Copyright © 1998-2014 Ravenbrook Limited. All rights reserved.
|
||||
<http://www.ravenbrook.com/>. This is an open source license. Contact
|
||||
Ravenbrook for commercial licensing options.
|
||||
|
||||
|
|
@ -374,14 +374,14 @@ 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
|
||||
#. 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
|
||||
#. 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
|
||||
#. 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
|
||||
|
|
|
|||
|
|
@ -26,15 +26,15 @@ Implementation
|
|||
|
||||
_`.level`: There are three levels of checking:
|
||||
|
||||
1. _`.level.sig`: The lowest level checks only that the
|
||||
#. _`.level.sig`: The lowest level checks only that the
|
||||
structure has a valid ``Signature`` (see
|
||||
design.mps.sig).
|
||||
|
||||
2. _`.level.shallow`: Shallow checking checks all local fields
|
||||
#. _`.level.shallow`: Shallow checking checks all local fields
|
||||
(including signature) and also checks the signatures of any parent
|
||||
or child structures.
|
||||
|
||||
3. _`.level.deep`: Deep checking checks all local fields
|
||||
#. _`.level.deep`: Deep checking checks all local fields
|
||||
(including signatures), the signatures of any parent structures,
|
||||
and does full recursive checking on any child structures.
|
||||
|
||||
|
|
@ -124,7 +124,7 @@ Document History
|
|||
Copyright and License
|
||||
---------------------
|
||||
|
||||
Copyright © 2013 Ravenbrook Limited. All rights reserved.
|
||||
Copyright © 2013-2014 Ravenbrook Limited. All rights reserved.
|
||||
<http://www.ravenbrook.com/>. This is an open source license. Contact
|
||||
Ravenbrook for commercial licensing options.
|
||||
|
||||
|
|
@ -132,14 +132,14 @@ 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
|
||||
#. 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
|
||||
#. 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
|
||||
#. 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
|
||||
|
|
|
|||
|
|
@ -277,7 +277,7 @@ Document history
|
|||
Copyright and License
|
||||
---------------------
|
||||
|
||||
Copyright © 2013 Ravenbrook Limited. All rights reserved.
|
||||
Copyright © 2013-2014 Ravenbrook Limited. All rights reserved.
|
||||
<http://www.ravenbrook.com/>. This is an open source license. Contact
|
||||
Ravenbrook for commercial licensing options.
|
||||
|
||||
|
|
@ -285,14 +285,14 @@ 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
|
||||
#. 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
|
||||
#. 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
|
||||
#. 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
|
||||
|
|
|
|||
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