mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-17 01:34:21 +00:00
Catch-up merge from master sources to branch/2015-08-11/compact.
Copied from Perforce Change: 190901 ServerID: perforce.ravenbrook.com
This commit is contained in:
commit
b8ea44a99f
359 changed files with 9156 additions and 6423 deletions
|
|
@ -8,16 +8,25 @@
|
|||
# Patch results
|
||||
*.orig
|
||||
*.rej
|
||||
# Autoconf and Automake output
|
||||
Makefile
|
||||
autom4te.cache
|
||||
config.log
|
||||
config.status
|
||||
.deps
|
||||
.dirstamp
|
||||
bin
|
||||
lib
|
||||
# Misc
|
||||
TAGS
|
||||
*.dSYM
|
||||
code/*/*/*.d
|
||||
*.pyc
|
||||
test/obj
|
||||
test/test/log
|
||||
test/test/obj
|
||||
....gcda
|
||||
....gcno
|
||||
....gcno
|
||||
\#*#
|
||||
*~
|
||||
.#.*
|
||||
core
|
||||
|
|
|
|||
1
mps/.renamed-gitignore
Symbolic link
1
mps/.renamed-gitignore
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
.p4ignore
|
||||
|
|
@ -2,9 +2,16 @@
|
|||
# $Id$
|
||||
# See <http://about.travis-ci.org/docs/user/languages/c/>.
|
||||
language: c
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
compiler:
|
||||
- clang
|
||||
- gcc
|
||||
matrix:
|
||||
exclude:
|
||||
- os: osx
|
||||
compiler: gcc
|
||||
notifications:
|
||||
email:
|
||||
- mps-travis@ravenbrook.com
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Makefile.in -- source for autoconf Makefile
|
||||
#
|
||||
# $Id$
|
||||
# Copyright (C) 2012-2014 Ravenbrook Limited. See end of file for license.
|
||||
# Copyright (C) 2012-2016 Ravenbrook Limited. See end of file for license.
|
||||
#
|
||||
# YOU DON'T NEED AUTOCONF TO BUILD THE MPS
|
||||
# This is just here for people who want or expect a configure script.
|
||||
|
|
@ -80,3 +80,44 @@ test-xcode-build:
|
|||
$(XCODEBUILD) -config Release -target testci
|
||||
|
||||
test: @TEST_TARGET@
|
||||
|
||||
|
||||
# C. COPYRIGHT AND LICENSE
|
||||
#
|
||||
# Copyright (C) 2012-2016 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.
|
||||
|
|
|
|||
|
|
@ -5,15 +5,17 @@ anangc
|
|||
ananll
|
||||
ananmv
|
||||
fri3gc
|
||||
fri3ll
|
||||
fri6gc
|
||||
fri6ll
|
||||
lii3gc
|
||||
lii6gc
|
||||
lii6ll
|
||||
w3i3mv
|
||||
w3i3pc
|
||||
w3i6mv
|
||||
w3i6pc
|
||||
xci3gc
|
||||
xci3ll
|
||||
xci6gc
|
||||
xci6ll
|
||||
# Visual Studio junk
|
||||
Debug
|
||||
|
|
@ -33,6 +35,7 @@ mpsio*.txt
|
|||
*.lib
|
||||
*.exe
|
||||
a.out
|
||||
core
|
||||
# Xcode junk
|
||||
xc
|
||||
mps.xcodeproj/xcuserdata
|
||||
|
|
@ -51,3 +54,7 @@ tags
|
|||
9
|
||||
# Mac OS X Finder turds
|
||||
.DS_Store
|
||||
# Emacs backups
|
||||
*~
|
||||
# GNU make dependencies
|
||||
*/*/*.d
|
||||
|
|
|
|||
1
mps/code/.renamed-gitignore
Symbolic link
1
mps/code/.renamed-gitignore
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
.p4ignore
|
||||
|
|
@ -41,8 +41,7 @@ Res ABQInit(Arena arena, ABQ abq, void *owner, Count elements, Size elementSize)
|
|||
"empty" from "full" */
|
||||
elements = elements + 1;
|
||||
|
||||
res = ControlAlloc(&p, arena, ABQQueueSize(elements, elementSize),
|
||||
/* withReservoirPermit */ FALSE);
|
||||
res = ControlAlloc(&p, arena, ABQQueueSize(elements, elementSize));
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
|
|
@ -232,7 +231,7 @@ Count ABQDepth(ABQ abq)
|
|||
|
||||
|
||||
/* ABQIterate -- call 'visitor' for each element in an ABQ */
|
||||
void ABQIterate(ABQ abq, ABQVisitor visitor, void *closureP, Size closureS)
|
||||
void ABQIterate(ABQ abq, ABQVisitor visitor, void *closure)
|
||||
{
|
||||
Index copy, index, in;
|
||||
|
||||
|
|
@ -247,7 +246,7 @@ void ABQIterate(ABQ abq, ABQVisitor visitor, void *closureP, Size closureS)
|
|||
void *element = ABQElement(abq, index);
|
||||
Bool delete = FALSE;
|
||||
Bool cont;
|
||||
cont = (*visitor)(&delete, element, closureP, closureS);
|
||||
cont = (*visitor)(&delete, element, closure);
|
||||
AVERT(Bool, cont);
|
||||
AVERT(Bool, delete);
|
||||
if (!delete) {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
typedef struct ABQStruct *ABQ;
|
||||
typedef Res (*ABQDescribeElement)(void *element, mps_lib_FILE *stream, Count depth);
|
||||
typedef Bool (*ABQVisitor)(Bool *deleteReturn, void *element, void *closureP, Size closureS);
|
||||
typedef Bool (*ABQVisitor)(Bool *deleteReturn, void *element, void *closure);
|
||||
|
||||
extern Res ABQInit(Arena arena, ABQ abq, void *owner, Count elements, Size elementSize);
|
||||
extern Bool ABQCheck(ABQ abq);
|
||||
|
|
@ -36,7 +36,7 @@ extern Res ABQDescribe(ABQ abq, ABQDescribeElement describeElement, mps_lib_FILE
|
|||
extern Bool ABQIsEmpty(ABQ abq);
|
||||
extern Bool ABQIsFull(ABQ abq);
|
||||
extern Count ABQDepth(ABQ abq);
|
||||
extern void ABQIterate(ABQ abq, ABQVisitor visitor, void *closureP, Size closureS);
|
||||
extern void ABQIterate(ABQ abq, ABQVisitor visitor, void *closure);
|
||||
|
||||
|
||||
/* Types */
|
||||
|
|
|
|||
|
|
@ -92,12 +92,10 @@ typedef struct TestClosureStruct {
|
|||
} TestClosureStruct;
|
||||
|
||||
static Bool TestDeleteCallback(Bool *deleteReturn, void *element,
|
||||
void *closureP, Size closureS)
|
||||
void *closure)
|
||||
{
|
||||
TestBlock *a = (TestBlock *)element;
|
||||
TestClosure cl = (TestClosure)closureP;
|
||||
AVER(closureS == UNUSED_SIZE);
|
||||
UNUSED(closureS);
|
||||
TestClosure cl = (TestClosure)closure;
|
||||
if (*a == cl->b) {
|
||||
*deleteReturn = TRUE;
|
||||
cl->res = ResOK;
|
||||
|
|
@ -145,7 +143,7 @@ static void step(void)
|
|||
cdie(b != NULL, "found to delete");
|
||||
cl.b = b;
|
||||
cl.res = ResFAIL;
|
||||
ABQIterate(&abq, TestDeleteCallback, &cl, UNUSED_SIZE);
|
||||
ABQIterate(&abq, TestDeleteCallback, &cl);
|
||||
cdie(cl.res == ResOK, "ABQIterate");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* airtest.c: AMBIGUOUS INTERIOR REFERENCE TEST
|
||||
*
|
||||
* $Id: //info.ravenbrook.com/project/mps/branch/2014-01-15/nailboard/code/fotest.c#1 $
|
||||
* Copyright (c) 2014 Ravenbrook Limited. See end of file for license.
|
||||
* $Id$
|
||||
* Copyright (c) 2014-2016 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .overview: This test case creates a bunch of vectors, registers
|
||||
* them for finalization, and then discards the base pointers to those
|
||||
|
|
@ -127,8 +127,7 @@ static void test_main(void *marker, int interior, int stack)
|
|||
error("Couldn't register thread");
|
||||
|
||||
if (stack) {
|
||||
res = mps_root_create_reg(®_root, scheme_arena, mps_rank_ambig(), 0,
|
||||
thread, mps_stack_scan_ambig, marker, 0);
|
||||
res = mps_root_create_thread(®_root, scheme_arena, thread, marker);
|
||||
if (res != MPS_RES_OK)
|
||||
error("Couldn't create root");
|
||||
}
|
||||
|
|
@ -164,7 +163,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (c) 2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (c) 2014-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ static mps_gen_param_s testChain[genCOUNT] = {
|
|||
#define objNULL ((mps_addr_t)MPS_WORD_CONST(0xDECEA5ED))
|
||||
|
||||
|
||||
static mps_arena_t arena;
|
||||
static mps_ap_t ap;
|
||||
static mps_addr_t exactRoots[exactRootsCOUNT];
|
||||
static mps_addr_t ambigRoots[ambigRootsCOUNT];
|
||||
|
|
@ -51,7 +52,7 @@ static unsigned long nCollsDone;
|
|||
|
||||
/* report -- report statistics from any messages */
|
||||
|
||||
static void report(mps_arena_t arena)
|
||||
static void report(void)
|
||||
{
|
||||
mps_message_type_t type;
|
||||
|
||||
|
|
@ -103,8 +104,10 @@ static mps_addr_t make(size_t rootsCount)
|
|||
|
||||
do {
|
||||
MPS_RESERVE_BLOCK(res, p, ap, size);
|
||||
if (res)
|
||||
if (res) {
|
||||
ArenaDescribe(arena, mps_lib_get_stderr(), 4);
|
||||
die(res, "MPS_RESERVE_BLOCK");
|
||||
}
|
||||
res = dylan_init(p, size, exactRoots, rootsCount);
|
||||
if (res)
|
||||
die(res, "dylan_init");
|
||||
|
|
@ -127,8 +130,7 @@ static void test_stepper(mps_addr_t object, mps_fmt_t fmt, mps_pool_t pool,
|
|||
|
||||
/* test -- the body of the test */
|
||||
|
||||
static void test(mps_arena_t arena, mps_pool_class_t pool_class,
|
||||
size_t roots_count)
|
||||
static void test(mps_pool_class_t pool_class, size_t roots_count)
|
||||
{
|
||||
mps_fmt_t format;
|
||||
mps_chain_t chain;
|
||||
|
|
@ -180,7 +182,7 @@ static void test(mps_arena_t arena, mps_pool_class_t pool_class,
|
|||
while (collections < collectionsCOUNT) {
|
||||
size_t r;
|
||||
|
||||
report(arena);
|
||||
report();
|
||||
if (collections != nCollsStart) {
|
||||
if (!described) {
|
||||
die(ArenaDescribe(arena, mps_lib_get_stdout(), 0), "ArenaDescribe");
|
||||
|
|
@ -276,7 +278,7 @@ static void test(mps_arena_t arena, mps_pool_class_t pool_class,
|
|||
*(int*)busy_init = -1; /* check that the buffer is still there */
|
||||
|
||||
if (objs % 1024 == 0) {
|
||||
report(arena);
|
||||
report();
|
||||
putchar('.');
|
||||
(void)fflush(stdout);
|
||||
}
|
||||
|
|
@ -299,7 +301,6 @@ static void test(mps_arena_t arena, mps_pool_class_t pool_class,
|
|||
int main(int argc, char *argv[])
|
||||
{
|
||||
size_t i, grainSize;
|
||||
mps_arena_t arena;
|
||||
mps_thr_t thread;
|
||||
|
||||
testlib_init(argc, argv);
|
||||
|
|
@ -316,12 +317,11 @@ int main(int argc, char *argv[])
|
|||
} MPS_ARGS_END(args);
|
||||
mps_message_type_enable(arena, mps_message_type_gc());
|
||||
mps_message_type_enable(arena, mps_message_type_gc_start());
|
||||
die(mps_arena_commit_limit_set(arena, scale * testArenaSIZE), "set limit");
|
||||
die(mps_thread_reg(&thread, arena), "thread_reg");
|
||||
test(arena, mps_class_amc(), exactRootsCOUNT);
|
||||
test(arena, mps_class_amcz(), 0);
|
||||
test(mps_class_amc(), exactRootsCOUNT);
|
||||
test(mps_class_amcz(), 0);
|
||||
mps_thread_dereg(thread);
|
||||
report(arena);
|
||||
report();
|
||||
mps_arena_destroy(arena);
|
||||
|
||||
printf("%s: Conclusion: Failed to find any defects.\n", argv[0]);
|
||||
|
|
|
|||
|
|
@ -254,7 +254,6 @@ int main(int argc, char *argv[])
|
|||
die(mps_arena_create_k(&arena, mps_arena_class_vm(), args), "arena_create");
|
||||
} MPS_ARGS_END(args);
|
||||
mps_message_type_enable(arena, mps_message_type_gc());
|
||||
die(mps_arena_commit_limit_set(arena, testArenaSIZE), "set limit");
|
||||
die(mps_thread_reg(&thread, arena), "thread_reg");
|
||||
test(arena, mps_class_amc(), exactRootsCOUNT);
|
||||
test(arena, mps_class_amcz(), 0);
|
||||
|
|
|
|||
|
|
@ -1,21 +1,13 @@
|
|||
/* amcssth.c: POOL CLASS AMC STRESS TEST WITH TWO THREADS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (c) 2002 Global Graphics Software.
|
||||
*
|
||||
* .mode: This test case has two modes:
|
||||
*
|
||||
* .mode.walk: In this mode, the main thread parks the arena half way
|
||||
* through the test case and runs mps_arena_formatted_objects_walk().
|
||||
* This checks that walking works while the other threads continue to
|
||||
* allocate in the background.
|
||||
*
|
||||
* .mode.commit: In this mode, the arena's commit limit is set. This
|
||||
* checks that the MPS can make progress inside a tight limit in the
|
||||
* presence of allocation on multiple threads. But this is
|
||||
* incompatible with .mode.walk: if the arena is parked, then the
|
||||
* arena has no chance to make progress.
|
||||
* The main thread parks the arena half way through the test case and
|
||||
* runs mps_arena_formatted_objects_walk(). This checks that walking
|
||||
* works while the other threads continue to allocate in the
|
||||
* background.
|
||||
*/
|
||||
|
||||
#include "fmtdy.h"
|
||||
|
|
@ -28,11 +20,6 @@
|
|||
|
||||
#include <stdio.h> /* fflush, printf, putchar */
|
||||
|
||||
enum {
|
||||
ModeWALK = 0, /* .mode.walk */
|
||||
ModeCOMMIT = 1 /* .mode.commit */
|
||||
};
|
||||
|
||||
|
||||
/* These values have been tuned in the hope of getting one dynamic collection. */
|
||||
#define testArenaSIZE ((size_t)1000*1024)
|
||||
|
|
@ -139,8 +126,8 @@ static void *kid_thread(void *arg)
|
|||
closure_t cl = arg;
|
||||
|
||||
die(mps_thread_reg(&thread, (mps_arena_t)arena), "thread_reg");
|
||||
die(mps_root_create_reg(®_root, arena, mps_rank_ambig(), 0, thread,
|
||||
mps_stack_scan_ambig, marker, 0), "root_create");
|
||||
die(mps_root_create_thread(®_root, arena, thread, marker),
|
||||
"root_create");
|
||||
|
||||
die(mps_ap_create(&ap, cl->pool, mps_rank_exact()), "BufferCreate(fooey)");
|
||||
while(mps_collections(arena) < collectionsCOUNT) {
|
||||
|
|
@ -157,8 +144,7 @@ static void *kid_thread(void *arg)
|
|||
|
||||
/* test -- the body of the test */
|
||||
|
||||
static void test_pool(const char *name, mps_pool_t pool, size_t roots_count,
|
||||
int mode)
|
||||
static void test_pool(const char *name, mps_pool_t pool, size_t roots_count)
|
||||
{
|
||||
size_t i;
|
||||
mps_word_t rampSwitch;
|
||||
|
|
@ -170,8 +156,7 @@ static void test_pool(const char *name, mps_pool_t pool, size_t roots_count,
|
|||
closure_s cl;
|
||||
int walked = FALSE, ramped = FALSE;
|
||||
|
||||
printf("\n------ mode: %s pool: %s-------\n",
|
||||
mode == ModeWALK ? "WALK" : "COMMIT", name);
|
||||
printf("\n------ pool: %s-------\n", name);
|
||||
|
||||
cl.pool = pool;
|
||||
cl.roots_count = roots_count;
|
||||
|
|
@ -217,7 +202,7 @@ static void test_pool(const char *name, mps_pool_t pool, size_t roots_count,
|
|||
cdie(exactRoots[i] == objNULL || dylan_check(exactRoots[i]),
|
||||
"all roots check");
|
||||
|
||||
if (mode == ModeWALK && collections >= collectionsCOUNT / 2 && !walked)
|
||||
if (collections >= collectionsCOUNT / 2 && !walked)
|
||||
{
|
||||
unsigned long count = 0;
|
||||
mps_arena_park(arena);
|
||||
|
|
@ -278,7 +263,7 @@ static void test_pool(const char *name, mps_pool_t pool, size_t roots_count,
|
|||
testthr_join(&kids[i], NULL);
|
||||
}
|
||||
|
||||
static void test_arena(int mode)
|
||||
static void test_arena(void)
|
||||
{
|
||||
size_t i;
|
||||
mps_fmt_t format;
|
||||
|
|
@ -293,8 +278,6 @@ static void test_arena(int mode)
|
|||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_GRAIN_SIZE, rnd_grain(testArenaSIZE));
|
||||
die(mps_arena_create_k(&arena, mps_arena_class_vm(), args), "arena_create");
|
||||
} MPS_ARGS_END(args);
|
||||
if (mode == ModeCOMMIT)
|
||||
die(mps_arena_commit_limit_set(arena, 2 * testArenaSIZE), "set limit");
|
||||
mps_message_type_enable(arena, mps_message_type_gc());
|
||||
mps_message_type_enable(arena, mps_message_type_gc_start());
|
||||
|
||||
|
|
@ -316,16 +299,16 @@ static void test_arena(int mode)
|
|||
&ambigRoots[0], ambigRootsCOUNT),
|
||||
"root_create_table(ambig)");
|
||||
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");
|
||||
die(mps_root_create_thread(®_root, arena, thread, marker),
|
||||
"root_create");
|
||||
|
||||
die(mps_pool_create(&amc_pool, arena, mps_class_amc(), format, chain),
|
||||
"pool_create(amc)");
|
||||
die(mps_pool_create(&amcz_pool, arena, mps_class_amcz(), format, chain),
|
||||
"pool_create(amcz)");
|
||||
|
||||
test_pool("AMC", amc_pool, exactRootsCOUNT, mode);
|
||||
test_pool("AMCZ", amcz_pool, 0, mode);
|
||||
test_pool("AMC", amc_pool, exactRootsCOUNT);
|
||||
test_pool("AMCZ", amcz_pool, 0);
|
||||
|
||||
mps_arena_park(arena);
|
||||
mps_pool_destroy(amc_pool);
|
||||
|
|
@ -342,8 +325,7 @@ static void test_arena(int mode)
|
|||
int main(int argc, char *argv[])
|
||||
{
|
||||
testlib_init(argc, argv);
|
||||
test_arena(ModeWALK);
|
||||
test_arena(ModeCOMMIT);
|
||||
test_arena();
|
||||
|
||||
printf("%s: Conclusion: Failed to find any defects.\n", argv[0]);
|
||||
return 0;
|
||||
|
|
@ -352,7 +334,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -211,7 +211,6 @@ int main(int argc, char *argv[])
|
|||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_GRAIN_SIZE, rnd_grain(testArenaSIZE));
|
||||
die(mps_arena_create_k(&arena, mps_arena_class_vm(), args), "arena_create");
|
||||
} MPS_ARGS_END(args);
|
||||
die(mps_arena_commit_limit_set(arena, 2 * testArenaSIZE), "commit_limit_set");
|
||||
|
||||
mps_message_type_enable(arena, mps_message_type_gc_start());
|
||||
mps_message_type_enable(arena, mps_message_type_gc());
|
||||
|
|
|
|||
|
|
@ -16,8 +16,9 @@ MPMPF = \
|
|||
[than] \
|
||||
[vman]
|
||||
|
||||
!INCLUDE commpre.nmk
|
||||
!INCLUDE mv.nmk
|
||||
!INCLUDE comm.nmk
|
||||
!INCLUDE commpost.nmk
|
||||
|
||||
|
||||
# C. COPYRIGHT AND LICENSE
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#define testArenaSIZE ((((size_t)3)<<24) - 4)
|
||||
#define testSetSIZE 200
|
||||
#define testLOOPS 10
|
||||
#define MAX_ALIGN 64 /* TODO: Make this test work up to arena_grain_size? */
|
||||
|
||||
|
||||
/* make -- allocate one object */
|
||||
|
|
@ -87,6 +88,14 @@ static mps_res_t stress(mps_arena_t arena, mps_pool_debug_option_s *options,
|
|||
check_allocated_size(pool, ap, allocated);
|
||||
}
|
||||
|
||||
/* Check introspection functions */
|
||||
for (i = 0; i < NELEMS(ps); ++i) {
|
||||
mps_pool_t addr_pool = NULL;
|
||||
Insist(mps_arena_has_addr(arena, ps[i]));
|
||||
Insist(mps_addr_pool(&addr_pool, arena, ps[i]));
|
||||
Insist(addr_pool == pool);
|
||||
}
|
||||
|
||||
mps_pool_check_fenceposts(pool);
|
||||
|
||||
for (k=0; k<testLOOPS; ++k) {
|
||||
|
|
@ -156,12 +165,21 @@ static mps_pool_debug_option_s fenceOptions = {
|
|||
};
|
||||
|
||||
|
||||
/* testInArena -- test all the pool classes in the given arena */
|
||||
/* test -- create arena using given class and arguments; test all the
|
||||
* pool classes in this arena
|
||||
*/
|
||||
|
||||
static void testInArena(mps_arena_t arena, mps_pool_debug_option_s *options)
|
||||
static void test(mps_arena_class_t arena_class, mps_arg_s arena_args[],
|
||||
size_t arena_grain_size,
|
||||
mps_pool_debug_option_s *options)
|
||||
{
|
||||
mps_arena_t arena;
|
||||
die(mps_arena_create_k(&arena, arena_class, arena_args), "mps_arena_create");
|
||||
|
||||
(void)arena_grain_size; /* TODO: test larger alignments up to this */
|
||||
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
mps_align_t align = sizeof(void *) << (rnd() % 4);
|
||||
mps_align_t align = rnd_align(sizeof(void *), MAX_ALIGN);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ALIGN, align);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_ARENA_HIGH, TRUE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_MVFF_SLOT_HIGH, TRUE);
|
||||
|
|
@ -171,18 +189,19 @@ static void testInArena(mps_arena_t arena, mps_pool_debug_option_s *options)
|
|||
mps_class_mvff(), args), "stress MVFF");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
/* IWBN to test MVFFDebug, but the MPS doesn't support debugging APs, */
|
||||
/* yet (MV Debug works here, because it fakes it through PoolAlloc). */
|
||||
/* IWBN to test MVFFDebug, but the MPS doesn't support debugging
|
||||
APs, yet (MV Debug works here, because it fakes it through
|
||||
PoolAlloc). See job003995. */
|
||||
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
mps_align_t align = (mps_align_t)1 << (rnd() % 6);
|
||||
mps_align_t align = rnd_align(sizeof(void *), MAX_ALIGN);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ALIGN, align);
|
||||
die(stress(arena, NULL, align, randomSizeAligned, "MV",
|
||||
mps_class_mv(), args), "stress MV");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
mps_align_t align = (mps_align_t)1 << (rnd() % 6);
|
||||
mps_align_t align = rnd_align(sizeof(void *), MAX_ALIGN);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ALIGN, align);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_POOL_DEBUG_OPTIONS, options);
|
||||
die(stress(arena, options, align, randomSizeAligned, "MV debug",
|
||||
|
|
@ -190,50 +209,48 @@ static void testInArena(mps_arena_t arena, mps_pool_debug_option_s *options)
|
|||
} MPS_ARGS_END(args);
|
||||
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
mps_align_t align = sizeof(void *) << (rnd() % 4);
|
||||
mps_align_t align = rnd_align(sizeof(void *), MAX_ALIGN);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ALIGN, align);
|
||||
die(stress(arena, NULL, align, randomSizeAligned, "MVT",
|
||||
mps_class_mvt(), args), "stress MVT");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
/* Manual allocation should not cause any garbage collections. */
|
||||
Insist(mps_collections(arena) == 0);
|
||||
mps_arena_destroy(arena);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
mps_arena_t arena;
|
||||
|
||||
size_t arena_grain_size;
|
||||
|
||||
testlib_init(argc, argv);
|
||||
|
||||
arena_grain_size = rnd_grain(2 * testArenaSIZE);
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, 2 * testArenaSIZE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_GRAIN_SIZE, rnd_grain(2*testArenaSIZE));
|
||||
die(mps_arena_create_k(&arena, mps_arena_class_vm(), args),
|
||||
"mps_arena_create");
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_GRAIN_SIZE, arena_grain_size);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_COMMIT_LIMIT, testArenaSIZE);
|
||||
test(mps_arena_class_vm(), args, arena_grain_size, &fenceOptions);
|
||||
} MPS_ARGS_END(args);
|
||||
die(mps_arena_commit_limit_set(arena, testArenaSIZE), "commit limit");
|
||||
testInArena(arena, &fenceOptions);
|
||||
mps_arena_destroy(arena);
|
||||
|
||||
arena_grain_size = rnd_grain(2 * testArenaSIZE);
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, 2 * testArenaSIZE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_ZONED, FALSE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_GRAIN_SIZE, rnd_grain(2*testArenaSIZE));
|
||||
die(mps_arena_create_k(&arena, mps_arena_class_vm(), args),
|
||||
"mps_arena_create");
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_GRAIN_SIZE, arena_grain_size);
|
||||
test(mps_arena_class_vm(), args, arena_grain_size, &bothOptions);
|
||||
} MPS_ARGS_END(args);
|
||||
testInArena(arena, &bothOptions);
|
||||
mps_arena_destroy(arena);
|
||||
|
||||
arena_grain_size = rnd_grain(testArenaSIZE);
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, testArenaSIZE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_ZONED, FALSE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_CL_BASE, malloc(testArenaSIZE));
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_GRAIN_SIZE, rnd_grain(testArenaSIZE));
|
||||
die(mps_arena_create_k(&arena, mps_arena_class_cl(), args),
|
||||
"mps_arena_create");
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_GRAIN_SIZE, arena_grain_size);
|
||||
test(mps_arena_class_cl(), args, arena_grain_size, &bothOptions);
|
||||
} MPS_ARGS_END(args);
|
||||
testInArena(arena, &bothOptions);
|
||||
mps_arena_destroy(arena);
|
||||
|
||||
printf("%s: Conclusion: Failed to find any defects.\n", argv[0]);
|
||||
return 0;
|
||||
|
|
|
|||
266
mps/code/arena.c
266
mps/code/arena.c
|
|
@ -138,7 +138,6 @@ Bool ArenaCheck(Arena arena)
|
|||
CHECKL(BoolCheck(arena->poolReady));
|
||||
if (arena->poolReady) { /* <design/arena/#pool.ready> */
|
||||
CHECKD(MV, &arena->controlPoolStruct);
|
||||
CHECKD(Reservoir, &arena->reservoirStruct);
|
||||
}
|
||||
|
||||
/* .reserved.check: Would like to check that arena->committed <=
|
||||
|
|
@ -149,6 +148,7 @@ Bool ArenaCheck(Arena arena)
|
|||
*/
|
||||
CHECKL(arena->committed <= arena->commitLimit);
|
||||
CHECKL(arena->spareCommitted <= arena->committed);
|
||||
CHECKL(0.0 <= arena->pauseTime);
|
||||
|
||||
CHECKL(ShiftCheck(arena->zoneShift));
|
||||
CHECKL(ArenaGrainSizeCheck(arena->grainSize));
|
||||
|
|
@ -197,6 +197,9 @@ Res ArenaInit(Arena arena, ArenaClass class, Size grainSize, ArgList args)
|
|||
{
|
||||
Res res;
|
||||
Bool zoned = ARENA_DEFAULT_ZONED;
|
||||
Size commitLimit = ARENA_DEFAULT_COMMIT_LIMIT;
|
||||
Size spareCommitLimit = ARENA_DEFAULT_SPARE_COMMIT_LIMIT;
|
||||
double pauseTime = ARENA_DEFAULT_PAUSE_TIME;
|
||||
mps_arg_s arg;
|
||||
|
||||
AVER(arena != NULL);
|
||||
|
|
@ -205,16 +208,21 @@ Res ArenaInit(Arena arena, ArenaClass class, Size grainSize, ArgList args)
|
|||
|
||||
if (ArgPick(&arg, args, MPS_KEY_ARENA_ZONED))
|
||||
zoned = arg.val.b;
|
||||
if (ArgPick(&arg, args, MPS_KEY_COMMIT_LIMIT))
|
||||
commitLimit = arg.val.size;
|
||||
if (ArgPick(&arg, args, MPS_KEY_SPARE_COMMIT_LIMIT))
|
||||
spareCommitLimit = arg.val.size;
|
||||
if (ArgPick(&arg, args, MPS_KEY_PAUSE_TIME))
|
||||
pauseTime = arg.val.d;
|
||||
|
||||
arena->class = class;
|
||||
|
||||
arena->reserved = (Size)0;
|
||||
arena->committed = (Size)0;
|
||||
/* commitLimit may be overridden by init (but probably not */
|
||||
/* as there's not much point) */
|
||||
arena->commitLimit = (Size)-1;
|
||||
arena->commitLimit = commitLimit;
|
||||
arena->spareCommitted = (Size)0;
|
||||
arena->spareCommitLimit = ARENA_INIT_SPARE_COMMIT_LIMIT;
|
||||
arena->spareCommitLimit = spareCommitLimit;
|
||||
arena->pauseTime = pauseTime;
|
||||
arena->grainSize = grainSize;
|
||||
/* zoneShift is usually overridden by init */
|
||||
arena->zoneShift = ARENA_ZONESHIFT;
|
||||
|
|
@ -255,16 +263,9 @@ Res ArenaInit(Arena arena, ArenaClass class, Size grainSize, ArgList args)
|
|||
if (res != ResOK)
|
||||
goto failMFSInit;
|
||||
|
||||
/* initialize the reservoir, <design/reservoir/> */
|
||||
res = ReservoirInit(&arena->reservoirStruct, arena);
|
||||
if (res != ResOK)
|
||||
goto failReservoirInit;
|
||||
|
||||
AVERT(Arena, arena);
|
||||
return ResOK;
|
||||
|
||||
failReservoirInit:
|
||||
PoolFinish(ArenaCBSBlockPool(arena));
|
||||
failMFSInit:
|
||||
GlobalsFinish(ArenaGlobals(arena));
|
||||
failGlobalsInit:
|
||||
|
|
@ -285,9 +286,12 @@ ARG_DEFINE_KEY(VMW3_TOP_DOWN, Bool);
|
|||
|
||||
/* ArenaCreate -- create the arena and call initializers */
|
||||
|
||||
ARG_DEFINE_KEY(ARENA_SIZE, Size);
|
||||
ARG_DEFINE_KEY(ARENA_GRAIN_SIZE, Size);
|
||||
ARG_DEFINE_KEY(ARENA_SIZE, Size);
|
||||
ARG_DEFINE_KEY(ARENA_ZONED, Bool);
|
||||
ARG_DEFINE_KEY(COMMIT_LIMIT, Size);
|
||||
ARG_DEFINE_KEY(SPARE_COMMIT_LIMIT, Size);
|
||||
ARG_DEFINE_KEY(PAUSE_TIME, double);
|
||||
|
||||
static Res arenaFreeLandInit(Arena arena)
|
||||
{
|
||||
|
|
@ -388,7 +392,6 @@ Res ArenaCreate(Arena *arenaReturn, ArenaClass class, ArgList args)
|
|||
void ArenaFinish(Arena arena)
|
||||
{
|
||||
PoolFinish(ArenaCBSBlockPool(arena));
|
||||
ReservoirFinish(ArenaReservoir(arena));
|
||||
arena->sig = SigInvalid;
|
||||
GlobalsFinish(ArenaGlobals(arena));
|
||||
LocusFinish(arena);
|
||||
|
|
@ -400,13 +403,11 @@ void ArenaFinish(Arena arena)
|
|||
/* ArenaDestroy -- destroy the arena */
|
||||
|
||||
static void arenaMFSPageFreeVisitor(Pool pool, Addr base, Size size,
|
||||
void *closureP, Size closureS)
|
||||
void *closure)
|
||||
{
|
||||
AVERT(Pool, pool);
|
||||
AVER(closureP == UNUSED_POINTER);
|
||||
AVER(closureS == UNUSED_SIZE);
|
||||
UNUSED(closureP);
|
||||
UNUSED(closureS);
|
||||
AVER(closure == UNUSED_POINTER);
|
||||
UNUSED(closure);
|
||||
UNUSED(size);
|
||||
AVER(size == ArenaGrainSize(PoolArena(pool)));
|
||||
arenaFreePage(PoolArena(pool), base, pool);
|
||||
|
|
@ -417,10 +418,15 @@ static void arenaFreeLandFinish(Arena arena)
|
|||
AVERT(Arena, arena);
|
||||
AVER(arena->hasFreeLand);
|
||||
|
||||
/* We're about to free the memory occupied by the free land, which
|
||||
contains a CBS. We want to make sure that LandFinish doesn't try
|
||||
to check the CBS, so nuke it here. TODO: LandReset? */
|
||||
arena->freeLandStruct.splayTreeStruct.root = TreeEMPTY;
|
||||
|
||||
/* The CBS block pool can't free its own memory via ArenaFree because
|
||||
* that would use the free land. */
|
||||
MFSFinishTracts(ArenaCBSBlockPool(arena), arenaMFSPageFreeVisitor,
|
||||
UNUSED_POINTER, UNUSED_SIZE);
|
||||
UNUSED_POINTER);
|
||||
|
||||
arena->hasFreeLand = FALSE;
|
||||
LandFinish(ArenaFreeLand(arena));
|
||||
|
|
@ -432,9 +438,6 @@ void ArenaDestroy(Arena arena)
|
|||
|
||||
GlobalsPrepareToDestroy(ArenaGlobals(arena));
|
||||
|
||||
/* Empty the reservoir - see <code/reserv.c#reservoir.finish> */
|
||||
ReservoirSetLimit(ArenaReservoir(arena), 0);
|
||||
|
||||
ControlFinish(arena);
|
||||
|
||||
/* We must tear down the free land before the chunks, because pages
|
||||
|
|
@ -635,8 +638,7 @@ Res ArenaDescribeTracts(Arena arena, mps_lib_FILE *stream, Count depth)
|
|||
* with void* (<design/type/#addr.use>), ControlAlloc must take care of
|
||||
* allocating so that the block can be addressed with a void*. */
|
||||
|
||||
Res ControlAlloc(void **baseReturn, Arena arena, size_t size,
|
||||
Bool withReservoirPermit)
|
||||
Res ControlAlloc(void **baseReturn, Arena arena, size_t size)
|
||||
{
|
||||
Addr base;
|
||||
Res res;
|
||||
|
|
@ -644,11 +646,9 @@ Res ControlAlloc(void **baseReturn, Arena arena, size_t size,
|
|||
AVERT(Arena, arena);
|
||||
AVER(baseReturn != NULL);
|
||||
AVER(size > 0);
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
AVER(arena->poolReady);
|
||||
|
||||
res = PoolAlloc(&base, ArenaControlPool(arena), (Size)size,
|
||||
withReservoirPermit);
|
||||
res = PoolAlloc(&base, ArenaControlPool(arena), (Size)size);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
|
|
@ -747,7 +747,7 @@ void ArenaChunkRemoved(Arena arena, Chunk chunk)
|
|||
* This is a primitive allocator used to allocate pages for the arena
|
||||
* Land. It is called rarely and can use a simple search. It may not
|
||||
* use the Land or any pool, because it is used as part of the
|
||||
* bootstrap.
|
||||
* bootstrap. See design.mps.bootstrap.land.sol.alloc.
|
||||
*/
|
||||
|
||||
static Res arenaAllocPageInChunk(Addr *baseReturn, Chunk chunk, Pool pool)
|
||||
|
|
@ -855,7 +855,7 @@ static void arenaExcludePage(Arena arena, Range pageRange)
|
|||
* The arena's free land can't get memory for its block pool in the
|
||||
* usual way (via ArenaAlloc), because it is the mechanism behind
|
||||
* ArenaAlloc! So we extend the block pool via a back door (see
|
||||
* arenaExtendCBSBlockPool).
|
||||
* arenaExtendCBSBlockPool). See design.mps.bootstrap.land.sol.pool.
|
||||
*
|
||||
* Only fails if it can't get a page for the block pool.
|
||||
*/
|
||||
|
|
@ -993,22 +993,32 @@ void ArenaFreeLandDelete(Arena arena, Addr base, Addr limit)
|
|||
}
|
||||
|
||||
|
||||
static Res arenaAllocFromLand(Tract *tractReturn, ZoneSet zones, Bool high,
|
||||
Size size, Pool pool)
|
||||
/* ArenaFreeLandAlloc -- allocate a continguous range of tracts of
|
||||
* size bytes from the arena's free land.
|
||||
*
|
||||
* size, zones, and high are as for LandFindInZones.
|
||||
*
|
||||
* If successful, mark the allocated tracts as belonging to pool, set
|
||||
* *tractReturn to point to the first tract in the range, and return
|
||||
* ResOK.
|
||||
*/
|
||||
|
||||
Res ArenaFreeLandAlloc(Tract *tractReturn, Arena arena, ZoneSet zones,
|
||||
Bool high, Size size, Pool pool)
|
||||
{
|
||||
Arena arena;
|
||||
RangeStruct range, oldRange;
|
||||
Chunk chunk;
|
||||
Chunk chunk = NULL; /* suppress uninit warning */
|
||||
Bool found, b;
|
||||
Index baseIndex;
|
||||
Count pages;
|
||||
Res res;
|
||||
|
||||
AVER(tractReturn != NULL);
|
||||
AVERT(Arena, arena);
|
||||
/* ZoneSet is arbitrary */
|
||||
AVER(size > (Size)0);
|
||||
AVERT(Pool, pool);
|
||||
arena = PoolArena(pool);
|
||||
AVER(arena == PoolArena(pool));
|
||||
AVER(SizeIsArenaGrains(size, arena));
|
||||
|
||||
if (!arena->zoned)
|
||||
|
|
@ -1067,146 +1077,27 @@ static Res arenaAllocFromLand(Tract *tractReturn, ZoneSet zones, Bool high,
|
|||
}
|
||||
|
||||
|
||||
/* arenaAllocPolicy -- arena allocation policy implementation
|
||||
*
|
||||
* This is the code responsible for making decisions about where to allocate
|
||||
* memory. Avoid distributing code for doing this elsewhere, so that policy
|
||||
* can be maintained and adjusted.
|
||||
*
|
||||
* TODO: This currently duplicates the policy from VMAllocPolicy in
|
||||
* //info.ravenbrook.com/project/mps/master/code/arenavm.c#36 in order
|
||||
* to avoid disruption to clients, but needs revision.
|
||||
*/
|
||||
|
||||
static Res arenaAllocPolicy(Tract *tractReturn, Arena arena, LocusPref pref,
|
||||
Size size, Pool pool)
|
||||
{
|
||||
Res res;
|
||||
Tract tract;
|
||||
ZoneSet zones, moreZones, evenMoreZones;
|
||||
|
||||
AVER(tractReturn != NULL);
|
||||
AVERT(LocusPref, pref);
|
||||
AVER(size > (Size)0);
|
||||
AVERT(Pool, pool);
|
||||
|
||||
/* Don't attempt to allocate if doing so would definitely exceed the
|
||||
commit limit. */
|
||||
if (arena->spareCommitted < size) {
|
||||
Size necessaryCommitIncrease = size - arena->spareCommitted;
|
||||
if (arena->committed + necessaryCommitIncrease > arena->commitLimit
|
||||
|| arena->committed + necessaryCommitIncrease < arena->committed) {
|
||||
return ResCOMMIT_LIMIT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Plan A: allocate from the free Land in the requested zones */
|
||||
zones = ZoneSetDiff(pref->zones, pref->avoid);
|
||||
if (zones != ZoneSetEMPTY) {
|
||||
res = arenaAllocFromLand(&tract, zones, pref->high, size, pool);
|
||||
if (res == ResOK)
|
||||
goto found;
|
||||
}
|
||||
|
||||
/* Plan B: add free zones that aren't blacklisted */
|
||||
/* TODO: Pools without ambiguous roots might not care about the blacklist. */
|
||||
/* TODO: zones are precious and (currently) never deallocated, so we
|
||||
should consider extending the arena first if address space is plentiful.
|
||||
See also job003384. */
|
||||
moreZones = ZoneSetUnion(pref->zones, ZoneSetDiff(arena->freeZones, pref->avoid));
|
||||
if (moreZones != zones) {
|
||||
res = arenaAllocFromLand(&tract, moreZones, pref->high, size, pool);
|
||||
if (res == ResOK)
|
||||
goto found;
|
||||
}
|
||||
|
||||
/* Plan C: Extend the arena, then try A and B again. */
|
||||
if (moreZones != ZoneSetEMPTY) {
|
||||
res = arena->class->grow(arena, pref, size);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
if (zones != ZoneSetEMPTY) {
|
||||
res = arenaAllocFromLand(&tract, zones, pref->high, size, pool);
|
||||
if (res == ResOK)
|
||||
goto found;
|
||||
}
|
||||
if (moreZones != zones) {
|
||||
zones = ZoneSetUnion(zones, ZoneSetDiff(arena->freeZones, pref->avoid));
|
||||
res = arenaAllocFromLand(&tract, moreZones, pref->high, size, pool);
|
||||
if (res == ResOK)
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
|
||||
/* Plan D: add every zone that isn't blacklisted. This might mix GC'd
|
||||
objects with those from other generations, causing the zone check
|
||||
to give false positives and slowing down the collector. */
|
||||
/* TODO: log an event for this */
|
||||
evenMoreZones = ZoneSetDiff(ZoneSetUNIV, pref->avoid);
|
||||
if (evenMoreZones != moreZones) {
|
||||
res = arenaAllocFromLand(&tract, evenMoreZones, pref->high, size, pool);
|
||||
if (res == ResOK)
|
||||
goto found;
|
||||
}
|
||||
|
||||
/* Last resort: try anywhere. This might put GC'd objects in zones where
|
||||
common ambiguous bit patterns pin them down, causing the zone check
|
||||
to give even more false positives permanently, and possibly retaining
|
||||
garbage indefinitely. */
|
||||
res = arenaAllocFromLand(&tract, ZoneSetUNIV, pref->high, size, pool);
|
||||
if (res == ResOK)
|
||||
goto found;
|
||||
|
||||
/* Uh oh. */
|
||||
return res;
|
||||
|
||||
found:
|
||||
*tractReturn = tract;
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
||||
/* ArenaAlloc -- allocate some tracts from the arena */
|
||||
|
||||
Res ArenaAlloc(Addr *baseReturn, LocusPref pref, Size size, Pool pool,
|
||||
Bool withReservoirPermit)
|
||||
Res ArenaAlloc(Addr *baseReturn, LocusPref pref, Size size, Pool pool)
|
||||
{
|
||||
Res res;
|
||||
Arena arena;
|
||||
Addr base;
|
||||
Tract tract;
|
||||
Reservoir reservoir;
|
||||
|
||||
AVER(baseReturn != NULL);
|
||||
AVERT(LocusPref, pref);
|
||||
AVER(size > (Size)0);
|
||||
AVERT(Pool, pool);
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
arena = PoolArena(pool);
|
||||
AVERT(Arena, arena);
|
||||
AVER(SizeIsArenaGrains(size, arena));
|
||||
reservoir = ArenaReservoir(arena);
|
||||
AVERT(Reservoir, reservoir);
|
||||
|
||||
if (pool != ReservoirPool(reservoir)) {
|
||||
res = ReservoirEnsureFull(reservoir);
|
||||
if (res != ResOK) {
|
||||
AVER(ResIsAllocFailure(res));
|
||||
if (!withReservoirPermit)
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
res = arenaAllocPolicy(&tract, arena, pref, size, pool);
|
||||
if (res != ResOK) {
|
||||
if (withReservoirPermit) {
|
||||
Res resRes = ReservoirWithdraw(&base, &tract, reservoir, size, pool);
|
||||
if (resRes != ResOK)
|
||||
goto allocFail;
|
||||
} else
|
||||
goto allocFail;
|
||||
}
|
||||
res = PolicyAlloc(&tract, arena, pref, size, pool);
|
||||
if (res != ResOK)
|
||||
goto allocFail;
|
||||
|
||||
base = TractBase(tract);
|
||||
|
||||
|
|
@ -1231,8 +1122,6 @@ void ArenaFree(Addr base, Size size, Pool pool)
|
|||
{
|
||||
Arena arena;
|
||||
Addr limit;
|
||||
Reservoir reservoir;
|
||||
Res res;
|
||||
Addr wholeBase;
|
||||
Size wholeSize;
|
||||
RangeStruct range, oldRange;
|
||||
|
|
@ -1242,8 +1131,6 @@ void ArenaFree(Addr base, Size size, Pool pool)
|
|||
AVER(size > (Size)0);
|
||||
arena = PoolArena(pool);
|
||||
AVERT(Arena, arena);
|
||||
reservoir = ArenaReservoir(arena);
|
||||
AVERT(Reservoir, reservoir);
|
||||
AVER(AddrIsArenaGrain(base, arena));
|
||||
AVER(SizeIsArenaGrains(size, arena));
|
||||
|
||||
|
|
@ -1257,18 +1144,6 @@ void ArenaFree(Addr base, Size size, Pool pool)
|
|||
wholeBase = base;
|
||||
wholeSize = size;
|
||||
|
||||
if (pool != ReservoirPool(reservoir)) {
|
||||
res = ReservoirEnsureFull(reservoir);
|
||||
if (res != ResOK) {
|
||||
AVER(ResIsAllocFailure(res));
|
||||
if (!ReservoirDeposit(reservoir, &base, &size))
|
||||
goto allDeposited;
|
||||
}
|
||||
}
|
||||
|
||||
/* Just in case the shenanigans with the reservoir mucked this up. */
|
||||
AVER(limit == AddrAdd(base, size));
|
||||
|
||||
RangeInit(&range, base, limit);
|
||||
|
||||
arenaFreeLandInsertSteal(&oldRange, arena, &range); /* may update range */
|
||||
|
|
@ -1278,7 +1153,6 @@ void ArenaFree(Addr base, Size size, Pool pool)
|
|||
/* Freeing memory might create spare pages, but not more than this. */
|
||||
CHECKL(arena->spareCommitted <= arena->spareCommitLimit);
|
||||
|
||||
allDeposited:
|
||||
EVENT3(ArenaFree, arena, wholeBase, wholeSize);
|
||||
return;
|
||||
}
|
||||
|
|
@ -1320,7 +1194,20 @@ void ArenaSetSpareCommitLimit(Arena arena, Size limit)
|
|||
}
|
||||
|
||||
EVENT2(SpareCommitLimitSet, arena, limit);
|
||||
return;
|
||||
}
|
||||
|
||||
double ArenaPauseTime(Arena arena)
|
||||
{
|
||||
AVERT(Arena, arena);
|
||||
return arena->pauseTime;
|
||||
}
|
||||
|
||||
void ArenaSetPauseTime(Arena arena, double pauseTime)
|
||||
{
|
||||
AVERT(Arena, arena);
|
||||
AVER(0.0 <= pauseTime);
|
||||
arena->pauseTime = pauseTime;
|
||||
EVENT2(PauseTimeSet, arena, pauseTime);
|
||||
}
|
||||
|
||||
/* Used by arenas which don't use spare committed memory */
|
||||
|
|
@ -1393,10 +1280,33 @@ Size ArenaAvail(Arena arena)
|
|||
this information from the operating system. It also depends on the
|
||||
arena class, of course. */
|
||||
|
||||
AVER(sSwap >= arena->committed);
|
||||
return sSwap - arena->committed + arena->spareCommitted;
|
||||
}
|
||||
|
||||
|
||||
/* ArenaCollectable -- return estimate of collectable memory in arena */
|
||||
|
||||
Size ArenaCollectable(Arena arena)
|
||||
{
|
||||
/* Conservative estimate -- see job003929. */
|
||||
Size committed = ArenaCommitted(arena);
|
||||
Size spareCommitted = ArenaSpareCommitted(arena);
|
||||
AVER(committed >= spareCommitted);
|
||||
return committed - spareCommitted;
|
||||
}
|
||||
|
||||
|
||||
/* ArenaAccumulateTime -- accumulate time spent tracing */
|
||||
|
||||
void ArenaAccumulateTime(Arena arena, Clock start, Clock end)
|
||||
{
|
||||
AVERT(Arena, arena);
|
||||
AVER(start <= end);
|
||||
arena->tracedTime += (end - start) / (double) ClocksPerSec();
|
||||
}
|
||||
|
||||
|
||||
/* ArenaExtend -- Add a new chunk in the arena */
|
||||
|
||||
Res ArenaExtend(Arena arena, Addr base, Size size)
|
||||
|
|
@ -1450,10 +1360,10 @@ static void ArenaTrivCompact(Arena arena, Trace trace)
|
|||
|
||||
Bool ArenaHasAddr(Arena arena, Addr addr)
|
||||
{
|
||||
Seg seg;
|
||||
Tract tract;
|
||||
|
||||
AVERT(Arena, arena);
|
||||
return SegOfAddr(&seg, arena, addr);
|
||||
return TractOfAddr(&tract, arena, addr);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ static Res ClientChunkInit(Chunk chunk, BootBlock boot)
|
|||
|
||||
/* clientChunkDestroy -- destroy a ClientChunk */
|
||||
|
||||
static Bool clientChunkDestroy(Tree tree, void *closureP, Size closureS)
|
||||
static Bool clientChunkDestroy(Tree tree, void *closure)
|
||||
{
|
||||
Arena arena;
|
||||
Chunk chunk;
|
||||
|
|
@ -190,10 +190,8 @@ static Bool clientChunkDestroy(Tree tree, void *closureP, Size closureS)
|
|||
Size size;
|
||||
|
||||
AVERT(Tree, tree);
|
||||
AVER(closureP == UNUSED_POINTER);
|
||||
UNUSED(closureP);
|
||||
AVER(closureS == UNUSED_SIZE);
|
||||
UNUSED(closureS);
|
||||
AVER(closure == UNUSED_POINTER);
|
||||
UNUSED(closure);
|
||||
|
||||
chunk = ChunkOfTree(tree);
|
||||
AVERT(Chunk, chunk);
|
||||
|
|
@ -337,7 +335,7 @@ static void ClientArenaFinish(Arena arena)
|
|||
* <design/arena/#chunk.delete> */
|
||||
arena->primary = NULL;
|
||||
TreeTraverseAndDelete(&arena->chunkTree, clientChunkDestroy,
|
||||
UNUSED_POINTER, UNUSED_SIZE);
|
||||
UNUSED_POINTER);
|
||||
|
||||
clientArena->sig = SigInvalid;
|
||||
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ static Res allocAsTract(AllocInfoStruct *aiReturn, LocusPref pref,
|
|||
{
|
||||
Res res;
|
||||
Addr base;
|
||||
res = ArenaAlloc(&base, pref, size, pool, FALSE);
|
||||
res = ArenaAlloc(&base, pref, size, pool);
|
||||
if (res == ResOK) {
|
||||
aiReturn->the.tractData.base = base;
|
||||
aiReturn->the.tractData.size = size;
|
||||
|
|
@ -249,7 +249,7 @@ static Res allocAsSeg(AllocInfoStruct *aiReturn, LocusPref pref,
|
|||
{
|
||||
Res res;
|
||||
Seg seg;
|
||||
res = SegAlloc(&seg, SegClassGet(), pref, size, pool, FALSE, argsNone);
|
||||
res = SegAlloc(&seg, SegClassGet(), pref, size, pool, argsNone);
|
||||
if (res == ResOK) {
|
||||
aiReturn->the.segData.seg = seg;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -409,16 +409,14 @@ static Res VMChunkInit(Chunk chunk, BootBlock boot)
|
|||
|
||||
/* vmChunkDestroy -- destroy a VMChunk */
|
||||
|
||||
static Bool vmChunkDestroy(Tree tree, void *closureP, Size closureS)
|
||||
static Bool vmChunkDestroy(Tree tree, void *closure)
|
||||
{
|
||||
Chunk chunk;
|
||||
VMChunk vmChunk;
|
||||
|
||||
AVERT(Tree, tree);
|
||||
AVER(closureP == UNUSED_POINTER);
|
||||
UNUSED(closureP);
|
||||
AVER(closureS == UNUSED_SIZE);
|
||||
UNUSED(closureS);
|
||||
AVER(closure == UNUSED_POINTER);
|
||||
UNUSED(closure);
|
||||
|
||||
chunk = ChunkOfTree(tree);
|
||||
AVERT(Chunk, chunk);
|
||||
|
|
@ -636,7 +634,7 @@ static void VMArenaFinish(Arena arena)
|
|||
* <design/arena/#chunk.delete> */
|
||||
arena->primary = NULL;
|
||||
TreeTraverseAndDelete(&arena->chunkTree, vmChunkDestroy,
|
||||
UNUSED_POINTER, UNUSED_SIZE);
|
||||
UNUSED_POINTER);
|
||||
|
||||
/* Destroying the chunks should have purged and removed all spare pages. */
|
||||
RingFinish(&vmArena->spareRing);
|
||||
|
|
@ -744,8 +742,8 @@ static Res VMArenaGrow(Arena arena, LocusPref pref, Size size)
|
|||
vmArenaGrow_Done:
|
||||
EVENT2(vmArenaExtendDone, chunkSize, ArenaReserved(VMArena2Arena(vmArena)));
|
||||
vmArena->extended(VMArena2Arena(vmArena),
|
||||
newChunk->base,
|
||||
AddrOffset(newChunk->base, newChunk->limit));
|
||||
newChunk->base,
|
||||
AddrOffset(newChunk->base, newChunk->limit));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
@ -992,7 +990,7 @@ static Size arenaUnmapSpare(Arena arena, Size size, Chunk filter)
|
|||
while (RingNext(node) != &vmArena->spareRing && purged < size) {
|
||||
Ring next = RingNext(node);
|
||||
Page page = PageOfSpareRing(next);
|
||||
Chunk chunk;
|
||||
Chunk chunk = NULL; /* suppress uninit warning */
|
||||
Bool b;
|
||||
/* Use the fact that the page table resides in the chunk to find the
|
||||
chunk that owns the page. */
|
||||
|
|
@ -1094,16 +1092,14 @@ static void VMFree(Addr base, Size size, Pool pool)
|
|||
|
||||
/* vmChunkCompact -- delete chunk if empty and not primary */
|
||||
|
||||
static Bool vmChunkCompact(Tree tree, void *closureP, Size closureS)
|
||||
static Bool vmChunkCompact(Tree tree, void *closure)
|
||||
{
|
||||
Chunk chunk;
|
||||
Arena arena = closureP;
|
||||
Arena arena = closure;
|
||||
VMArena vmArena;
|
||||
|
||||
AVERT(Tree, tree);
|
||||
AVERT(Arena, arena);
|
||||
AVER(closureS == UNUSED_SIZE);
|
||||
UNUSED(closureS);
|
||||
|
||||
vmArena = Arena2VMArena(arena);
|
||||
AVERT(VMArena, vmArena);
|
||||
|
|
@ -1117,7 +1113,7 @@ static Bool vmChunkCompact(Tree tree, void *closureP, Size closureS)
|
|||
/* Callback before destroying the chunk, as the arena is (briefly)
|
||||
invalid afterwards. See job003893. */
|
||||
(*vmArena->contracted)(arena, base, size);
|
||||
vmChunkDestroy(tree, UNUSED_POINTER, UNUSED_SIZE);
|
||||
vmChunkDestroy(tree, UNUSED_POINTER);
|
||||
return TRUE;
|
||||
} else {
|
||||
/* Keep this chunk. */
|
||||
|
|
@ -1140,8 +1136,7 @@ static void VMCompact(Arena arena, Trace trace)
|
|||
/* Destroy chunks that are completely free, but not the primary
|
||||
* chunk. See <design/arena/#chunk.delete>
|
||||
* TODO: add hysteresis here. See job003815. */
|
||||
TreeTraverseAndDelete(&arena->chunkTree, vmChunkCompact, arena,
|
||||
UNUSED_SIZE);
|
||||
TreeTraverseAndDelete(&arena->chunkTree, vmChunkCompact, arena);
|
||||
|
||||
{
|
||||
Size vmem0 = trace->preTraceArenaReserved;
|
||||
|
|
|
|||
|
|
@ -93,8 +93,8 @@ Bool ArgCheckRank(Arg arg) {
|
|||
}
|
||||
|
||||
Bool ArgCheckdouble(Arg arg) {
|
||||
/* It would be nice if we could check doubles with C89, but
|
||||
it doesn't have isfinite() etc. which are in C99. */
|
||||
/* Don't call isfinite() here because it's not in C89, and because
|
||||
infinity is a valid value for MPS_KEY_PAUSE_TIME. */
|
||||
UNUSED(arg);
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -267,8 +267,7 @@ static void *setup(void *v, size_t s)
|
|||
arena = guff->arena;
|
||||
thr = guff->thr;
|
||||
|
||||
die(mps_root_create_reg(&stack, arena, mps_rank_ambig(), 0, thr,
|
||||
mps_stack_scan_ambig, v, 0),
|
||||
die(mps_root_create_thread(&stack, arena, thr, v),
|
||||
"Root Create\n");
|
||||
die(mps_fmt_create_A(&dylanfmt, arena, dylan_fmt_A()),
|
||||
"Format Create\n");
|
||||
|
|
|
|||
|
|
@ -271,8 +271,7 @@ static void *setup(void *v, size_t s)
|
|||
arena = guff->arena;
|
||||
thr = guff->thr;
|
||||
|
||||
die(mps_root_create_reg(&stack, arena, mps_rank_ambig(), 0, thr,
|
||||
mps_stack_scan_ambig, v, 0),
|
||||
die(mps_root_create_thread(&stack, arena, thr, v),
|
||||
"Root Create\n");
|
||||
die(EnsureHeaderFormat(&dylanfmt, arena), "EnsureHeaderFormat");
|
||||
die(EnsureHeaderWeakFormat(&dylanweakfmt, arena), "EnsureHeaderWeakFormat");
|
||||
|
|
|
|||
|
|
@ -254,8 +254,7 @@ static void *setup(void *v, size_t s)
|
|||
arena = guff->arena;
|
||||
thr = guff->thr;
|
||||
|
||||
die(mps_root_create_reg(&stack, arena, mps_rank_ambig(), 0, thr,
|
||||
mps_stack_scan_ambig, v, 0),
|
||||
die(mps_root_create_thread(&stack, arena, thr, v),
|
||||
"Root Create\n");
|
||||
die(mps_fmt_create_A(&dylanfmt, arena, dylan_fmt_A()),
|
||||
"Format Create\n");
|
||||
|
|
|
|||
|
|
@ -191,8 +191,7 @@ Res BTCreate(BT *btReturn, Arena arena, Count length)
|
|||
AVERT(Arena, arena);
|
||||
AVER(length > 0);
|
||||
|
||||
res = ControlAlloc(&p, arena, BTSize(length),
|
||||
/* withReservoirPermit */ FALSE);
|
||||
res = ControlAlloc(&p, arena, BTSize(length));
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
bt = (BT)p;
|
||||
|
|
|
|||
|
|
@ -279,8 +279,7 @@ Res BufferCreate(Buffer *bufferReturn, BufferClass class,
|
|||
arena = PoolArena(pool);
|
||||
|
||||
/* Allocate memory for the buffer descriptor structure. */
|
||||
res = ControlAlloc(&p, arena, class->size,
|
||||
/* withReservoirPermit */ FALSE);
|
||||
res = ControlAlloc(&p, arena, class->size);
|
||||
if (res != ResOK)
|
||||
goto failAlloc;
|
||||
buffer = p;
|
||||
|
|
@ -588,8 +587,7 @@ Res BufferFramePop(Buffer buffer, AllocFrame frame)
|
|||
*
|
||||
* .reserve: Keep in sync with <code/mps.h#reserve>. */
|
||||
|
||||
Res BufferReserve(Addr *pReturn, Buffer buffer, Size size,
|
||||
Bool withReservoirPermit)
|
||||
Res BufferReserve(Addr *pReturn, Buffer buffer, Size size)
|
||||
{
|
||||
Addr next;
|
||||
|
||||
|
|
@ -598,7 +596,6 @@ Res BufferReserve(Addr *pReturn, Buffer buffer, Size size,
|
|||
AVER(size > 0);
|
||||
AVER(SizeIsAligned(size, BufferPool(buffer)->alignment));
|
||||
AVER(BufferIsReady(buffer));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
/* Is there enough room in the unallocated portion of the buffer to */
|
||||
/* satisfy the request? If so, just increase the alloc marker and */
|
||||
|
|
@ -612,7 +609,7 @@ Res BufferReserve(Addr *pReturn, Buffer buffer, Size size,
|
|||
}
|
||||
|
||||
/* If the buffer can't accommodate the request, call "fill". */
|
||||
return BufferFill(pReturn, buffer, size, withReservoirPermit);
|
||||
return BufferFill(pReturn, buffer, size);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -673,8 +670,7 @@ void BufferAttach(Buffer buffer, Addr base, Addr limit,
|
|||
* allocation request. This might be because the buffer has been
|
||||
* trapped and "limit" has been set to zero. */
|
||||
|
||||
Res BufferFill(Addr *pReturn, Buffer buffer, Size size,
|
||||
Bool withReservoirPermit)
|
||||
Res BufferFill(Addr *pReturn, Buffer buffer, Size size)
|
||||
{
|
||||
Res res;
|
||||
Pool pool;
|
||||
|
|
@ -721,9 +717,7 @@ Res BufferFill(Addr *pReturn, Buffer buffer, Size size,
|
|||
BufferDetach(buffer, pool);
|
||||
|
||||
/* Ask the pool for some memory. */
|
||||
res = (*pool->class->bufferFill)(&base, &limit,
|
||||
pool, buffer, size,
|
||||
withReservoirPermit);
|
||||
res = (*pool->class->bufferFill)(&base, &limit, pool, buffer, size);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
|
|
|
|||
105
mps/code/cbs.c
105
mps/code/cbs.c
|
|
@ -117,36 +117,37 @@ static TreeKey cbsKey(Tree tree)
|
|||
|
||||
/* cbsTestNode, cbsTestTree -- test for nodes larger than the S parameter */
|
||||
|
||||
static Bool cbsTestNode(SplayTree splay, Tree tree,
|
||||
void *closureP, Size size)
|
||||
static Bool cbsTestNode(SplayTree splay, Tree tree, void *closure)
|
||||
{
|
||||
CBSBlock block;
|
||||
Size *sizeP = closure;
|
||||
|
||||
AVERT(SplayTree, splay);
|
||||
AVERT(Tree, tree);
|
||||
AVER(closureP == NULL);
|
||||
AVER(size > 0);
|
||||
AVER(sizeP != NULL);
|
||||
AVER(*sizeP > 0);
|
||||
AVER(IsLandSubclass(CBSLand(cbsOfSplay(splay)), CBSFastLandClass));
|
||||
|
||||
block = cbsBlockOfTree(tree);
|
||||
|
||||
return CBSBlockSize(block) >= size;
|
||||
return CBSBlockSize(block) >= *sizeP;
|
||||
}
|
||||
|
||||
static Bool cbsTestTree(SplayTree splay, Tree tree,
|
||||
void *closureP, Size size)
|
||||
void *closure)
|
||||
{
|
||||
CBSFastBlock block;
|
||||
Size *sizeP = closure;
|
||||
|
||||
AVERT(SplayTree, splay);
|
||||
AVERT(Tree, tree);
|
||||
AVER(closureP == NULL);
|
||||
AVER(size > 0);
|
||||
AVER(sizeP != NULL);
|
||||
AVER(*sizeP > 0);
|
||||
AVER(IsLandSubclass(CBSLand(cbsOfSplay(splay)), CBSFastLandClass));
|
||||
|
||||
block = cbsFastBlockOfTree(tree);
|
||||
|
||||
return block->maxSize >= size;
|
||||
return block->maxSize >= *sizeP;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -401,8 +402,7 @@ static Res cbsBlockAlloc(CBSBlock *blockReturn, CBS cbs, Range range)
|
|||
AVERT(CBS, cbs);
|
||||
AVERT(Range, range);
|
||||
|
||||
res = PoolAlloc(&p, cbsBlockPool(cbs), cbs->blockStructSize,
|
||||
/* withReservoirPermit */ FALSE);
|
||||
res = PoolAlloc(&p, cbsBlockPool(cbs), cbs->blockStructSize);
|
||||
if (res != ResOK)
|
||||
goto failPoolAlloc;
|
||||
block = (CBSBlock)p;
|
||||
|
|
@ -726,25 +726,24 @@ static Res cbsZonedSplayNodeDescribe(Tree tree, mps_lib_FILE *stream)
|
|||
typedef struct CBSIterateClosure {
|
||||
Land land;
|
||||
LandVisitor visitor;
|
||||
void *closureP;
|
||||
void *visitorClosure;
|
||||
} CBSIterateClosure;
|
||||
|
||||
static Bool cbsIterateVisit(Tree tree, void *closureP, Size closureS)
|
||||
static Bool cbsIterateVisit(Tree tree, void *closure)
|
||||
{
|
||||
CBSIterateClosure *closure = closureP;
|
||||
Land land = closure->land;
|
||||
CBSIterateClosure *my = closure;
|
||||
Land land = my->land;
|
||||
CBSBlock cbsBlock = cbsBlockOfTree(tree);
|
||||
RangeStruct range;
|
||||
RangeInit(&range, CBSBlockBase(cbsBlock), CBSBlockLimit(cbsBlock));
|
||||
return (*closure->visitor)(land, &range, closure->closureP, closureS);
|
||||
return my->visitor(land, &range, my->visitorClosure);
|
||||
}
|
||||
|
||||
static Bool cbsIterate(Land land, LandVisitor visitor,
|
||||
void *closureP, Size closureS)
|
||||
static Bool cbsIterate(Land land, LandVisitor visitor, void *visitorClosure)
|
||||
{
|
||||
CBS cbs;
|
||||
SplayTree splay;
|
||||
CBSIterateClosure closure;
|
||||
CBSIterateClosure iterateClosure;
|
||||
|
||||
AVERT(Land, land);
|
||||
cbs = cbsOfLand(land);
|
||||
|
|
@ -756,11 +755,11 @@ static Bool cbsIterate(Land land, LandVisitor visitor,
|
|||
/* searches and meter it. */
|
||||
METER_ACC(cbs->treeSearch, cbs->treeSize);
|
||||
|
||||
closure.land = land;
|
||||
closure.visitor = visitor;
|
||||
closure.closureP = closureP;
|
||||
iterateClosure.land = land;
|
||||
iterateClosure.visitor = visitor;
|
||||
iterateClosure.visitorClosure = visitorClosure;
|
||||
return TreeTraverse(SplayTreeRoot(splay), splay->compare, splay->nodeKey,
|
||||
cbsIterateVisit, &closure, closureS);
|
||||
cbsIterateVisit, &iterateClosure);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -773,33 +772,33 @@ typedef struct CBSIterateAndDeleteClosure {
|
|||
Land land;
|
||||
LandDeleteVisitor visitor;
|
||||
Bool cont;
|
||||
void *closureP;
|
||||
void *visitorClosure;
|
||||
} CBSIterateAndDeleteClosure;
|
||||
|
||||
static Bool cbsIterateAndDeleteVisit(Tree tree, void *closureP, Size closureS)
|
||||
static Bool cbsIterateAndDeleteVisit(Tree tree, void *closure)
|
||||
{
|
||||
CBSIterateAndDeleteClosure *closure = closureP;
|
||||
Land land = closure->land;
|
||||
CBSIterateAndDeleteClosure *my = closure;
|
||||
Land land = my->land;
|
||||
CBS cbs = cbsOfLand(land);
|
||||
CBSBlock cbsBlock = cbsBlockOfTree(tree);
|
||||
Bool deleteNode = FALSE;
|
||||
RangeStruct range;
|
||||
|
||||
RangeInit(&range, CBSBlockBase(cbsBlock), CBSBlockLimit(cbsBlock));
|
||||
if (closure->cont)
|
||||
closure->cont = (*closure->visitor)(&deleteNode, land, &range,
|
||||
closure->closureP, closureS);
|
||||
if (my->cont)
|
||||
my->cont = my->visitor(&deleteNode, land, &range,
|
||||
my->visitorClosure);
|
||||
if (deleteNode)
|
||||
cbsBlockDestroy(cbs, cbsBlock);
|
||||
return deleteNode;
|
||||
}
|
||||
|
||||
static Bool cbsIterateAndDelete(Land land, LandDeleteVisitor visitor,
|
||||
void *closureP, Size closureS)
|
||||
void *visitorClosure)
|
||||
{
|
||||
CBS cbs;
|
||||
SplayTree splay;
|
||||
CBSIterateAndDeleteClosure closure;
|
||||
CBSIterateAndDeleteClosure iterateClosure;
|
||||
|
||||
AVERT(Land, land);
|
||||
cbs = cbsOfLand(land);
|
||||
|
|
@ -811,13 +810,13 @@ static Bool cbsIterateAndDelete(Land land, LandDeleteVisitor visitor,
|
|||
/* searches and meter it. */
|
||||
METER_ACC(cbs->treeSearch, cbs->treeSize);
|
||||
|
||||
closure.land = land;
|
||||
closure.visitor = visitor;
|
||||
closure.closureP = closureP;
|
||||
closure.cont = TRUE;
|
||||
iterateClosure.land = land;
|
||||
iterateClosure.visitor = visitor;
|
||||
iterateClosure.visitorClosure = visitorClosure;
|
||||
iterateClosure.cont = TRUE;
|
||||
TreeTraverseAndDelete(&splay->root, cbsIterateAndDeleteVisit,
|
||||
&closure, closureS);
|
||||
return closure.cont;
|
||||
&iterateClosure);
|
||||
return iterateClosure.cont;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -904,7 +903,7 @@ static Bool cbsFindFirst(Range rangeReturn, Range oldRangeReturn,
|
|||
|
||||
METER_ACC(cbs->treeSearch, cbs->treeSize);
|
||||
found = SplayFindFirst(&tree, cbsSplay(cbs), &cbsTestNode,
|
||||
&cbsTestTree, NULL, size);
|
||||
&cbsTestTree, &size);
|
||||
if (found) {
|
||||
CBSBlock block;
|
||||
RangeStruct range;
|
||||
|
|
@ -934,36 +933,32 @@ typedef struct cbsTestNodeInZonesClosureStruct {
|
|||
} cbsTestNodeInZonesClosureStruct, *cbsTestNodeInZonesClosure;
|
||||
|
||||
static Bool cbsTestNodeInZones(SplayTree splay, Tree tree,
|
||||
void *closureP, Size closureS)
|
||||
void *closure)
|
||||
{
|
||||
CBSBlock block = cbsBlockOfTree(tree);
|
||||
cbsTestNodeInZonesClosure closure = closureP;
|
||||
cbsTestNodeInZonesClosure my = closure;
|
||||
RangeInZoneSet search;
|
||||
|
||||
UNUSED(splay);
|
||||
AVER(closureS == UNUSED_SIZE);
|
||||
UNUSED(closureS);
|
||||
|
||||
search = closure->high ? RangeInZoneSetLast : RangeInZoneSetFirst;
|
||||
search = my->high ? RangeInZoneSetLast : RangeInZoneSetFirst;
|
||||
|
||||
return search(&closure->base, &closure->limit,
|
||||
return search(&my->base, &my->limit,
|
||||
CBSBlockBase(block), CBSBlockLimit(block),
|
||||
closure->arena, closure->zoneSet, closure->size);
|
||||
my->arena, my->zoneSet, my->size);
|
||||
}
|
||||
|
||||
static Bool cbsTestTreeInZones(SplayTree splay, Tree tree,
|
||||
void *closureP, Size closureS)
|
||||
void *closure)
|
||||
{
|
||||
CBSFastBlock fastBlock = cbsFastBlockOfTree(tree);
|
||||
CBSZonedBlock zonedBlock = cbsZonedBlockOfTree(tree);
|
||||
cbsTestNodeInZonesClosure closure = closureP;
|
||||
cbsTestNodeInZonesClosure my = closure;
|
||||
|
||||
UNUSED(splay);
|
||||
AVER(closureS == UNUSED_SIZE);
|
||||
UNUSED(closureS);
|
||||
|
||||
return fastBlock->maxSize >= closure->size
|
||||
&& ZoneSetInter(zonedBlock->zones, closure->zoneSet) != ZoneSetEMPTY;
|
||||
return fastBlock->maxSize >= my->size
|
||||
&& ZoneSetInter(zonedBlock->zones, my->zoneSet) != ZoneSetEMPTY;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -989,7 +984,7 @@ static Bool cbsFindLast(Range rangeReturn, Range oldRangeReturn,
|
|||
|
||||
METER_ACC(cbs->treeSearch, cbs->treeSize);
|
||||
found = SplayFindLast(&tree, cbsSplay(cbs), &cbsTestNode,
|
||||
&cbsTestTree, NULL, size);
|
||||
&cbsTestTree, &size);
|
||||
if (found) {
|
||||
CBSBlock block;
|
||||
RangeStruct range;
|
||||
|
|
@ -1033,7 +1028,7 @@ static Bool cbsFindLargest(Range rangeReturn, Range oldRangeReturn,
|
|||
CBSBlock block;
|
||||
METER_ACC(cbs->treeSearch, cbs->treeSize);
|
||||
found = SplayFindFirst(&tree, cbsSplay(cbs), &cbsTestNode,
|
||||
&cbsTestTree, NULL, maxSize);
|
||||
&cbsTestTree, &maxSize);
|
||||
AVER(found); /* maxSize is exact, so we will find it. */
|
||||
block = cbsBlockOfTree(tree);
|
||||
AVER(CBSBlockSize(block) >= maxSize);
|
||||
|
|
@ -1093,7 +1088,7 @@ static Res cbsFindInZones(Bool *foundReturn, Range rangeReturn,
|
|||
closure.high = high;
|
||||
if (!(*splayFind)(&tree, cbsSplay(cbs),
|
||||
cbsTestNodeInZones, cbsTestTreeInZones,
|
||||
&closure, UNUSED_SIZE))
|
||||
&closure))
|
||||
goto fail;
|
||||
|
||||
block = cbsBlockOfTree(tree);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
/* clock.h -- Fast clocks and timers
|
||||
*
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
* $Id$
|
||||
*
|
||||
* .design: <design/clock/>.
|
||||
*/
|
||||
|
||||
#ifndef clock_h
|
||||
|
|
@ -176,7 +178,7 @@ typedef mps_clock_t EventClock;
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
# comm.gmk: COMMON GNUMAKEFILE FRAGMENT
|
||||
#
|
||||
# $Id$
|
||||
# Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
# Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
|
|
@ -148,7 +148,7 @@ ARFLAGS=rc$(ARFLAGSPFM)
|
|||
# platforms.
|
||||
|
||||
AMC = poolamc.c
|
||||
AMS = poolams.c poolamsi.c
|
||||
AMS = poolams.c
|
||||
AWL = poolawl.c
|
||||
LO = poollo.c
|
||||
SNC = poolsnc.c
|
||||
|
|
@ -187,6 +187,7 @@ MPMCOMMON = \
|
|||
mpm.c \
|
||||
mpsi.c \
|
||||
nailboard.c \
|
||||
policy.c \
|
||||
pool.c \
|
||||
poolabs.c \
|
||||
poolmfs.c \
|
||||
|
|
@ -195,11 +196,11 @@ MPMCOMMON = \
|
|||
protocol.c \
|
||||
range.c \
|
||||
ref.c \
|
||||
reserv.c \
|
||||
ring.c \
|
||||
root.c \
|
||||
sa.c \
|
||||
sac.c \
|
||||
scan.c \
|
||||
seg.c \
|
||||
shield.c \
|
||||
splay.c \
|
||||
|
|
@ -283,6 +284,7 @@ TEST_TARGETS=\
|
|||
sacss \
|
||||
segsmss \
|
||||
steptest \
|
||||
tagtest \
|
||||
teletest \
|
||||
walkt0 \
|
||||
zcoll \
|
||||
|
|
@ -316,10 +318,24 @@ $(addprefix $(PFM)/$(VARIETY)/,$(TEST_SUITES)): $(TEST_TARGETS)
|
|||
../tool/testrun.sh -s "$(notdir $@)" "$(PFM)/$(VARIETY)"
|
||||
|
||||
|
||||
# == MMQA test suite ==
|
||||
#
|
||||
# See test/README for documentation on running the MMQA test suite.
|
||||
|
||||
MMQA=perl test/qa -i ../code -l ../code/$(PFM)/$(VARIETY)/mps.o
|
||||
|
||||
$(PFM)/$(VARIETY)/testmmqa:
|
||||
$(MAKE) -f $(PFM).gmk VARIETY=$(VARIETY) TARGET=mps.o variety
|
||||
(if [ "$(VARIETY)" = "cool" ]; then cd ../test && $(MMQA) runset testsets/coolonly; fi)
|
||||
(cd ../test && $(MMQA) runset testsets/argerr)
|
||||
(cd ../test && $(MMQA) runset testsets/conerr)
|
||||
(cd ../test && $(MMQA) runset testsets/passing)
|
||||
|
||||
|
||||
# These convenience targets allow one to type "make foo" to build target
|
||||
# foo in selected varieties (or none, for the latter rule).
|
||||
|
||||
$(ALL_TARGETS) $(TEST_SUITES): phony
|
||||
$(ALL_TARGETS) $(TEST_SUITES) testmmqa: phony
|
||||
ifdef VARIETY
|
||||
$(MAKE) -f $(PFM).gmk TARGET=$@ variety
|
||||
else
|
||||
|
|
@ -510,6 +526,9 @@ $(PFM)/$(VARIETY)/sacss: $(PFM)/$(VARIETY)/sacss.o \
|
|||
$(PFM)/$(VARIETY)/segsmss: $(PFM)/$(VARIETY)/segsmss.o \
|
||||
$(FMTDYTSTOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a
|
||||
|
||||
$(PFM)/$(VARIETY)/tagtest: $(PFM)/$(VARIETY)/tagtest.o \
|
||||
$(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a
|
||||
|
||||
$(PFM)/$(VARIETY)/teletest: $(PFM)/$(VARIETY)/teletest.o \
|
||||
$(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a
|
||||
|
||||
|
|
@ -661,7 +680,7 @@ find-puns: phony
|
|||
|
||||
# C. COPYRIGHT AND LICENSE
|
||||
#
|
||||
# Copyright (c) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
# Copyright (c) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
# All rights reserved. This is an open source license. Contact
|
||||
# Ravenbrook for commercial licensing options.
|
||||
#
|
||||
|
|
|
|||
|
|
@ -1,330 +1,11 @@
|
|||
# -*- makefile -*-
|
||||
#
|
||||
# comm.nmk: COMMON NMAKE FRAGMENT
|
||||
# commpost.nmk: SECOND COMMON FRAGMENT FOR PLATFORMS USING NMAKE -*- makefile -*-
|
||||
#
|
||||
# $Id$
|
||||
# Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This makefile fragment is included in more specific makefiles for
|
||||
# platforms which use nmake.
|
||||
#
|
||||
# %%PART: When adding a new part, add a new parameter for the files included
|
||||
# in the part
|
||||
# Parameters:
|
||||
# PFM platform code, e.g. "w3i3mv"
|
||||
# PFMDEFS /D options to define platforms preprocessor symbols
|
||||
# to the compiler. Avoid using this if possible, as it
|
||||
# prevents the MPS being built with a simple command like
|
||||
# "cl mps.c".
|
||||
# MPMCOMMON list of sources which make up the "mpm" part for all
|
||||
# platforms. Each source is stripped of its .c extension
|
||||
# and surrounded with [brackets].
|
||||
# MPMPF as above for the current platform.
|
||||
# PLINTH as above for the "plinth" part
|
||||
# AMC as above for the "amc" part
|
||||
# AMS as above for the "ams" part
|
||||
# LO as above for the "lo" part
|
||||
# POOLN as above for the "pooln" part
|
||||
# SNC as above for the "snc" part
|
||||
# POOLS as above for all pools included in the target
|
||||
# MPM as above for the MPMCOMMON + MPMPF + PLINTH + POOLS
|
||||
# DW as above for the "dw" part
|
||||
# FMTTEST as above for the "fmttest" part
|
||||
# FMTSCHEME as above for the "fmtscheme" part
|
||||
# TESTLIB as above for the "testlib" part
|
||||
# TESTTHR as above for the "testthr" part
|
||||
# NOISY if defined, causes command to be emitted
|
||||
#
|
||||
#
|
||||
# EDITING
|
||||
#
|
||||
# To add new targets. varieties, and parts:
|
||||
# Search for the string "%%TARGET", "%%VARIETY", or "%%PART" in this makefile
|
||||
# and follow the instructions.
|
||||
#
|
||||
|
||||
|
||||
# TARGETS
|
||||
#
|
||||
#
|
||||
# %%TARGET: When adding a new target, add it to one of the variables
|
||||
# in this section. Library components go in LIB_TARGETS.
|
||||
|
||||
LIB_TARGETS=mps.lib
|
||||
|
||||
# Test cases go in TEST_TARGETS.
|
||||
|
||||
TEST_TARGETS=\
|
||||
abqtest.exe \
|
||||
airtest.exe \
|
||||
amcss.exe \
|
||||
amcsshe.exe \
|
||||
amcssth.exe \
|
||||
amsss.exe \
|
||||
amssshe.exe \
|
||||
apss.exe \
|
||||
arenacv.exe \
|
||||
awlut.exe \
|
||||
awluthe.exe \
|
||||
awlutth.exe \
|
||||
btcv.exe \
|
||||
bttest.exe \
|
||||
djbench.exe \
|
||||
exposet0.exe \
|
||||
expt825.exe \
|
||||
finalcv.exe \
|
||||
finaltest.exe \
|
||||
fotest.exe \
|
||||
gcbench.exe \
|
||||
landtest.exe \
|
||||
locbwcss.exe \
|
||||
lockcov.exe \
|
||||
lockut.exe \
|
||||
locusss.exe \
|
||||
locv.exe \
|
||||
messtest.exe \
|
||||
mpmss.exe \
|
||||
mpsicv.exe \
|
||||
mv2test.exe \
|
||||
nailboardtest.exe \
|
||||
poolncv.exe \
|
||||
qs.exe \
|
||||
sacss.exe \
|
||||
segsmss.exe \
|
||||
steptest.exe \
|
||||
teletest.exe \
|
||||
walkt0.exe \
|
||||
zcoll.exe \
|
||||
zmess.exe
|
||||
|
||||
# Stand-alone programs go in EXTRA_TARGETS if they should always be
|
||||
# built, or in OPTIONAL_TARGETS if they should only be built if
|
||||
|
||||
EXTRA_TARGETS=mpseventcnv.exe mpseventtxt.exe
|
||||
OPTIONAL_TARGETS=mpseventsql.exe
|
||||
|
||||
# This target records programs that we were once able to build but
|
||||
# can't at the moment:
|
||||
#
|
||||
# replay -- depends on the EPVM pool.
|
||||
|
||||
UNBUILDABLE_TARGETS=replay.exe
|
||||
|
||||
ALL_TARGETS=$(LIB_TARGETS) $(TEST_TARGETS) $(EXTRA_TARGETS)
|
||||
|
||||
|
||||
# PARAMETERS
|
||||
#
|
||||
#
|
||||
# %%PART: When adding a new part, add the sources for the new part here.
|
||||
|
||||
MPMCOMMON=\
|
||||
[abq] \
|
||||
[arena] \
|
||||
[arenacl] \
|
||||
[arenavm] \
|
||||
[arg] \
|
||||
[boot] \
|
||||
[bt] \
|
||||
[buffer] \
|
||||
[cbs] \
|
||||
[dbgpool] \
|
||||
[dbgpooli] \
|
||||
[event] \
|
||||
[failover] \
|
||||
[format] \
|
||||
[freelist] \
|
||||
[global] \
|
||||
[land] \
|
||||
[ld] \
|
||||
[locus] \
|
||||
[message] \
|
||||
[meter] \
|
||||
[mpm] \
|
||||
[mpsi] \
|
||||
[nailboard] \
|
||||
[pool] \
|
||||
[poolabs] \
|
||||
[poolmfs] \
|
||||
[poolmrg] \
|
||||
[poolmv2] \
|
||||
[poolmv] \
|
||||
[protocol] \
|
||||
[range] \
|
||||
[ref] \
|
||||
[reserv] \
|
||||
[ring] \
|
||||
[root] \
|
||||
[sa] \
|
||||
[sac] \
|
||||
[seg] \
|
||||
[shield] \
|
||||
[splay] \
|
||||
[ss] \
|
||||
[table] \
|
||||
[trace] \
|
||||
[traceanc] \
|
||||
[tract] \
|
||||
[tree] \
|
||||
[version] \
|
||||
[vm] \
|
||||
[walk]
|
||||
PLINTH = [mpsliban] [mpsioan]
|
||||
AMC = [poolamc]
|
||||
AMS = [poolams] [poolamsi]
|
||||
AWL = [poolawl]
|
||||
LO = [poollo]
|
||||
MVFF = [poolmvff]
|
||||
POOLN = [pooln]
|
||||
SNC = [poolsnc]
|
||||
FMTDY = [fmtdy] [fmtno]
|
||||
FMTTEST = [fmthe] [fmtdy] [fmtno] [fmtdytst]
|
||||
FMTSCHEME = [fmtscheme]
|
||||
TESTLIB = [testlib] [getoptl]
|
||||
TESTTHR = [testthrw3]
|
||||
POOLS = $(AMC) $(AMS) $(AWL) $(LO) $(MV2) $(MVFF) $(SNC)
|
||||
MPM = $(MPMCOMMON) $(MPMPF) $(POOLS) $(PLINTH)
|
||||
|
||||
|
||||
# CHECK PARAMETERS
|
||||
#
|
||||
#
|
||||
# %%PART: When adding a new part, add checks for the parameter with the
|
||||
# sources for the new part.
|
||||
|
||||
!IFNDEF PFM
|
||||
!ERROR comm.nmk: PFM not defined
|
||||
!ENDIF
|
||||
!IFNDEF MPM
|
||||
!ERROR comm.nmk: MPM not defined
|
||||
!ENDIF
|
||||
!IFNDEF MPMCOMMON
|
||||
!ERROR comm.nmk: MPMCOMMON not defined
|
||||
!ENDIF
|
||||
!IFNDEF MPMPF
|
||||
!ERROR comm.nmk: MPMPF not defined
|
||||
!ENDIF
|
||||
!IFNDEF PLINTH
|
||||
!ERROR comm.nmk: PLINTH not defined
|
||||
!ENDIF
|
||||
!IFNDEF LO
|
||||
!ERROR comm.nmk: LO not defined
|
||||
!ENDIF
|
||||
!IFNDEF AMC
|
||||
!ERROR comm.nmk: AMC not defined
|
||||
!ENDIF
|
||||
!IFNDEF AMS
|
||||
!ERROR comm.nmk: AMS not defined
|
||||
!ENDIF
|
||||
!IFNDEF POOLN
|
||||
!ERROR comm.nmk: POOLN not defined
|
||||
!ENDIF
|
||||
!IFNDEF SNC
|
||||
!ERROR comm.nmk: SNC not defined
|
||||
!ENDIF
|
||||
!IFNDEF FMTDY
|
||||
!ERROR comm.nmk: FMTDY not defined
|
||||
!ENDIF
|
||||
!IFNDEF FMTTEST
|
||||
!ERROR comm.nmk: FMTTEST not defined
|
||||
!ENDIF
|
||||
!IFNDEF FMTSCHEME
|
||||
!ERROR comm.nmk: FMTSCHEME not defined
|
||||
!ENDIF
|
||||
!IFNDEF TESTLIB
|
||||
!ERROR comm.nmk: TESTLIB not defined
|
||||
!ENDIF
|
||||
!IFNDEF TESTTHR
|
||||
!ERROR comm.nmk: TESTTHR not defined
|
||||
!ENDIF
|
||||
|
||||
|
||||
# DECLARATIONS
|
||||
|
||||
|
||||
!IFDEF NOISY
|
||||
ECHO = rem
|
||||
!ELSE
|
||||
.SILENT:
|
||||
ECHO = echo
|
||||
!ENDIF
|
||||
|
||||
|
||||
# C FLAGS
|
||||
|
||||
CFLAGSTARGETPRE =
|
||||
CFLAGSTARGETPOST =
|
||||
CRTFLAGSHOT =
|
||||
CRTFLAGSCOOL =
|
||||
LINKFLAGSHOT =
|
||||
LINKFLAGSCOOL =
|
||||
|
||||
CFLAGSSQLPRE = /nologo $(PFMDEFS)
|
||||
CFLAGSCOMMONPRE = /nologo $(PFMDEFS) $(CFLAGSTARGETPRE)
|
||||
CFLAGSSQLPOST =
|
||||
CFLAGSCOMMONPOST = $(CFLAGSTARGETPOST)
|
||||
|
||||
# Flags for use in the variety combinations
|
||||
CFLAGSHOT = /O2
|
||||
# (above /O2 (maximise speed) used to be set to /Ox
|
||||
# (maximise optimisations) in for tool versions before VS 9)
|
||||
# We used to have /GZ here (stack probe).
|
||||
# Note that GZ is specific to version 12 of the cl tool. drj 2003-11-04
|
||||
# It is ignored on earlier versions of the cl tool.
|
||||
# /GZ here generates a dependency on the C library and when we are
|
||||
# building a DLL, mpsdy.dll, the linker step will fail (error LNK2001:
|
||||
# unresolved external symbol __chkesp). See
|
||||
# http://support.microsoft.com/kb/q191669/
|
||||
CFLAGSCOOL =
|
||||
CFLAGSINTERNAL = /Zi
|
||||
CFLAGSEXTERNAL =
|
||||
|
||||
# The combinations of variety
|
||||
# %%VARIETY: When adding a new variety, define a macro containing the set
|
||||
# of flags for the new variety.
|
||||
CFRASH = /DCONFIG_VAR_RASH $(CRTFLAGSHOT) $(CFLAGSHOT) $(CFLAGSEXTERNAL)
|
||||
CFHOT = /DCONFIG_VAR_HOT $(CRTFLAGSHOT) $(CFLAGSHOT) $(CFLAGSINTERNAL)
|
||||
CFCOOL = /DCONFIG_VAR_COOL $(CRTFLAGSCOOL) $(CFLAGSCOOL) $(CFLAGSINTERNAL)
|
||||
|
||||
# Microsoft documentation is not very clear on the point of using both
|
||||
# optimization and debug information
|
||||
|
||||
# LINKER FLAGS
|
||||
# %%VARIETY: When adding a new variety, define a macro containing the flags
|
||||
# for the new variety
|
||||
LINKER = link
|
||||
LINKFLAGSCOMMON = /nologo /LARGEADDRESSAWARE
|
||||
LINKFLAGSINTERNAL = /DEBUG
|
||||
# ( Internal flags used to be set to /DEBUG:full )
|
||||
LINKFLAGSEXTERNAL = /RELEASE
|
||||
|
||||
LFRASH = $(LINKFLAGSHOT) $(LINKFLAGSEXTERNAL)
|
||||
LFHOT = $(LINKFLAGSHOT) $(LINKFLAGSINTERNAL)
|
||||
LFCOOL = $(LINKFLAGSCOOL) $(LINKFLAGSINTERNAL)
|
||||
|
||||
#LFCV = /PROFILE /DEBUG:full /DEBUGTYPE:cv
|
||||
|
||||
# Library manager
|
||||
# %%VARIETY: When adding a new variety, define a macro containing the flags
|
||||
# for the new variety
|
||||
LIBMAN = lib # can't call this LIB - it screws the environment
|
||||
LIBFLAGSCOMMON =
|
||||
|
||||
LIBFLAGSRASH =
|
||||
LIBFLAGSHOT =
|
||||
LIBFLAGSCOOL =
|
||||
|
||||
# Browser database manager [not used at present]
|
||||
#BSC = bscmake
|
||||
#BSCFLAGS = /nologo /n
|
||||
|
||||
|
||||
# == Common definitions ==
|
||||
# %%PART: When adding a new part, add it here, unless it's platform-specific
|
||||
# [It is not possible use a macro, like $(PFM), in a substitution,
|
||||
# hence all parts end up being platform-specific.]
|
||||
# Second common makefile fragment for w3*mv.nmk. See commpre.nmk
|
||||
|
||||
|
||||
# == Pseudo-targets ==
|
||||
|
|
@ -610,6 +291,9 @@ $(PFM)\$(VARIETY)\segsmss.exe: $(PFM)\$(VARIETY)\segsmss.obj \
|
|||
$(PFM)\$(VARIETY)\steptest.exe: $(PFM)\$(VARIETY)\steptest.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib $(FMTTESTOBJ) $(TESTLIBOBJ)
|
||||
|
||||
$(PFM)\$(VARIETY)\tagtest.exe: $(PFM)\$(VARIETY)\tagtest.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
|
||||
|
||||
$(PFM)\$(VARIETY)\teletest.exe: $(PFM)\$(VARIETY)\teletest.obj \
|
||||
$(PFM)\$(VARIETY)\mps.lib $(TESTLIBOBJ)
|
||||
|
||||
|
|
@ -701,18 +385,18 @@ $(PFM)\$(VARIETY)\sqlite3.obj:
|
|||
# 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.
|
||||
#
|
||||
#
|
||||
# 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
|
||||
|
|
@ -723,7 +407,7 @@ $(PFM)\$(VARIETY)\sqlite3.obj:
|
|||
# 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
|
||||
371
mps/code/commpre.nmk
Normal file
371
mps/code/commpre.nmk
Normal file
|
|
@ -0,0 +1,371 @@
|
|||
# commpre.nmk: FIRST COMMON FRAGMENT FOR PLATFORMS USING NMAKE -*- makefile -*-1
|
||||
#
|
||||
# $Id$
|
||||
# Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# .description: This makefile fragment is included in more specific
|
||||
# makefiles for platforms which use the "mv" builder. This is
|
||||
# the first of two common makefile fragements (the other is commpost.nmk).
|
||||
# Alas, due to shortcomings in nmake, it is not possible to use only one
|
||||
# common fragment.
|
||||
#
|
||||
# %%PART: When adding a new part, add a new parameter for the files included
|
||||
# in the part
|
||||
# Parameters:
|
||||
# PFM platform code, e.g. "w3i3mv"
|
||||
# PFMDEFS /D options to define platforms preprocessor symbols
|
||||
# to the compiler. Avoid using this if possible, as it
|
||||
# prevents the MPS being built with a simple command like
|
||||
# "cl mps.c".
|
||||
# MPMCOMMON list of sources which make up the "mpm" part for all
|
||||
# platforms. Each source is stripped of its .c extension
|
||||
# and surrounded with [brackets].
|
||||
# MPMPF as above for the current platform.
|
||||
# PLINTH as above for the "plinth" part
|
||||
# AMC as above for the "amc" part
|
||||
# AMS as above for the "ams" part
|
||||
# LO as above for the "lo" part
|
||||
# POOLN as above for the "pooln" part
|
||||
# SNC as above for the "snc" part
|
||||
# POOLS as above for all pools included in the target
|
||||
# MPM as above for the MPMCOMMON + MPMPF + PLINTH + POOLS
|
||||
# DW as above for the "dw" part
|
||||
# FMTTEST as above for the "fmttest" part
|
||||
# FMTSCHEME as above for the "fmtscheme" part
|
||||
# TESTLIB as above for the "testlib" part
|
||||
# TESTTHR as above for the "testthr" part
|
||||
# NOISY if defined, causes command to be emitted
|
||||
#
|
||||
#
|
||||
# EDITING
|
||||
#
|
||||
# To add new targets. varieties, and parts:
|
||||
# Search for the string "%%TARGET", "%%VARIETY", or "%%PART" in this makefile
|
||||
# and follow the instructions.
|
||||
#
|
||||
|
||||
|
||||
# TARGETS
|
||||
#
|
||||
#
|
||||
# %%TARGET: When adding a new target, add it to one of the variables
|
||||
# in this section. Library components go in LIB_TARGETS.
|
||||
|
||||
LIB_TARGETS=mps.lib
|
||||
|
||||
# Test cases go in TEST_TARGETS.
|
||||
|
||||
TEST_TARGETS=\
|
||||
abqtest.exe \
|
||||
airtest.exe \
|
||||
amcss.exe \
|
||||
amcsshe.exe \
|
||||
amcssth.exe \
|
||||
amsss.exe \
|
||||
amssshe.exe \
|
||||
apss.exe \
|
||||
arenacv.exe \
|
||||
awlut.exe \
|
||||
awluthe.exe \
|
||||
awlutth.exe \
|
||||
btcv.exe \
|
||||
bttest.exe \
|
||||
djbench.exe \
|
||||
exposet0.exe \
|
||||
expt825.exe \
|
||||
finalcv.exe \
|
||||
finaltest.exe \
|
||||
fotest.exe \
|
||||
gcbench.exe \
|
||||
landtest.exe \
|
||||
locbwcss.exe \
|
||||
lockcov.exe \
|
||||
lockut.exe \
|
||||
locusss.exe \
|
||||
locv.exe \
|
||||
messtest.exe \
|
||||
mpmss.exe \
|
||||
mpsicv.exe \
|
||||
mv2test.exe \
|
||||
nailboardtest.exe \
|
||||
poolncv.exe \
|
||||
qs.exe \
|
||||
sacss.exe \
|
||||
segsmss.exe \
|
||||
steptest.exe \
|
||||
tagtest.exe \
|
||||
teletest.exe \
|
||||
walkt0.exe \
|
||||
zcoll.exe \
|
||||
zmess.exe
|
||||
|
||||
# Stand-alone programs go in EXTRA_TARGETS if they should always be
|
||||
# built, or in OPTIONAL_TARGETS if they should only be built if
|
||||
|
||||
EXTRA_TARGETS=mpseventcnv.exe mpseventtxt.exe
|
||||
OPTIONAL_TARGETS=mpseventsql.exe
|
||||
|
||||
# This target records programs that we were once able to build but
|
||||
# can't at the moment:
|
||||
#
|
||||
# replay -- depends on the EPVM pool.
|
||||
|
||||
UNBUILDABLE_TARGETS=replay.exe
|
||||
|
||||
ALL_TARGETS=$(LIB_TARGETS) $(TEST_TARGETS) $(EXTRA_TARGETS)
|
||||
|
||||
|
||||
# PARAMETERS
|
||||
#
|
||||
#
|
||||
# %%PART: When adding a new part, add the sources for the new part here.
|
||||
|
||||
MPMCOMMON=\
|
||||
[abq] \
|
||||
[arena] \
|
||||
[arenacl] \
|
||||
[arenavm] \
|
||||
[arg] \
|
||||
[boot] \
|
||||
[bt] \
|
||||
[buffer] \
|
||||
[cbs] \
|
||||
[dbgpool] \
|
||||
[dbgpooli] \
|
||||
[event] \
|
||||
[failover] \
|
||||
[format] \
|
||||
[freelist] \
|
||||
[global] \
|
||||
[land] \
|
||||
[ld] \
|
||||
[locus] \
|
||||
[message] \
|
||||
[meter] \
|
||||
[mpm] \
|
||||
[mpsi] \
|
||||
[nailboard] \
|
||||
[policy] \
|
||||
[pool] \
|
||||
[poolabs] \
|
||||
[poolmfs] \
|
||||
[poolmrg] \
|
||||
[poolmv2] \
|
||||
[poolmv] \
|
||||
[protocol] \
|
||||
[range] \
|
||||
[ref] \
|
||||
[ring] \
|
||||
[root] \
|
||||
[sa] \
|
||||
[sac] \
|
||||
[scan] \
|
||||
[seg] \
|
||||
[shield] \
|
||||
[splay] \
|
||||
[ss] \
|
||||
[table] \
|
||||
[trace] \
|
||||
[traceanc] \
|
||||
[tract] \
|
||||
[tree] \
|
||||
[version] \
|
||||
[vm] \
|
||||
[walk]
|
||||
PLINTH = [mpsliban] [mpsioan]
|
||||
AMC = [poolamc]
|
||||
AMS = [poolams]
|
||||
AWL = [poolawl]
|
||||
LO = [poollo]
|
||||
MVFF = [poolmvff]
|
||||
POOLN = [pooln]
|
||||
SNC = [poolsnc]
|
||||
FMTDY = [fmtdy] [fmtno]
|
||||
FMTTEST = [fmthe] [fmtdy] [fmtno] [fmtdytst]
|
||||
FMTSCHEME = [fmtscheme]
|
||||
TESTLIB = [testlib] [getoptl]
|
||||
TESTTHR = [testthrw3]
|
||||
POOLS = $(AMC) $(AMS) $(AWL) $(LO) $(MV2) $(MVFF) $(SNC)
|
||||
MPM = $(MPMCOMMON) $(MPMPF) $(POOLS) $(PLINTH)
|
||||
|
||||
|
||||
# CHECK PARAMETERS
|
||||
#
|
||||
#
|
||||
# %%PART: When adding a new part, add checks for the parameter with the
|
||||
# sources for the new part.
|
||||
|
||||
!IFNDEF PFM
|
||||
!ERROR commpre.nmk: PFM not defined
|
||||
!ENDIF
|
||||
!IFNDEF MPM
|
||||
!ERROR commpre.nmk: MPM not defined
|
||||
!ENDIF
|
||||
!IFNDEF MPMCOMMON
|
||||
!ERROR commpre.nmk: MPMCOMMON not defined
|
||||
!ENDIF
|
||||
!IFNDEF MPMPF
|
||||
!ERROR commpre.nmk: MPMPF not defined
|
||||
!ENDIF
|
||||
!IFNDEF PLINTH
|
||||
!ERROR commpre.nmk: PLINTH not defined
|
||||
!ENDIF
|
||||
!IFNDEF LO
|
||||
!ERROR commpre.nmk: LO not defined
|
||||
!ENDIF
|
||||
!IFNDEF AMC
|
||||
!ERROR commpre.nmk: AMC not defined
|
||||
!ENDIF
|
||||
!IFNDEF AMS
|
||||
!ERROR commpre.nmk: AMS not defined
|
||||
!ENDIF
|
||||
!IFNDEF POOLN
|
||||
!ERROR commpre.nmk: POOLN not defined
|
||||
!ENDIF
|
||||
!IFNDEF SNC
|
||||
!ERROR commpre.nmk: SNC not defined
|
||||
!ENDIF
|
||||
!IFNDEF FMTDY
|
||||
!ERROR commpre.nmk: FMTDY not defined
|
||||
!ENDIF
|
||||
!IFNDEF FMTTEST
|
||||
!ERROR commpre.nmk: FMTTEST not defined
|
||||
!ENDIF
|
||||
!IFNDEF FMTSCHEME
|
||||
!ERROR commpre.nmk: FMTSCHEME not defined
|
||||
!ENDIF
|
||||
!IFNDEF TESTLIB
|
||||
!ERROR commpre.nmk: TESTLIB not defined
|
||||
!ENDIF
|
||||
!IFNDEF TESTTHR
|
||||
!ERROR commpre.nmk: TESTTHR not defined
|
||||
!ENDIF
|
||||
|
||||
|
||||
# DECLARATIONS
|
||||
|
||||
|
||||
!IFDEF NOISY
|
||||
ECHO = rem
|
||||
!ELSE
|
||||
.SILENT:
|
||||
ECHO = echo
|
||||
!ENDIF
|
||||
|
||||
|
||||
# C FLAGS
|
||||
|
||||
CFLAGSTARGETPRE =
|
||||
CFLAGSTARGETPOST =
|
||||
CRTFLAGSHOT =
|
||||
CRTFLAGSCOOL =
|
||||
LINKFLAGSHOT =
|
||||
LINKFLAGSCOOL =
|
||||
|
||||
CFLAGSSQLPRE = /nologo $(PFMDEFS)
|
||||
CFLAGSCOMMONPRE = /nologo $(PFMDEFS) $(CFLAGSTARGETPRE)
|
||||
CFLAGSSQLPOST =
|
||||
CFLAGSCOMMONPOST = $(CFLAGSTARGETPOST)
|
||||
|
||||
# Flags for use in the variety combinations
|
||||
CFLAGSHOT = /O2
|
||||
# (above /O2 (maximise speed) used to be set to /Ox
|
||||
# (maximise optimisations) in for tool versions before VS 9)
|
||||
# We used to have /GZ here (stack probe).
|
||||
# Note that GZ is specific to version 12 of the cl tool. drj 2003-11-04
|
||||
# It is ignored on earlier versions of the cl tool.
|
||||
# /GZ here generates a dependency on the C library and when we are
|
||||
# building a DLL, mpsdy.dll, the linker step will fail (error LNK2001:
|
||||
# unresolved external symbol __chkesp). See
|
||||
# http://support.microsoft.com/kb/q191669/
|
||||
CFLAGSCOOL =
|
||||
CFLAGSINTERNAL = /Zi
|
||||
CFLAGSEXTERNAL =
|
||||
|
||||
# The combinations of variety
|
||||
# %%VARIETY: When adding a new variety, define a macro containing the set
|
||||
# of flags for the new variety.
|
||||
CFRASH = /DCONFIG_VAR_RASH $(CRTFLAGSHOT) $(CFLAGSHOT) $(CFLAGSEXTERNAL)
|
||||
CFHOT = /DCONFIG_VAR_HOT $(CRTFLAGSHOT) $(CFLAGSHOT) $(CFLAGSINTERNAL)
|
||||
CFCOOL = /DCONFIG_VAR_COOL $(CRTFLAGSCOOL) $(CFLAGSCOOL) $(CFLAGSINTERNAL)
|
||||
|
||||
# Microsoft documentation is not very clear on the point of using both
|
||||
# optimization and debug information
|
||||
|
||||
# LINKER FLAGS
|
||||
# %%VARIETY: When adding a new variety, define a macro containing the flags
|
||||
# for the new variety
|
||||
LINKER = link
|
||||
LINKFLAGSCOMMON = /nologo /LARGEADDRESSAWARE
|
||||
LINKFLAGSINTERNAL = /DEBUG
|
||||
# ( Internal flags used to be set to /DEBUG:full )
|
||||
LINKFLAGSEXTERNAL = /RELEASE
|
||||
|
||||
LFRASH = $(LINKFLAGSHOT) $(LINKFLAGSEXTERNAL)
|
||||
LFHOT = $(LINKFLAGSHOT) $(LINKFLAGSINTERNAL)
|
||||
LFCOOL = $(LINKFLAGSCOOL) $(LINKFLAGSINTERNAL)
|
||||
|
||||
#LFCV = /PROFILE /DEBUG:full /DEBUGTYPE:cv
|
||||
|
||||
# Library manager
|
||||
# %%VARIETY: When adding a new variety, define a macro containing the flags
|
||||
# for the new variety
|
||||
LIBMAN = lib # can't call this LIB - it screws the environment
|
||||
LIBFLAGSCOMMON =
|
||||
|
||||
LIBFLAGSRASH =
|
||||
LIBFLAGSHOT =
|
||||
LIBFLAGSCOOL =
|
||||
|
||||
# Browser database manager [not used at present]
|
||||
#BSC = bscmake
|
||||
#BSCFLAGS = /nologo /n
|
||||
|
||||
|
||||
# == Common definitions ==
|
||||
# %%PART: When adding a new part, add it here, unless it's platform-specific
|
||||
# [It is not possible use a macro, like $(PFM), in a substitution,
|
||||
# hence all parts end up being platform-specific.]
|
||||
|
||||
|
||||
# C. COPYRIGHT AND LICENSE
|
||||
#
|
||||
# Copyright (C) 2001-2016 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.
|
||||
|
|
@ -392,25 +392,68 @@
|
|||
#define MVT_FRAG_LIMIT_DEFAULT 30
|
||||
|
||||
|
||||
/* Arena Configuration -- see <code/arena.c>
|
||||
*
|
||||
* .client.seg-size: ARENA_CLIENT_GRAIN_SIZE is the minimum size, in
|
||||
* bytes, of a grain in the client arena. It's set at 8192 with no
|
||||
* particular justification.
|
||||
*/
|
||||
/* Arena Configuration -- see <code/arena.c> */
|
||||
|
||||
#define ArenaPollALLOCTIME (65536.0)
|
||||
|
||||
#define ARENA_ZONESHIFT ((Shift)20)
|
||||
|
||||
/* .client.seg-size: ARENA_CLIENT_GRAIN_SIZE is the minimum size, in
|
||||
* bytes, of a grain in the client arena. It's set at 8192 with no
|
||||
* particular justification. */
|
||||
|
||||
#define ARENA_CLIENT_GRAIN_SIZE ((Size)8192)
|
||||
|
||||
#define ARENA_DEFAULT_COMMIT_LIMIT ((Size)-1)
|
||||
|
||||
/* TODO: This should be proportional to the memory usage of the MPS, not
|
||||
* a constant. That will require design, and then some interface and
|
||||
* documentation changes. */
|
||||
#define ARENA_DEFAULT_SPARE_COMMIT_LIMIT ((Size)10uL*1024uL*1024uL)
|
||||
|
||||
/* ARENA_DEFAULT_PAUSE_TIME is the maximum time (in seconds) that
|
||||
* operations within the arena may pause the mutator for. The default
|
||||
* is set for typical human interaction. See mps_arena_pause_time_set
|
||||
* in the manual. */
|
||||
|
||||
#define ARENA_DEFAULT_PAUSE_TIME (0.1)
|
||||
|
||||
#define ARENA_DEFAULT_ZONED TRUE
|
||||
|
||||
/* ARENA_MINIMUM_COLLECTABLE_SIZE is the minimum size (in bytes) of
|
||||
* collectable memory that might be considered worthwhile to run a
|
||||
* full garbage collection. */
|
||||
|
||||
#define ARENA_MINIMUM_COLLECTABLE_SIZE ((Size)1000000)
|
||||
|
||||
/* ARENA_DEFAULT_COLLECTION_RATE is an estimate of the MPS's
|
||||
* collection rate (in work per second; see <design/type/#work>), for
|
||||
* use in the case where there isn't enough data to use a measured
|
||||
* value. */
|
||||
|
||||
#define ARENA_DEFAULT_COLLECTION_RATE (25000000.0)
|
||||
|
||||
/* ARENA_DEFAULT_COLLECTION_OVERHEAD is an estimate of the MPS's
|
||||
* collection overhead (in seconds), for use in the case where there
|
||||
* isn't enough data to use a measured value. */
|
||||
|
||||
#define ARENA_DEFAULT_COLLECTION_OVERHEAD (0.1)
|
||||
|
||||
/* ARENA_MAX_COLLECT_FRACTION is the maximum fraction of runtime that
|
||||
* ArenaStep is prepared to spend in collections. */
|
||||
|
||||
#define ARENA_MAX_COLLECT_FRACTION (0.1)
|
||||
|
||||
/* ArenaDefaultZONESET is the zone set used by LocusPrefDEFAULT.
|
||||
*
|
||||
* TODO: This is left over from before branches 2014-01-29/mps-chain-zones
|
||||
* and 2014-01-17/cbs-tract-alloc reformed allocation, and may now be
|
||||
* doing more harm than good. Experiment with setting to ZoneSetUNIV. */
|
||||
|
||||
#define ArenaDefaultZONESET (ZoneSetUNIV << (MPS_WORD_WIDTH / 2))
|
||||
/* TODO: This is left over from before the branch/2014-01-29/mps-chain-zones
|
||||
and 2014-01-17/cbs-tract-alloc reformed allocation, and may now be doing
|
||||
more harm than good. Experiment with setting to ZoneSetUNIV. */
|
||||
|
||||
/* LocusPrefDEFAULT is the allocation preference used by manual pool
|
||||
* classes (these don't care where they allocate). */
|
||||
|
||||
#define LocusPrefDEFAULT { \
|
||||
LocusPrefSig, /* sig */ \
|
||||
|
|
@ -440,8 +483,8 @@
|
|||
|
||||
/* Shield Configuration -- see <code/shield.c> */
|
||||
|
||||
#define ShieldCacheSIZE ((size_t)16)
|
||||
#define ShieldDepthWIDTH (4)
|
||||
#define ShieldQueueLENGTH 512 /* initial length of shield queue */
|
||||
#define ShieldDepthWIDTH 4 /* log2(max nested exposes + 1) */
|
||||
|
||||
|
||||
/* VM Configuration -- see <code/vm*.c> */
|
||||
|
|
@ -611,11 +654,6 @@
|
|||
#define MPS_PROD_STRING "mps"
|
||||
#define MPS_PROD_MPS
|
||||
|
||||
/* TODO: This should be proportional to the memory usage of the MPS, not
|
||||
a constant. That will require design, and then some interface and
|
||||
documenation changes. */
|
||||
#define ARENA_INIT_SPARE_COMMIT_LIMIT ((Size)10uL*1024uL*1024uL)
|
||||
|
||||
|
||||
/* Default chain for GC pools
|
||||
*
|
||||
|
|
@ -630,6 +668,25 @@
|
|||
}
|
||||
|
||||
|
||||
/* Write barrier deferral
|
||||
*
|
||||
* See design.mps.write-barrier.deferral.
|
||||
*
|
||||
* TODO: These settings were determined by trial and error, but should
|
||||
* be based on measurement of the protection overhead on each
|
||||
* platform. We know it's extremely different between OS X and
|
||||
* Windows, for example. See design.mps.write-barrier.improv.by-os.
|
||||
*
|
||||
* TODO: Consider basing the count on the amount of time that has
|
||||
* passed in the mutator rather than the number of scans.
|
||||
*/
|
||||
|
||||
#define WB_DEFER_BITS 2 /* bitfield width for deferral count */
|
||||
#define WB_DEFER_INIT 3 /* boring scans after new segment */
|
||||
#define WB_DEFER_DELAY 3 /* boring scans after interesting scan */
|
||||
#define WB_DEFER_HIT 1 /* boring scans after barrier hit */
|
||||
|
||||
|
||||
#endif /* config_h */
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -397,14 +397,14 @@ static Bool freeCheck(PoolDebugMixin debug, Pool pool, Addr base, Addr limit)
|
|||
/* freeCheckAlloc -- allocation wrapper for free-checking */
|
||||
|
||||
static Res freeCheckAlloc(Addr *aReturn, PoolDebugMixin debug, Pool pool,
|
||||
Size size, Bool withReservoir)
|
||||
Size size)
|
||||
{
|
||||
Res res;
|
||||
Addr new;
|
||||
|
||||
AVER(aReturn != NULL);
|
||||
|
||||
res = SuperclassOfPool(pool)->alloc(&new, pool, size, withReservoir);
|
||||
res = SuperclassOfPool(pool)->alloc(&new, pool, size);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
if (debug->freeSize != 0)
|
||||
|
|
@ -445,7 +445,7 @@ static void freeCheckFree(PoolDebugMixin debug,
|
|||
*/
|
||||
|
||||
static Res fenceAlloc(Addr *aReturn, PoolDebugMixin debug, Pool pool,
|
||||
Size size, Bool withReservoir)
|
||||
Size size)
|
||||
{
|
||||
Res res;
|
||||
Addr obj, startFence, clientNew, clientLimit, limit;
|
||||
|
|
@ -458,8 +458,7 @@ static Res fenceAlloc(Addr *aReturn, PoolDebugMixin debug, Pool pool,
|
|||
alignedFenceSize = SizeAlignUp(debug->fenceSize, PoolAlignment(pool));
|
||||
alignedSize = SizeAlignUp(size, PoolAlignment(pool));
|
||||
res = freeCheckAlloc(&obj, debug, pool,
|
||||
alignedSize + 2 * alignedFenceSize,
|
||||
withReservoir);
|
||||
alignedSize + 2 * alignedFenceSize);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
|
|
@ -526,7 +525,7 @@ static void fenceFree(PoolDebugMixin debug,
|
|||
/* tagAlloc -- allocation wrapper for tagged pools */
|
||||
|
||||
static Res tagAlloc(PoolDebugMixin debug,
|
||||
Pool pool, Addr new, Size size, Bool withReservoir)
|
||||
Pool pool, Addr new, Size size)
|
||||
{
|
||||
Tag tag;
|
||||
Res res;
|
||||
|
|
@ -534,15 +533,9 @@ static Res tagAlloc(PoolDebugMixin debug,
|
|||
Addr addr;
|
||||
|
||||
UNUSED(pool);
|
||||
res = PoolAlloc(&addr, debug->tagPool, debug->tagSize, FALSE);
|
||||
if (res != ResOK) {
|
||||
if (withReservoir) { /* <design/object-debug/#out-of-space */
|
||||
debug->missingTags++;
|
||||
return ResOK;
|
||||
} else {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
res = PoolAlloc(&addr, debug->tagPool, debug->tagSize);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
tag = (Tag)addr;
|
||||
tag->addr = new; tag->size = size;
|
||||
TreeInit(TagTree(tag));
|
||||
|
|
@ -585,8 +578,7 @@ static void tagFree(PoolDebugMixin debug, Pool pool, Addr old, Size size)
|
|||
* Eventually, tag init args will need to be handled somewhere here.
|
||||
*/
|
||||
|
||||
static Res DebugPoolAlloc(Addr *aReturn,
|
||||
Pool pool, Size size, Bool withReservoir)
|
||||
static Res DebugPoolAlloc(Addr *aReturn, Pool pool, Size size)
|
||||
{
|
||||
Res res;
|
||||
Addr new = NULL; /* suppress "may be used uninitialized" warning */
|
||||
|
|
@ -595,20 +587,19 @@ static Res DebugPoolAlloc(Addr *aReturn,
|
|||
AVER(aReturn != NULL);
|
||||
AVERT(Pool, pool);
|
||||
AVER(size > 0);
|
||||
AVERT(Bool, withReservoir);
|
||||
|
||||
debug = DebugPoolDebugMixin(pool);
|
||||
AVER(debug != NULL);
|
||||
AVERT(PoolDebugMixin, debug);
|
||||
if (debug->fenceSize != 0)
|
||||
res = fenceAlloc(&new, debug, pool, size, withReservoir);
|
||||
res = fenceAlloc(&new, debug, pool, size);
|
||||
else
|
||||
res = freeCheckAlloc(&new, debug, pool, size, withReservoir);
|
||||
res = freeCheckAlloc(&new, debug, pool, size);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
/* Allocate object first, so it fits even when the tag doesn't. */
|
||||
if (debug->tagInit != NULL) {
|
||||
res = tagAlloc(debug, pool, new, size, withReservoir);
|
||||
res = tagAlloc(debug, pool, new, size);
|
||||
if (res != ResOK)
|
||||
goto tagFail;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
*/
|
||||
|
||||
#define EVENT_VERSION_MAJOR ((unsigned)1)
|
||||
#define EVENT_VERSION_MEDIAN ((unsigned)4)
|
||||
#define EVENT_VERSION_MEDIAN ((unsigned)6)
|
||||
#define EVENT_VERSION_MINOR ((unsigned)0)
|
||||
|
||||
|
||||
|
|
@ -67,7 +67,7 @@
|
|||
*/
|
||||
|
||||
#define EventNameMAX ((size_t)19)
|
||||
#define EventCodeMAX ((EventCode)0x0086)
|
||||
#define EventCodeMAX ((EventCode)0x0087)
|
||||
|
||||
#define EVENT_LIST(EVENT, X) \
|
||||
/* 0123456789012345678 <- don't exceed without changing EventNameMAX */ \
|
||||
|
|
@ -160,7 +160,7 @@
|
|||
/* PoolPush/Pop go under Object, because they're user ops. */ \
|
||||
/* EVENT(X, PoolPush , 0x0060, TRUE, Object) */ \
|
||||
/* EVENT(X, PoolPop , 0x0061, TRUE, Object) */ \
|
||||
EVENT(X, ReservoirLimitSet , 0x0062, TRUE, Arena) \
|
||||
/* EVENT(X, ReservoirLimitSet , 0x0062, TRUE, Arena) */ \
|
||||
EVENT(X, CommitLimitSet , 0x0063, TRUE, Arena) \
|
||||
EVENT(X, SpareCommitLimitSet, 0x0064, TRUE, Arena) \
|
||||
EVENT(X, ArenaAlloc , 0x0065, TRUE, Arena) \
|
||||
|
|
@ -192,7 +192,8 @@
|
|||
EVENT(X, TraceCondemnZones , 0x0083, TRUE, Trace) \
|
||||
EVENT(X, ArenaGenZoneAdd , 0x0084, TRUE, Arena) \
|
||||
EVENT(X, ArenaUseFreeZone , 0x0085, TRUE, Arena) \
|
||||
/* EVENT(X, ArenaBlacklistZone , 0x0086, TRUE, Arena) */
|
||||
/* EVENT(X, ArenaBlacklistZone , 0x0086, TRUE, Arena) */ \
|
||||
EVENT(X, PauseTimeSet , 0x0087, TRUE, Arena)
|
||||
|
||||
|
||||
/* Remember to update EventNameMAX and EventCodeMAX above!
|
||||
|
|
@ -447,7 +448,7 @@
|
|||
PARAM(X, 1, W, condemned) \
|
||||
PARAM(X, 2, W, notCondemned) \
|
||||
PARAM(X, 3, W, foundation) \
|
||||
PARAM(X, 4, W, rate) \
|
||||
PARAM(X, 4, W, quantumWork) \
|
||||
PARAM(X, 5, D, mortality) \
|
||||
PARAM(X, 6, D, finishingTime)
|
||||
|
||||
|
|
@ -551,10 +552,6 @@
|
|||
PARAM(X, 2, B, isMutator) \
|
||||
PARAM(X, 3, U, rank)
|
||||
|
||||
#define EVENT_ReservoirLimitSet_PARAMS(PARAM, X) \
|
||||
PARAM(X, 0, P, arena) \
|
||||
PARAM(X, 1, W, size)
|
||||
|
||||
#define EVENT_CommitLimitSet_PARAMS(PARAM, X) \
|
||||
PARAM(X, 0, P, arena) \
|
||||
PARAM(X, 1, W, limit) \
|
||||
|
|
@ -583,8 +580,7 @@
|
|||
|
||||
#define EVENT_SegMerge_PARAMS(PARAM, X) \
|
||||
PARAM(X, 0, P, segLo) \
|
||||
PARAM(X, 1, P, segHi) \
|
||||
PARAM(X, 2, B, withReservoirPermit)
|
||||
PARAM(X, 1, P, segHi)
|
||||
|
||||
#define EVENT_SegSplit_PARAMS(PARAM, X) \
|
||||
PARAM(X, 0, P, seg) \
|
||||
|
|
@ -655,7 +651,7 @@
|
|||
#define EVENT_ArenaPoll_PARAMS(PARAM, X) \
|
||||
PARAM(X, 0, P, arena) \
|
||||
PARAM(X, 1, W, start) \
|
||||
PARAM(X, 2, W, quanta)
|
||||
PARAM(X, 2, B, workWasDone)
|
||||
|
||||
#define EVENT_ArenaSetEmergency_PARAMS(PARAM, X) \
|
||||
PARAM(X, 0, P, arena) \
|
||||
|
|
@ -674,7 +670,7 @@
|
|||
PARAM(X, 4, W, notCondemned) /* collectible but not condemned bytes */ \
|
||||
PARAM(X, 5, W, foundation) /* foundation size */ \
|
||||
PARAM(X, 6, W, white) /* white reference set */ \
|
||||
PARAM(X, 7, W, rate) /* segs to scan per increment */
|
||||
PARAM(X, 7, W, quantumWork) /* tracing work to be done in each poll */
|
||||
|
||||
#define EVENT_VMCompact_PARAMS(PARAM, X) \
|
||||
PARAM(X, 0, W, vmem0) /* pre-collection reserved size */ \
|
||||
|
|
@ -740,6 +736,10 @@
|
|||
PARAM(X, 0, P, arena) /* the arena */ \
|
||||
PARAM(X, 1, W, zoneSet) /* zones that aren't free any longer */
|
||||
|
||||
#define EVENT_PauseTimeSet_PARAMS(PARAM, X) \
|
||||
PARAM(X, 0, P, arena) /* the arena */ \
|
||||
PARAM(X, 1, D, pauseTime) /* the new maximum pause time, in seconds */
|
||||
|
||||
|
||||
#endif /* eventdef_h */
|
||||
|
||||
|
|
|
|||
|
|
@ -189,11 +189,11 @@ static void objDefine(objectTable table,
|
|||
if (table != NULL) {
|
||||
Res ires;
|
||||
|
||||
ires = TableDefine(table->startTable, (Word)logObj, obj);
|
||||
ires = TableDefine(table->startTable, (TableKey)logObj, obj);
|
||||
verify(ires == ResOK);
|
||||
if (table->endTable != NULL) {
|
||||
ires = TableDefine(table->endTable,
|
||||
(Word)PointerAdd(logObj, size),
|
||||
(TableKey)PointerAdd(logObj, size),
|
||||
PointerAdd(obj, size));
|
||||
verify(ires == ResOK);
|
||||
}
|
||||
|
|
@ -212,13 +212,13 @@ static void objRemove(void **objReturn, objectTable table,
|
|||
void *end;
|
||||
void *logEnd;
|
||||
|
||||
found = TableLookup(&obj, table->startTable, (Word)logObj);
|
||||
found = TableLookup(&obj, table->startTable, (TableKey)logObj);
|
||||
if (found) {
|
||||
ires = TableRemove(table->startTable, (Word)logObj);
|
||||
ires = TableRemove(table->startTable, (TableKey)logObj);
|
||||
verify(ires == ResOK);
|
||||
if (table->endTable != NULL) {
|
||||
ires = TableRemove(table->endTable,
|
||||
(Word)PointerAdd(logObj, size));
|
||||
(TableKey)PointerAdd(logObj, size));
|
||||
verify(ires == ResOK);
|
||||
}
|
||||
*objReturn = obj;
|
||||
|
|
@ -227,13 +227,13 @@ static void objRemove(void **objReturn, objectTable table,
|
|||
/* Must be a truncation. */
|
||||
verify(table->endTable != NULL);
|
||||
logEnd = PointerAdd(logObj, size);
|
||||
found = TableLookup(&end, table->endTable, (Word)logEnd);
|
||||
found = TableLookup(&end, table->endTable, (TableKey)logEnd);
|
||||
verify(found);
|
||||
obj = PointerSub(end, size);
|
||||
/* Remove the old end and insert the new one. */
|
||||
ires = TableRemove(table->endTable, (Word)logEnd);
|
||||
ires = TableRemove(table->endTable, (TableKey)logEnd);
|
||||
verify(ires == ResOK);
|
||||
ires = TableDefine(table->endTable, (Word)logObj, obj);
|
||||
ires = TableDefine(table->endTable, (TableKey)logObj, obj);
|
||||
verify(ires == ResOK);
|
||||
*objReturn = obj;
|
||||
return;
|
||||
|
|
@ -254,7 +254,7 @@ static void poolRecreate(void *logPool, void *logArena,
|
|||
void *entry;
|
||||
Bool found;
|
||||
|
||||
found = TableLookup(&entry, arenaTable, (Word)logArena);
|
||||
found = TableLookup(&entry, arenaTable, (TableKey)logArena);
|
||||
verify(found);
|
||||
va_start(args, bufferClassLevel);
|
||||
eres = mps_pool_create_v(&pool, (mps_arena_t)entry, class, args);
|
||||
|
|
@ -265,7 +265,7 @@ static void poolRecreate(void *logPool, void *logArena,
|
|||
rep->pool = pool;
|
||||
rep->objects = objectTableCreate(support);
|
||||
rep->bufferClassLevel = bufferClassLevel;
|
||||
ires = TableDefine(poolTable, (Word)logPool, (void *)rep);
|
||||
ires = TableDefine(poolTable, (TableKey)logPool, (void *)rep);
|
||||
verify(ires == ResOK);
|
||||
}
|
||||
|
||||
|
|
@ -279,11 +279,11 @@ static void poolRedestroy(void *logPool)
|
|||
Bool found;
|
||||
poolRep rep;
|
||||
|
||||
found = TableLookup(&entry, poolTable, (Word)logPool);
|
||||
found = TableLookup(&entry, poolTable, (TableKey)logPool);
|
||||
verify(found);
|
||||
rep = (poolRep)entry;
|
||||
mps_pool_destroy(rep->pool);
|
||||
ires = TableRemove(poolTable, (Word)logPool);
|
||||
ires = TableRemove(poolTable, (TableKey)logPool);
|
||||
verify(ires == ResOK);
|
||||
objectTableDestroy(rep->objects);
|
||||
free(rep);
|
||||
|
|
@ -303,7 +303,7 @@ static void apRecreate(void *logAp, void *logPool, ...)
|
|||
void *entry;
|
||||
Bool found;
|
||||
|
||||
found = TableLookup(&entry, poolTable, (Word)logPool);
|
||||
found = TableLookup(&entry, poolTable, (TableKey)logPool);
|
||||
verify(found);
|
||||
pRep = (poolRep)entry;
|
||||
va_start(args, logPool);
|
||||
|
|
@ -314,7 +314,7 @@ static void apRecreate(void *logAp, void *logPool, ...)
|
|||
verify(aRep != NULL);
|
||||
aRep->ap = ap;
|
||||
aRep->objects = pRep->objects;
|
||||
ires = TableDefine(apTable, (Word)logAp, (void *)aRep);
|
||||
ires = TableDefine(apTable, (TableKey)logAp, (void *)aRep);
|
||||
verify(ires == ResOK);
|
||||
}
|
||||
|
||||
|
|
@ -328,11 +328,11 @@ static void apRedestroy(void *logAp)
|
|||
Bool found;
|
||||
apRep rep;
|
||||
|
||||
found = TableLookup(&entry, apTable, (Word)logAp);
|
||||
found = TableLookup(&entry, apTable, (TableKey)logAp);
|
||||
verify(found);
|
||||
rep = (apRep)entry;
|
||||
mps_ap_destroy(rep->ap);
|
||||
ires = TableRemove(apTable, (Word)logAp);
|
||||
ires = TableRemove(apTable, (TableKey)logAp);
|
||||
verify(ires == ResOK);
|
||||
free(rep);
|
||||
}
|
||||
|
|
@ -358,7 +358,7 @@ void EventReplay(Event event, Word etime)
|
|||
eres = mps_arena_create(&arena, mps_arena_class_vm(),
|
||||
event->pww.w1);
|
||||
verifyMPS(eres);
|
||||
ires = TableDefine(arenaTable, (Word)event->pww.p0, (void *)arena);
|
||||
ires = TableDefine(arenaTable, (TableKey)event->pww.p0, (void *)arena);
|
||||
verify(ires == ResOK);
|
||||
arenaJustCreated = TRUE;
|
||||
} break;
|
||||
|
|
@ -368,7 +368,7 @@ void EventReplay(Event event, Word etime)
|
|||
eres = mps_arena_create(&arena, mps_arena_class_vmnz(),
|
||||
event->pww.w1);
|
||||
verifyMPS(eres);
|
||||
ires = TableDefine(arenaTable, (Word)event->pww.p0, (void *)arena);
|
||||
ires = TableDefine(arenaTable, (TableKey)event->pww.p0, (void *)arena);
|
||||
verify(ires == ResOK);
|
||||
arenaJustCreated = TRUE;
|
||||
} break;
|
||||
|
|
@ -381,15 +381,15 @@ void EventReplay(Event event, Word etime)
|
|||
eres = mps_arena_create(&arena, mps_arena_class_cl(),
|
||||
(Size)event->pwa.w1, base);
|
||||
verifyMPS(eres);
|
||||
ires = TableDefine(arenaTable, (Word)event->pw.p0, (void *)arena);
|
||||
ires = TableDefine(arenaTable, (TableKey)event->pw.p0, (void *)arena);
|
||||
verify(ires == ResOK);
|
||||
arenaJustCreated = TRUE;
|
||||
} break;
|
||||
case EventArenaDestroy: { /* arena */
|
||||
found = TableLookup(&entry, arenaTable, (Word)event->p.p0);
|
||||
found = TableLookup(&entry, arenaTable, (TableKey)event->p.p0);
|
||||
verify(found);
|
||||
mps_arena_destroy((mps_arena_t)entry);
|
||||
ires = TableRemove(arenaTable, (Word)event->pw.p0);
|
||||
ires = TableRemove(arenaTable, (TableKey)event->pw.p0);
|
||||
verify(ires == ResOK);
|
||||
} break;
|
||||
case EventPoolInitMVFF: {
|
||||
|
|
@ -423,7 +423,7 @@ void EventReplay(Event event, Word etime)
|
|||
++discardedEvents;
|
||||
} break;
|
||||
case EventPoolFinish: { /* pool */
|
||||
found = TableLookup(&entry, poolTable, (Word)event->p.p0);
|
||||
found = TableLookup(&entry, poolTable, (TableKey)event->p.p0);
|
||||
if (found) {
|
||||
poolRedestroy(event->p.p0);
|
||||
} else {
|
||||
|
|
@ -432,7 +432,7 @@ void EventReplay(Event event, Word etime)
|
|||
} break;
|
||||
case EventBufferInit: { /* buffer, pool, isMutator */
|
||||
if ((Bool)event->ppu.u2) {
|
||||
found = TableLookup(&entry, poolTable, (Word)event->ppu.p1);
|
||||
found = TableLookup(&entry, poolTable, (TableKey)event->ppu.p1);
|
||||
if (found) {
|
||||
poolRep rep = (poolRep)entry;
|
||||
|
||||
|
|
@ -450,7 +450,7 @@ void EventReplay(Event event, Word etime)
|
|||
} break;
|
||||
case EventBufferInitSeg: { /* buffer, pool, isMutator */
|
||||
if ((Bool)event->ppu.u2) {
|
||||
found = TableLookup(&entry, poolTable, (Word)event->ppu.p1);
|
||||
found = TableLookup(&entry, poolTable, (TableKey)event->ppu.p1);
|
||||
if (found) {
|
||||
poolRep rep = (poolRep)entry;
|
||||
|
||||
|
|
@ -468,7 +468,7 @@ void EventReplay(Event event, Word etime)
|
|||
} break;
|
||||
case EventBufferInitRank: { /* buffer, pool, isMutator, rank */
|
||||
if ((Bool)event->ppuu.u2) {
|
||||
found = TableLookup(&entry, poolTable, (Word)event->ppuu.p1);
|
||||
found = TableLookup(&entry, poolTable, (TableKey)event->ppuu.p1);
|
||||
if (found) {
|
||||
poolRep rep = (poolRep)entry;
|
||||
|
||||
|
|
@ -485,7 +485,7 @@ void EventReplay(Event event, Word etime)
|
|||
}
|
||||
} break;
|
||||
case EventBufferFinish: { /* buffer */
|
||||
found = TableLookup(&entry, apTable, (Word)event->p.p0);
|
||||
found = TableLookup(&entry, apTable, (TableKey)event->p.p0);
|
||||
if (found) {
|
||||
apRedestroy(event->p.p0);
|
||||
} else {
|
||||
|
|
@ -493,7 +493,7 @@ void EventReplay(Event event, Word etime)
|
|||
}
|
||||
} break;
|
||||
case EventBufferReserve: { /* buffer, init, size */
|
||||
found = TableLookup(&entry, apTable, (Word)event->paw.p0);
|
||||
found = TableLookup(&entry, apTable, (TableKey)event->paw.p0);
|
||||
if (found) {
|
||||
apRep rep = (apRep)entry;
|
||||
mps_addr_t p;
|
||||
|
|
@ -505,7 +505,7 @@ void EventReplay(Event event, Word etime)
|
|||
}
|
||||
} break;
|
||||
case EventBufferCommit: { /* buffer, p, size, clientClass */
|
||||
found = TableLookup(&entry, apTable, (Word)event->pawa.p0);
|
||||
found = TableLookup(&entry, apTable, (TableKey)event->pawa.p0);
|
||||
if (found) {
|
||||
apRep rep = (apRep)entry;
|
||||
mps_addr_t obj = rep->ap->init;
|
||||
|
|
@ -520,7 +520,7 @@ void EventReplay(Event event, Word etime)
|
|||
}
|
||||
} break;
|
||||
case EventPoolAlloc: { /* pool, obj, size */
|
||||
found = TableLookup(&entry, poolTable, (Word)event->paw.p0);
|
||||
found = TableLookup(&entry, poolTable, (TableKey)event->paw.p0);
|
||||
if (found) {
|
||||
poolRep rep = (poolRep)entry;
|
||||
void *obj;
|
||||
|
|
@ -534,7 +534,7 @@ void EventReplay(Event event, Word etime)
|
|||
}
|
||||
} break;
|
||||
case EventPoolFree: { /* pool, obj, size */
|
||||
found = TableLookup(&entry, poolTable, (Word)event->paw.p0);
|
||||
found = TableLookup(&entry, poolTable, (TableKey)event->paw.p0);
|
||||
if (found) {
|
||||
poolRep rep = (poolRep)entry;
|
||||
void *obj;
|
||||
|
|
@ -547,7 +547,7 @@ void EventReplay(Event event, Word etime)
|
|||
}
|
||||
} break;
|
||||
case EventCommitLimitSet: { /* arena, limit, succeeded */
|
||||
found = TableLookup(&entry, arenaTable, (Word)event->pwu.p0);
|
||||
found = TableLookup(&entry, arenaTable, (TableKey)event->pwu.p0);
|
||||
verify(found);
|
||||
eres = mps_arena_commit_limit_set((mps_arena_t)entry,
|
||||
(size_t)event->pwu.w1);
|
||||
|
|
@ -555,16 +555,11 @@ void EventReplay(Event event, Word etime)
|
|||
? MPS_RES_OK : MPS_RES_FAIL);
|
||||
} break;
|
||||
case EventSpareCommitLimitSet: { /* arena, limit */
|
||||
found = TableLookup(&entry, arenaTable, (Word)event->pw.p0);
|
||||
found = TableLookup(&entry, arenaTable, (TableKey)event->pw.p0);
|
||||
verify(found);
|
||||
(void)mps_arena_spare_commit_limit_set((mps_arena_t)entry,
|
||||
(size_t)event->pw.w1);
|
||||
} break;
|
||||
case EventReservoirLimitSet: { /* arena, limit */
|
||||
found = TableLookup(&entry, arenaTable, (Word)event->pw.p0);
|
||||
verify(found);
|
||||
mps_reservoir_limit_set((mps_arena_t)entry, (size_t)event->pw.w1);
|
||||
} break;
|
||||
case EventVMMap: case EventVMUnmap:
|
||||
case EventVMInit: case EventVMFinish:
|
||||
case EventArenaWriteFaults:
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ static void createTables(mps_pool_t pool)
|
|||
res = TableCreate(&internTable,
|
||||
(size_t)1<<4,
|
||||
tableAlloc, tableFree, pool,
|
||||
(Word)-1, (Word)-2);
|
||||
(TableKey)-1, (TableKey)-2);
|
||||
if (res != ResOK)
|
||||
everror("Couldn't make intern table.");
|
||||
|
||||
|
|
@ -280,7 +280,7 @@ static void recordIntern(mps_pool_t pool, char *p)
|
|||
if (res != MPS_RES_OK)
|
||||
everror("Couldn't allocate space for a string.");
|
||||
(void)strcpy(copy, string);
|
||||
res = TableDefine(internTable, (Word)stringId, (void *)copy);
|
||||
res = TableDefine(internTable, (TableKey)stringId, (void *)copy);
|
||||
if (res != ResOK)
|
||||
everror("Couldn't create an intern mapping.");
|
||||
}
|
||||
|
|
@ -359,7 +359,7 @@ static void recordLabel(mps_pool_t pool, EventClock clock, char *p)
|
|||
return;
|
||||
}
|
||||
|
||||
if (TableLookup(&tmp, labelTable, address)) {
|
||||
if (TableLookup(&tmp, labelTable, (TableKey)address)) {
|
||||
list = tmp;
|
||||
} else {
|
||||
/* First label for this address */
|
||||
|
|
@ -368,7 +368,7 @@ static void recordLabel(mps_pool_t pool, EventClock clock, char *p)
|
|||
everror("Can't allocate space for a label list");
|
||||
list = tmp;
|
||||
list->n = 0;
|
||||
res = TableDefine(labelTable, (Word)address, list);
|
||||
res = TableDefine(labelTable, (TableKey)address, list);
|
||||
if (res != ResOK)
|
||||
everror("Couldn't create a label mapping.");
|
||||
}
|
||||
|
|
@ -408,13 +408,13 @@ static void printAddr(EventClock clock, ulongest_t addr, const char *ident)
|
|||
void *tmp;
|
||||
|
||||
printf("%s:%0*" PRIXLONGEST, ident, hexWordWidth, addr);
|
||||
if (TableLookup(&tmp, labelTable, addr)) {
|
||||
if (TableLookup(&tmp, labelTable, (TableKey)addr)) {
|
||||
LabelList list = tmp;
|
||||
size_t pos = labelFind(list, clock);
|
||||
if (pos > 0) {
|
||||
ulongest_t id = list->labels[pos - 1].id;
|
||||
putchar('[');
|
||||
if (TableLookup(&tmp, internTable, id))
|
||||
if (TableLookup(&tmp, internTable, (TableKey)id))
|
||||
printStr((char *)tmp);
|
||||
else
|
||||
printf("unknown label %" PRIXLONGEST, id);
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ static Res failoverDelete(Range rangeReturn, Land land, Range range)
|
|||
}
|
||||
|
||||
|
||||
static Bool failoverIterate(Land land, LandVisitor visitor, void *closureP, Size closureS)
|
||||
static Bool failoverIterate(Land land, LandVisitor visitor, void *closure)
|
||||
{
|
||||
Failover fo;
|
||||
|
||||
|
|
@ -186,8 +186,8 @@ static Bool failoverIterate(Land land, LandVisitor visitor, void *closureP, Size
|
|||
AVERT(Failover, fo);
|
||||
AVER(visitor != NULL);
|
||||
|
||||
return LandIterate(fo->primary, visitor, closureP, closureS)
|
||||
&& LandIterate(fo->secondary, visitor, closureP, closureS);
|
||||
return LandIterate(fo->primary, visitor, closure)
|
||||
&& LandIterate(fo->secondary, visitor, closure);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -94,13 +94,11 @@ static void describe(FBMState state) {
|
|||
}
|
||||
|
||||
|
||||
static Bool checkCallback(Range range, void *closureP, Size closureS)
|
||||
static Bool checkCallback(Range range, void *closure)
|
||||
{
|
||||
Addr base, limit;
|
||||
CheckFBMClosure cl = (CheckFBMClosure)closureP;
|
||||
CheckFBMClosure cl = (CheckFBMClosure)closure;
|
||||
|
||||
AVER(closureS == UNUSED_SIZE);
|
||||
UNUSED(closureS);
|
||||
Insist(cl != NULL);
|
||||
|
||||
base = RangeBase(range);
|
||||
|
|
@ -126,18 +124,18 @@ static Bool checkCallback(Range range, void *closureP, Size closureS)
|
|||
|
||||
|
||||
static Bool checkCBSCallback(CBS cbs, Range range,
|
||||
void *closureP, Size closureS)
|
||||
void *closure)
|
||||
{
|
||||
UNUSED(cbs);
|
||||
return checkCallback(range, closureP, closureS);
|
||||
return checkCallback(range, closure);
|
||||
}
|
||||
|
||||
|
||||
static Bool checkFLCallback(Bool *deleteReturn, Range range,
|
||||
void *closureP, Size closureS)
|
||||
void *closure)
|
||||
{
|
||||
*deleteReturn = FALSE;
|
||||
return checkCallback(range, closureP, closureS);
|
||||
return checkCallback(range, closure);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -151,10 +149,10 @@ static void check(FBMState state)
|
|||
|
||||
switch (state->type) {
|
||||
case FBMTypeCBS:
|
||||
CBSIterate(state->the.cbs, checkCBSCallback, &closure, UNUSED_SIZE);
|
||||
CBSIterate(state->the.cbs, checkCBSCallback, &closure);
|
||||
break;
|
||||
case FBMTypeFreelist:
|
||||
FreelistIterate(state->the.fl, checkFLCallback, &closure, UNUSED_SIZE);
|
||||
FreelistIterate(state->the.fl, checkFLCallback, &closure);
|
||||
break;
|
||||
default:
|
||||
cdie(0, "invalid state->type");
|
||||
|
|
@ -578,8 +576,7 @@ extern int main(int argc, char *argv[])
|
|||
|
||||
/* We're not going to use this block, but I feel unhappy just */
|
||||
/* inventing addresses. */
|
||||
die((mps_res_t)ControlAlloc(&p, arena, ArraySize * align,
|
||||
/* withReservoirPermit */ FALSE),
|
||||
die((mps_res_t)ControlAlloc(&p, arena, ArraySize * align);
|
||||
"failed to allocate block");
|
||||
dummyBlock = p; /* avoid pun */
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,9 @@
|
|||
#include "mps.h"
|
||||
#include "mpsavm.h"
|
||||
#include "mpscamc.h"
|
||||
#include "mpscams.h"
|
||||
#include "mpscawl.h"
|
||||
#include "mpsclo.h"
|
||||
#include "mpslib.h"
|
||||
#include "mpstd.h"
|
||||
#include "testlib.h"
|
||||
|
|
@ -37,6 +40,7 @@
|
|||
#define finalizationRATE 6
|
||||
#define gcINTERVAL ((size_t)150 * 1024)
|
||||
#define collectionCOUNT 3
|
||||
#define messageCOUNT 3
|
||||
|
||||
/* 3 words: wrapper | vector-len | first-slot */
|
||||
#define vectorSIZE (3*sizeof(mps_word_t))
|
||||
|
|
@ -95,35 +99,37 @@ enum {
|
|||
};
|
||||
|
||||
|
||||
static void *test(void *arg, size_t s)
|
||||
static void test(mps_arena_t arena, mps_pool_class_t pool_class)
|
||||
{
|
||||
unsigned i; /* index */
|
||||
size_t i; /* index */
|
||||
mps_ap_t ap;
|
||||
mps_fmt_t fmt;
|
||||
mps_chain_t chain;
|
||||
mps_pool_t amc;
|
||||
mps_pool_t pool;
|
||||
mps_res_t e;
|
||||
mps_root_t mps_root[2];
|
||||
mps_addr_t nullref = NULL;
|
||||
int state[rootCOUNT];
|
||||
mps_arena_t arena;
|
||||
void *p = NULL;
|
||||
mps_message_t message;
|
||||
size_t messages = 0;
|
||||
void *p;
|
||||
|
||||
arena = (mps_arena_t)arg;
|
||||
(void)s;
|
||||
printf("---- finalcv: pool class %s ----\n", pool_class->name);
|
||||
|
||||
die(mps_fmt_create_A(&fmt, arena, dylan_fmt_A()), "fmt_create\n");
|
||||
die(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create");
|
||||
die(mps_pool_create(&amc, arena, mps_class_amc(), fmt, chain),
|
||||
"pool_create amc\n");
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_FORMAT, fmt);
|
||||
die(mps_pool_create_k(&pool, arena, pool_class, args), "pool_create\n");
|
||||
} MPS_ARGS_END(args);
|
||||
die(mps_root_create_table(&mps_root[0], arena, mps_rank_exact(), (mps_rm_t)0,
|
||||
root, (size_t)rootCOUNT),
|
||||
"root_create\n");
|
||||
die(mps_root_create_table(&mps_root[1], arena, mps_rank_exact(), (mps_rm_t)0,
|
||||
&p, (size_t)1),
|
||||
"root_create\n");
|
||||
die(mps_ap_create(&ap, amc, mps_rank_exact()), "ap_create\n");
|
||||
die(mps_ap_create(&ap, pool, mps_rank_exact()), "ap_create\n");
|
||||
|
||||
/* Make registered-for-finalization objects. */
|
||||
/* <design/poolmrg/#test.promise.ut.alloc> */
|
||||
|
|
@ -142,12 +148,10 @@ static void *test(void *arg, size_t s)
|
|||
}
|
||||
p = NULL;
|
||||
|
||||
die(ArenaDescribe(arena, mps_lib_get_stdout(), 0), "ArenaDescribe");
|
||||
|
||||
mps_message_type_enable(arena, mps_message_type_finalization());
|
||||
|
||||
/* <design/poolmrg/#test.promise.ut.churn> */
|
||||
while (mps_collections(arena) < collectionCOUNT) {
|
||||
while (messages < messageCOUNT && mps_collections(arena) < collectionCOUNT) {
|
||||
|
||||
/* Perhaps cause (minor) collection */
|
||||
churn(ap);
|
||||
|
|
@ -197,36 +201,34 @@ static void *test(void *arg, size_t s)
|
|||
if (rnd() % 2 == 0)
|
||||
root[objind] = objaddr;
|
||||
mps_message_discard(arena, message);
|
||||
++ messages;
|
||||
}
|
||||
}
|
||||
|
||||
/* @@@@ <design/poolmrg/#test.promise.ut.nofinal.check> missing */
|
||||
|
||||
mps_arena_park(arena);
|
||||
mps_ap_destroy(ap);
|
||||
mps_root_destroy(mps_root[1]);
|
||||
mps_root_destroy(mps_root[0]);
|
||||
mps_pool_destroy(amc);
|
||||
mps_pool_destroy(pool);
|
||||
mps_chain_destroy(chain);
|
||||
mps_fmt_destroy(fmt);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
mps_arena_t arena;
|
||||
mps_thr_t thread;
|
||||
void *r;
|
||||
|
||||
testlib_init(argc, argv);
|
||||
|
||||
die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE),
|
||||
"arena_create\n");
|
||||
die(mps_thread_reg(&thread, arena), "thread_reg\n");
|
||||
mps_tramp(&r, test, arena, 0);
|
||||
mps_thread_dereg(thread);
|
||||
|
||||
test(arena, mps_class_amc());
|
||||
test(arena, mps_class_amcz());
|
||||
test(arena, mps_class_awl());
|
||||
test(arena, mps_class_ams());
|
||||
test(arena, mps_class_lo());
|
||||
|
||||
mps_arena_destroy(arena);
|
||||
|
||||
printf("%s: Conclusion: Failed to find any defects.\n", argv[0]);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* fmtscheme.c: SCHEME OBJECT FORMAT IMPLEMENTATION
|
||||
*
|
||||
* $Id: //info.ravenbrook.com/project/mps/branch/2014-01-15/nailboard/code/fmtdy.c#1 $
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
|
@ -460,7 +460,7 @@ void scheme_fmt(mps_fmt_t *fmt)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 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 @@
|
|||
/* fmtscheme.h: SCHEME OBJECT FORMAT INTERFACE
|
||||
*
|
||||
* $Id: //info.ravenbrook.com/project/mps/branch/2014-01-15/nailboard/code/fmtdy.h#1 $
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
*/
|
||||
|
||||
#ifndef fmtscheme_h
|
||||
|
|
@ -40,55 +40,55 @@ typedef struct type_s {
|
|||
} type_s;
|
||||
|
||||
typedef struct pair_s {
|
||||
type_t type; /* TYPE_PAIR */
|
||||
obj_t car, cdr; /* first and second projections */
|
||||
type_t type; /* TYPE_PAIR */
|
||||
obj_t car, cdr; /* first and second projections */
|
||||
} pair_s;
|
||||
|
||||
typedef struct symbol_s {
|
||||
type_t type; /* TYPE_SYMBOL */
|
||||
size_t length; /* length of symbol string (excl. NUL) */
|
||||
char string[1]; /* symbol string, NUL terminated */
|
||||
type_t type; /* TYPE_SYMBOL */
|
||||
size_t length; /* length of symbol string (excl. NUL) */
|
||||
char string[1]; /* symbol string, NUL terminated */
|
||||
} symbol_s;
|
||||
|
||||
typedef struct integer_s {
|
||||
type_t type; /* TYPE_INTEGER */
|
||||
long integer; /* the integer */
|
||||
type_t type; /* TYPE_INTEGER */
|
||||
long integer; /* the integer */
|
||||
} integer_s;
|
||||
|
||||
typedef struct special_s {
|
||||
type_t type; /* TYPE_SPECIAL */
|
||||
char *name; /* printed representation, NUL terminated */
|
||||
type_t type; /* TYPE_SPECIAL */
|
||||
char *name; /* printed representation, NUL terminated */
|
||||
} special_s;
|
||||
|
||||
typedef struct operator_s {
|
||||
type_t type; /* TYPE_OPERATOR */
|
||||
char *name; /* printed name, NUL terminated */
|
||||
entry_t entry; /* entry point -- see eval() */
|
||||
obj_t arguments, body; /* function arguments and code */
|
||||
obj_t env, op_env; /* closure environments */
|
||||
type_t type; /* TYPE_OPERATOR */
|
||||
char *name; /* printed name, NUL terminated */
|
||||
entry_t entry; /* entry point -- see eval() */
|
||||
obj_t arguments, body; /* function arguments and code */
|
||||
obj_t env, op_env; /* closure environments */
|
||||
} operator_s;
|
||||
|
||||
typedef struct string_s {
|
||||
type_t type; /* TYPE_STRING */
|
||||
size_t length; /* number of chars in string */
|
||||
char string[1]; /* string, NUL terminated */
|
||||
type_t type; /* TYPE_STRING */
|
||||
size_t length; /* number of chars in string */
|
||||
char string[1]; /* string, NUL terminated */
|
||||
} string_s;
|
||||
|
||||
typedef struct port_s {
|
||||
type_t type; /* TYPE_PORT */
|
||||
obj_t name; /* name of stream */
|
||||
type_t type; /* TYPE_PORT */
|
||||
obj_t name; /* name of stream */
|
||||
FILE *stream;
|
||||
} port_s;
|
||||
|
||||
typedef struct character_s {
|
||||
type_t type; /* TYPE_CHARACTER */
|
||||
char c; /* the character */
|
||||
type_t type; /* TYPE_CHARACTER */
|
||||
char c; /* the character */
|
||||
} character_s;
|
||||
|
||||
typedef struct vector_s {
|
||||
type_t type; /* TYPE_VECTOR */
|
||||
size_t length; /* number of elements */
|
||||
obj_t vector[1]; /* vector elements */
|
||||
type_t type; /* TYPE_VECTOR */
|
||||
size_t length; /* number of elements */
|
||||
obj_t vector[1]; /* vector elements */
|
||||
} vector_s;
|
||||
|
||||
typedef struct table_s {
|
||||
|
|
@ -134,7 +134,7 @@ typedef struct pad_s {
|
|||
|
||||
|
||||
typedef union obj_u {
|
||||
type_s type; /* one of TYPE_* */
|
||||
type_s type; /* one of TYPE_* */
|
||||
pair_s pair;
|
||||
symbol_s symbol;
|
||||
integer_s integer;
|
||||
|
|
@ -154,17 +154,17 @@ typedef union obj_u {
|
|||
|
||||
/* structure macros */
|
||||
|
||||
#define TYPE(obj) ((obj)->type.type)
|
||||
#define CAR(obj) ((obj)->pair.car)
|
||||
#define CDR(obj) ((obj)->pair.cdr)
|
||||
#define CAAR(obj) CAR(CAR(obj))
|
||||
#define CADR(obj) CAR(CDR(obj))
|
||||
#define CDAR(obj) CDR(CAR(obj))
|
||||
#define CDDR(obj) CDR(CDR(obj))
|
||||
#define CADDR(obj) CAR(CDDR(obj))
|
||||
#define CDDDR(obj) CDR(CDDR(obj))
|
||||
#define CDDAR(obj) CDR(CDAR(obj))
|
||||
#define CADAR(obj) CAR(CDAR(obj))
|
||||
#define TYPE(obj) ((obj)->type.type)
|
||||
#define CAR(obj) ((obj)->pair.car)
|
||||
#define CDR(obj) ((obj)->pair.cdr)
|
||||
#define CAAR(obj) CAR(CAR(obj))
|
||||
#define CADR(obj) CAR(CDR(obj))
|
||||
#define CDAR(obj) CDR(CAR(obj))
|
||||
#define CDDR(obj) CDR(CDR(obj))
|
||||
#define CADDR(obj) CAR(CDDR(obj))
|
||||
#define CDDDR(obj) CDR(CDDR(obj))
|
||||
#define CDDAR(obj) CDR(CDAR(obj))
|
||||
#define CADAR(obj) CAR(CDAR(obj))
|
||||
|
||||
|
||||
extern obj_t scheme_make_bool(int condition);
|
||||
|
|
@ -193,7 +193,7 @@ extern mps_ap_t obj_ap;
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -133,14 +133,14 @@ Res FormatCreate(Format *formatReturn, Arena arena, ArgList args)
|
|||
if (ArgPick(&arg, args, MPS_KEY_FMT_CLASS))
|
||||
fmtClass = arg.val.fmt_class;
|
||||
|
||||
res = ControlAlloc(&p, arena, sizeof(FormatStruct),
|
||||
/* withReservoirPermit */ FALSE);
|
||||
res = ControlAlloc(&p, arena, sizeof(FormatStruct));
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
format = (Format)p; /* avoid pun */
|
||||
|
||||
format->arena = arena;
|
||||
RingInit(&format->arenaRing);
|
||||
format->poolCount = 0;
|
||||
format->alignment = fmtAlign;
|
||||
format->headerSize = fmtHeaderSize;
|
||||
format->scan = fmtScan;
|
||||
|
|
@ -168,6 +168,7 @@ Res FormatCreate(Format *formatReturn, Arena arena, ArgList args)
|
|||
void FormatDestroy(Format format)
|
||||
{
|
||||
AVERT(Format, format);
|
||||
AVER(format->poolCount == 0);
|
||||
|
||||
RingRemove(&format->arenaRing);
|
||||
|
||||
|
|
@ -190,6 +191,36 @@ Arena FormatArena(Format format)
|
|||
}
|
||||
|
||||
|
||||
/* FormatScan -- scan formatted objects for references
|
||||
*
|
||||
* This is a wrapper for formatted objects scanning functions, which
|
||||
* should not otherwise be called directly from within the MPS. This
|
||||
* function checks arguments and takes care of accounting for the
|
||||
* scanned memory.
|
||||
*
|
||||
* c.f. TraceScanArea()
|
||||
*/
|
||||
|
||||
Res FormatScan(Format format, ScanState ss, Addr base, Addr limit)
|
||||
{
|
||||
/* TODO: How critical are these? */
|
||||
AVERT_CRITICAL(Format, format);
|
||||
AVERT_CRITICAL(ScanState, ss);
|
||||
AVER_CRITICAL(base != NULL);
|
||||
AVER_CRITICAL(limit != NULL);
|
||||
AVER_CRITICAL(base < limit);
|
||||
|
||||
/* TODO: EVENT here? */
|
||||
|
||||
/* scannedSize is accumulated whether or not format->scan succeeds,
|
||||
so it's safe to accumulate now so that we can tail-call
|
||||
format->scan. */
|
||||
ss->scannedSize += AddrOffset(base, limit);
|
||||
|
||||
return format->scan(&ss->ss_s, base, limit);
|
||||
}
|
||||
|
||||
|
||||
/* FormatDescribe -- describe a format */
|
||||
|
||||
Res FormatDescribe(Format format, mps_lib_FILE *stream, Count depth)
|
||||
|
|
@ -200,6 +231,7 @@ Res FormatDescribe(Format format, mps_lib_FILE *stream, Count depth)
|
|||
"Format $P ($U) {\n", (WriteFP)format, (WriteFU)format->serial,
|
||||
" arena $P ($U)\n",
|
||||
(WriteFP)format->arena, (WriteFU)format->arena->serial,
|
||||
" poolCount $U\n", (WriteFU)format->poolCount,
|
||||
" alignment $W\n", (WriteFW)format->alignment,
|
||||
" scan $F\n", (WriteFF)format->scan,
|
||||
" skip $F\n", (WriteFF)format->skip,
|
||||
|
|
|
|||
|
|
@ -45,13 +45,11 @@ extern Land _mps_mvt_cbs(Pool);
|
|||
/* "OOM" pool class -- dummy alloc/free pool class whose alloc()
|
||||
* method always fails and whose free method does nothing. */
|
||||
|
||||
static Res oomAlloc(Addr *pReturn, Pool pool, Size size,
|
||||
Bool withReservoirPermit)
|
||||
static Res oomAlloc(Addr *pReturn, Pool pool, Size size)
|
||||
{
|
||||
UNUSED(pReturn);
|
||||
UNUSED(pool);
|
||||
UNUSED(size);
|
||||
UNUSED(withReservoirPermit);
|
||||
switch (rnd() % 3) {
|
||||
case 0:
|
||||
return ResRESOURCE;
|
||||
|
|
|
|||
|
|
@ -444,7 +444,7 @@ static Res freelistDelete(Range rangeReturn, Land land, Range range)
|
|||
|
||||
|
||||
static Bool freelistIterate(Land land, LandVisitor visitor,
|
||||
void *closureP, Size closureS)
|
||||
void *closure)
|
||||
{
|
||||
Freelist fl;
|
||||
FreelistBlock cur, next;
|
||||
|
|
@ -453,7 +453,7 @@ static Bool freelistIterate(Land land, LandVisitor visitor,
|
|||
fl = freelistOfLand(land);
|
||||
AVERT(Freelist, fl);
|
||||
AVER(FUNCHECK(visitor));
|
||||
/* closureP and closureS are arbitrary */
|
||||
/* closure arbitrary */
|
||||
|
||||
for (cur = fl->list; cur != freelistEND; cur = next) {
|
||||
RangeStruct range;
|
||||
|
|
@ -462,7 +462,7 @@ static Bool freelistIterate(Land land, LandVisitor visitor,
|
|||
* visitor touches the block. */
|
||||
next = freelistBlockNext(cur);
|
||||
RangeInit(&range, freelistBlockBase(cur), freelistBlockLimit(fl, cur));
|
||||
cont = (*visitor)(land, &range, closureP, closureS);
|
||||
cont = (*visitor)(land, &range, closure);
|
||||
if (!cont)
|
||||
return FALSE;
|
||||
}
|
||||
|
|
@ -471,7 +471,7 @@ static Bool freelistIterate(Land land, LandVisitor visitor,
|
|||
|
||||
|
||||
static Bool freelistIterateAndDelete(Land land, LandDeleteVisitor visitor,
|
||||
void *closureP, Size closureS)
|
||||
void *closure)
|
||||
{
|
||||
Freelist fl;
|
||||
FreelistBlock prev, cur, next;
|
||||
|
|
@ -480,7 +480,7 @@ static Bool freelistIterateAndDelete(Land land, LandDeleteVisitor visitor,
|
|||
fl = freelistOfLand(land);
|
||||
AVERT(Freelist, fl);
|
||||
AVER(FUNCHECK(visitor));
|
||||
/* closureP and closureS are arbitrary */
|
||||
/* closure arbitrary */
|
||||
|
||||
prev = freelistEND;
|
||||
cur = fl->list;
|
||||
|
|
@ -492,7 +492,7 @@ static Bool freelistIterateAndDelete(Land land, LandDeleteVisitor visitor,
|
|||
next = freelistBlockNext(cur); /* See .next.first. */
|
||||
size = freelistBlockSize(fl, cur);
|
||||
RangeInit(&range, freelistBlockBase(cur), freelistBlockLimit(fl, cur));
|
||||
cont = (*visitor)(&delete, land, &range, closureP, closureS);
|
||||
cont = (*visitor)(&delete, land, &range, closure);
|
||||
if (delete) {
|
||||
freelistBlockSetPrevNext(fl, prev, next, -1);
|
||||
AVER(fl->size >= size);
|
||||
|
|
@ -746,24 +746,28 @@ static Res freelistFindInZones(Bool *foundReturn, Range rangeReturn,
|
|||
/* freelistDescribeVisitor -- visitor method for freelistDescribe
|
||||
*
|
||||
* Writes a decription of the range into the stream pointed to by
|
||||
* closureP.
|
||||
* closure.
|
||||
*/
|
||||
|
||||
typedef struct FreelistDescribeClosureStruct {
|
||||
mps_lib_FILE *stream;
|
||||
Count depth;
|
||||
} FreelistDescribeClosureStruct, *FreelistDescribeClosure;
|
||||
|
||||
static Bool freelistDescribeVisitor(Land land, Range range,
|
||||
void *closureP, Size closureS)
|
||||
void *closure)
|
||||
{
|
||||
Res res;
|
||||
mps_lib_FILE *stream = closureP;
|
||||
Count depth = closureS;
|
||||
FreelistDescribeClosure my = closure;
|
||||
|
||||
if (!TESTT(Land, land))
|
||||
return FALSE;
|
||||
if (!RangeCheck(range))
|
||||
return FALSE;
|
||||
if (stream == NULL)
|
||||
if (my->stream == NULL)
|
||||
return FALSE;
|
||||
|
||||
res = WriteF(stream, depth,
|
||||
res = WriteF(my->stream, my->depth,
|
||||
"[$P,", (WriteFP)RangeBase(range),
|
||||
"$P)", (WriteFP)RangeLimit(range),
|
||||
" {$U}\n", (WriteFU)RangeSize(range),
|
||||
|
|
@ -778,6 +782,7 @@ static Res freelistDescribe(Land land, mps_lib_FILE *stream, Count depth)
|
|||
Freelist fl;
|
||||
Res res;
|
||||
Bool b;
|
||||
FreelistDescribeClosureStruct closure;
|
||||
|
||||
if (!TESTT(Land, land))
|
||||
return ResFAIL;
|
||||
|
|
@ -793,7 +798,9 @@ static Res freelistDescribe(Land land, mps_lib_FILE *stream, Count depth)
|
|||
" size = $U\n", (WriteFU)fl->size,
|
||||
NULL);
|
||||
|
||||
b = LandIterate(land, freelistDescribeVisitor, stream, depth + 2);
|
||||
closure.stream = stream;
|
||||
closure.depth = depth + 2;
|
||||
b = LandIterate(land, freelistDescribeVisitor, &closure);
|
||||
if (!b)
|
||||
return ResFAIL;
|
||||
|
||||
|
|
|
|||
71
mps/code/fri3ll.gmk
Normal file
71
mps/code/fri3ll.gmk
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
# -*- makefile -*-
|
||||
#
|
||||
# fri3ll.gmk: BUILD FOR FreeBSD/i386/GCC PLATFORM
|
||||
#
|
||||
# $Id$
|
||||
# Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
|
||||
PFM = fri3ll
|
||||
|
||||
MPMPF = \
|
||||
lockix.c \
|
||||
prmcan.c \
|
||||
prmci3fr.c \
|
||||
protix.c \
|
||||
protsgix.c \
|
||||
pthrdext.c \
|
||||
span.c \
|
||||
ssixi3.c \
|
||||
thix.c \
|
||||
vmix.c
|
||||
|
||||
LIBS = -lm -pthread
|
||||
|
||||
include ll.gmk
|
||||
|
||||
# For SQLite3.
|
||||
LINKFLAGS += -L/usr/local/lib
|
||||
CFLAGSCOMPILER += -I/usr/local/include
|
||||
|
||||
include comm.gmk
|
||||
|
||||
|
||||
# C. COPYRIGHT AND LICENSE
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# 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.
|
||||
68
mps/code/fri6ll.gmk
Normal file
68
mps/code/fri6ll.gmk
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
# -*- makefile -*-
|
||||
#
|
||||
# fri6ll.gmk: BUILD FOR FreeBSD/x86-64/GCC PLATFORM
|
||||
#
|
||||
# $Id$
|
||||
# Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
|
||||
PFM = fri6ll
|
||||
|
||||
MPMPF = lockix.c thix.c pthrdext.c vmix.c \
|
||||
protix.c protsgix.c prmcan.c prmci6fr.c ssixi6.c span.c
|
||||
|
||||
LIBS = -lm -pthread
|
||||
|
||||
include ll.gmk
|
||||
|
||||
# FIXME: We pun types through the MPS interface, setting off this warning.
|
||||
# Can we avoid this? The puns might indeed be dangerous.
|
||||
#CFLAGSCOMPILER += -Wno-strict-aliasing
|
||||
|
||||
# For SQLite3.
|
||||
LINKFLAGS += -L/usr/local/lib
|
||||
CFLAGSCOMPILER += -I/usr/local/include
|
||||
|
||||
CC = cc
|
||||
|
||||
include comm.gmk
|
||||
|
||||
|
||||
# C. COPYRIGHT AND LICENSE
|
||||
#
|
||||
# Copyright (C) 2001-2016 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.
|
||||
|
|
@ -27,7 +27,7 @@ CFLAGSCOMPILER := \
|
|||
-Wstrict-prototypes \
|
||||
-Wswitch-default \
|
||||
-Wwrite-strings
|
||||
CFLAGSCOMPILERSTRICT := -ansi -pedantic
|
||||
CFLAGSCOMPILERSTRICT := -std=c89 -pedantic
|
||||
|
||||
# A different set of compiler flags for less strict compilation, for
|
||||
# instance when we need to #include a third-party header file that
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ static size_t arena_size = 256ul * 1024 * 1024; /* arena size */
|
|||
static size_t arena_grain_size = 1; /* arena grain size */
|
||||
static unsigned pinleaf = FALSE; /* are leaf objects pinned at start */
|
||||
static mps_bool_t zoned = TRUE; /* arena allocates using zones */
|
||||
static double pause_time = ARENA_DEFAULT_PAUSE_TIME; /* maximum pause time */
|
||||
|
||||
typedef struct gcthread_s *gcthread_t;
|
||||
|
||||
|
|
@ -176,10 +177,8 @@ static void *start(void *p) {
|
|||
gcthread_t thread = p;
|
||||
void *marker;
|
||||
RESMUST(mps_thread_reg(&thread->mps_thread, arena));
|
||||
RESMUST(mps_root_create_reg(&thread->reg_root, arena,
|
||||
mps_rank_ambig(), (mps_rm_t)0,
|
||||
thread->mps_thread, &mps_stack_scan_ambig,
|
||||
&marker, (size_t)0));
|
||||
RESMUST(mps_root_create_thread(&thread->reg_root, arena,
|
||||
thread->mps_thread, &marker));
|
||||
RESMUST(mps_ap_create_k(&thread->ap, pool, mps_args_none));
|
||||
thread->fn(thread);
|
||||
mps_ap_destroy(thread->ap);
|
||||
|
|
@ -237,6 +236,7 @@ static void arena_setup(gcthread_fn_t fn,
|
|||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, arena_size);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_GRAIN_SIZE, arena_grain_size);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_ZONED, zoned);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_PAUSE_TIME, pause_time);
|
||||
RESMUST(mps_arena_create_k(&arena, mps_arena_class_vm(), args));
|
||||
} MPS_ARGS_END(args);
|
||||
RESMUST(dylan_fmt(&format, arena));
|
||||
|
|
@ -279,6 +279,7 @@ static struct option longopts[] = {
|
|||
{"pin-leaf", no_argument, NULL, 'l'},
|
||||
{"seed", required_argument, NULL, 'x'},
|
||||
{"arena-unzoned", no_argument, NULL, 'z'},
|
||||
{"pause-time", required_argument, NULL, 'P'},
|
||||
{NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
|
|
@ -308,7 +309,8 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
putchar('\n');
|
||||
|
||||
while ((ch = getopt_long(argc, argv, "ht:i:p:g:m:a:w:d:r:u:lx:z", longopts, NULL)) != -1)
|
||||
while ((ch = getopt_long(argc, argv, "ht:i:p:g:m:a:w:d:r:u:lx:zP:",
|
||||
longopts, NULL)) != -1)
|
||||
switch (ch) {
|
||||
case 't':
|
||||
nthreads = (unsigned)strtoul(optarg, NULL, 10);
|
||||
|
|
@ -397,6 +399,9 @@ int main(int argc, char *argv[]) {
|
|||
case 'z':
|
||||
zoned = FALSE;
|
||||
break;
|
||||
case 'P':
|
||||
pause_time = strtod(optarg, NULL);
|
||||
break;
|
||||
default:
|
||||
/* This is printed in parts to keep within the 509 character
|
||||
limit for string literals in portable standard C. */
|
||||
|
|
@ -442,9 +447,12 @@ int main(int argc, char *argv[]) {
|
|||
fprintf(stderr,
|
||||
" -z, --arena-unzoned\n"
|
||||
" Disable zoned allocation in the arena\n"
|
||||
" -P t, --pause-time\n"
|
||||
" Maximum pause time in seconds (default %f) \n"
|
||||
"Tests:\n"
|
||||
" amc pool class AMC\n"
|
||||
" ams pool class AMS\n");
|
||||
" ams pool class AMS\n",
|
||||
pause_time);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
argc -= optind;
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
* in the Memory Pool System test programs.
|
||||
*/
|
||||
|
||||
/* $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ */
|
||||
/* $FreeBSD: src/include/getopt.h,v 1.6.30.1.8.1 2012/03/03 06:15:13 kensmith Exp $ */
|
||||
/* $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ */
|
||||
/* $FreeBSD: src/include/getopt.h,v 1.6.30.1.8.1 2012/03/03 06:15:13 kensmith Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
|
|
@ -57,33 +57,33 @@
|
|||
#define optional_argument 2
|
||||
|
||||
struct option {
|
||||
/* name of long option */
|
||||
const char *name;
|
||||
/*
|
||||
* one of no_argument, required_argument, and optional_argument:
|
||||
* whether option takes an argument
|
||||
*/
|
||||
int has_arg;
|
||||
/* if not NULL, set *flag to val when option found */
|
||||
int *flag;
|
||||
/* if flag not NULL, value to set *flag to; else return value */
|
||||
int val;
|
||||
/* name of long option */
|
||||
const char *name;
|
||||
/*
|
||||
* one of no_argument, required_argument, and optional_argument:
|
||||
* whether option takes an argument
|
||||
*/
|
||||
int has_arg;
|
||||
/* if not NULL, set *flag to val when option found */
|
||||
int *flag;
|
||||
/* if flag not NULL, value to set *flag to; else return value */
|
||||
int val;
|
||||
};
|
||||
|
||||
int getopt_long(int, char * const *, const char *,
|
||||
const struct option *, int *);
|
||||
int getopt_long_only(int, char * const *, const char *,
|
||||
const struct option *, int *);
|
||||
int getopt_long(int, char * const *, const char *,
|
||||
const struct option *, int *);
|
||||
int getopt_long_only(int, char * const *, const char *,
|
||||
const struct option *, int *);
|
||||
#ifndef _GETOPT_DECLARED
|
||||
#define _GETOPT_DECLARED
|
||||
int getopt(int, char * const [], const char *);
|
||||
#define _GETOPT_DECLARED
|
||||
int getopt(int, char * const [], const char *);
|
||||
|
||||
extern char *optarg; /* getopt(3) external variables */
|
||||
extern char *optarg; /* getopt(3) external variables */
|
||||
extern int optind, opterr, optopt;
|
||||
#endif
|
||||
#ifndef _OPTRESET_DECLARED
|
||||
#define _OPTRESET_DECLARED
|
||||
extern int optreset; /* getopt(3) external variable */
|
||||
#define _OPTRESET_DECLARED
|
||||
extern int optreset; /* getopt(3) external variable */
|
||||
#endif
|
||||
|
||||
#endif /* !_GETOPT_H_ */
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
* in the Memory Pool System test programs.
|
||||
*/
|
||||
|
||||
/* $OpenBSD: getopt_long.c,v 1.21 2006/09/22 17:22:05 millert Exp $ */
|
||||
/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */
|
||||
/* $OpenBSD: getopt_long.c,v 1.21 2006/09/22 17:22:05 millert Exp $ */
|
||||
/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
|
|
@ -73,38 +73,38 @@
|
|||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define GNU_COMPATIBLE /* Be more compatible, configure's use us! */
|
||||
#define GNU_COMPATIBLE /* Be more compatible, configure's use us! */
|
||||
|
||||
int opterr = 1; /* if error message should be printed */
|
||||
int optind = 1; /* index into parent argv vector */
|
||||
int optopt = '?'; /* character checked for validity */
|
||||
int optreset; /* reset getopt */
|
||||
char *optarg; /* argument associated with option */
|
||||
int opterr = 1; /* if error message should be printed */
|
||||
int optind = 1; /* index into parent argv vector */
|
||||
int optopt = '?'; /* character checked for validity */
|
||||
int optreset; /* reset getopt */
|
||||
char *optarg; /* argument associated with option */
|
||||
|
||||
#define PRINT_ERROR ((opterr) && (*options != ':'))
|
||||
#define PRINT_ERROR ((opterr) && (*options != ':'))
|
||||
|
||||
#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
|
||||
#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
|
||||
#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
|
||||
#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
|
||||
#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
|
||||
#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
|
||||
|
||||
/* return values */
|
||||
#define BADCH (int)'?'
|
||||
#define BADARG ((*options == ':') ? (int)':' : (int)'?')
|
||||
#define INORDER (int)1
|
||||
#define BADCH (int)'?'
|
||||
#define BADARG ((*options == ':') ? (int)':' : (int)'?')
|
||||
#define INORDER (int)1
|
||||
|
||||
#define EMSG ""
|
||||
#define EMSG ""
|
||||
|
||||
#ifdef GNU_COMPATIBLE
|
||||
#define NO_PREFIX (-1)
|
||||
#define D_PREFIX 0
|
||||
#define DD_PREFIX 1
|
||||
#define W_PREFIX 2
|
||||
#define NO_PREFIX (-1)
|
||||
#define D_PREFIX 0
|
||||
#define DD_PREFIX 1
|
||||
#define W_PREFIX 2
|
||||
#endif
|
||||
|
||||
static int getopt_internal(int, char * const *, const char *,
|
||||
const struct option *, int *, int);
|
||||
const struct option *, int *, int);
|
||||
static int parse_long_options(char * const *, const char *,
|
||||
const struct option *, int *, int, int);
|
||||
const struct option *, int *, int, int);
|
||||
static int gcd(int, int);
|
||||
static void permute_args(int, int, int, char * const *);
|
||||
|
||||
|
|
@ -136,7 +136,7 @@ static const char illoptstring[] = "unknown option -- %s";
|
|||
static void
|
||||
warnx(const char *fmt, ...)
|
||||
{
|
||||
va_list varargs;
|
||||
va_list varargs;
|
||||
va_start(varargs, fmt);
|
||||
vfprintf(stderr, fmt, varargs);
|
||||
fputc('\n', stderr);
|
||||
|
|
@ -149,16 +149,16 @@ warnx(const char *fmt, ...)
|
|||
static int
|
||||
gcd(int a, int b)
|
||||
{
|
||||
int c;
|
||||
int c;
|
||||
|
||||
c = a % b;
|
||||
while (c != 0) {
|
||||
a = b;
|
||||
b = c;
|
||||
c = a % b;
|
||||
}
|
||||
c = a % b;
|
||||
while (c != 0) {
|
||||
a = b;
|
||||
b = c;
|
||||
c = a % b;
|
||||
}
|
||||
|
||||
return (b);
|
||||
return (b);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -168,427 +168,427 @@ gcd(int a, int b)
|
|||
*/
|
||||
static void
|
||||
permute_args(int panonopt_start, int panonopt_end, int opt_end,
|
||||
char * const *nargv)
|
||||
char * const *nargv)
|
||||
{
|
||||
int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
|
||||
char *swap;
|
||||
int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
|
||||
char *swap;
|
||||
|
||||
/*
|
||||
* compute lengths of blocks and number and size of cycles
|
||||
*/
|
||||
nnonopts = panonopt_end - panonopt_start;
|
||||
nopts = opt_end - panonopt_end;
|
||||
ncycle = gcd(nnonopts, nopts);
|
||||
cyclelen = (opt_end - panonopt_start) / ncycle;
|
||||
/*
|
||||
* compute lengths of blocks and number and size of cycles
|
||||
*/
|
||||
nnonopts = panonopt_end - panonopt_start;
|
||||
nopts = opt_end - panonopt_end;
|
||||
ncycle = gcd(nnonopts, nopts);
|
||||
cyclelen = (opt_end - panonopt_start) / ncycle;
|
||||
|
||||
for (i = 0; i < ncycle; i++) {
|
||||
cstart = panonopt_end+i;
|
||||
pos = cstart;
|
||||
for (j = 0; j < cyclelen; j++) {
|
||||
if (pos >= panonopt_end)
|
||||
pos -= nnonopts;
|
||||
else
|
||||
pos += nopts;
|
||||
swap = nargv[pos];
|
||||
/* LINTED const cast */
|
||||
((char **) nargv)[pos] = nargv[cstart];
|
||||
/* LINTED const cast */
|
||||
((char **)nargv)[cstart] = swap;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < ncycle; i++) {
|
||||
cstart = panonopt_end+i;
|
||||
pos = cstart;
|
||||
for (j = 0; j < cyclelen; j++) {
|
||||
if (pos >= panonopt_end)
|
||||
pos -= nnonopts;
|
||||
else
|
||||
pos += nopts;
|
||||
swap = nargv[pos];
|
||||
/* LINTED const cast */
|
||||
((char **) nargv)[pos] = nargv[cstart];
|
||||
/* LINTED const cast */
|
||||
((char **)nargv)[cstart] = swap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* parse_long_options --
|
||||
* Parse long options in argc/argv argument vector.
|
||||
* Parse long options in argc/argv argument vector.
|
||||
* Returns -1 if short_too is set and the option does not match long_options.
|
||||
*/
|
||||
static int
|
||||
parse_long_options(char * const *nargv, const char *options,
|
||||
const struct option *long_options, int *idx, int short_too, int flags)
|
||||
const struct option *long_options, int *idx, int short_too, int flags)
|
||||
{
|
||||
char *current_argv, *has_equal;
|
||||
char *current_argv, *has_equal;
|
||||
#ifdef GNU_COMPATIBLE
|
||||
const char *current_dash;
|
||||
const char *current_dash;
|
||||
#endif
|
||||
size_t current_argv_len;
|
||||
int i, match, exact_match, second_partial_match;
|
||||
size_t current_argv_len;
|
||||
int i, match, exact_match, second_partial_match;
|
||||
|
||||
current_argv = place;
|
||||
current_argv = place;
|
||||
#ifdef GNU_COMPATIBLE
|
||||
switch (dash_prefix) {
|
||||
case D_PREFIX:
|
||||
current_dash = "-";
|
||||
break;
|
||||
case DD_PREFIX:
|
||||
current_dash = "--";
|
||||
break;
|
||||
case W_PREFIX:
|
||||
current_dash = "-W ";
|
||||
break;
|
||||
default:
|
||||
current_dash = "";
|
||||
break;
|
||||
}
|
||||
switch (dash_prefix) {
|
||||
case D_PREFIX:
|
||||
current_dash = "-";
|
||||
break;
|
||||
case DD_PREFIX:
|
||||
current_dash = "--";
|
||||
break;
|
||||
case W_PREFIX:
|
||||
current_dash = "-W ";
|
||||
break;
|
||||
default:
|
||||
current_dash = "";
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
match = -1;
|
||||
exact_match = 0;
|
||||
second_partial_match = 0;
|
||||
match = -1;
|
||||
exact_match = 0;
|
||||
second_partial_match = 0;
|
||||
|
||||
optind++;
|
||||
optind++;
|
||||
|
||||
if ((has_equal = strchr(current_argv, '=')) != NULL) {
|
||||
/* argument found (--option=arg) */
|
||||
if ((has_equal = strchr(current_argv, '=')) != NULL) {
|
||||
/* argument found (--option=arg) */
|
||||
assert(has_equal > current_argv);
|
||||
current_argv_len = (size_t)(has_equal - current_argv);
|
||||
has_equal++;
|
||||
} else
|
||||
current_argv_len = strlen(current_argv);
|
||||
current_argv_len = (size_t)(has_equal - current_argv);
|
||||
has_equal++;
|
||||
} else
|
||||
current_argv_len = strlen(current_argv);
|
||||
|
||||
for (i = 0; long_options[i].name; i++) {
|
||||
/* find matching long option */
|
||||
if (strncmp(current_argv, long_options[i].name,
|
||||
current_argv_len))
|
||||
continue;
|
||||
for (i = 0; long_options[i].name; i++) {
|
||||
/* find matching long option */
|
||||
if (strncmp(current_argv, long_options[i].name,
|
||||
current_argv_len))
|
||||
continue;
|
||||
|
||||
if (strlen(long_options[i].name) == current_argv_len) {
|
||||
/* exact match */
|
||||
match = i;
|
||||
exact_match = 1;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* If this is a known short option, don't allow
|
||||
* a partial match of a single character.
|
||||
*/
|
||||
if (short_too && current_argv_len == 1)
|
||||
continue;
|
||||
if (strlen(long_options[i].name) == current_argv_len) {
|
||||
/* exact match */
|
||||
match = i;
|
||||
exact_match = 1;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* If this is a known short option, don't allow
|
||||
* a partial match of a single character.
|
||||
*/
|
||||
if (short_too && current_argv_len == 1)
|
||||
continue;
|
||||
|
||||
if (match == -1) /* first partial match */
|
||||
match = i;
|
||||
else if ((flags & FLAG_LONGONLY) ||
|
||||
long_options[i].has_arg !=
|
||||
long_options[match].has_arg ||
|
||||
long_options[i].flag != long_options[match].flag ||
|
||||
long_options[i].val != long_options[match].val)
|
||||
second_partial_match = 1;
|
||||
}
|
||||
if (!exact_match && second_partial_match) {
|
||||
/* ambiguous abbreviation */
|
||||
if (PRINT_ERROR)
|
||||
fprintf(stderr,
|
||||
if (match == -1) /* first partial match */
|
||||
match = i;
|
||||
else if ((flags & FLAG_LONGONLY) ||
|
||||
long_options[i].has_arg !=
|
||||
long_options[match].has_arg ||
|
||||
long_options[i].flag != long_options[match].flag ||
|
||||
long_options[i].val != long_options[match].val)
|
||||
second_partial_match = 1;
|
||||
}
|
||||
if (!exact_match && second_partial_match) {
|
||||
/* ambiguous abbreviation */
|
||||
if (PRINT_ERROR)
|
||||
fprintf(stderr,
|
||||
ambig,
|
||||
#ifdef GNU_COMPATIBLE
|
||||
current_dash,
|
||||
current_dash,
|
||||
#endif
|
||||
(int)current_argv_len,
|
||||
current_argv);
|
||||
optopt = 0;
|
||||
return (BADCH);
|
||||
}
|
||||
if (match != -1) { /* option found */
|
||||
if (long_options[match].has_arg == no_argument
|
||||
&& has_equal) {
|
||||
if (PRINT_ERROR)
|
||||
warnx(noarg,
|
||||
(int)current_argv_len,
|
||||
current_argv);
|
||||
optopt = 0;
|
||||
return (BADCH);
|
||||
}
|
||||
if (match != -1) { /* option found */
|
||||
if (long_options[match].has_arg == no_argument
|
||||
&& has_equal) {
|
||||
if (PRINT_ERROR)
|
||||
warnx(noarg,
|
||||
#ifdef GNU_COMPATIBLE
|
||||
current_dash,
|
||||
current_dash,
|
||||
#endif
|
||||
(int)current_argv_len,
|
||||
current_argv);
|
||||
/*
|
||||
* XXX: GNU sets optopt to val regardless of flag
|
||||
*/
|
||||
if (long_options[match].flag == NULL)
|
||||
optopt = long_options[match].val;
|
||||
else
|
||||
optopt = 0;
|
||||
(int)current_argv_len,
|
||||
current_argv);
|
||||
/*
|
||||
* XXX: GNU sets optopt to val regardless of flag
|
||||
*/
|
||||
if (long_options[match].flag == NULL)
|
||||
optopt = long_options[match].val;
|
||||
else
|
||||
optopt = 0;
|
||||
#ifdef GNU_COMPATIBLE
|
||||
return (BADCH);
|
||||
return (BADCH);
|
||||
#else
|
||||
return (BADARG);
|
||||
return (BADARG);
|
||||
#endif
|
||||
}
|
||||
if (long_options[match].has_arg == required_argument ||
|
||||
long_options[match].has_arg == optional_argument) {
|
||||
if (has_equal)
|
||||
optarg = has_equal;
|
||||
else if (long_options[match].has_arg ==
|
||||
required_argument) {
|
||||
/*
|
||||
* optional argument doesn't use next nargv
|
||||
*/
|
||||
optarg = nargv[optind++];
|
||||
}
|
||||
}
|
||||
if ((long_options[match].has_arg == required_argument)
|
||||
&& (optarg == NULL)) {
|
||||
/*
|
||||
* Missing argument; leading ':' indicates no error
|
||||
* should be generated.
|
||||
*/
|
||||
if (PRINT_ERROR)
|
||||
warnx(recargstring,
|
||||
}
|
||||
if (long_options[match].has_arg == required_argument ||
|
||||
long_options[match].has_arg == optional_argument) {
|
||||
if (has_equal)
|
||||
optarg = has_equal;
|
||||
else if (long_options[match].has_arg ==
|
||||
required_argument) {
|
||||
/*
|
||||
* optional argument doesn't use next nargv
|
||||
*/
|
||||
optarg = nargv[optind++];
|
||||
}
|
||||
}
|
||||
if ((long_options[match].has_arg == required_argument)
|
||||
&& (optarg == NULL)) {
|
||||
/*
|
||||
* Missing argument; leading ':' indicates no error
|
||||
* should be generated.
|
||||
*/
|
||||
if (PRINT_ERROR)
|
||||
warnx(recargstring,
|
||||
#ifdef GNU_COMPATIBLE
|
||||
current_dash,
|
||||
current_dash,
|
||||
#endif
|
||||
current_argv);
|
||||
/*
|
||||
* XXX: GNU sets optopt to val regardless of flag
|
||||
*/
|
||||
if (long_options[match].flag == NULL)
|
||||
optopt = long_options[match].val;
|
||||
else
|
||||
optopt = 0;
|
||||
--optind;
|
||||
return (BADARG);
|
||||
}
|
||||
} else { /* unknown option */
|
||||
if (short_too) {
|
||||
--optind;
|
||||
return (-1);
|
||||
}
|
||||
if (PRINT_ERROR)
|
||||
warnx(illoptstring,
|
||||
current_argv);
|
||||
/*
|
||||
* XXX: GNU sets optopt to val regardless of flag
|
||||
*/
|
||||
if (long_options[match].flag == NULL)
|
||||
optopt = long_options[match].val;
|
||||
else
|
||||
optopt = 0;
|
||||
--optind;
|
||||
return (BADARG);
|
||||
}
|
||||
} else { /* unknown option */
|
||||
if (short_too) {
|
||||
--optind;
|
||||
return (-1);
|
||||
}
|
||||
if (PRINT_ERROR)
|
||||
warnx(illoptstring,
|
||||
#ifdef GNU_COMPATIBLE
|
||||
current_dash,
|
||||
current_dash,
|
||||
#endif
|
||||
current_argv);
|
||||
optopt = 0;
|
||||
return (BADCH);
|
||||
}
|
||||
if (idx)
|
||||
*idx = match;
|
||||
if (long_options[match].flag) {
|
||||
*long_options[match].flag = long_options[match].val;
|
||||
return (0);
|
||||
} else
|
||||
return (long_options[match].val);
|
||||
current_argv);
|
||||
optopt = 0;
|
||||
return (BADCH);
|
||||
}
|
||||
if (idx)
|
||||
*idx = match;
|
||||
if (long_options[match].flag) {
|
||||
*long_options[match].flag = long_options[match].val;
|
||||
return (0);
|
||||
} else
|
||||
return (long_options[match].val);
|
||||
}
|
||||
|
||||
/*
|
||||
* getopt_internal --
|
||||
* Parse argc/argv argument vector. Called by user level routines.
|
||||
* Parse argc/argv argument vector. Called by user level routines.
|
||||
*/
|
||||
static int
|
||||
getopt_internal(int nargc, char * const *nargv, const char *options,
|
||||
const struct option *long_options, int *idx, int flags)
|
||||
const struct option *long_options, int *idx, int flags)
|
||||
{
|
||||
char *oli; /* option letter list index */
|
||||
int optchar, short_too;
|
||||
int posixly_correct; /* no static, can be changed on the fly */
|
||||
char *oli; /* option letter list index */
|
||||
int optchar, short_too;
|
||||
int posixly_correct; /* no static, can be changed on the fly */
|
||||
|
||||
if (options == NULL)
|
||||
return (-1);
|
||||
if (options == NULL)
|
||||
return (-1);
|
||||
|
||||
/*
|
||||
* Disable GNU extensions if POSIXLY_CORRECT is set or options
|
||||
* string begins with a '+'.
|
||||
*/
|
||||
posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
|
||||
/*
|
||||
* Disable GNU extensions if POSIXLY_CORRECT is set or options
|
||||
* string begins with a '+'.
|
||||
*/
|
||||
posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
|
||||
#ifdef GNU_COMPATIBLE
|
||||
if (*options == '-')
|
||||
flags |= FLAG_ALLARGS;
|
||||
else if (posixly_correct || *options == '+')
|
||||
flags &= ~FLAG_PERMUTE;
|
||||
if (*options == '-')
|
||||
flags |= FLAG_ALLARGS;
|
||||
else if (posixly_correct || *options == '+')
|
||||
flags &= ~FLAG_PERMUTE;
|
||||
#else
|
||||
if (posixly_correct || *options == '+')
|
||||
flags &= ~FLAG_PERMUTE;
|
||||
else if (*options == '-')
|
||||
flags |= FLAG_ALLARGS;
|
||||
if (posixly_correct || *options == '+')
|
||||
flags &= ~FLAG_PERMUTE;
|
||||
else if (*options == '-')
|
||||
flags |= FLAG_ALLARGS;
|
||||
#endif
|
||||
if (*options == '+' || *options == '-')
|
||||
options++;
|
||||
if (*options == '+' || *options == '-')
|
||||
options++;
|
||||
|
||||
/*
|
||||
* XXX Some GNU programs (like cvs) set optind to 0 instead of
|
||||
* XXX using optreset. Work around this braindamage.
|
||||
*/
|
||||
if (optind == 0)
|
||||
optind = optreset = 1;
|
||||
/*
|
||||
* XXX Some GNU programs (like cvs) set optind to 0 instead of
|
||||
* XXX using optreset. Work around this braindamage.
|
||||
*/
|
||||
if (optind == 0)
|
||||
optind = optreset = 1;
|
||||
|
||||
optarg = NULL;
|
||||
if (optreset)
|
||||
nonopt_start = nonopt_end = -1;
|
||||
optarg = NULL;
|
||||
if (optreset)
|
||||
nonopt_start = nonopt_end = -1;
|
||||
start:
|
||||
if (optreset || !*place) { /* update scanning pointer */
|
||||
optreset = 0;
|
||||
if (optind >= nargc) { /* end of argument vector */
|
||||
place = emsg;
|
||||
if (nonopt_end != -1) {
|
||||
/* do permutation, if we have to */
|
||||
permute_args(nonopt_start, nonopt_end,
|
||||
optind, nargv);
|
||||
optind -= nonopt_end - nonopt_start;
|
||||
}
|
||||
else if (nonopt_start != -1) {
|
||||
/*
|
||||
* If we skipped non-options, set optind
|
||||
* to the first of them.
|
||||
*/
|
||||
optind = nonopt_start;
|
||||
}
|
||||
nonopt_start = nonopt_end = -1;
|
||||
return (-1);
|
||||
}
|
||||
if (*(place = nargv[optind]) != '-' ||
|
||||
if (optreset || !*place) { /* update scanning pointer */
|
||||
optreset = 0;
|
||||
if (optind >= nargc) { /* end of argument vector */
|
||||
place = emsg;
|
||||
if (nonopt_end != -1) {
|
||||
/* do permutation, if we have to */
|
||||
permute_args(nonopt_start, nonopt_end,
|
||||
optind, nargv);
|
||||
optind -= nonopt_end - nonopt_start;
|
||||
}
|
||||
else if (nonopt_start != -1) {
|
||||
/*
|
||||
* If we skipped non-options, set optind
|
||||
* to the first of them.
|
||||
*/
|
||||
optind = nonopt_start;
|
||||
}
|
||||
nonopt_start = nonopt_end = -1;
|
||||
return (-1);
|
||||
}
|
||||
if (*(place = nargv[optind]) != '-' ||
|
||||
#ifdef GNU_COMPATIBLE
|
||||
place[1] == '\0') {
|
||||
place[1] == '\0') {
|
||||
#else
|
||||
(place[1] == '\0' && strchr(options, '-') == NULL)) {
|
||||
(place[1] == '\0' && strchr(options, '-') == NULL)) {
|
||||
#endif
|
||||
place = emsg; /* found non-option */
|
||||
if (flags & FLAG_ALLARGS) {
|
||||
/*
|
||||
* GNU extension:
|
||||
* return non-option as argument to option 1
|
||||
*/
|
||||
optarg = nargv[optind++];
|
||||
return (INORDER);
|
||||
}
|
||||
if (!(flags & FLAG_PERMUTE)) {
|
||||
/*
|
||||
* If no permutation wanted, stop parsing
|
||||
* at first non-option.
|
||||
*/
|
||||
return (-1);
|
||||
}
|
||||
/* do permutation */
|
||||
if (nonopt_start == -1)
|
||||
nonopt_start = optind;
|
||||
else if (nonopt_end != -1) {
|
||||
permute_args(nonopt_start, nonopt_end,
|
||||
optind, nargv);
|
||||
nonopt_start = optind -
|
||||
(nonopt_end - nonopt_start);
|
||||
nonopt_end = -1;
|
||||
}
|
||||
optind++;
|
||||
/* process next argument */
|
||||
goto start;
|
||||
}
|
||||
if (nonopt_start != -1 && nonopt_end == -1)
|
||||
nonopt_end = optind;
|
||||
place = emsg; /* found non-option */
|
||||
if (flags & FLAG_ALLARGS) {
|
||||
/*
|
||||
* GNU extension:
|
||||
* return non-option as argument to option 1
|
||||
*/
|
||||
optarg = nargv[optind++];
|
||||
return (INORDER);
|
||||
}
|
||||
if (!(flags & FLAG_PERMUTE)) {
|
||||
/*
|
||||
* If no permutation wanted, stop parsing
|
||||
* at first non-option.
|
||||
*/
|
||||
return (-1);
|
||||
}
|
||||
/* do permutation */
|
||||
if (nonopt_start == -1)
|
||||
nonopt_start = optind;
|
||||
else if (nonopt_end != -1) {
|
||||
permute_args(nonopt_start, nonopt_end,
|
||||
optind, nargv);
|
||||
nonopt_start = optind -
|
||||
(nonopt_end - nonopt_start);
|
||||
nonopt_end = -1;
|
||||
}
|
||||
optind++;
|
||||
/* process next argument */
|
||||
goto start;
|
||||
}
|
||||
if (nonopt_start != -1 && nonopt_end == -1)
|
||||
nonopt_end = optind;
|
||||
|
||||
/*
|
||||
* If we have "-" do nothing, if "--" we are done.
|
||||
*/
|
||||
if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
|
||||
optind++;
|
||||
place = emsg;
|
||||
/*
|
||||
* We found an option (--), so if we skipped
|
||||
* non-options, we have to permute.
|
||||
*/
|
||||
if (nonopt_end != -1) {
|
||||
permute_args(nonopt_start, nonopt_end,
|
||||
optind, nargv);
|
||||
optind -= nonopt_end - nonopt_start;
|
||||
}
|
||||
nonopt_start = nonopt_end = -1;
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* If we have "-" do nothing, if "--" we are done.
|
||||
*/
|
||||
if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
|
||||
optind++;
|
||||
place = emsg;
|
||||
/*
|
||||
* We found an option (--), so if we skipped
|
||||
* non-options, we have to permute.
|
||||
*/
|
||||
if (nonopt_end != -1) {
|
||||
permute_args(nonopt_start, nonopt_end,
|
||||
optind, nargv);
|
||||
optind -= nonopt_end - nonopt_start;
|
||||
}
|
||||
nonopt_start = nonopt_end = -1;
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check long options if:
|
||||
* 1) we were passed some
|
||||
* 2) the arg is not just "-"
|
||||
* 3) either the arg starts with -- we are getopt_long_only()
|
||||
*/
|
||||
if (long_options != NULL && place != nargv[optind] &&
|
||||
(*place == '-' || (flags & FLAG_LONGONLY))) {
|
||||
short_too = 0;
|
||||
/*
|
||||
* Check long options if:
|
||||
* 1) we were passed some
|
||||
* 2) the arg is not just "-"
|
||||
* 3) either the arg starts with -- we are getopt_long_only()
|
||||
*/
|
||||
if (long_options != NULL && place != nargv[optind] &&
|
||||
(*place == '-' || (flags & FLAG_LONGONLY))) {
|
||||
short_too = 0;
|
||||
#ifdef GNU_COMPATIBLE
|
||||
dash_prefix = D_PREFIX;
|
||||
dash_prefix = D_PREFIX;
|
||||
#endif
|
||||
if (*place == '-') {
|
||||
place++; /* --foo long option */
|
||||
if (*place == '-') {
|
||||
place++; /* --foo long option */
|
||||
#ifdef GNU_COMPATIBLE
|
||||
dash_prefix = DD_PREFIX;
|
||||
dash_prefix = DD_PREFIX;
|
||||
#endif
|
||||
} else if (*place != ':' && strchr(options, *place) != NULL)
|
||||
short_too = 1; /* could be short option too */
|
||||
} else if (*place != ':' && strchr(options, *place) != NULL)
|
||||
short_too = 1; /* could be short option too */
|
||||
|
||||
optchar = parse_long_options(nargv, options, long_options,
|
||||
idx, short_too, flags);
|
||||
if (optchar != -1) {
|
||||
place = emsg;
|
||||
return (optchar);
|
||||
}
|
||||
}
|
||||
optchar = parse_long_options(nargv, options, long_options,
|
||||
idx, short_too, flags);
|
||||
if (optchar != -1) {
|
||||
place = emsg;
|
||||
return (optchar);
|
||||
}
|
||||
}
|
||||
|
||||
if ((optchar = (int)*place++) == (int)':' ||
|
||||
(optchar == (int)'-' && *place != '\0') ||
|
||||
(oli = strchr(options, optchar)) == NULL) {
|
||||
/*
|
||||
* If the user specified "-" and '-' isn't listed in
|
||||
* options, return -1 (non-option) as per POSIX.
|
||||
* Otherwise, it is an unknown option character (or ':').
|
||||
*/
|
||||
if (optchar == (int)'-' && *place == '\0')
|
||||
return (-1);
|
||||
if (!*place)
|
||||
++optind;
|
||||
if ((optchar = (int)*place++) == (int)':' ||
|
||||
(optchar == (int)'-' && *place != '\0') ||
|
||||
(oli = strchr(options, optchar)) == NULL) {
|
||||
/*
|
||||
* If the user specified "-" and '-' isn't listed in
|
||||
* options, return -1 (non-option) as per POSIX.
|
||||
* Otherwise, it is an unknown option character (or ':').
|
||||
*/
|
||||
if (optchar == (int)'-' && *place == '\0')
|
||||
return (-1);
|
||||
if (!*place)
|
||||
++optind;
|
||||
#ifdef GNU_COMPATIBLE
|
||||
if (PRINT_ERROR)
|
||||
warnx(posixly_correct ? illoptchar : gnuoptchar,
|
||||
optchar);
|
||||
if (PRINT_ERROR)
|
||||
warnx(posixly_correct ? illoptchar : gnuoptchar,
|
||||
optchar);
|
||||
#else
|
||||
if (PRINT_ERROR)
|
||||
warnx(illoptchar, optchar);
|
||||
if (PRINT_ERROR)
|
||||
warnx(illoptchar, optchar);
|
||||
#endif
|
||||
optopt = optchar;
|
||||
return (BADCH);
|
||||
}
|
||||
if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
|
||||
/* -W long-option */
|
||||
if (*place) /* no space */
|
||||
/* NOTHING */;
|
||||
else if (++optind >= nargc) { /* no arg */
|
||||
place = emsg;
|
||||
if (PRINT_ERROR)
|
||||
warnx(recargchar, optchar);
|
||||
optopt = optchar;
|
||||
return (BADARG);
|
||||
} else /* white space */
|
||||
place = nargv[optind];
|
||||
optopt = optchar;
|
||||
return (BADCH);
|
||||
}
|
||||
if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
|
||||
/* -W long-option */
|
||||
if (*place) /* no space */
|
||||
/* NOTHING */;
|
||||
else if (++optind >= nargc) { /* no arg */
|
||||
place = emsg;
|
||||
if (PRINT_ERROR)
|
||||
warnx(recargchar, optchar);
|
||||
optopt = optchar;
|
||||
return (BADARG);
|
||||
} else /* white space */
|
||||
place = nargv[optind];
|
||||
#ifdef GNU_COMPATIBLE
|
||||
dash_prefix = W_PREFIX;
|
||||
dash_prefix = W_PREFIX;
|
||||
#endif
|
||||
optchar = parse_long_options(nargv, options, long_options,
|
||||
idx, 0, flags);
|
||||
place = emsg;
|
||||
return (optchar);
|
||||
}
|
||||
if (*++oli != ':') { /* doesn't take argument */
|
||||
if (!*place)
|
||||
++optind;
|
||||
} else { /* takes (optional) argument */
|
||||
optarg = NULL;
|
||||
if (*place) /* no white space */
|
||||
optarg = place;
|
||||
else if (oli[1] != ':') { /* arg not optional */
|
||||
if (++optind >= nargc) { /* no arg */
|
||||
place = emsg;
|
||||
if (PRINT_ERROR)
|
||||
warnx(recargchar, optchar);
|
||||
optopt = optchar;
|
||||
return (BADARG);
|
||||
} else
|
||||
optarg = nargv[optind];
|
||||
}
|
||||
place = emsg;
|
||||
++optind;
|
||||
}
|
||||
/* dump back option letter */
|
||||
return (optchar);
|
||||
optchar = parse_long_options(nargv, options, long_options,
|
||||
idx, 0, flags);
|
||||
place = emsg;
|
||||
return (optchar);
|
||||
}
|
||||
if (*++oli != ':') { /* doesn't take argument */
|
||||
if (!*place)
|
||||
++optind;
|
||||
} else { /* takes (optional) argument */
|
||||
optarg = NULL;
|
||||
if (*place) /* no white space */
|
||||
optarg = place;
|
||||
else if (oli[1] != ':') { /* arg not optional */
|
||||
if (++optind >= nargc) { /* no arg */
|
||||
place = emsg;
|
||||
if (PRINT_ERROR)
|
||||
warnx(recargchar, optchar);
|
||||
optopt = optchar;
|
||||
return (BADARG);
|
||||
} else
|
||||
optarg = nargv[optind];
|
||||
}
|
||||
place = emsg;
|
||||
++optind;
|
||||
}
|
||||
/* dump back option letter */
|
||||
return (optchar);
|
||||
}
|
||||
|
||||
#ifdef REPLACE_GETOPT
|
||||
/*
|
||||
* getopt --
|
||||
* Parse argc/argv argument vector.
|
||||
* Parse argc/argv argument vector.
|
||||
*
|
||||
* [eventually this will replace the BSD getopt]
|
||||
*/
|
||||
|
|
@ -596,40 +596,40 @@ int
|
|||
getopt(int nargc, char * const *nargv, const char *options)
|
||||
{
|
||||
|
||||
/*
|
||||
* We don't pass FLAG_PERMUTE to getopt_internal() since
|
||||
* the BSD getopt(3) (unlike GNU) has never done this.
|
||||
*
|
||||
* Furthermore, since many privileged programs call getopt()
|
||||
* before dropping privileges it makes sense to keep things
|
||||
* as simple (and bug-free) as possible.
|
||||
*/
|
||||
return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
|
||||
/*
|
||||
* We don't pass FLAG_PERMUTE to getopt_internal() since
|
||||
* the BSD getopt(3) (unlike GNU) has never done this.
|
||||
*
|
||||
* Furthermore, since many privileged programs call getopt()
|
||||
* before dropping privileges it makes sense to keep things
|
||||
* as simple (and bug-free) as possible.
|
||||
*/
|
||||
return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
|
||||
}
|
||||
#endif /* REPLACE_GETOPT */
|
||||
|
||||
/*
|
||||
* getopt_long --
|
||||
* Parse argc/argv argument vector.
|
||||
* Parse argc/argv argument vector.
|
||||
*/
|
||||
int
|
||||
getopt_long(int nargc, char * const *nargv, const char *options,
|
||||
const struct option *long_options, int *idx)
|
||||
const struct option *long_options, int *idx)
|
||||
{
|
||||
|
||||
return (getopt_internal(nargc, nargv, options, long_options, idx,
|
||||
FLAG_PERMUTE));
|
||||
return (getopt_internal(nargc, nargv, options, long_options, idx,
|
||||
FLAG_PERMUTE));
|
||||
}
|
||||
|
||||
/*
|
||||
* getopt_long_only --
|
||||
* Parse argc/argv argument vector.
|
||||
* Parse argc/argv argument vector.
|
||||
*/
|
||||
int
|
||||
getopt_long_only(int nargc, char * const *nargv, const char *options,
|
||||
const struct option *long_options, int *idx)
|
||||
const struct option *long_options, int *idx)
|
||||
{
|
||||
|
||||
return (getopt_internal(nargc, nargv, options, long_options, idx,
|
||||
FLAG_PERMUTE|FLAG_LONGONLY));
|
||||
return (getopt_internal(nargc, nargv, options, long_options, idx,
|
||||
FLAG_PERMUTE|FLAG_LONGONLY));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,7 +108,6 @@ Bool GlobalsCheck(Globals arenaGlobals)
|
|||
TraceId ti;
|
||||
Trace trace;
|
||||
Index i;
|
||||
Size depth;
|
||||
RefSet rs;
|
||||
Rank rank;
|
||||
|
||||
|
|
@ -153,21 +152,9 @@ Bool GlobalsCheck(Globals arenaGlobals)
|
|||
}
|
||||
|
||||
CHECKD_NOSIG(Ring, &arena->threadRing);
|
||||
CHECKD_NOSIG(Ring, &arena->deadRing);
|
||||
|
||||
CHECKL(BoolCheck(arena->insideShield));
|
||||
CHECKL(arena->shCacheLimit <= ShieldCacheSIZE);
|
||||
CHECKL(arena->shCacheI < arena->shCacheLimit);
|
||||
CHECKL(BoolCheck(arena->suspended));
|
||||
|
||||
depth = 0;
|
||||
for (i = 0; i < arena->shCacheLimit; ++i) {
|
||||
Seg seg = arena->shCache[i];
|
||||
if (seg != NULL) {
|
||||
CHECKD(Seg, seg);
|
||||
depth += SegDepth(seg);
|
||||
}
|
||||
}
|
||||
CHECKL(depth <= arena->shDepth);
|
||||
CHECKD(Shield, ArenaShield(arena));
|
||||
|
||||
CHECKL(TraceSetCheck(arena->busyTraces));
|
||||
CHECKL(TraceSetCheck(arena->flippedTraces));
|
||||
|
|
@ -189,7 +176,7 @@ Bool GlobalsCheck(Globals arenaGlobals)
|
|||
CHECKD_NOSIG(Ring, &arena->greyRing[rank]);
|
||||
CHECKD_NOSIG(Ring, &arena->chainRing);
|
||||
|
||||
CHECKL(arena->tracedSize >= 0.0);
|
||||
CHECKL(arena->tracedWork >= 0.0);
|
||||
CHECKL(arena->tracedTime >= 0.0);
|
||||
/* no check for arena->lastWorldCollect (Clock) */
|
||||
|
||||
|
|
@ -214,6 +201,8 @@ Bool GlobalsCheck(Globals arenaGlobals)
|
|||
CHECKL(RingCheck(&arenaRing));
|
||||
|
||||
CHECKL(BoolCheck(arena->emergency));
|
||||
/* There can only be an emergency when a trace is busy. */
|
||||
CHECKL(!arena->emergency || arena->busyTraces != TraceSetEMPTY);
|
||||
|
||||
if (arenaGlobals->defaultChain != NULL)
|
||||
CHECKD(Chain, arenaGlobals->defaultChain);
|
||||
|
|
@ -277,6 +266,7 @@ Res GlobalsInit(Globals arenaGlobals)
|
|||
arenaGlobals->rememberedSummaryIndex = 0;
|
||||
|
||||
RingInit(&arena->threadRing);
|
||||
RingInit(&arena->deadRing);
|
||||
arena->threadSerial = (Serial)0;
|
||||
RingInit(&arena->formatRing);
|
||||
arena->formatSerial = (Serial)0;
|
||||
|
|
@ -287,16 +277,10 @@ Res GlobalsInit(Globals arenaGlobals)
|
|||
arena->finalPool = NULL;
|
||||
arena->busyTraces = TraceSetEMPTY; /* <code/trace.c> */
|
||||
arena->flippedTraces = TraceSetEMPTY; /* <code/trace.c> */
|
||||
arena->tracedSize = 0.0;
|
||||
arena->tracedWork = 0.0;
|
||||
arena->tracedTime = 0.0;
|
||||
arena->lastWorldCollect = ClockNow();
|
||||
arena->insideShield = FALSE; /* <code/shield.c> */
|
||||
arena->shCacheI = (Size)0;
|
||||
arena->shCacheLimit = (Size)1;
|
||||
arena->shDepth = (Size)0;
|
||||
arena->suspended = FALSE;
|
||||
for(i = 0; i < ShieldCacheSIZE; i++)
|
||||
arena->shCache[i] = NULL;
|
||||
ShieldInit(ArenaShield(arena));
|
||||
|
||||
for (ti = 0; ti < TraceLIMIT; ++ti) {
|
||||
/* <design/arena/#trace.invalid> */
|
||||
|
|
@ -350,7 +334,7 @@ Res GlobalsCompleteCreate(Globals arenaGlobals)
|
|||
{
|
||||
void *v;
|
||||
|
||||
res = ControlAlloc(&v, arena, BTSize(MessageTypeLIMIT), FALSE);
|
||||
res = ControlAlloc(&v, arena, BTSize(MessageTypeLIMIT));
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
arena->enabledMessageTypes = v;
|
||||
|
|
@ -364,7 +348,7 @@ Res GlobalsCompleteCreate(Globals arenaGlobals)
|
|||
return res;
|
||||
TRACE_SET_ITER_END(ti, trace, TraceSetUNIV, arena);
|
||||
|
||||
res = ControlAlloc(&p, arena, LockSize(), FALSE);
|
||||
res = ControlAlloc(&p, arena, LockSize());
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
arenaGlobals->lock = (Lock)p;
|
||||
|
|
@ -401,10 +385,12 @@ void GlobalsFinish(Globals arenaGlobals)
|
|||
|
||||
arenaGlobals->sig = SigInvalid;
|
||||
|
||||
ShieldFinish(ArenaShield(arena));
|
||||
RingFinish(&arena->formatRing);
|
||||
RingFinish(&arena->chainRing);
|
||||
RingFinish(&arena->messageRing);
|
||||
RingFinish(&arena->threadRing);
|
||||
RingFinish(&arena->deadRing);
|
||||
for(rank = RankMIN; rank < RankLIMIT; ++rank)
|
||||
RingFinish(&arena->greyRing[rank]);
|
||||
RingFinish(&arenaGlobals->rootRing);
|
||||
|
|
@ -432,6 +418,7 @@ void GlobalsPrepareToDestroy(Globals arenaGlobals)
|
|||
ArenaPark(arenaGlobals);
|
||||
|
||||
arena = GlobalsArena(arenaGlobals);
|
||||
|
||||
arenaDenounce(arena);
|
||||
|
||||
defaultChain = arenaGlobals->defaultChain;
|
||||
|
|
@ -483,6 +470,8 @@ void GlobalsPrepareToDestroy(Globals arenaGlobals)
|
|||
PoolDestroy(pool);
|
||||
}
|
||||
|
||||
ShieldDestroyQueue(ArenaShield(arena), arena);
|
||||
|
||||
/* Check that the tear-down is complete: that the client has
|
||||
* destroyed all data structures associated with the arena. We do
|
||||
* this here rather than in GlobalsFinish because by the time that
|
||||
|
|
@ -495,18 +484,18 @@ void GlobalsPrepareToDestroy(Globals arenaGlobals)
|
|||
AVER(RingIsSingle(&arena->chainRing));
|
||||
AVER(RingIsSingle(&arena->messageRing));
|
||||
AVER(RingIsSingle(&arena->threadRing));
|
||||
AVER(RingIsSingle(&arena->deadRing));
|
||||
AVER(RingIsSingle(&arenaGlobals->rootRing));
|
||||
for(rank = RankMIN; rank < RankLIMIT; ++rank)
|
||||
AVER(RingIsSingle(&arena->greyRing[rank]));
|
||||
|
||||
/* At this point the following pools still exist:
|
||||
* 0. arena->freeCBSBlockPoolStruct
|
||||
* 1. arena->reservoirStruct
|
||||
* 2. arena->controlPoolStruct
|
||||
* 3. arena->controlPoolStruct.blockPoolStruct
|
||||
* 4. arena->controlPoolStruct.spanPoolStruct
|
||||
* 1. arena->controlPoolStruct
|
||||
* 2. arena->controlPoolStruct.blockPoolStruct
|
||||
* 3. arena->controlPoolStruct.spanPoolStruct
|
||||
*/
|
||||
AVER(RingLength(&arenaGlobals->poolRing) == 5);
|
||||
AVER(RingLength(&arenaGlobals->poolRing) == 4);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -704,9 +693,8 @@ void (ArenaPoll)(Globals globals)
|
|||
{
|
||||
Arena arena;
|
||||
Clock start;
|
||||
Count quanta;
|
||||
Size tracedSize;
|
||||
double nextPollThreshold = 0.0;
|
||||
Bool moreWork, workWasDone = FALSE;
|
||||
Work tracedWork;
|
||||
|
||||
AVERT(Globals, globals);
|
||||
|
||||
|
|
@ -714,98 +702,41 @@ void (ArenaPoll)(Globals globals)
|
|||
return;
|
||||
if (globals->insidePoll)
|
||||
return;
|
||||
if(globals->fillMutatorSize < globals->pollThreshold)
|
||||
arena = GlobalsArena(globals);
|
||||
if (!PolicyPoll(arena))
|
||||
return;
|
||||
|
||||
globals->insidePoll = TRUE;
|
||||
|
||||
/* fillMutatorSize has advanced; call TracePoll enough to catch up. */
|
||||
arena = GlobalsArena(globals);
|
||||
start = ClockNow();
|
||||
quanta = 0;
|
||||
|
||||
EVENT3(ArenaPoll, arena, start, 0);
|
||||
EVENT3(ArenaPoll, arena, start, FALSE);
|
||||
|
||||
while(globals->pollThreshold <= globals->fillMutatorSize) {
|
||||
tracedSize = TracePoll(globals);
|
||||
|
||||
if(tracedSize == 0) {
|
||||
/* No work to do. Sleep until NOW + a bit. */
|
||||
nextPollThreshold = globals->fillMutatorSize + ArenaPollALLOCTIME;
|
||||
} else {
|
||||
/* We did one quantum of work; consume one unit of 'time'. */
|
||||
quanta += 1;
|
||||
arena->tracedSize += tracedSize;
|
||||
nextPollThreshold = globals->pollThreshold + ArenaPollALLOCTIME;
|
||||
do {
|
||||
moreWork = TracePoll(&tracedWork, globals);
|
||||
if (moreWork) {
|
||||
workWasDone = TRUE;
|
||||
}
|
||||
|
||||
/* Advance pollThreshold; check: enough precision? */
|
||||
AVER(nextPollThreshold > globals->pollThreshold);
|
||||
globals->pollThreshold = nextPollThreshold;
|
||||
}
|
||||
} while (PolicyPollAgain(arena, start, moreWork, tracedWork));
|
||||
|
||||
/* Don't count time spent checking for work, if there was no work to do. */
|
||||
if(quanta > 0) {
|
||||
arena->tracedTime += (ClockNow() - start) / (double) ClocksPerSec();
|
||||
if (workWasDone) {
|
||||
ArenaAccumulateTime(arena, start, ClockNow());
|
||||
}
|
||||
|
||||
AVER(globals->fillMutatorSize < globals->pollThreshold);
|
||||
|
||||
EVENT3(ArenaPoll, arena, start, quanta);
|
||||
EVENT3(ArenaPoll, arena, start, BOOLOF(workWasDone));
|
||||
|
||||
globals->insidePoll = FALSE;
|
||||
}
|
||||
|
||||
/* Work out whether we have enough time here to collect the world,
|
||||
* and whether much time has passed since the last time we did that
|
||||
* opportunistically. */
|
||||
static Bool arenaShouldCollectWorld(Arena arena,
|
||||
double interval,
|
||||
double multiplier,
|
||||
Clock now,
|
||||
Clock clocks_per_sec)
|
||||
{
|
||||
double scanRate;
|
||||
Size arenaSize;
|
||||
double arenaScanTime;
|
||||
double sinceLastWorldCollect;
|
||||
|
||||
/* don't collect the world if we're not given any time */
|
||||
if ((interval > 0.0) && (multiplier > 0.0)) {
|
||||
/* don't collect the world if we're already collecting. */
|
||||
if (arena->busyTraces == TraceSetEMPTY) {
|
||||
/* don't collect the world if it's very small */
|
||||
arenaSize = ArenaCommitted(arena) - ArenaSpareCommitted(arena);
|
||||
if (arenaSize > 1000000) {
|
||||
/* how long would it take to collect the world? */
|
||||
if ((arena->tracedSize > 1000000.0) &&
|
||||
(arena->tracedTime > 1.0))
|
||||
scanRate = arena->tracedSize / arena->tracedTime;
|
||||
else
|
||||
scanRate = 25000000.0; /* a reasonable default. */
|
||||
arenaScanTime = arenaSize / scanRate;
|
||||
arenaScanTime += 0.1; /* for overheads. */
|
||||
|
||||
/* how long since we last collected the world? */
|
||||
sinceLastWorldCollect = ((now - arena->lastWorldCollect) /
|
||||
(double) clocks_per_sec);
|
||||
/* have to be offered enough time, and it has to be a long time
|
||||
* since we last did it. */
|
||||
if ((interval * multiplier > arenaScanTime) &&
|
||||
sinceLastWorldCollect > arenaScanTime * 10.0) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
/* ArenaStep -- use idle time for collection work */
|
||||
|
||||
Bool ArenaStep(Globals globals, double interval, double multiplier)
|
||||
{
|
||||
Size scanned;
|
||||
Bool stepped;
|
||||
Clock start, end, now;
|
||||
Bool workWasDone = FALSE;
|
||||
Clock start, intervalEnd, availableEnd, now;
|
||||
Clock clocks_per_sec;
|
||||
Arena arena;
|
||||
|
||||
|
|
@ -816,39 +747,45 @@ Bool ArenaStep(Globals globals, double interval, double multiplier)
|
|||
arena = GlobalsArena(globals);
|
||||
clocks_per_sec = ClocksPerSec();
|
||||
|
||||
start = ClockNow();
|
||||
end = start + (Clock)(interval * clocks_per_sec);
|
||||
AVER(end >= start);
|
||||
|
||||
stepped = FALSE;
|
||||
|
||||
if (arenaShouldCollectWorld(arena, interval, multiplier,
|
||||
start, clocks_per_sec))
|
||||
{
|
||||
Res res;
|
||||
Trace trace;
|
||||
res = TraceStartCollectAll(&trace, arena, TraceStartWhyOPPORTUNISM);
|
||||
if (res == ResOK) {
|
||||
arena->lastWorldCollect = start;
|
||||
stepped = TRUE;
|
||||
}
|
||||
}
|
||||
start = now = ClockNow();
|
||||
intervalEnd = start + (Clock)(interval * clocks_per_sec);
|
||||
AVER(intervalEnd >= start);
|
||||
availableEnd = start + (Clock)(interval * multiplier * clocks_per_sec);
|
||||
AVER(availableEnd >= start);
|
||||
|
||||
/* loop while there is work to do and time on the clock. */
|
||||
do {
|
||||
scanned = TracePoll(globals);
|
||||
now = ClockNow();
|
||||
if (scanned > 0) {
|
||||
stepped = TRUE;
|
||||
arena->tracedSize += scanned;
|
||||
Trace trace;
|
||||
if (arena->busyTraces != TraceSetEMPTY) {
|
||||
trace = ArenaTrace(arena, (TraceId)0);
|
||||
} else {
|
||||
/* No traces are running: consider collecting the world. */
|
||||
if (PolicyShouldCollectWorld(arena, (double)(availableEnd - now), now,
|
||||
clocks_per_sec))
|
||||
{
|
||||
Res res;
|
||||
res = TraceStartCollectAll(&trace, arena, TraceStartWhyOPPORTUNISM);
|
||||
if (res != ResOK)
|
||||
break;
|
||||
arena->lastWorldCollect = now;
|
||||
} else {
|
||||
/* Not worth collecting the world; consider starting a trace. */
|
||||
if (!PolicyStartTrace(&trace, arena))
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while ((scanned > 0) && (now < end));
|
||||
TraceAdvance(trace);
|
||||
if (trace->state == TraceFINISHED)
|
||||
TraceDestroyFinished(trace);
|
||||
workWasDone = TRUE;
|
||||
now = ClockNow();
|
||||
} while (now < intervalEnd);
|
||||
|
||||
if (stepped) {
|
||||
arena->tracedTime += (now - start) / (double) clocks_per_sec;
|
||||
if (workWasDone) {
|
||||
ArenaAccumulateTime(arena, start, now);
|
||||
}
|
||||
|
||||
return stepped;
|
||||
return workWasDone;
|
||||
}
|
||||
|
||||
/* ArenaFinalize -- registers an object for finalization
|
||||
|
|
@ -858,17 +795,19 @@ Bool ArenaStep(Globals globals, double interval, double multiplier)
|
|||
Res ArenaFinalize(Arena arena, Ref obj)
|
||||
{
|
||||
Res res;
|
||||
Pool refpool;
|
||||
|
||||
AVERT(Arena, arena);
|
||||
AVER(ArenaHasAddr(arena, (Addr)obj));
|
||||
AVER(PoolOfAddr(&refpool, arena, (Addr)obj));
|
||||
AVER(PoolHasAttr(refpool, AttrGC));
|
||||
|
||||
if (!arena->isFinalPool) {
|
||||
Pool pool;
|
||||
Pool finalpool;
|
||||
|
||||
res = PoolCreate(&pool, arena, PoolClassMRG(), argsNone);
|
||||
res = PoolCreate(&finalpool, arena, PoolClassMRG(), argsNone);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
arena->finalPool = pool;
|
||||
arena->finalPool = finalpool;
|
||||
arena->isFinalPool = TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -1045,7 +984,6 @@ Res GlobalsDescribe(Globals arenaGlobals, mps_lib_FILE *stream, Count depth)
|
|||
"rootSerial $U\n", (WriteFU)arenaGlobals->rootSerial,
|
||||
"formatSerial $U\n", (WriteFU)arena->formatSerial,
|
||||
"threadSerial $U\n", (WriteFU)arena->threadSerial,
|
||||
arena->insideShield ? "inside" : "outside", " shield\n",
|
||||
"busyTraces $B\n", (WriteFB)arena->busyTraces,
|
||||
"flippedTraces $B\n", (WriteFB)arena->flippedTraces,
|
||||
"epoch $U\n", (WriteFU)arena->epoch,
|
||||
|
|
@ -1064,13 +1002,7 @@ Res GlobalsDescribe(Globals arenaGlobals, mps_lib_FILE *stream, Count depth)
|
|||
return res;
|
||||
}
|
||||
|
||||
res = WriteF(stream, depth,
|
||||
"} history\n",
|
||||
"suspended $S\n", WriteFYesNo(arena->suspended),
|
||||
"shDepth $U\n", (WriteFU)arena->shDepth,
|
||||
"shCacheI $U\n", (WriteFU)arena->shCacheI,
|
||||
/* @@@@ should SegDescribe the cached segs? */
|
||||
NULL);
|
||||
res = ShieldDescribe(ArenaShield(arena), stream, depth);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
|
|
|
|||
|
|
@ -117,8 +117,7 @@ Res LandCreate(Land *landReturn, Arena arena, LandClass class, Align alignment,
|
|||
AVERT(Arena, arena);
|
||||
AVERT(LandClass, class);
|
||||
|
||||
res = ControlAlloc(&p, arena, class->size,
|
||||
/* withReservoirPermit */ FALSE);
|
||||
res = ControlAlloc(&p, arena, class->size);
|
||||
if (res != ResOK)
|
||||
goto failAlloc;
|
||||
land = p;
|
||||
|
|
@ -235,14 +234,14 @@ Res LandDelete(Range rangeReturn, Land land, Range range)
|
|||
* See <design/land/#function.iterate>
|
||||
*/
|
||||
|
||||
Bool LandIterate(Land land, LandVisitor visitor, void *closureP, Size closureS)
|
||||
Bool LandIterate(Land land, LandVisitor visitor, void *closure)
|
||||
{
|
||||
Bool b;
|
||||
AVERT(Land, land);
|
||||
AVER(FUNCHECK(visitor));
|
||||
landEnter(land);
|
||||
|
||||
b = (*land->class->iterate)(land, visitor, closureP, closureS);
|
||||
b = (*land->class->iterate)(land, visitor, closure);
|
||||
|
||||
landLeave(land);
|
||||
return b;
|
||||
|
|
@ -255,14 +254,14 @@ Bool LandIterate(Land land, LandVisitor visitor, void *closureP, Size closureS)
|
|||
* See <design/land/#function.iterate.and.delete>
|
||||
*/
|
||||
|
||||
Bool LandIterateAndDelete(Land land, LandDeleteVisitor visitor, void *closureP, Size closureS)
|
||||
Bool LandIterateAndDelete(Land land, LandDeleteVisitor visitor, void *closure)
|
||||
{
|
||||
Bool b;
|
||||
AVERT(Land, land);
|
||||
AVER(FUNCHECK(visitor));
|
||||
landEnter(land);
|
||||
|
||||
b = (*land->class->iterateAndDelete)(land, visitor, closureP, closureS);
|
||||
b = (*land->class->iterateAndDelete)(land, visitor, closure);
|
||||
|
||||
landLeave(land);
|
||||
return b;
|
||||
|
|
@ -403,11 +402,11 @@ Res LandDescribe(Land land, mps_lib_FILE *stream, Count depth)
|
|||
|
||||
/* landFlushVisitor -- visitor for LandFlush.
|
||||
*
|
||||
* closureP argument is the destination Land. Attempt to insert the
|
||||
* closure argument is the destination Land. Attempt to insert the
|
||||
* range into the destination.
|
||||
*/
|
||||
static Bool landFlushVisitor(Bool *deleteReturn, Land land, Range range,
|
||||
void *closureP, Size closureS)
|
||||
void *closure)
|
||||
{
|
||||
Res res;
|
||||
RangeStruct newRange;
|
||||
|
|
@ -416,11 +415,9 @@ static Bool landFlushVisitor(Bool *deleteReturn, Land land, Range range,
|
|||
AVER(deleteReturn != NULL);
|
||||
AVERT(Land, land);
|
||||
AVERT(Range, range);
|
||||
AVER(closureP != NULL);
|
||||
AVER(closureS == UNUSED_SIZE);
|
||||
UNUSED(closureS);
|
||||
AVER(closure != NULL);
|
||||
|
||||
dest = closureP;
|
||||
dest = closure;
|
||||
res = LandInsert(&newRange, dest, range);
|
||||
if (res == ResOK) {
|
||||
*deleteReturn = TRUE;
|
||||
|
|
@ -442,7 +439,7 @@ Bool LandFlush(Land dest, Land src)
|
|||
AVERT(Land, dest);
|
||||
AVERT(Land, src);
|
||||
|
||||
return LandIterateAndDelete(src, landFlushVisitor, dest, UNUSED_SIZE);
|
||||
return LandIterateAndDelete(src, landFlushVisitor, dest);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -491,17 +488,15 @@ static Size landNoSize(Land land)
|
|||
/* LandSlowSize -- generic size method but slow */
|
||||
|
||||
static Bool landSizeVisitor(Land land, Range range,
|
||||
void *closureP, Size closureS)
|
||||
void *closure)
|
||||
{
|
||||
Size *size;
|
||||
|
||||
AVERT(Land, land);
|
||||
AVERT(Range, range);
|
||||
AVER(closureP != NULL);
|
||||
AVER(closureS == UNUSED_SIZE);
|
||||
UNUSED(closureS);
|
||||
AVER(closure != NULL);
|
||||
|
||||
size = closureP;
|
||||
size = closure;
|
||||
*size += RangeSize(range);
|
||||
|
||||
return TRUE;
|
||||
|
|
@ -510,7 +505,7 @@ static Bool landSizeVisitor(Land land, Range range,
|
|||
Size LandSlowSize(Land land)
|
||||
{
|
||||
Size size = 0;
|
||||
Bool b = LandIterate(land, landSizeVisitor, &size, UNUSED_SIZE);
|
||||
Bool b = LandIterate(land, landSizeVisitor, &size);
|
||||
AVER(b);
|
||||
return size;
|
||||
}
|
||||
|
|
@ -531,21 +526,19 @@ static Res landNoDelete(Range rangeReturn, Land land, Range range)
|
|||
return ResUNIMPL;
|
||||
}
|
||||
|
||||
static Bool landNoIterate(Land land, LandVisitor visitor, void *closureP, Size closureS)
|
||||
static Bool landNoIterate(Land land, LandVisitor visitor, void *closure)
|
||||
{
|
||||
AVERT(Land, land);
|
||||
AVER(visitor != NULL);
|
||||
UNUSED(closureP);
|
||||
UNUSED(closureS);
|
||||
UNUSED(closure);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static Bool landNoIterateAndDelete(Land land, LandDeleteVisitor visitor, void *closureP, Size closureS)
|
||||
static Bool landNoIterateAndDelete(Land land, LandDeleteVisitor visitor, void *closure)
|
||||
{
|
||||
AVERT(Land, land);
|
||||
AVER(visitor != NULL);
|
||||
UNUSED(closureP);
|
||||
UNUSED(closureS);
|
||||
UNUSED(closure);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -67,13 +67,12 @@ static void describe(TestState state) {
|
|||
}
|
||||
|
||||
|
||||
static Bool checkVisitor(Land land, Range range, void *closureP, Size closureS)
|
||||
static Bool checkVisitor(Land land, Range range, void *closure)
|
||||
{
|
||||
Addr base, limit;
|
||||
CheckTestClosure cl = closureP;
|
||||
CheckTestClosure cl = closure;
|
||||
|
||||
testlib_unused(land);
|
||||
Insist(closureS == UNUSED_SIZE);
|
||||
Insist(cl != NULL);
|
||||
|
||||
base = RangeBase(range);
|
||||
|
|
@ -106,7 +105,7 @@ static void check(TestState state)
|
|||
closure.limit = addrOfIndex(state, state->size);
|
||||
closure.oldLimit = state->block;
|
||||
|
||||
b = LandIterate(state->land, checkVisitor, &closure, UNUSED_SIZE);
|
||||
b = LandIterate(state->land, checkVisitor, &closure);
|
||||
Insist(b);
|
||||
|
||||
if (closure.oldLimit == state->block)
|
||||
|
|
@ -460,8 +459,7 @@ extern int main(int argc, char *argv[])
|
|||
die((mps_res_t)BTCreate(&state.allocTable, arena, state.size),
|
||||
"failed to create alloc table");
|
||||
|
||||
die((mps_res_t)ControlAlloc(&p, arena, (state.size + 1) * state.align,
|
||||
/* withReservoirPermit */ FALSE),
|
||||
die((mps_res_t)ControlAlloc(&p, arena, (state.size + 1) * state.align),
|
||||
"failed to allocate block");
|
||||
state.block = AddrAlignUp(p, state.align);
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ CC = clang
|
|||
CFLAGSDEBUG = -O0 -g3
|
||||
CFLAGSOPT = -O2 -g3
|
||||
CFLAGSCOMPILER := \
|
||||
-pedantic \
|
||||
-Waggregate-return \
|
||||
-Wall \
|
||||
-Wcast-qual \
|
||||
|
|
@ -32,7 +31,7 @@ CFLAGSCOMPILER := \
|
|||
-Wstrict-prototypes \
|
||||
-Wunreachable-code \
|
||||
-Wwrite-strings
|
||||
CFLAGSCOMPILERSTRICT :=
|
||||
CFLAGSCOMPILERSTRICT := -std=c89 -pedantic
|
||||
|
||||
# A different set of compiler flags for less strict compilation, for
|
||||
# instance when we need to #include a third-party header file that
|
||||
|
|
|
|||
|
|
@ -1,83 +0,0 @@
|
|||
/* lo.h: LEAF OBJECT POOL CLASS INTERFACE
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* The Leaf Object PoolClass is an automatically managed (ie garbage
|
||||
* collected) pool for managing "leaf" objects. Leaf objects are
|
||||
* objects that have no references or no references that need tracing
|
||||
* (ie the objects they refer too are non-moving and are manually
|
||||
* managed).
|
||||
*
|
||||
* This Class has the following features:
|
||||
*
|
||||
* Approximately 6% (asymptotically) space overhead on managed objects.
|
||||
*
|
||||
* Automatically reclaims memory used by objects no longer reachable
|
||||
* from the roots.
|
||||
*
|
||||
* Non-moving. References to objects in this pool will never change
|
||||
* due to "fixing".
|
||||
*
|
||||
* Buffers will always "commit". When allocating using a buffer,
|
||||
* commit will never fail.
|
||||
*
|
||||
* The following caveat applies:
|
||||
*
|
||||
* Space and time performance will degrade when fragmentation
|
||||
* increases.
|
||||
*/
|
||||
|
||||
#ifndef lo_h
|
||||
#define lo_h
|
||||
|
||||
#include "mpm.h"
|
||||
|
||||
typedef struct LOStruct *LO;
|
||||
|
||||
extern PoolClass PoolClassLO(void);
|
||||
|
||||
#endif /* lo_h */
|
||||
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
/* locus.c: LOCUS MANAGER
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* DESIGN
|
||||
*
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
* collection strategy.
|
||||
*/
|
||||
|
||||
#include "chain.h"
|
||||
#include "locus.h"
|
||||
#include "ring.h"
|
||||
#include "mpm.h"
|
||||
#include "mpstd.h"
|
||||
|
|
@ -103,7 +103,7 @@ Res LocusPrefDescribe(LocusPref pref, mps_lib_FILE *stream, Count depth)
|
|||
/* GenDescCheck -- check a GenDesc */
|
||||
|
||||
ATTRIBUTE_UNUSED
|
||||
static Bool GenDescCheck(GenDesc gen)
|
||||
Bool GenDescCheck(GenDesc gen)
|
||||
{
|
||||
CHECKS(GenDesc, gen);
|
||||
/* nothing to check for zones */
|
||||
|
|
@ -117,11 +117,13 @@ static Bool GenDescCheck(GenDesc gen)
|
|||
|
||||
/* GenDescNewSize -- return effective size of generation */
|
||||
|
||||
static Size GenDescNewSize(GenDesc gen)
|
||||
Size GenDescNewSize(GenDesc gen)
|
||||
{
|
||||
Size size = 0;
|
||||
Ring node, nextNode;
|
||||
|
||||
AVERT(GenDesc, gen);
|
||||
|
||||
RING_FOR(node, &gen->locusRing, nextNode) {
|
||||
PoolGen pgen = RING_ELT(PoolGen, genRing, node);
|
||||
AVERT(PoolGen, pgen);
|
||||
|
|
@ -133,11 +135,13 @@ static Size GenDescNewSize(GenDesc gen)
|
|||
|
||||
/* GenDescTotalSize -- return total size of generation */
|
||||
|
||||
static Size GenDescTotalSize(GenDesc gen)
|
||||
Size GenDescTotalSize(GenDesc gen)
|
||||
{
|
||||
Size size = 0;
|
||||
Ring node, nextNode;
|
||||
|
||||
AVERT(GenDesc, gen);
|
||||
|
||||
RING_FOR(node, &gen->locusRing, nextNode) {
|
||||
PoolGen pgen = RING_ELT(PoolGen, genRing, node);
|
||||
AVERT(PoolGen, pgen);
|
||||
|
|
@ -201,7 +205,7 @@ Res ChainCreate(Chain *chainReturn, Arena arena, size_t genCount,
|
|||
AVER(params[i].mortality < 1.0);
|
||||
}
|
||||
|
||||
res = ControlAlloc(&p, arena, genCount * sizeof(GenDescStruct), FALSE);
|
||||
res = ControlAlloc(&p, arena, genCount * sizeof(GenDescStruct));
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
gens = (GenDescStruct *)p;
|
||||
|
|
@ -215,7 +219,7 @@ Res ChainCreate(Chain *chainReturn, Arena arena, size_t genCount,
|
|||
AVERT(GenDesc, &gens[i]);
|
||||
}
|
||||
|
||||
res = ControlAlloc(&p, arena, sizeof(ChainStruct), FALSE);
|
||||
res = ControlAlloc(&p, arena, sizeof(ChainStruct));
|
||||
if (res != ResOK)
|
||||
goto failChainAlloc;
|
||||
chain = (Chain)p;
|
||||
|
|
@ -309,7 +313,7 @@ GenDesc ChainGen(Chain chain, Index gen)
|
|||
*/
|
||||
|
||||
Res PoolGenAlloc(Seg *segReturn, PoolGen pgen, SegClass class, Size size,
|
||||
Bool withReservoirPermit, ArgList args)
|
||||
ArgList args)
|
||||
{
|
||||
LocusPrefStruct pref;
|
||||
Res res;
|
||||
|
|
@ -322,7 +326,6 @@ Res PoolGenAlloc(Seg *segReturn, PoolGen pgen, SegClass class, Size size,
|
|||
AVERT(PoolGen, pgen);
|
||||
AVERT(SegClass, class);
|
||||
AVER(size > 0);
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
AVERT(ArgList, args);
|
||||
|
||||
arena = PoolArena(pgen->pool);
|
||||
|
|
@ -333,8 +336,7 @@ Res PoolGenAlloc(Seg *segReturn, PoolGen pgen, SegClass class, Size size,
|
|||
pref.high = FALSE;
|
||||
pref.zones = zones;
|
||||
pref.avoid = ZoneSetBlacklist(arena);
|
||||
res = SegAlloc(&seg, class, &pref, size, pgen->pool, withReservoirPermit,
|
||||
args);
|
||||
res = SegAlloc(&seg, class, &pref, size, pgen->pool, args);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
|
|
@ -381,69 +383,6 @@ double ChainDeferral(Chain chain)
|
|||
}
|
||||
|
||||
|
||||
/* ChainCondemnAuto -- condemn approriate parts of this chain
|
||||
*
|
||||
* This is only called if ChainDeferral returned a value sufficiently
|
||||
* low that the tracer decided to start the collection. (Usually
|
||||
* such values are less than zero; see <design/trace/>)
|
||||
*/
|
||||
Res ChainCondemnAuto(double *mortalityReturn, Chain chain, Trace trace)
|
||||
{
|
||||
Res res;
|
||||
size_t topCondemnedGen, i;
|
||||
GenDesc gen;
|
||||
ZoneSet condemnedSet = ZoneSetEMPTY;
|
||||
Size condemnedSize = 0, survivorSize = 0, genNewSize, genTotalSize;
|
||||
|
||||
AVERT(Chain, chain);
|
||||
AVERT(Trace, trace);
|
||||
|
||||
/* Find the highest generation that's over capacity. We will condemn
|
||||
* this and all lower generations in the chain. */
|
||||
topCondemnedGen = chain->genCount;
|
||||
for (;;) {
|
||||
/* It's an error to call this function unless some generation is
|
||||
* over capacity as reported by ChainDeferral. */
|
||||
AVER(topCondemnedGen > 0);
|
||||
if (topCondemnedGen == 0)
|
||||
return ResFAIL;
|
||||
-- topCondemnedGen;
|
||||
gen = &chain->gens[topCondemnedGen];
|
||||
AVERT(GenDesc, gen);
|
||||
genNewSize = GenDescNewSize(gen);
|
||||
if (genNewSize >= gen->capacity * (Size)1024)
|
||||
break;
|
||||
}
|
||||
|
||||
/* At this point, we've decided to condemn topCondemnedGen and all
|
||||
* lower generations. */
|
||||
for (i = 0; i <= topCondemnedGen; ++i) {
|
||||
gen = &chain->gens[i];
|
||||
AVERT(GenDesc, gen);
|
||||
condemnedSet = ZoneSetUnion(condemnedSet, gen->zones);
|
||||
genTotalSize = GenDescTotalSize(gen);
|
||||
genNewSize = GenDescNewSize(gen);
|
||||
condemnedSize += genTotalSize;
|
||||
survivorSize += (Size)(genNewSize * (1.0 - gen->mortality))
|
||||
/* predict survivors will survive again */
|
||||
+ (genTotalSize - genNewSize);
|
||||
}
|
||||
|
||||
AVER(condemnedSet != ZoneSetEMPTY || condemnedSize == 0);
|
||||
EVENT3(ChainCondemnAuto, chain, topCondemnedGen, chain->genCount);
|
||||
|
||||
/* Condemn everything in these zones. */
|
||||
if (condemnedSet != ZoneSetEMPTY) {
|
||||
res = TraceCondemnZones(trace, condemnedSet);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
}
|
||||
|
||||
*mortalityReturn = 1.0 - (double)survivorSize / condemnedSize;
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
||||
/* ChainStartGC -- called to notify start of GC for this chain */
|
||||
|
||||
void ChainStartGC(Chain chain, Trace trace)
|
||||
|
|
@ -825,7 +764,7 @@ Bool LocusCheck(Arena arena)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
/* chain.h: GENERATION CHAINS
|
||||
/* locus.h: GENERATION CHAINS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
*/
|
||||
|
||||
#ifndef chain_h
|
||||
#define chain_h
|
||||
#ifndef locus_h
|
||||
#define locus_h
|
||||
|
||||
#include "mpmtypes.h"
|
||||
#include "ring.h"
|
||||
|
|
@ -75,6 +75,9 @@ typedef struct mps_chain_s {
|
|||
} ChainStruct;
|
||||
|
||||
|
||||
extern Bool GenDescCheck(GenDesc gen);
|
||||
extern Size GenDescNewSize(GenDesc gen);
|
||||
extern Size GenDescTotalSize(GenDesc gen);
|
||||
extern Res GenDescDescribe(GenDesc gen, mps_lib_FILE *stream, Count depth);
|
||||
|
||||
extern Res ChainCreate(Chain *chainReturn, Arena arena, size_t genCount,
|
||||
|
|
@ -83,7 +86,6 @@ extern void ChainDestroy(Chain chain);
|
|||
extern Bool ChainCheck(Chain chain);
|
||||
|
||||
extern double ChainDeferral(Chain chain);
|
||||
extern Res ChainCondemnAuto(double *mortalityReturn, Chain chain, Trace trace);
|
||||
extern void ChainStartGC(Chain chain, Trace trace);
|
||||
extern void ChainEndGC(Chain chain, Trace trace);
|
||||
extern size_t ChainGens(Chain chain);
|
||||
|
|
@ -94,7 +96,7 @@ extern Bool PoolGenCheck(PoolGen pgen);
|
|||
extern Res PoolGenInit(PoolGen pgen, GenDesc gen, Pool pool);
|
||||
extern void PoolGenFinish(PoolGen pgen);
|
||||
extern Res PoolGenAlloc(Seg *segReturn, PoolGen pgen, SegClass class,
|
||||
Size size, Bool withReservoirPermit, ArgList args);
|
||||
Size size, ArgList args);
|
||||
extern void PoolGenFree(PoolGen pgen, Seg seg, Size freeSize, Size oldSize,
|
||||
Size newSize, Bool deferred);
|
||||
extern void PoolGenAccountForFill(PoolGen pgen, Size size, Bool deferred);
|
||||
|
|
@ -106,12 +108,12 @@ extern void PoolGenAccountForSegSplit(PoolGen pgen);
|
|||
extern void PoolGenAccountForSegMerge(PoolGen pgen);
|
||||
extern Res PoolGenDescribe(PoolGen gen, mps_lib_FILE *stream, Count depth);
|
||||
|
||||
#endif /* chain_h */
|
||||
#endif /* locus_h */
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
@ -219,13 +219,11 @@ static void runArenaTest(size_t size,
|
|||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, size);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_ZONED, FALSE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_COMMIT_LIMIT, size - chunkSize);
|
||||
die(mps_arena_create_k(&arena, mps_arena_class_vm(), args),
|
||||
"mps_arena_create");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
die(mps_arena_commit_limit_set(arena, size - chunkSize),
|
||||
"mps_arena_commit_limit_set");
|
||||
|
||||
testInArena(arena, failcase, usefulFailcase);
|
||||
|
||||
mps_arena_destroy(arena);
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ static void postDummyMessage(Arena arena, MessageClass class,
|
|||
void *p;
|
||||
Message message;
|
||||
|
||||
die((mps_res_t)ControlAlloc(&p, arena, sizeof(MessageStruct), FALSE),
|
||||
die((mps_res_t)ControlAlloc(&p, arena, sizeof(MessageStruct)),
|
||||
"AllocMessage");
|
||||
message = (Message)p;
|
||||
MessageInit(arena, message, class, type);
|
||||
|
|
|
|||
159
mps/code/mpm.c
159
mps/code/mpm.c
|
|
@ -9,6 +9,7 @@
|
|||
* .sources: <design/writef/> */
|
||||
|
||||
#include "check.h"
|
||||
#include "misc.h"
|
||||
#include "mpm.h"
|
||||
#include "vm.h"
|
||||
|
||||
|
|
@ -88,6 +89,11 @@ Bool MPMCheck(void)
|
|||
* <design/sp/#sol.depth.constraint>. */
|
||||
CHECKL(StackProbeDEPTH * sizeof(Word) < PageSize());
|
||||
|
||||
/* Check these values will fit in their bitfield. */
|
||||
CHECKL(WB_DEFER_INIT <= ((1ul << WB_DEFER_BITS) - 1));
|
||||
CHECKL(WB_DEFER_DELAY <= ((1ul << WB_DEFER_BITS) - 1));
|
||||
CHECKL(WB_DEFER_HIT <= ((1ul << WB_DEFER_BITS) - 1));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -614,16 +620,19 @@ Res WriteF_firstformat_v(mps_lib_FILE *stream, Count depth,
|
|||
|
||||
size_t StringLength(const char *s)
|
||||
{
|
||||
size_t i;
|
||||
size_t i = 0;
|
||||
|
||||
AVER(s != NULL);
|
||||
|
||||
for(i = 0; s[i] != '\0'; i++)
|
||||
NOOP;
|
||||
return(i);
|
||||
while (s[i] != '\0')
|
||||
++i;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
#if 0 /* This code is currently not in use in the MPS */
|
||||
|
||||
/* StringEqual -- slow substitute for (strcmp == 0) */
|
||||
|
||||
Bool StringEqual(const char *s1, const char *s2)
|
||||
|
|
@ -644,6 +653,148 @@ Bool StringEqual(const char *s1, const char *s2)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
#endif /* not currently in use */
|
||||
|
||||
|
||||
/* Random -- a random number generator
|
||||
*
|
||||
* TODO: This is a copy of the generator from testlib.c, which has
|
||||
* extensive notes and verification tests. The notes need to go to a
|
||||
* design document, and the tests to a test.
|
||||
*/
|
||||
|
||||
static unsigned RandomSeed = 1;
|
||||
#define Random_m 2147483647UL
|
||||
#define Random_a 48271UL
|
||||
unsigned Random32(void)
|
||||
{
|
||||
/* requires m == 2^31-1, a < 2^16 */
|
||||
unsigned bot = Random_a * (RandomSeed & 0x7FFF);
|
||||
unsigned top = Random_a * (RandomSeed >> 15);
|
||||
AVER(UINT_MAX >= 4294967295U);
|
||||
RandomSeed = bot + ((top & 0xFFFF) << 15) + (top >> 16);
|
||||
if (RandomSeed > Random_m)
|
||||
RandomSeed -= Random_m;
|
||||
return RandomSeed;
|
||||
}
|
||||
|
||||
Word RandomWord(void)
|
||||
{
|
||||
Word word = 0;
|
||||
Index i;
|
||||
for (i = 0; i < MPS_WORD_WIDTH; i += 31)
|
||||
word = (word << 31) | Random32();
|
||||
return word;
|
||||
}
|
||||
|
||||
|
||||
/* QuickSort -- non-recursive bounded sort
|
||||
*
|
||||
* We can't rely on the standard library's qsort, which might have
|
||||
* O(n) stack usage. This version does not recurse.
|
||||
*/
|
||||
|
||||
#ifdef QUICKSORT_DEBUG
|
||||
static Bool quickSorted(void *array[], Count length,
|
||||
QuickSortCompare compare, void *closure)
|
||||
{
|
||||
Index i;
|
||||
if (length > 0) {
|
||||
for (i = 0; i < length - 1; ++i) {
|
||||
if (compare(array[i], array[i+1], closure) == CompareGREATER)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
void QuickSort(void *array[], Count length,
|
||||
QuickSortCompare compare, void *closure,
|
||||
SortStruct *sortStruct)
|
||||
{
|
||||
Index left, right, sp, lo, hi, leftLimit, rightBase;
|
||||
void *pivot, *temp;
|
||||
|
||||
AVER(array != NULL);
|
||||
/* can't check length */
|
||||
AVER(FUNCHECK(compare));
|
||||
/* can't check closure */
|
||||
AVER(sortStruct != NULL);
|
||||
|
||||
sp = 0;
|
||||
left = 0;
|
||||
right = length;
|
||||
|
||||
for (;;) {
|
||||
while (right - left > 1) { /* only need to sort if two or more */
|
||||
/* Pick a random pivot. */
|
||||
pivot = array[left + RandomWord() % (right - left)];
|
||||
|
||||
/* Hoare partition: scan from left to right, dividing it into
|
||||
elements less than the pivot and elements greater or
|
||||
equal. */
|
||||
lo = left;
|
||||
hi = right;
|
||||
for (;;) {
|
||||
while (compare(array[lo], pivot, closure) == CompareLESS)
|
||||
++lo;
|
||||
do
|
||||
--hi;
|
||||
while (compare(pivot, array[hi], closure) == CompareLESS);
|
||||
if (lo >= hi)
|
||||
break;
|
||||
temp = array[hi];
|
||||
array[hi] = array[lo];
|
||||
array[lo] = temp;
|
||||
++lo; /* step over what we just swapped */
|
||||
}
|
||||
|
||||
/* After partition, if we ended up at a pivot, then it is in its
|
||||
final position and we must skip it to ensure termination.
|
||||
This handles the case where the pivot is at the start of the
|
||||
array, and one of the partitions is the whole array, for
|
||||
example. */
|
||||
if (lo == hi) {
|
||||
AVER_CRITICAL(array[hi] == pivot); /* and it's in place */
|
||||
leftLimit = lo;
|
||||
rightBase = lo + 1;
|
||||
} else {
|
||||
AVER_CRITICAL(lo == hi + 1);
|
||||
leftLimit = lo;
|
||||
rightBase = lo;
|
||||
}
|
||||
|
||||
/* Sort the smaller part now, so that we're sure to use at most
|
||||
log2 length stack levels. Push the larger part on the stack
|
||||
for later. */
|
||||
AVER_CRITICAL(sp < sizeof sortStruct->stack / sizeof sortStruct->stack[0]);
|
||||
if (leftLimit - left < right - rightBase) {
|
||||
sortStruct->stack[sp].left = rightBase;
|
||||
sortStruct->stack[sp].right = right;
|
||||
++sp;
|
||||
right = leftLimit;
|
||||
} else {
|
||||
sortStruct->stack[sp].left = left;
|
||||
sortStruct->stack[sp].right = leftLimit;
|
||||
++sp;
|
||||
left = rightBase;
|
||||
}
|
||||
}
|
||||
|
||||
if (sp == 0)
|
||||
break;
|
||||
|
||||
--sp;
|
||||
left = sortStruct->stack[sp].left;
|
||||
right = sortStruct->stack[sp].right;
|
||||
AVER_CRITICAL(left < right); /* we will have done a zero-length part first */
|
||||
}
|
||||
|
||||
#ifdef QUICKSORT_DEBUG
|
||||
AVER(quickSorted(array, length, compare, closure));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
|
|
|
|||
163
mps/code/mpm.h
163
mps/code/mpm.h
|
|
@ -171,6 +171,15 @@ extern Res WriteF_firstformat_v(mps_lib_FILE *stream, Count depth,
|
|||
extern size_t StringLength(const char *s);
|
||||
extern Bool StringEqual(const char *s1, const char *s2);
|
||||
|
||||
extern unsigned Random32(void);
|
||||
extern Word RandomWord(void);
|
||||
|
||||
typedef Compare QuickSortCompare(void *left, void *right,
|
||||
void *closure);
|
||||
extern void QuickSort(void *array[], Count length,
|
||||
QuickSortCompare compare, void *closure,
|
||||
SortStruct *sortStruct);
|
||||
|
||||
|
||||
/* Version Determination
|
||||
*
|
||||
|
|
@ -208,8 +217,7 @@ extern Res PoolCreate(Pool *poolReturn, Arena arena, PoolClass class,
|
|||
ArgList args);
|
||||
extern void PoolDestroy(Pool pool);
|
||||
extern BufferClass PoolDefaultBufferClass(Pool pool);
|
||||
extern Res PoolAlloc(Addr *pReturn, Pool pool, Size size,
|
||||
Bool withReservoirPermit);
|
||||
extern Res PoolAlloc(Addr *pReturn, Pool pool, Size size);
|
||||
extern void PoolFree(Pool pool, Addr old, Size size);
|
||||
extern Res PoolTraceBegin(Pool pool, Trace trace);
|
||||
extern Res PoolAccess(Pool pool, Seg seg, Addr addr,
|
||||
|
|
@ -233,18 +241,14 @@ extern Size PoolFreeSize(Pool pool);
|
|||
|
||||
extern Res PoolTrivInit(Pool pool, ArgList arg);
|
||||
extern void PoolTrivFinish(Pool pool);
|
||||
extern Res PoolNoAlloc(Addr *pReturn, Pool pool, Size size,
|
||||
Bool withReservoirPermit);
|
||||
extern Res PoolTrivAlloc(Addr *pReturn, Pool pool, Size size,
|
||||
Bool withReservoirPermit);
|
||||
extern Res PoolNoAlloc(Addr *pReturn, Pool pool, Size size);
|
||||
extern Res PoolTrivAlloc(Addr *pReturn, Pool pool, Size size);
|
||||
extern void PoolNoFree(Pool pool, Addr old, Size size);
|
||||
extern void PoolTrivFree(Pool pool, Addr old, Size size);
|
||||
extern Res PoolNoBufferFill(Addr *baseReturn, Addr *limitReturn,
|
||||
Pool pool, Buffer buffer, Size size,
|
||||
Bool withReservoirPermit);
|
||||
Pool pool, Buffer buffer, Size size);
|
||||
extern Res PoolTrivBufferFill(Addr *baseReturn, Addr *limitReturn,
|
||||
Pool pool, Buffer buffer, Size size,
|
||||
Bool withReservoirPermit);
|
||||
Pool pool, Buffer buffer, Size size);
|
||||
extern void PoolNoBufferEmpty(Pool pool, Buffer buffer,
|
||||
Addr init, Addr limit);
|
||||
extern void PoolTrivBufferEmpty(Pool pool, Buffer buffer,
|
||||
|
|
@ -394,17 +398,19 @@ extern Bool TraceIdCheck(TraceId id);
|
|||
extern Bool TraceSetCheck(TraceSet ts);
|
||||
extern Bool TraceCheck(Trace trace);
|
||||
extern Res TraceCreate(Trace *traceReturn, Arena arena, int why);
|
||||
extern void TraceDestroy(Trace trace);
|
||||
extern void TraceDestroyInit(Trace trace);
|
||||
extern void TraceDestroyFinished(Trace trace);
|
||||
|
||||
extern Bool TraceIsEmpty(Trace trace);
|
||||
extern Res TraceAddWhite(Trace trace, Seg seg);
|
||||
extern Res TraceCondemnZones(Trace trace, ZoneSet condemnedSet);
|
||||
extern Res TraceStart(Trace trace, double mortality, double finishingTime);
|
||||
extern Size TracePoll(Globals globals);
|
||||
extern Bool TracePoll(Work *workReturn, Globals globals);
|
||||
|
||||
extern Rank TraceRankForAccess(Arena arena, Seg seg);
|
||||
extern void TraceSegAccess(Arena arena, Seg seg, AccessSet mode);
|
||||
|
||||
extern void TraceQuantum(Trace trace);
|
||||
extern void TraceAdvance(Trace trace);
|
||||
extern Res TraceStartCollectAll(Trace *traceReturn, Arena arena, int why);
|
||||
extern Res TraceDescribe(Trace trace, mps_lib_FILE *stream, Count depth);
|
||||
|
||||
|
|
@ -473,10 +479,9 @@ extern double TraceWorkFactor;
|
|||
} \
|
||||
END
|
||||
|
||||
extern Res TraceScanArea(ScanState ss, Addr *base, Addr *limit);
|
||||
extern Res TraceScanAreaTagged(ScanState ss, Addr *base, Addr *limit);
|
||||
extern Res TraceScanAreaMasked(ScanState ss,
|
||||
Addr *base, Addr *limit, Word mask);
|
||||
extern Res TraceScanArea(ScanState ss, Word *base, Word *limit,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure);
|
||||
extern void TraceScanSingleRef(TraceSet ts, Rank rank, Arena arena,
|
||||
Seg seg, Ref *refIO);
|
||||
|
||||
|
|
@ -521,6 +526,7 @@ extern Ring GlobalsRememberedSummaryRing(Globals);
|
|||
#define GlobalsArena(glob) PARENT(ArenaStruct, globals, glob)
|
||||
|
||||
#define ArenaThreadRing(arena) (&(arena)->threadRing)
|
||||
#define ArenaDeadRing(arena) (&(arena)->deadRing)
|
||||
#define ArenaEpoch(arena) ((arena)->epoch) /* .epoch.ts */
|
||||
#define ArenaTrace(arena, ti) (&(arena)->trace[ti])
|
||||
#define ArenaZoneShift(arena) ((arena)->zoneShift)
|
||||
|
|
@ -530,6 +536,7 @@ extern Ring GlobalsRememberedSummaryRing(Globals);
|
|||
#define ArenaPoolRing(arena) (&ArenaGlobals(arena)->poolRing)
|
||||
#define ArenaChunkTree(arena) RVALUE((arena)->chunkTree)
|
||||
#define ArenaChunkRing(arena) RVALUE(&(arena)->chunkRing)
|
||||
#define ArenaShield(arena) (&(arena)->shieldStruct)
|
||||
|
||||
extern Bool ArenaGrainSizeCheck(Size size);
|
||||
#define AddrArenaGrainUp(addr, arena) AddrAlignUp(addr, ArenaGrainSize(arena))
|
||||
|
|
@ -571,14 +578,14 @@ extern Bool ArenaHasAddr(Arena arena, Addr addr);
|
|||
extern Res ArenaAddrObject(Addr *pReturn, Arena arena, Addr addr);
|
||||
extern void ArenaChunkInsert(Arena arena, Chunk chunk);
|
||||
extern void ArenaChunkRemoved(Arena arena, Chunk chunk);
|
||||
extern void ArenaAccumulateTime(Arena arena, Clock start, Clock now);
|
||||
|
||||
extern void ArenaSetEmergency(Arena arena, Bool emergency);
|
||||
extern Bool ArenaEmergency(Arena arean);
|
||||
|
||||
extern Res ControlInit(Arena arena);
|
||||
extern void ControlFinish(Arena arena);
|
||||
extern Res ControlAlloc(void **baseReturn, Arena arena, size_t size,
|
||||
Bool withReservoirPermit);
|
||||
extern Res ControlAlloc(void **baseReturn, Arena arena, size_t size);
|
||||
extern void ControlFree(Arena arena, void *base, size_t size);
|
||||
extern Res ControlDescribe(Arena arena, mps_lib_FILE *stream, Count depth);
|
||||
|
||||
|
|
@ -622,11 +629,13 @@ extern Size ArenaCommitLimit(Arena arena);
|
|||
extern Res ArenaSetCommitLimit(Arena arena, Size limit);
|
||||
extern Size ArenaSpareCommitLimit(Arena arena);
|
||||
extern void ArenaSetSpareCommitLimit(Arena arena, Size limit);
|
||||
extern double ArenaPauseTime(Arena arena);
|
||||
extern void ArenaSetPauseTime(Arena arena, double pauseTime);
|
||||
extern Size ArenaNoPurgeSpare(Arena arena, Size size);
|
||||
extern Res ArenaNoGrow(Arena arena, LocusPref pref, Size size);
|
||||
|
||||
extern double ArenaMutatorAllocSize(Arena arena);
|
||||
extern Size ArenaAvail(Arena arena);
|
||||
extern Size ArenaCollectable(Arena arena);
|
||||
|
||||
extern Res ArenaExtend(Arena, Addr base, Size size);
|
||||
|
||||
|
|
@ -635,27 +644,26 @@ extern void ArenaCompact(Arena arena, Trace trace);
|
|||
extern Res ArenaFinalize(Arena arena, Ref obj);
|
||||
extern Res ArenaDefinalize(Arena arena, Ref obj);
|
||||
|
||||
#define ArenaReservoir(arena) (&(arena)->reservoirStruct)
|
||||
#define ReservoirPool(reservoir) (&(reservoir)->poolStruct)
|
||||
|
||||
extern Bool ReservoirCheck(Reservoir reservoir);
|
||||
extern Res ReservoirInit(Reservoir reservoir, Arena arena);
|
||||
extern void ReservoirFinish (Reservoir reservoir);
|
||||
extern Size ReservoirLimit(Reservoir reservoir);
|
||||
extern void ReservoirSetLimit(Reservoir reservoir, Size size);
|
||||
extern Size ReservoirAvailable(Reservoir reservoir);
|
||||
extern Res ReservoirEnsureFull(Reservoir reservoir);
|
||||
extern Bool ReservoirDeposit(Reservoir reservoir, Addr *baseIO, Size *sizeIO);
|
||||
extern Res ReservoirWithdraw(Addr *baseReturn, Tract *baseTractReturn,
|
||||
Reservoir reservoir, Size size, Pool pool);
|
||||
|
||||
extern Res ArenaAlloc(Addr *baseReturn, LocusPref pref,
|
||||
Size size, Pool pool, Bool withReservoirPermit);
|
||||
Size size, Pool pool);
|
||||
extern Res ArenaFreeLandAlloc(Tract *tractReturn, Arena arena, ZoneSet zones,
|
||||
Bool high, Size size, Pool pool);
|
||||
extern void ArenaFree(Addr base, Size size, Pool pool);
|
||||
|
||||
extern Res ArenaNoExtend(Arena arena, Addr base, Size size);
|
||||
|
||||
|
||||
/* Policy interface */
|
||||
|
||||
extern Res PolicyAlloc(Tract *tractReturn, Arena arena, LocusPref pref,
|
||||
Size size, Pool pool);
|
||||
extern Bool PolicyShouldCollectWorld(Arena arena, double availableTime,
|
||||
Clock now, Clock clocks_per_sec);
|
||||
extern Bool PolicyStartTrace(Trace *traceReturn, Arena arena);
|
||||
extern Bool PolicyPoll(Arena arena);
|
||||
extern Bool PolicyPollAgain(Arena arena, Clock start, Bool moreWork, Work tracedWork);
|
||||
|
||||
|
||||
/* Locus interface */
|
||||
|
||||
extern Bool LocusPrefCheck(LocusPref pref);
|
||||
|
|
@ -672,7 +680,7 @@ extern Bool LocusCheck(Arena arena);
|
|||
/* Segment interface */
|
||||
|
||||
extern Res SegAlloc(Seg *segReturn, SegClass class, LocusPref pref,
|
||||
Size size, Pool pool, Bool withReservoirPermit,
|
||||
Size size, Pool pool,
|
||||
ArgList args);
|
||||
extern void SegFree(Seg seg);
|
||||
extern Bool SegOfAddr(Seg *segReturn, Arena arena, Addr addr);
|
||||
|
|
@ -683,10 +691,8 @@ extern void SegSetWhite(Seg seg, TraceSet white);
|
|||
extern void SegSetGrey(Seg seg, TraceSet grey);
|
||||
extern void SegSetRankSet(Seg seg, RankSet rankSet);
|
||||
extern void SegSetRankAndSummary(Seg seg, RankSet rankSet, RefSet summary);
|
||||
extern Res SegMerge(Seg *mergedSegReturn, Seg segLo, Seg segHi,
|
||||
Bool withReservoirPermit);
|
||||
extern Res SegSplit(Seg *segLoReturn, Seg *segHiReturn, Seg seg, Addr at,
|
||||
Bool withReservoirPermit);
|
||||
extern Res SegMerge(Seg *mergedSegReturn, Seg segLo, Seg segHi);
|
||||
extern Res SegSplit(Seg *segLoReturn, Seg *segHiReturn, Seg seg, Addr at);
|
||||
extern Res SegDescribe(Seg seg, mps_lib_FILE *stream, Count depth);
|
||||
extern void SegSetSummary(Seg seg, RefSet summary);
|
||||
extern Buffer SegBuffer(Seg seg);
|
||||
|
|
@ -719,15 +725,15 @@ extern Addr (SegLimit)(Seg seg);
|
|||
/* .bitfield.promote: The bit field accesses need to be cast to the */
|
||||
/* right type, otherwise they'll be promoted to signed int, see */
|
||||
/* standard.ansic.6.2.1.1. */
|
||||
#define SegRankSet(seg) ((RankSet)(seg)->rankSet)
|
||||
#define SegPM(seg) ((AccessSet)(seg)->pm)
|
||||
#define SegSM(seg) ((AccessSet)(seg)->sm)
|
||||
#define SegDepth(seg) ((unsigned)(seg)->depth)
|
||||
#define SegGrey(seg) ((TraceSet)(seg)->grey)
|
||||
#define SegWhite(seg) ((TraceSet)(seg)->white)
|
||||
#define SegNailed(seg) ((TraceSet)(seg)->nailed)
|
||||
#define SegPoolRing(seg) (&(seg)->poolRing)
|
||||
#define SegOfPoolRing(node) (RING_ELT(Seg, poolRing, (node)))
|
||||
#define SegRankSet(seg) RVALUE((RankSet)(seg)->rankSet)
|
||||
#define SegPM(seg) RVALUE((AccessSet)(seg)->pm)
|
||||
#define SegSM(seg) RVALUE((AccessSet)(seg)->sm)
|
||||
#define SegDepth(seg) RVALUE((unsigned)(seg)->depth)
|
||||
#define SegGrey(seg) RVALUE((TraceSet)(seg)->grey)
|
||||
#define SegWhite(seg) RVALUE((TraceSet)(seg)->white)
|
||||
#define SegNailed(seg) RVALUE((TraceSet)(seg)->nailed)
|
||||
#define SegPoolRing(seg) RVALUE(&(seg)->poolRing)
|
||||
#define SegOfPoolRing(node) RING_ELT(Seg, poolRing, (node))
|
||||
#define SegOfGreyRing(node) (&(RING_ELT(GCSeg, greyRing, (node)) \
|
||||
->segStruct))
|
||||
|
||||
|
|
@ -747,21 +753,19 @@ extern void BufferDestroy(Buffer buffer);
|
|||
extern Bool BufferCheck(Buffer buffer);
|
||||
extern Bool SegBufCheck(SegBuf segbuf);
|
||||
extern Res BufferDescribe(Buffer buffer, mps_lib_FILE *stream, Count depth);
|
||||
extern Res BufferReserve(Addr *pReturn, Buffer buffer, Size size,
|
||||
Bool withReservoirPermit);
|
||||
extern Res BufferReserve(Addr *pReturn, Buffer buffer, Size size);
|
||||
/* macro equivalent for BufferReserve, keep in sync with <code/buffer.c> */
|
||||
/* TODO: Perhaps this isn't really necessary now that we build the MPS with
|
||||
more global optimisation and inlining. RB 2012-09-07 */
|
||||
#define BUFFER_RESERVE(pReturn, buffer, size, withReservoirPermit) \
|
||||
#define BUFFER_RESERVE(pReturn, buffer, size) \
|
||||
(AddrAdd(BufferAlloc(buffer), size) > BufferAlloc(buffer) && \
|
||||
AddrAdd(BufferAlloc(buffer), size) <= (Addr)BufferAP(buffer)->limit ? \
|
||||
(*(pReturn) = BufferAlloc(buffer), \
|
||||
BufferAP(buffer)->alloc = AddrAdd(BufferAlloc(buffer), size), \
|
||||
ResOK) : \
|
||||
BufferFill(pReturn, buffer, size, withReservoirPermit))
|
||||
BufferFill(pReturn, buffer, size))
|
||||
|
||||
extern Res BufferFill(Addr *pReturn, Buffer buffer, Size size,
|
||||
Bool withReservoirPermit);
|
||||
extern Res BufferFill(Addr *pReturn, Buffer buffer, Size size);
|
||||
|
||||
extern Bool BufferCommit(Buffer buffer, Addr p, Size size);
|
||||
/* macro equivalent for BufferCommit, keep in sync with <code/buffer.c> */
|
||||
|
|
@ -846,6 +850,7 @@ extern Res FormatCreate(Format *formatReturn, Arena arena, ArgList args);
|
|||
extern void FormatDestroy(Format format);
|
||||
extern Arena FormatArena(Format format);
|
||||
extern Res FormatDescribe(Format format, mps_lib_FILE *stream, Count depth);
|
||||
extern Res FormatScan(Format format, ScanState ss, Addr base, Addr limit);
|
||||
|
||||
|
||||
/* Reference Interface -- see <code/ref.c> */
|
||||
|
|
@ -905,14 +910,19 @@ extern ZoneSet ZoneSetBlacklist(Arena arena);
|
|||
|
||||
/* Shield Interface -- see <code/shield.c> */
|
||||
|
||||
extern void ShieldInit(Shield shield);
|
||||
extern void ShieldFinish(Shield shield);
|
||||
extern Bool ShieldCheck(Shield shield);
|
||||
extern Res ShieldDescribe(Shield shield, mps_lib_FILE *stream, Count depth);
|
||||
extern void ShieldDestroyQueue(Shield shield, Arena arena);
|
||||
extern void (ShieldRaise)(Arena arena, Seg seg, AccessSet mode);
|
||||
extern void (ShieldLower)(Arena arena, Seg seg, AccessSet mode);
|
||||
extern void (ShieldEnter)(Arena arena);
|
||||
extern void (ShieldLeave)(Arena arena);
|
||||
extern void (ShieldExpose)(Arena arena, Seg seg);
|
||||
extern void (ShieldCover)(Arena arena, Seg seg);
|
||||
extern void (ShieldSuspend)(Arena arena);
|
||||
extern void (ShieldResume)(Arena arena);
|
||||
extern void (ShieldHold)(Arena arena);
|
||||
extern void (ShieldRelease)(Arena arena);
|
||||
extern void (ShieldFlush)(Arena arena);
|
||||
|
||||
#if defined(SHIELD)
|
||||
|
|
@ -928,8 +938,8 @@ extern void (ShieldFlush)(Arena arena);
|
|||
BEGIN UNUSED(arena); UNUSED(seg); END
|
||||
#define ShieldCover(arena, seg) \
|
||||
BEGIN UNUSED(arena); UNUSED(seg); END
|
||||
#define ShieldSuspend(arena) BEGIN UNUSED(arena); END
|
||||
#define ShieldResume(arena) BEGIN UNUSED(arena); END
|
||||
#define ShieldHold(arena) BEGIN UNUSED(arena); END
|
||||
#define ShieldRelease(arena) BEGIN UNUSED(arena); END
|
||||
#define ShieldFlush(arena) BEGIN UNUSED(arena); END
|
||||
#else
|
||||
#error "No shield configuration."
|
||||
|
|
@ -948,17 +958,26 @@ extern void LDMerge(mps_ld_t ld, Arena arena, mps_ld_t from);
|
|||
|
||||
/* Root Interface -- see <code/root.c> */
|
||||
|
||||
extern Res RootCreateTable(Root *rootReturn, Arena arena,
|
||||
Rank rank, RootMode mode,
|
||||
Addr *base, Addr *limit);
|
||||
extern Res RootCreateTableMasked(Root *rootReturn, Arena arena,
|
||||
Rank rank, RootMode mode,
|
||||
Addr *base, Addr *limit,
|
||||
Word mask);
|
||||
extern Res RootCreateReg(Root *rootReturn, Arena arena,
|
||||
Rank rank, Thread thread,
|
||||
mps_reg_scan_t scan,
|
||||
void *p, size_t s);
|
||||
extern Res RootCreateArea(Root *rootReturn, Arena arena,
|
||||
Rank rank, RootMode mode,
|
||||
Word *base, Word *limit,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure);
|
||||
extern Res RootCreateAreaTagged(Root *rootReturn, Arena arena,
|
||||
Rank rank, RootMode mode,
|
||||
Word *base, Word *limit,
|
||||
mps_area_scan_t scan_area,
|
||||
Word mask, Word pattern);
|
||||
extern Res RootCreateThread(Root *rootReturn, Arena arena,
|
||||
Rank rank, Thread thread,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure,
|
||||
Word *stackCold);
|
||||
extern Res RootCreateThreadTagged(Root *rootReturn, Arena arena,
|
||||
Rank rank, Thread thread,
|
||||
mps_area_scan_t scan_area,
|
||||
Word mask, Word pattern,
|
||||
Word *stackCold);
|
||||
extern Res RootCreateFmt(Root *rootReturn, Arena arena,
|
||||
Rank rank, RootMode mode,
|
||||
mps_fmt_scan_t scan,
|
||||
|
|
@ -995,8 +1014,8 @@ extern void LandDestroy(Land land);
|
|||
extern void LandFinish(Land land);
|
||||
extern Res LandInsert(Range rangeReturn, Land land, Range range);
|
||||
extern Res LandDelete(Range rangeReturn, Land land, Range range);
|
||||
extern Bool LandIterate(Land land, LandVisitor visitor, void *closureP, Size closureS);
|
||||
extern Bool LandIterateAndDelete(Land land, LandDeleteVisitor visitor, void *closureP, Size closureS);
|
||||
extern Bool LandIterate(Land land, LandVisitor visitor, void *closure);
|
||||
extern Bool LandIterateAndDelete(Land land, LandDeleteVisitor visitor, void *closure);
|
||||
extern Bool LandFindFirst(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete);
|
||||
extern Bool LandFindLast(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete);
|
||||
extern Bool LandFindLargest(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete);
|
||||
|
|
|
|||
|
|
@ -212,6 +212,8 @@ static void testInArena(mps_arena_class_t arena_class, mps_arg_s *arena_args,
|
|||
mps_class_mfs(), args), "stress MFS");
|
||||
} MPS_ARGS_END(args);
|
||||
|
||||
/* Manual allocation should not cause any garbage collections. */
|
||||
Insist(mps_collections(arena) == 0);
|
||||
mps_arena_destroy(arena);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* mpmst.h: MEMORY POOL MANAGER DATA STRUCTURES
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (C) 2001 Global Graphics Software.
|
||||
*
|
||||
* .design: This header file crosses module boundaries. The relevant
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
#include "protocol.h"
|
||||
#include "ring.h"
|
||||
#include "chain.h"
|
||||
#include "locus.h"
|
||||
#include "splay.h"
|
||||
#include "meter.h"
|
||||
|
||||
|
|
@ -165,27 +165,6 @@ typedef struct MVStruct { /* MV pool outer structure */
|
|||
} MVStruct;
|
||||
|
||||
|
||||
/* ReservoirStruct -- Reservoir structure
|
||||
*
|
||||
* .reservoir: See <code/reserv.c>, <design/reservoir/>.
|
||||
*
|
||||
* The Reservoir structure is declared here because it is in-lined in
|
||||
* the arena for storing segments for the low-memory reservoir. It is
|
||||
* implemented as a pool - but doesn't follow the normal pool naming
|
||||
* conventions because it's not intended for general use and the use of
|
||||
* a pool is an incidental detail. */
|
||||
|
||||
#define ReservoirSig ((Sig)0x5196e599) /* SIGnature REServoir */
|
||||
|
||||
typedef struct ReservoirStruct { /* Reservoir structure */
|
||||
PoolStruct poolStruct; /* generic pool structure */
|
||||
Tract reserve; /* linked list of reserve tracts */
|
||||
Size reservoirLimit; /* desired reservoir size */
|
||||
Size reservoirSize; /* actual reservoir size */
|
||||
Sig sig; /* <design/sig/> */
|
||||
} ReservoirStruct;
|
||||
|
||||
|
||||
/* MessageClassStruct -- Message Class structure
|
||||
*
|
||||
* See <design/message/#class.struct> (and <design/message/#message>,
|
||||
|
|
@ -274,13 +253,15 @@ typedef struct SegStruct { /* segment structure */
|
|||
Tract firstTract; /* first tract of segment */
|
||||
RingStruct poolRing; /* link in list of segs in pool */
|
||||
Addr limit; /* limit of segment */
|
||||
unsigned depth : ShieldDepthWIDTH; /* see <code/shield.c#def.depth> */
|
||||
unsigned depth : ShieldDepthWIDTH; /* see design.mps.shield.def.depth */
|
||||
BOOLFIELD(queued); /* in shield queue? */
|
||||
AccessSet pm : AccessLIMIT; /* protection mode, <code/shield.c> */
|
||||
AccessSet sm : AccessLIMIT; /* shield mode, <code/shield.c> */
|
||||
TraceSet grey : TraceLIMIT; /* traces for which seg is grey */
|
||||
TraceSet white : TraceLIMIT; /* traces for which seg is white */
|
||||
TraceSet nailed : TraceLIMIT; /* traces for which seg has nailed objects */
|
||||
RankSet rankSet : RankLIMIT; /* ranks of references in this seg */
|
||||
unsigned defer : WB_DEFER_BITS; /* defer write barrier for this many scans */
|
||||
} SegStruct;
|
||||
|
||||
|
||||
|
|
@ -406,6 +387,7 @@ typedef struct mps_fmt_s {
|
|||
Serial serial; /* from arena->formatSerial */
|
||||
Arena arena; /* owning arena */
|
||||
RingStruct arenaRing; /* formats are attached to the arena */
|
||||
Count poolCount; /* number of pools using the format */
|
||||
Align alignment; /* alignment of formatted objects */
|
||||
mps_fmt_scan_t scan;
|
||||
mps_fmt_skip_t skip;
|
||||
|
|
@ -486,7 +468,7 @@ typedef struct TraceStruct {
|
|||
Size condemned; /* condemned bytes */
|
||||
Size notCondemned; /* collectable but not condemned */
|
||||
Size foundation; /* initial grey set size */
|
||||
Size rate; /* segs to scan per increment */
|
||||
Work quantumWork; /* tracing work to be done in each poll */
|
||||
STATISTIC_DECL(Count greySegCount); /* number of grey segs */
|
||||
STATISTIC_DECL(Count greySegMax); /* max number of grey segs */
|
||||
STATISTIC_DECL(Count rootScanCount); /* number of roots scanned */
|
||||
|
|
@ -696,9 +678,46 @@ typedef struct FreelistStruct {
|
|||
} FreelistStruct;
|
||||
|
||||
|
||||
/* SortStruct -- extra memory required by sorting
|
||||
*
|
||||
* See QuickSort in mpm.c. This exists so that the caller can make
|
||||
* the choice about where to allocate the memory, since the MPS has to
|
||||
* operate in tight stack constraints -- see design.mps.sp.
|
||||
*/
|
||||
|
||||
typedef struct SortStruct {
|
||||
struct {
|
||||
Index left, right;
|
||||
} stack[MPS_WORD_WIDTH];
|
||||
} SortStruct;
|
||||
|
||||
|
||||
/* ShieldStruct -- per-arena part of the shield
|
||||
*
|
||||
* See design.mps.shield, impl.c.shield.
|
||||
*/
|
||||
|
||||
#define ShieldSig ((Sig)0x519581E1) /* SIGnature SHEILd */
|
||||
|
||||
typedef struct ShieldStruct {
|
||||
Sig sig; /* design.mps.sig */
|
||||
Bool inside; /* design.mps.shield.def.inside */
|
||||
Seg *queue; /* queue of unsynced segs */
|
||||
Count length; /* number of elements in shield queue */
|
||||
Index next; /* next free element in shield queue */
|
||||
Index limit; /* high water mark for cache usage */
|
||||
Count depth; /* sum of depths of all segs */
|
||||
Count unsynced; /* number of unsynced segments */
|
||||
Count holds; /* number of holds */
|
||||
Bool suspended; /* mutator suspended? */
|
||||
SortStruct sortStruct; /* workspace for queue sort */
|
||||
} ShieldStruct;
|
||||
|
||||
|
||||
/* ArenaStruct -- generic arena
|
||||
*
|
||||
* See <code/arena.c>. */
|
||||
* See <code/arena.c>.
|
||||
*/
|
||||
|
||||
#define ArenaSig ((Sig)0x519A6E4A) /* SIGnature ARENA */
|
||||
|
||||
|
|
@ -711,14 +730,13 @@ typedef struct mps_arena_s {
|
|||
Bool poolReady; /* <design/arena/#pool.ready> */
|
||||
MVStruct controlPoolStruct; /* <design/arena/#pool> */
|
||||
|
||||
ReservoirStruct reservoirStruct; /* <design/reservoir/> */
|
||||
|
||||
Size reserved; /* total reserved address space */
|
||||
Size committed; /* total committed memory */
|
||||
Size commitLimit; /* client-configurable commit limit */
|
||||
|
||||
Size spareCommitted; /* Amount of memory in hysteresis fund */
|
||||
Size spareCommitLimit; /* Limit on spareCommitted */
|
||||
double pauseTime; /* Maximum pause time, in seconds. */
|
||||
|
||||
Shift zoneShift; /* see also <code/ref.c> */
|
||||
Size grainSize; /* <design/arena/#grain> */
|
||||
|
|
@ -755,16 +773,11 @@ typedef struct mps_arena_s {
|
|||
|
||||
/* thread fields (<code/thread.c>) */
|
||||
RingStruct threadRing; /* ring of attached threads */
|
||||
RingStruct deadRing; /* ring of dead threads */
|
||||
Serial threadSerial; /* serial of next thread */
|
||||
|
||||
/* shield fields (<code/shield.c>) */
|
||||
Bool insideShield; /* TRUE if and only if inside shield */
|
||||
Seg shCache[ShieldCacheSIZE]; /* Cache of unsynced segs */
|
||||
Size shCacheI; /* index into cache */
|
||||
Size shCacheLimit; /* High water mark for cache usage */
|
||||
Size shDepth; /* sum of depths of all segs */
|
||||
Bool suspended; /* TRUE iff mutator suspended */
|
||||
|
||||
ShieldStruct shieldStruct;
|
||||
|
||||
/* trace fields (<code/trace.c>) */
|
||||
TraceSet busyTraces; /* set of running traces */
|
||||
TraceSet flippedTraces; /* set of running and flipped traces */
|
||||
|
|
@ -776,7 +789,7 @@ typedef struct mps_arena_s {
|
|||
TraceMessage tMessage[TraceLIMIT]; /* <design/message-gc/> */
|
||||
|
||||
/* policy fields */
|
||||
double tracedSize;
|
||||
double tracedWork;
|
||||
double tracedTime;
|
||||
Clock lastWorldCollect;
|
||||
|
||||
|
|
@ -791,7 +804,7 @@ typedef struct mps_arena_s {
|
|||
|
||||
Bool emergency; /* garbage collect in emergency mode? */
|
||||
|
||||
Addr *stackAtArenaEnter; /* NULL or top of client stack, in the thread */
|
||||
Word *stackAtArenaEnter; /* NULL or hot end of client stack, in the thread */
|
||||
/* that then entered the MPS. */
|
||||
|
||||
Sig sig;
|
||||
|
|
@ -808,7 +821,7 @@ typedef struct AllocPatternStruct {
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ typedef Word Size; /* <design/type/#size> */
|
|||
typedef Word Count; /* <design/type/#count> */
|
||||
typedef Word Index; /* <design/type/#index> */
|
||||
typedef Word Align; /* <design/type/#align> */
|
||||
typedef Word Work; /* <design/type/#work> */
|
||||
typedef unsigned Shift; /* <design/type/#shift> */
|
||||
typedef unsigned Serial; /* <design/type/#serial> */
|
||||
typedef Addr Ref; /* <design/type/#ref> */
|
||||
|
|
@ -106,12 +107,12 @@ typedef struct MutatorFaultContextStruct
|
|||
typedef struct PoolDebugMixinStruct *PoolDebugMixin;
|
||||
typedef struct AllocPatternStruct *AllocPattern;
|
||||
typedef struct AllocFrameStruct *AllocFrame; /* <design/alloc-frame/> */
|
||||
typedef struct ReservoirStruct *Reservoir; /* <design/reservoir/> */
|
||||
typedef struct StackContextStruct *StackContext;
|
||||
typedef struct RangeStruct *Range; /* <design/range/> */
|
||||
typedef struct LandStruct *Land; /* <design/land/> */
|
||||
typedef struct LandClassStruct *LandClass; /* <design/land/> */
|
||||
typedef unsigned FindDelete; /* <design/land/> */
|
||||
typedef struct ShieldStruct *Shield; /* design.mps.shield */
|
||||
|
||||
|
||||
/* Arena*Method -- see <code/mpmst.h#ArenaClassStruct> */
|
||||
|
|
@ -157,7 +158,7 @@ typedef void (*FreeBlockVisitor)(Addr base, Addr limit, Pool pool, void *p);
|
|||
/* Seg*Method -- see <design/seg/> */
|
||||
|
||||
typedef Res (*SegInitMethod)(Seg seg, Pool pool, Addr base, Size size,
|
||||
Bool withReservoirPermit, ArgList args);
|
||||
ArgList args);
|
||||
typedef void (*SegFinishMethod)(Seg seg);
|
||||
typedef void (*SegSetGreyMethod)(Seg seg, TraceSet grey);
|
||||
typedef void (*SegSetWhiteMethod)(Seg seg, TraceSet white);
|
||||
|
|
@ -169,11 +170,9 @@ typedef Buffer (*SegBufferMethod)(Seg seg);
|
|||
typedef void (*SegSetBufferMethod)(Seg seg, Buffer buffer);
|
||||
typedef Res (*SegDescribeMethod)(Seg seg, mps_lib_FILE *stream, Count depth);
|
||||
typedef Res (*SegMergeMethod)(Seg seg, Seg segHi,
|
||||
Addr base, Addr mid, Addr limit,
|
||||
Bool withReservoirPermit);
|
||||
Addr base, Addr mid, Addr limit);
|
||||
typedef Res (*SegSplitMethod)(Seg seg, Seg segHi,
|
||||
Addr base, Addr mid, Addr limit,
|
||||
Bool withReservoirPermit);
|
||||
Addr base, Addr mid, Addr limit);
|
||||
|
||||
/* Buffer*Method -- see <design/buffer/> */
|
||||
|
||||
|
|
@ -197,12 +196,10 @@ typedef Res (*BufferDescribeMethod)(Buffer buffer, mps_lib_FILE *stream, Count d
|
|||
typedef void (*PoolVarargsMethod)(ArgStruct args[], va_list varargs);
|
||||
typedef Res (*PoolInitMethod)(Pool pool, ArgList args);
|
||||
typedef void (*PoolFinishMethod)(Pool pool);
|
||||
typedef Res (*PoolAllocMethod)(Addr *pReturn, Pool pool, Size size,
|
||||
Bool withReservoirPermit);
|
||||
typedef Res (*PoolAllocMethod)(Addr *pReturn, Pool pool, Size size);
|
||||
typedef void (*PoolFreeMethod)(Pool pool, Addr old, Size size);
|
||||
typedef Res (*PoolBufferFillMethod)(Addr *baseReturn, Addr *limitReturn,
|
||||
Pool pool, Buffer buffer, Size size,
|
||||
Bool withReservoirPermit);
|
||||
Pool pool, Buffer buffer, Size size);
|
||||
typedef void (*PoolBufferEmptyMethod)(Pool pool, Buffer buffer,
|
||||
Addr init, Addr limit);
|
||||
typedef Res (*PoolTraceBeginMethod)(Pool pool, Trace trace);
|
||||
|
|
@ -270,10 +267,10 @@ typedef void (*LandFinishMethod)(Land land);
|
|||
typedef Size (*LandSizeMethod)(Land land);
|
||||
typedef Res (*LandInsertMethod)(Range rangeReturn, Land land, Range range);
|
||||
typedef Res (*LandDeleteMethod)(Range rangeReturn, Land land, Range range);
|
||||
typedef Bool (*LandVisitor)(Land land, Range range, void *closureP, Size closureS);
|
||||
typedef Bool (*LandDeleteVisitor)(Bool *deleteReturn, Land land, Range range, void *closureP, Size closureS);
|
||||
typedef Bool (*LandIterateMethod)(Land land, LandVisitor visitor, void *closureP, Size closureS);
|
||||
typedef Bool (*LandIterateAndDeleteMethod)(Land land, LandDeleteVisitor visitor, void *closureP, Size closureS);
|
||||
typedef Bool (*LandVisitor)(Land land, Range range, void *closure);
|
||||
typedef Bool (*LandDeleteVisitor)(Bool *deleteReturn, Land land, Range range, void *closure);
|
||||
typedef Bool (*LandIterateMethod)(Land land, LandVisitor visitor, void *closure);
|
||||
typedef Bool (*LandIterateAndDeleteMethod)(Land land, LandDeleteVisitor visitor, void *closure);
|
||||
typedef Bool (*LandFindMethod)(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete);
|
||||
typedef Res (*LandFindInZonesMethod)(Bool *foundReturn, Range rangeReturn, Range oldRangeReturn, Land land, Size size, ZoneSet zoneSet, Bool high);
|
||||
typedef Res (*LandDescribeMethod)(Land land, mps_lib_FILE *stream, Count depth);
|
||||
|
|
@ -359,9 +356,10 @@ enum {
|
|||
|
||||
enum {
|
||||
RootFUN,
|
||||
RootTABLE,
|
||||
RootTABLE_MASKED,
|
||||
RootREG,
|
||||
RootAREA,
|
||||
RootAREA_TAGGED,
|
||||
RootTHREAD,
|
||||
RootTHREAD_TAGGED,
|
||||
RootFMT,
|
||||
RootLIMIT
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* mps.c: MEMORY POOL SYSTEM ALL-IN-ONE TRANSLATION UNIT
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (C) 2012-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (C) 2012-2016 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
|
||||
|
|
@ -39,12 +39,12 @@
|
|||
#include "locus.c"
|
||||
#include "tract.c"
|
||||
#include "walk.c"
|
||||
#include "reserv.c"
|
||||
#include "protocol.c"
|
||||
#include "pool.c"
|
||||
#include "poolabs.c"
|
||||
#include "trace.c"
|
||||
#include "traceanc.c"
|
||||
#include "scan.c"
|
||||
#include "root.c"
|
||||
#include "seg.c"
|
||||
#include "format.c"
|
||||
|
|
@ -79,12 +79,12 @@
|
|||
#include "land.c"
|
||||
#include "failover.c"
|
||||
#include "vm.c"
|
||||
#include "policy.c"
|
||||
|
||||
/* Additional pool classes */
|
||||
|
||||
#include "poolamc.c"
|
||||
#include "poolams.c"
|
||||
#include "poolamsi.c"
|
||||
#include "poolawl.c"
|
||||
#include "poollo.c"
|
||||
#include "poolsnc.c"
|
||||
|
|
@ -138,9 +138,9 @@
|
|||
#include "span.c" /* generic stack probe */
|
||||
#include "ssixi6.c" /* Posix on 64-bit Intel stack scan */
|
||||
|
||||
/* FreeBSD on 32-bit Intel built with GCC */
|
||||
/* FreeBSD on 32-bit Intel built with GCC or Clang */
|
||||
|
||||
#elif defined(MPS_PF_FRI3GC)
|
||||
#elif defined(MPS_PF_FRI3GC) || defined(MPS_PF_FRI3LL)
|
||||
|
||||
#include "lockix.c" /* Posix locks */
|
||||
#include "thix.c" /* Posix threading */
|
||||
|
|
@ -153,9 +153,9 @@
|
|||
#include "span.c" /* generic stack probe */
|
||||
#include "ssixi3.c" /* Posix on 32-bit Intel stack scan */
|
||||
|
||||
/* FreeBSD on 64-bit Intel built with GCC */
|
||||
/* FreeBSD on 64-bit Intel built with GCC or Clang */
|
||||
|
||||
#elif defined(MPS_PF_FRI6GC)
|
||||
#elif defined(MPS_PF_FRI6GC) || defined(MPS_PF_FRI6LL)
|
||||
|
||||
#include "lockix.c" /* Posix locks */
|
||||
#include "thix.c" /* Posix threading */
|
||||
|
|
@ -268,7 +268,7 @@
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2012-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2012-2016 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 @@
|
|||
/* mps.h: RAVENBROOK MEMORY POOL SYSTEM C INTERFACE
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (c) 2002 Global Graphics Software.
|
||||
*
|
||||
* THIS HEADER IS NOT DOCUMENTATION.
|
||||
|
|
@ -102,7 +102,14 @@ _mps_ENUM_DEF(_mps_RES_ENUM, MPS_RES_)
|
|||
/* see design.mps.root-interface */
|
||||
/* see design.mps.format-interface */
|
||||
|
||||
typedef struct mps_scan_tag_s *mps_scan_tag_t;
|
||||
typedef struct mps_scan_tag_s {
|
||||
mps_word_t mask;
|
||||
mps_word_t pattern;
|
||||
} mps_scan_tag_s;
|
||||
|
||||
typedef mps_res_t (*mps_root_scan_t)(mps_ss_t, void *, size_t);
|
||||
typedef mps_res_t (*mps_area_scan_t)(mps_ss_t, void *, void *, void *);
|
||||
typedef mps_res_t (*mps_fmt_scan_t)(mps_ss_t, mps_addr_t, mps_addr_t);
|
||||
typedef mps_res_t (*mps_reg_scan_t)(mps_ss_t, mps_thr_t,
|
||||
void *, size_t);
|
||||
|
|
@ -155,12 +162,12 @@ extern const struct mps_key_s _mps_key_ARGS_END;
|
|||
#define MPS_KEY_ARGS_END (&_mps_key_ARGS_END)
|
||||
extern mps_arg_s mps_args_none[];
|
||||
|
||||
extern const struct mps_key_s _mps_key_ARENA_SIZE;
|
||||
#define MPS_KEY_ARENA_SIZE (&_mps_key_ARENA_SIZE)
|
||||
#define MPS_KEY_ARENA_SIZE_FIELD size
|
||||
extern const struct mps_key_s _mps_key_ARENA_GRAIN_SIZE;
|
||||
#define MPS_KEY_ARENA_GRAIN_SIZE (&_mps_key_ARENA_GRAIN_SIZE)
|
||||
#define MPS_KEY_ARENA_GRAIN_SIZE_FIELD size
|
||||
extern const struct mps_key_s _mps_key_ARENA_SIZE;
|
||||
#define MPS_KEY_ARENA_SIZE (&_mps_key_ARENA_SIZE)
|
||||
#define MPS_KEY_ARENA_SIZE_FIELD size
|
||||
extern const struct mps_key_s _mps_key_ARENA_ZONED;
|
||||
#define MPS_KEY_ARENA_ZONED (&_mps_key_ARENA_ZONED)
|
||||
#define MPS_KEY_ARENA_ZONED_FIELD b
|
||||
|
|
@ -176,6 +183,15 @@ extern const struct mps_key_s _mps_key_GEN;
|
|||
extern const struct mps_key_s _mps_key_RANK;
|
||||
#define MPS_KEY_RANK (&_mps_key_RANK)
|
||||
#define MPS_KEY_RANK_FIELD rank
|
||||
extern const struct mps_key_s _mps_key_COMMIT_LIMIT;
|
||||
#define MPS_KEY_COMMIT_LIMIT (&_mps_key_COMMIT_LIMIT)
|
||||
#define MPS_KEY_COMMIT_LIMIT_FIELD size
|
||||
extern const struct mps_key_s _mps_key_SPARE_COMMIT_LIMIT;
|
||||
#define MPS_KEY_SPARE_COMMIT_LIMIT (&_mps_key_SPARE_COMMIT_LIMIT)
|
||||
#define MPS_KEY_SPARE_COMMIT_LIMIT_FIELD size
|
||||
extern const struct mps_key_s _mps_key_PAUSE_TIME;
|
||||
#define MPS_KEY_PAUSE_TIME (&_mps_key_PAUSE_TIME)
|
||||
#define MPS_KEY_PAUSE_TIME_FIELD d
|
||||
|
||||
extern const struct mps_key_s _mps_key_EXTEND_BY;
|
||||
#define MPS_KEY_EXTEND_BY (&_mps_key_EXTEND_BY)
|
||||
|
|
@ -444,6 +460,9 @@ extern mps_res_t mps_arena_commit_limit_set(mps_arena_t, size_t);
|
|||
extern void mps_arena_spare_commit_limit_set(mps_arena_t, size_t);
|
||||
extern size_t mps_arena_spare_commit_limit(mps_arena_t);
|
||||
|
||||
extern double mps_arena_pause_time(mps_arena_t);
|
||||
extern void mps_arena_pause_time_set(mps_arena_t, double);
|
||||
|
||||
extern mps_bool_t mps_arena_has_addr(mps_arena_t, mps_addr_t);
|
||||
extern mps_bool_t mps_addr_pool(mps_pool_t *, mps_arena_t, mps_addr_t);
|
||||
extern mps_bool_t mps_addr_fmt(mps_fmt_t *, mps_arena_t, mps_addr_t);
|
||||
|
|
@ -485,7 +504,7 @@ extern size_t mps_pool_free_size(mps_pool_t);
|
|||
|
||||
/* Chains */
|
||||
|
||||
/* .gen-param: This structure must match <code/chain.h#gen-param>. */
|
||||
/* .gen-param: This structure must match <code/locus.h#gen-param>. */
|
||||
typedef struct mps_gen_param_s {
|
||||
size_t mps_capacity;
|
||||
double mps_mortality;
|
||||
|
|
@ -514,6 +533,8 @@ extern mps_res_t (mps_reserve)(mps_addr_t *, mps_ap_t, size_t);
|
|||
extern mps_bool_t (mps_commit)(mps_ap_t, mps_addr_t, size_t);
|
||||
|
||||
extern mps_res_t mps_ap_fill(mps_addr_t *, mps_ap_t, size_t);
|
||||
|
||||
/* mps_ap_fill_with_reservoir_permit is deprecated */
|
||||
extern mps_res_t mps_ap_fill_with_reservoir_permit(mps_addr_t *,
|
||||
mps_ap_t,
|
||||
size_t);
|
||||
|
|
@ -596,7 +617,7 @@ extern void mps_sac_empty(mps_sac_t, mps_addr_t, size_t);
|
|||
#define MPS_SAC_FREE(sac, p, size) MPS_SAC_FREE_FAST(sac, p, size)
|
||||
|
||||
|
||||
/* Low memory reservoir */
|
||||
/* Low memory reservoir (deprecated) */
|
||||
|
||||
extern void mps_reservoir_limit_set(mps_arena_t, size_t);
|
||||
extern size_t mps_reservoir_limit(mps_arena_t);
|
||||
|
|
@ -632,17 +653,7 @@ extern mps_res_t mps_reserve_with_reservoir_permit(mps_addr_t *,
|
|||
MPS_END
|
||||
|
||||
|
||||
#define MPS_RESERVE_WITH_RESERVOIR_PERMIT_BLOCK(_res_v, _p_v, _mps_ap, _size) \
|
||||
MPS_BEGIN \
|
||||
char *_alloc = (char *)(_mps_ap)->alloc; \
|
||||
char *_next = _alloc + (_size); \
|
||||
if(_next > _alloc && _next <= (char *)(_mps_ap)->limit) { \
|
||||
(_mps_ap)->alloc = (mps_addr_t)_next; \
|
||||
(_p_v) = (_mps_ap)->init; \
|
||||
(_res_v) = MPS_RES_OK; \
|
||||
} else \
|
||||
(_res_v) = mps_ap_fill_with_reservoir_permit(&(_p_v), _mps_ap, _size); \
|
||||
MPS_END
|
||||
#define MPS_RESERVE_WITH_RESERVOIR_PERMIT_BLOCK MPS_RESERVE_BLOCK
|
||||
|
||||
|
||||
/* Commit Macros */
|
||||
|
|
@ -665,6 +676,15 @@ extern mps_res_t mps_root_create_table_masked(mps_root_t *, mps_arena_t,
|
|||
mps_rank_t, mps_rm_t,
|
||||
mps_addr_t *, size_t,
|
||||
mps_word_t);
|
||||
extern mps_res_t mps_root_create_area(mps_root_t *, mps_arena_t,
|
||||
mps_rank_t, mps_rm_t,
|
||||
void *, void *,
|
||||
mps_area_scan_t, void *);
|
||||
extern mps_res_t mps_root_create_area_tagged(mps_root_t *, mps_arena_t,
|
||||
mps_rank_t, mps_rm_t,
|
||||
void *, void *,
|
||||
mps_area_scan_t,
|
||||
mps_word_t, mps_word_t);
|
||||
extern mps_res_t mps_root_create_fmt(mps_root_t *, mps_arena_t,
|
||||
mps_rank_t, mps_rm_t,
|
||||
mps_fmt_scan_t, mps_addr_t,
|
||||
|
|
@ -672,6 +692,18 @@ extern mps_res_t mps_root_create_fmt(mps_root_t *, mps_arena_t,
|
|||
extern mps_res_t mps_root_create_reg(mps_root_t *, mps_arena_t,
|
||||
mps_rank_t, mps_rm_t, mps_thr_t,
|
||||
mps_reg_scan_t, void *, size_t);
|
||||
extern mps_res_t mps_root_create_thread(mps_root_t *, mps_arena_t,
|
||||
mps_thr_t, void *);
|
||||
extern mps_res_t mps_root_create_thread_scanned(mps_root_t *, mps_arena_t,
|
||||
mps_rank_t, mps_rm_t, mps_thr_t,
|
||||
mps_area_scan_t,
|
||||
void *,
|
||||
void *);
|
||||
extern mps_res_t mps_root_create_thread_tagged(mps_root_t *, mps_arena_t,
|
||||
mps_rank_t, mps_rm_t, mps_thr_t,
|
||||
mps_area_scan_t,
|
||||
mps_word_t, mps_word_t,
|
||||
void *);
|
||||
extern void mps_root_destroy(mps_root_t);
|
||||
|
||||
extern mps_res_t mps_stack_scan_ambig(mps_ss_t, mps_thr_t,
|
||||
|
|
@ -785,6 +817,11 @@ extern void mps_pool_check_free_space(mps_pool_t);
|
|||
|
||||
/* Scanner Support */
|
||||
|
||||
extern mps_res_t mps_scan_area(mps_ss_t, void *, void *, void *);
|
||||
extern mps_res_t mps_scan_area_masked(mps_ss_t, void *, void *, void *);
|
||||
extern mps_res_t mps_scan_area_tagged(mps_ss_t, void *, void *, void *);
|
||||
extern mps_res_t mps_scan_area_tagged_or_zero(mps_ss_t, void *, void *, void *);
|
||||
|
||||
extern mps_res_t mps_fix(mps_ss_t, mps_addr_t *);
|
||||
|
||||
#define MPS_SCAN_BEGIN(ss) \
|
||||
|
|
@ -828,7 +865,7 @@ extern mps_res_t _mps_fix2(mps_ss_t, mps_addr_t *);
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@
|
|||
22B2BC3B18B643B000C33E63 /* PBXTargetDependency */,
|
||||
3104B04A156D3AE4000A585A /* PBXTargetDependency */,
|
||||
31D6009D156D404B00337B26 /* PBXTargetDependency */,
|
||||
314CB6EB1C6D272A0073CA42 /* PBXTargetDependency */,
|
||||
3114A62E156E94AA001E0AA3 /* PBXTargetDependency */,
|
||||
3114A6B9156E9763001E0AA3 /* PBXTargetDependency */,
|
||||
31D60063156D3F5C00337B26 /* PBXTargetDependency */,
|
||||
|
|
@ -216,6 +217,9 @@
|
|||
3104B04F156D3B09000A585A /* fmtdy.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC6156BE48D00753214 /* fmtdy.c */; };
|
||||
3104B050156D3B09000A585A /* fmtdytst.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC7156BE48D00753214 /* fmtdytst.c */; };
|
||||
3104B051156D3B09000A585A /* fmtno.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CACC156BE4C200753214 /* fmtno.c */; };
|
||||
31108A3E1C6B90E900E728EA /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; };
|
||||
31108A411C6B90E900E728EA /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; };
|
||||
31108A481C6B911B00E728EA /* tagtest.c in Sources */ = {isa = PBXBuildFile; fileRef = 31108A391C6B90D600E728EA /* tagtest.c */; };
|
||||
3114A59B156E914B001E0AA3 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; };
|
||||
3114A59C156E914F001E0AA3 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; };
|
||||
3114A5A2156E9168001E0AA3 /* locv.c in Sources */ = {isa = PBXBuildFile; fileRef = 3114A5A1156E9168001E0AA3 /* locv.c */; };
|
||||
|
|
@ -670,6 +674,13 @@
|
|||
remoteGlobalIDString = 3104B03C156D3AD7000A585A;
|
||||
remoteInfo = segsmss;
|
||||
};
|
||||
31108A3C1C6B90E900E728EA /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 31EEABFA156AAF9D00714D05;
|
||||
remoteInfo = mps;
|
||||
};
|
||||
3114A59D156E9156001E0AA3 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */;
|
||||
|
|
@ -866,6 +877,13 @@
|
|||
remoteGlobalIDString = 3114A6C5156E9815001E0AA3;
|
||||
remoteInfo = mpseventcnv;
|
||||
};
|
||||
314CB6EA1C6D272A0073CA42 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 31108A3A1C6B90E900E728EA;
|
||||
remoteInfo = tagtest;
|
||||
};
|
||||
31A47BA9156C210D0039B1C2 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */;
|
||||
|
|
@ -1152,6 +1170,15 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
31108A421C6B90E900E728EA /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = /usr/share/man/man1/;
|
||||
dstSubfolderSpec = 0;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
3114A58E156E913C001E0AA3 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
|
@ -1471,6 +1498,8 @@
|
|||
3107DC4E173B03D100F705C8 /* arg.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = arg.h; sourceTree = "<group>"; };
|
||||
310F5D7118B6675F007EFCBC /* tree.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = tree.c; sourceTree = "<group>"; };
|
||||
310F5D7218B6675F007EFCBC /* tree.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = tree.h; sourceTree = "<group>"; };
|
||||
31108A391C6B90D600E728EA /* tagtest.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = tagtest.c; sourceTree = "<group>"; };
|
||||
31108A471C6B90E900E728EA /* tagtest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tagtest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3112ED3A18ABC57F00CC531A /* sa.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = sa.h; sourceTree = "<group>"; };
|
||||
3112ED3B18ABC75200CC531A /* sa.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = sa.c; sourceTree = "<group>"; };
|
||||
3114A590156E913C001E0AA3 /* locv */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = locv; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
|
|
@ -1540,13 +1569,11 @@
|
|||
31160DB61899540D0071EB17 /* poolmvff.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = poolmvff.txt; path = ../design/poolmvff.txt; sourceTree = "<group>"; };
|
||||
31160DB71899540D0071EB17 /* poolmvt.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = poolmvt.txt; path = ../design/poolmvt.txt; sourceTree = "<group>"; };
|
||||
31160DB81899540D0071EB17 /* prot.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = prot.txt; path = ../design/prot.txt; sourceTree = "<group>"; };
|
||||
31160DB91899540D0071EB17 /* protan.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = protan.txt; path = ../design/protan.txt; sourceTree = "<group>"; };
|
||||
31160DBA1899540D0071EB17 /* protli.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = protli.txt; path = ../design/protli.txt; sourceTree = "<group>"; };
|
||||
31160DBB1899540D0071EB17 /* protocol.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = protocol.txt; path = ../design/protocol.txt; sourceTree = "<group>"; };
|
||||
31160DBC1899540D0071EB17 /* protsu.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = protsu.txt; path = ../design/protsu.txt; sourceTree = "<group>"; };
|
||||
31160DBD1899540D0071EB17 /* pthreadext.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = pthreadext.txt; path = ../design/pthreadext.txt; sourceTree = "<group>"; };
|
||||
31160DBE1899540D0071EB17 /* range.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = range.txt; path = ../design/range.txt; sourceTree = "<group>"; };
|
||||
31160DBF1899540D0071EB17 /* reservoir.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = reservoir.txt; path = ../design/reservoir.txt; sourceTree = "<group>"; };
|
||||
31160DC01899540D0071EB17 /* ring.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = ring.txt; path = ../design/ring.txt; sourceTree = "<group>"; };
|
||||
31160DC11899540D0071EB17 /* root.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = root.txt; path = ../design/root.txt; sourceTree = "<group>"; };
|
||||
31160DC21899540D0071EB17 /* scan.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = scan.txt; path = ../design/scan.txt; sourceTree = "<group>"; };
|
||||
|
|
@ -1565,7 +1592,6 @@
|
|||
31160DCF1899540D0071EB17 /* version-library.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = "version-library.txt"; path = "../design/version-library.txt"; sourceTree = "<group>"; };
|
||||
31160DD01899540D0071EB17 /* version.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = version.txt; path = ../design/version.txt; sourceTree = "<group>"; };
|
||||
31160DD11899540D0071EB17 /* vm.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = vm.txt; path = ../design/vm.txt; sourceTree = "<group>"; };
|
||||
31160DD21899540D0071EB17 /* vman.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = vman.txt; path = ../design/vman.txt; sourceTree = "<group>"; };
|
||||
31160DD31899540D0071EB17 /* vmo1.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = vmo1.txt; path = ../design/vmo1.txt; sourceTree = "<group>"; };
|
||||
31160DD41899540D0071EB17 /* vmso.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = vmso.txt; path = ../design/vmso.txt; sourceTree = "<group>"; };
|
||||
31160DD51899540D0071EB17 /* writef.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = writef.txt; path = ../design/writef.txt; sourceTree = "<group>"; };
|
||||
|
|
@ -1577,7 +1603,6 @@
|
|||
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>"; };
|
||||
311F2F5317398AE900C15B6A /* chain.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = chain.h; sourceTree = "<group>"; };
|
||||
311F2F5417398AE900C15B6A /* check.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = check.h; sourceTree = "<group>"; };
|
||||
311F2F5517398AE900C15B6A /* clock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = clock.h; sourceTree = "<group>"; };
|
||||
311F2F5617398AE900C15B6A /* config.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; };
|
||||
|
|
@ -1586,7 +1611,6 @@
|
|||
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>"; };
|
||||
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>"; };
|
||||
311F2F5F17398B0E00C15B6A /* meter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = meter.h; sourceTree = "<group>"; };
|
||||
311F2F6017398B0E00C15B6A /* misc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = misc.h; sourceTree = "<group>"; };
|
||||
|
|
@ -1628,11 +1652,28 @@
|
|||
3124CAE4156BE6D500753214 /* fmthe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fmthe.c; sourceTree = "<group>"; };
|
||||
3124CAEB156BE7F300753214 /* amcss */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = amcss; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3124CAF5156BE81100753214 /* amcss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = amcss.c; sourceTree = "<group>"; };
|
||||
314562191C72ABFA00D7A514 /* scan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = scan.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>"; };
|
||||
318DA8CD1892B0F30089718C /* djbench */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = djbench; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
318DA8CE1892B1210089718C /* djbench.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = djbench.c; sourceTree = "<group>"; };
|
||||
31942A671C8EC3FC001AAF32 /* locus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = locus.h; sourceTree = "<group>"; };
|
||||
31942A6A1C8EC445001AAF32 /* an.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = an.txt; path = ../design/an.txt; sourceTree = "<group>"; };
|
||||
31942A6D1C8EC445001AAF32 /* boot.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = boot.txt; path = ../design/boot.txt; sourceTree = "<group>"; };
|
||||
31942A6E1C8EC445001AAF32 /* bootstrap.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = bootstrap.txt; path = ../design/bootstrap.txt; sourceTree = "<group>"; };
|
||||
31942A741C8EC445001AAF32 /* clock.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = clock.txt; path = ../design/clock.txt; sourceTree = "<group>"; };
|
||||
31942A791C8EC445001AAF32 /* exec-env.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = "exec-env.txt"; path = "../design/exec-env.txt"; sourceTree = "<group>"; };
|
||||
31942A801C8EC445001AAF32 /* guide.impl.c.naming.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = guide.impl.c.naming.txt; path = ../design/guide.impl.c.naming.txt; sourceTree = "<group>"; };
|
||||
31942A811C8EC445001AAF32 /* guide.review.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = guide.review.txt; path = ../design/guide.review.txt; sourceTree = "<group>"; };
|
||||
31942A8C1C8EC446001AAF32 /* nailboard-1.svg */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = "nailboard-1.svg"; path = "../design/nailboard-1.svg"; sourceTree = "<group>"; };
|
||||
31942A8D1C8EC446001AAF32 /* nailboard-2.svg */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = "nailboard-2.svg"; path = "../design/nailboard-2.svg"; sourceTree = "<group>"; };
|
||||
31942A8E1C8EC446001AAF32 /* nailboard-3.svg */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = "nailboard-3.svg"; path = "../design/nailboard-3.svg"; sourceTree = "<group>"; };
|
||||
31942A8F1C8EC446001AAF32 /* nailboard.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = nailboard.txt; path = ../design/nailboard.txt; sourceTree = "<group>"; };
|
||||
31942A9B1C8EC446001AAF32 /* prmc.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = prmc.txt; path = ../design/prmc.txt; sourceTree = "<group>"; };
|
||||
31942AA91C8EC446001AAF32 /* sp.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = sp.txt; path = ../design/sp.txt; sourceTree = "<group>"; };
|
||||
31942AAB1C8EC446001AAF32 /* ss.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = ss.txt; path = ../design/ss.txt; sourceTree = "<group>"; };
|
||||
31942AB01C8EC446001AAF32 /* testthr.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = testthr.txt; path = ../design/testthr.txt; 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>"; };
|
||||
|
|
@ -1664,7 +1705,6 @@
|
|||
31EEAC09156AB27B00714D05 /* pool.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pool.c; sourceTree = "<group>"; };
|
||||
31EEAC0A156AB27B00714D05 /* poolabs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = poolabs.c; sourceTree = "<group>"; };
|
||||
31EEAC0B156AB27B00714D05 /* protocol.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = protocol.c; sourceTree = "<group>"; };
|
||||
31EEAC0C156AB27B00714D05 /* reserv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = reserv.c; sourceTree = "<group>"; };
|
||||
31EEAC0D156AB27B00714D05 /* tract.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tract.c; sourceTree = "<group>"; };
|
||||
31EEAC0E156AB27B00714D05 /* walk.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = walk.c; sourceTree = "<group>"; };
|
||||
31EEAC19156AB2B200714D05 /* buffer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = buffer.c; sourceTree = "<group>"; };
|
||||
|
|
@ -1866,6 +1906,14 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
31108A401C6B90E900E728EA /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
31108A411C6B90E900E728EA /* libmps.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
3114A58D156E913C001E0AA3 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
|
@ -2128,23 +2176,30 @@
|
|||
children = (
|
||||
31160D921899540D0071EB17 /* abq.txt */,
|
||||
31160D931899540D0071EB17 /* alloc-frame.txt */,
|
||||
31942A6A1C8EC445001AAF32 /* an.txt */,
|
||||
31160D941899540D0071EB17 /* arena.txt */,
|
||||
31160D951899540D0071EB17 /* arenavm.txt */,
|
||||
31942A6D1C8EC445001AAF32 /* boot.txt */,
|
||||
31942A6E1C8EC445001AAF32 /* bootstrap.txt */,
|
||||
31160D961899540D0071EB17 /* bt.txt */,
|
||||
31160D971899540D0071EB17 /* buffer.txt */,
|
||||
31160D981899540D0071EB17 /* cbs.txt */,
|
||||
31160D991899540D0071EB17 /* check.txt */,
|
||||
31160D9A1899540D0071EB17 /* class-interface.txt */,
|
||||
31942A741C8EC445001AAF32 /* clock.txt */,
|
||||
31160D9B1899540D0071EB17 /* collection.txt */,
|
||||
31160D9C1899540D0071EB17 /* config.txt */,
|
||||
31160D9D1899540D0071EB17 /* critical-path.txt */,
|
||||
31160D9E1899540D0071EB17 /* diag.txt */,
|
||||
31942A791C8EC445001AAF32 /* exec-env.txt */,
|
||||
22DD93E118ED815F00240DD2 /* failover.txt */,
|
||||
31160D9F1899540D0071EB17 /* finalize.txt */,
|
||||
31160DA01899540D0071EB17 /* fix.txt */,
|
||||
31160DA11899540D0071EB17 /* freelist.txt */,
|
||||
31160DA21899540D0071EB17 /* guide.hex.trans.txt */,
|
||||
31160DA31899540D0071EB17 /* guide.impl.c.format.txt */,
|
||||
31942A801C8EC445001AAF32 /* guide.impl.c.naming.txt */,
|
||||
31942A811C8EC445001AAF32 /* guide.review.txt */,
|
||||
31160DA41899540D0071EB17 /* index.txt */,
|
||||
31160DA51899540D0071EB17 /* interface-c.txt */,
|
||||
31160DA61899540D0071EB17 /* io.txt */,
|
||||
|
|
@ -2155,6 +2210,10 @@
|
|||
31160DAA1899540D0071EB17 /* locus.txt */,
|
||||
31160DAB1899540D0071EB17 /* message-gc.txt */,
|
||||
31160DAC1899540D0071EB17 /* message.txt */,
|
||||
31942A8C1C8EC446001AAF32 /* nailboard-1.svg */,
|
||||
31942A8D1C8EC446001AAF32 /* nailboard-2.svg */,
|
||||
31942A8E1C8EC446001AAF32 /* nailboard-3.svg */,
|
||||
31942A8F1C8EC446001AAF32 /* nailboard.txt */,
|
||||
31160DAD1899540D0071EB17 /* object-debug.txt */,
|
||||
31160DAE1899540D0071EB17 /* pool.txt */,
|
||||
31160DAF1899540D0071EB17 /* poolamc.txt */,
|
||||
|
|
@ -2166,25 +2225,27 @@
|
|||
31160DB51899540D0071EB17 /* poolmv.txt */,
|
||||
31160DB61899540D0071EB17 /* poolmvff.txt */,
|
||||
31160DB71899540D0071EB17 /* poolmvt.txt */,
|
||||
31942A9B1C8EC446001AAF32 /* prmc.txt */,
|
||||
31160DB81899540D0071EB17 /* prot.txt */,
|
||||
31160DB91899540D0071EB17 /* protan.txt */,
|
||||
31160DBA1899540D0071EB17 /* protli.txt */,
|
||||
31160DBB1899540D0071EB17 /* protocol.txt */,
|
||||
31160DBC1899540D0071EB17 /* protsu.txt */,
|
||||
31160DBD1899540D0071EB17 /* pthreadext.txt */,
|
||||
31160DBE1899540D0071EB17 /* range.txt */,
|
||||
31160DBF1899540D0071EB17 /* reservoir.txt */,
|
||||
31160DC01899540D0071EB17 /* ring.txt */,
|
||||
31160DC11899540D0071EB17 /* root.txt */,
|
||||
31160DC21899540D0071EB17 /* scan.txt */,
|
||||
31160DC31899540D0071EB17 /* seg.txt */,
|
||||
31160DC41899540D0071EB17 /* shield.txt */,
|
||||
31160DC51899540D0071EB17 /* sig.txt */,
|
||||
31942AA91C8EC446001AAF32 /* sp.txt */,
|
||||
31160DC61899540D0071EB17 /* splay.txt */,
|
||||
31942AAB1C8EC446001AAF32 /* ss.txt */,
|
||||
31160DC71899540D0071EB17 /* sso1al.txt */,
|
||||
31160DC81899540D0071EB17 /* strategy.txt */,
|
||||
31160DC91899540D0071EB17 /* telemetry.txt */,
|
||||
31160DCA1899540D0071EB17 /* tests.txt */,
|
||||
31942AB01C8EC446001AAF32 /* testthr.txt */,
|
||||
31160DCB1899540D0071EB17 /* thread-manager.txt */,
|
||||
31160DCC1899540D0071EB17 /* thread-safety.txt */,
|
||||
31160DCD1899540D0071EB17 /* trace.txt */,
|
||||
|
|
@ -2192,7 +2253,6 @@
|
|||
31160DCF1899540D0071EB17 /* version-library.txt */,
|
||||
31160DD01899540D0071EB17 /* version.txt */,
|
||||
31160DD11899540D0071EB17 /* vm.txt */,
|
||||
31160DD21899540D0071EB17 /* vman.txt */,
|
||||
31160DD31899540D0071EB17 /* vmo1.txt */,
|
||||
31160DD41899540D0071EB17 /* vmso.txt */,
|
||||
31160DD51899540D0071EB17 /* writef.txt */,
|
||||
|
|
@ -2248,6 +2308,7 @@
|
|||
3104AFD6156D3602000A585A /* sacss.c */,
|
||||
31D60006156D3C5F00337B26 /* segsmss.c */,
|
||||
31D60098156D403C00337B26 /* steptest.c */,
|
||||
31108A391C6B90D600E728EA /* tagtest.c */,
|
||||
3114A628156E949A001E0AA3 /* teletest.c */,
|
||||
31EEAC9E156AB73400714D05 /* testlib.c */,
|
||||
2291A5F0175CB7A4001D4920 /* testlib.h */,
|
||||
|
|
@ -2345,6 +2406,7 @@
|
|||
22FACEED18880983000FDBC1 /* airtest */,
|
||||
22C2ACAF18BE400A006B3677 /* nailboardtest */,
|
||||
22F846BD18F437B900982BA7 /* lockut */,
|
||||
31108A471C6B90E900E728EA /* tagtest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -2352,6 +2414,7 @@
|
|||
31EEABF4156AAF6500714D05 /* MPM Core */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
31942A671C8EC3FC001AAF32 /* locus.h */,
|
||||
3114A645156E9525001E0AA3 /* abq.c */,
|
||||
2291A5EA175CB503001D4920 /* abq.h */,
|
||||
31EEAC05156AB27B00714D05 /* arena.c */,
|
||||
|
|
@ -2366,7 +2429,6 @@
|
|||
31EEAC19156AB2B200714D05 /* buffer.c */,
|
||||
31EEAC40156AB32500714D05 /* cbs.c */,
|
||||
311F2F5217398AE900C15B6A /* cbs.h */,
|
||||
311F2F5317398AE900C15B6A /* chain.h */,
|
||||
311F2F5417398AE900C15B6A /* check.h */,
|
||||
311F2F5517398AE900C15B6A /* clock.h */,
|
||||
311F2F5617398AE900C15B6A /* config.h */,
|
||||
|
|
@ -2428,7 +2490,6 @@
|
|||
2291A5EB175CB53E001D4920 /* range.c */,
|
||||
2291A5EC175CB53E001D4920 /* range.h */,
|
||||
31EEAC1B156AB2B200714D05 /* ref.c */,
|
||||
31EEAC0C156AB27B00714D05 /* reserv.c */,
|
||||
31EEAC30156AB2F200714D05 /* ring.c */,
|
||||
311F2F7317398B7100C15B6A /* ring.h */,
|
||||
31EEAC1C156AB2B200714D05 /* root.c */,
|
||||
|
|
@ -2437,6 +2498,7 @@
|
|||
31EEAC31156AB2F200714D05 /* sac.c */,
|
||||
311F2F7417398B7100C15B6A /* sac.h */,
|
||||
311F2F7517398B8E00C15B6A /* sc.h */,
|
||||
314562191C72ABFA00D7A514 /* scan.c */,
|
||||
31EEAC1D156AB2B200714D05 /* seg.c */,
|
||||
31EEAC32156AB2F200714D05 /* shield.c */,
|
||||
31EEAC43156AB32500714D05 /* splay.c */,
|
||||
|
|
@ -2483,7 +2545,6 @@
|
|||
31EEAC5A156AB40800714D05 /* Extra pools */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
311F2F5D17398B0400C15B6A /* lo.h */,
|
||||
31F6CCA91739B0CF00C48748 /* mpscamc.h */,
|
||||
31CD33BB173A9F1500524741 /* mpscams.h */,
|
||||
31F6CCAA1739B0CF00C48748 /* mpscawl.h */,
|
||||
|
|
@ -2873,6 +2934,24 @@
|
|||
productReference = 3104B03D156D3AD7000A585A /* segsmss */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
31108A3A1C6B90E900E728EA /* tagtest */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 31108A431C6B90E900E728EA /* Build configuration list for PBXNativeTarget "tagtest" */;
|
||||
buildPhases = (
|
||||
31108A3D1C6B90E900E728EA /* Sources */,
|
||||
31108A401C6B90E900E728EA /* Frameworks */,
|
||||
31108A421C6B90E900E728EA /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
31108A3B1C6B90E900E728EA /* PBXTargetDependency */,
|
||||
);
|
||||
name = tagtest;
|
||||
productName = teletest;
|
||||
productReference = 31108A471C6B90E900E728EA /* tagtest */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
3114A58F156E913C001E0AA3 /* locv */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 3114A599156E913C001E0AA3 /* Build configuration list for PBXNativeTarget "locv" */;
|
||||
|
|
@ -3446,6 +3525,7 @@
|
|||
2D604B9B16514B1A003AAF46 /* mpseventtxt */,
|
||||
31FCAE0917692403008C034C /* scheme */,
|
||||
22B2BC2C18B6434F00C33E63 /* scheme-advanced */,
|
||||
31108A3A1C6B90E900E728EA /* tagtest */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
|
@ -3725,6 +3805,15 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
31108A3D1C6B90E900E728EA /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
31108A3E1C6B90E900E728EA /* testlib.c in Sources */,
|
||||
31108A481C6B911B00E728EA /* tagtest.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
3114A58C156E913C001E0AA3 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
|
@ -4258,6 +4347,11 @@
|
|||
target = 3104B03C156D3AD7000A585A /* segsmss */;
|
||||
targetProxy = 3104B049156D3AE4000A585A /* PBXContainerItemProxy */;
|
||||
};
|
||||
31108A3B1C6B90E900E728EA /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 31EEABFA156AAF9D00714D05 /* mps */;
|
||||
targetProxy = 31108A3C1C6B90E900E728EA /* PBXContainerItemProxy */;
|
||||
};
|
||||
3114A59E156E9156001E0AA3 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 31EEABFA156AAF9D00714D05 /* mps */;
|
||||
|
|
@ -4398,6 +4492,11 @@
|
|||
target = 3114A6C5156E9815001E0AA3 /* mpseventcnv */;
|
||||
targetProxy = 3114A6D4156E9839001E0AA3 /* PBXContainerItemProxy */;
|
||||
};
|
||||
314CB6EB1C6D272A0073CA42 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 31108A3A1C6B90E900E728EA /* tagtest */;
|
||||
targetProxy = 314CB6EA1C6D272A0073CA42 /* PBXContainerItemProxy */;
|
||||
};
|
||||
31A47BAA156C210D0039B1C2 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 31EEABFA156AAF9D00714D05 /* mps */;
|
||||
|
|
@ -4903,6 +5002,27 @@
|
|||
};
|
||||
name = Release;
|
||||
};
|
||||
31108A441C6B90E900E728EA /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
31108A451C6B90E900E728EA /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
31108A461C6B90E900E728EA /* RASH */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = RASH;
|
||||
};
|
||||
3114A597156E913C001E0AA3 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
|
|
@ -5164,7 +5284,7 @@
|
|||
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
GCC_C_LANGUAGE_STANDARD = ansi;
|
||||
GCC_C_LANGUAGE_STANDARD = c89;
|
||||
GCC_OPTIMIZATION_LEVEL = s;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = CONFIG_VAR_RASH;
|
||||
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
|
||||
|
|
@ -5195,9 +5315,12 @@
|
|||
"-Waggregate-return",
|
||||
"-Wall",
|
||||
"-Wcast-qual",
|
||||
"-Wconversion",
|
||||
"-Wduplicate-enum",
|
||||
"-Wextra",
|
||||
"-Winline",
|
||||
"-Wmissing-prototypes",
|
||||
"-Wmissing-variable-declarations",
|
||||
"-Wnested-externs",
|
||||
"-Wno-extended-offsetof",
|
||||
"-Wpointer-arith",
|
||||
|
|
@ -5600,7 +5723,7 @@
|
|||
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = ansi;
|
||||
GCC_C_LANGUAGE_STANDARD = c89;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = CONFIG_VAR_COOL;
|
||||
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
|
||||
|
|
@ -5632,9 +5755,12 @@
|
|||
"-Waggregate-return",
|
||||
"-Wall",
|
||||
"-Wcast-qual",
|
||||
"-Wconversion",
|
||||
"-Wduplicate-enum",
|
||||
"-Wextra",
|
||||
"-Winline",
|
||||
"-Wmissing-prototypes",
|
||||
"-Wmissing-variable-declarations",
|
||||
"-Wnested-externs",
|
||||
"-Wno-extended-offsetof",
|
||||
"-Wpointer-arith",
|
||||
|
|
@ -5656,7 +5782,7 @@
|
|||
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
GCC_C_LANGUAGE_STANDARD = ansi;
|
||||
GCC_C_LANGUAGE_STANDARD = c89;
|
||||
GCC_OPTIMIZATION_LEVEL = s;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = CONFIG_VAR_HOT;
|
||||
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
|
||||
|
|
@ -5687,9 +5813,12 @@
|
|||
"-Waggregate-return",
|
||||
"-Wall",
|
||||
"-Wcast-qual",
|
||||
"-Wconversion",
|
||||
"-Wduplicate-enum",
|
||||
"-Wextra",
|
||||
"-Winline",
|
||||
"-Wmissing-prototypes",
|
||||
"-Wmissing-variable-declarations",
|
||||
"-Wnested-externs",
|
||||
"-Wno-extended-offsetof",
|
||||
"-Wpointer-arith",
|
||||
|
|
@ -6022,6 +6151,16 @@
|
|||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
31108A431C6B90E900E728EA /* Build configuration list for PBXNativeTarget "tagtest" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
31108A441C6B90E900E728EA /* Debug */,
|
||||
31108A451C6B90E900E728EA /* Release */,
|
||||
31108A461C6B90E900E728EA /* RASH */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
3114A599156E913C001E0AA3 /* Build configuration list for PBXNativeTarget "locv" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
|
|
|||
311
mps/code/mpsi.c
311
mps/code/mpsi.c
|
|
@ -40,13 +40,9 @@
|
|||
* present. This is because the MPM doesn't ever try to protect them.
|
||||
* In future, it will.
|
||||
*
|
||||
* .reg-scan: (rule.universal.complete) At present, we only support
|
||||
* register scanning using our own ambiguous register and stack scanning
|
||||
* method, mps_stack_scan_ambig. This may never change, but the way the
|
||||
* interface is designed allows for the possibility of change.
|
||||
*
|
||||
* .naming: (rule.impl.guide) The exported identifiers do not follow the
|
||||
* normal MPS naming conventions. See <design/interface-c/#naming>. */
|
||||
* normal MPS naming conventions. See <design/interface-c/#naming>.
|
||||
*/
|
||||
|
||||
#include "mpm.h"
|
||||
#include "mps.h"
|
||||
|
|
@ -221,6 +217,25 @@ size_t mps_arena_spare_commit_limit(mps_arena_t arena)
|
|||
return limit;
|
||||
}
|
||||
|
||||
double mps_arena_pause_time(mps_arena_t arena)
|
||||
{
|
||||
double pause_time;
|
||||
|
||||
ArenaEnter(arena);
|
||||
pause_time = ArenaPauseTime(arena);
|
||||
ArenaLeave(arena);
|
||||
|
||||
return pause_time;
|
||||
}
|
||||
|
||||
void mps_arena_pause_time_set(mps_arena_t arena, double pause_time)
|
||||
{
|
||||
ArenaEnter(arena);
|
||||
ArenaSetPauseTime(arena, pause_time);
|
||||
ArenaLeave(arena);
|
||||
}
|
||||
|
||||
|
||||
void mps_arena_clamp(mps_arena_t arena)
|
||||
{
|
||||
ArenaEnter(arena);
|
||||
|
|
@ -744,9 +759,7 @@ mps_res_t mps_alloc(mps_addr_t *p_o, mps_pool_t pool, size_t size)
|
|||
/* <design/class-interface/#alloc.size.align>. */
|
||||
/* Rest ignored, see .varargs. */
|
||||
|
||||
/* @@@@ There is currently no requirement for reservoirs to work */
|
||||
/* with unbuffered allocation. */
|
||||
res = PoolAlloc(&p, pool, size, FALSE);
|
||||
res = PoolAlloc(&p, pool, size);
|
||||
|
||||
ArenaLeave(arena);
|
||||
|
||||
|
|
@ -898,17 +911,7 @@ mps_res_t (mps_reserve)(mps_addr_t *p_o, mps_ap_t mps_ap, size_t size)
|
|||
mps_res_t mps_reserve_with_reservoir_permit(mps_addr_t *p_o,
|
||||
mps_ap_t mps_ap, size_t size)
|
||||
{
|
||||
mps_res_t res;
|
||||
|
||||
AVER(p_o != NULL);
|
||||
AVER(size > 0);
|
||||
AVER(mps_ap != NULL);
|
||||
AVER(TESTT(Buffer, BufferOfAP(mps_ap)));
|
||||
AVER(mps_ap->init == mps_ap->alloc);
|
||||
|
||||
MPS_RESERVE_WITH_RESERVOIR_PERMIT_BLOCK(res, *p_o, mps_ap, size);
|
||||
|
||||
return res;
|
||||
return mps_reserve(p_o, mps_ap, size);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1049,7 +1052,7 @@ mps_res_t mps_ap_fill(mps_addr_t *p_o, mps_ap_t mps_ap, size_t size)
|
|||
AVER(size > 0);
|
||||
AVER(SizeIsAligned(size, BufferPool(buf)->alignment));
|
||||
|
||||
res = BufferFill(&p, buf, size, FALSE);
|
||||
res = BufferFill(&p, buf, size);
|
||||
|
||||
ArenaLeave(arena);
|
||||
|
||||
|
|
@ -1063,32 +1066,7 @@ mps_res_t mps_ap_fill(mps_addr_t *p_o, mps_ap_t mps_ap, size_t size)
|
|||
mps_res_t mps_ap_fill_with_reservoir_permit(mps_addr_t *p_o, mps_ap_t mps_ap,
|
||||
size_t size)
|
||||
{
|
||||
Buffer buf = BufferOfAP(mps_ap);
|
||||
Arena arena;
|
||||
Addr p;
|
||||
Res res;
|
||||
|
||||
AVER(mps_ap != NULL);
|
||||
AVER(TESTT(Buffer, buf));
|
||||
arena = BufferArena(buf);
|
||||
|
||||
ArenaEnter(arena);
|
||||
|
||||
ArenaPoll(ArenaGlobals(arena)); /* .poll */
|
||||
|
||||
AVER(p_o != NULL);
|
||||
AVERT(Buffer, buf);
|
||||
AVER(size > 0);
|
||||
AVER(SizeIsAligned(size, BufferPool(buf)->alignment));
|
||||
|
||||
res = BufferFill(&p, buf, size, TRUE);
|
||||
|
||||
ArenaLeave(arena);
|
||||
|
||||
if (res != ResOK)
|
||||
return (mps_res_t)res;
|
||||
*p_o = (mps_addr_t)p;
|
||||
return MPS_RES_OK;
|
||||
return mps_ap_fill(p_o, mps_ap, size);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1197,10 +1175,11 @@ mps_res_t mps_sac_fill(mps_addr_t *p_o, mps_sac_t mps_sac, size_t size,
|
|||
AVER(p_o != NULL);
|
||||
AVER(TESTT(SAC, sac));
|
||||
arena = SACArena(sac);
|
||||
UNUSED(has_reservoir_permit); /* deprecated */
|
||||
|
||||
ArenaEnter(arena);
|
||||
|
||||
res = SACFill(&p, sac, size, (has_reservoir_permit != 0));
|
||||
res = SACFill(&p, sac, size);
|
||||
|
||||
ArenaLeave(arena);
|
||||
|
||||
|
|
@ -1299,12 +1278,14 @@ mps_res_t mps_root_create_table(mps_root_t *mps_root_o, mps_arena_t arena,
|
|||
AVER(base != NULL);
|
||||
AVER(size > 0);
|
||||
|
||||
/* .root.table-size: size is the length of the array at base, not */
|
||||
/* the size in bytes. However, RootCreateTable expects base and */
|
||||
/* limit pointers. Be careful. */
|
||||
/* .root.table-size: size is the length of the array at base, not
|
||||
the size in bytes. However, RootCreateArea expects base and limit
|
||||
pointers. Be careful. Avoid type punning by casting through
|
||||
void *. */
|
||||
|
||||
res = RootCreateTable(&root, arena, rank, mode,
|
||||
(Addr *)base, (Addr *)base + size);
|
||||
res = RootCreateArea(&root, arena, rank, mode,
|
||||
(void *)base, (void *)(base + size),
|
||||
mps_scan_area, NULL);
|
||||
|
||||
ArenaLeave(arena);
|
||||
|
||||
|
|
@ -1314,11 +1295,12 @@ mps_res_t mps_root_create_table(mps_root_t *mps_root_o, mps_arena_t arena,
|
|||
return MPS_RES_OK;
|
||||
}
|
||||
|
||||
mps_res_t mps_root_create_table_masked(mps_root_t *mps_root_o,
|
||||
mps_arena_t arena,
|
||||
mps_rank_t mps_rank, mps_rm_t mps_rm,
|
||||
mps_addr_t *base, size_t size,
|
||||
mps_word_t mask)
|
||||
mps_res_t mps_root_create_area(mps_root_t *mps_root_o,
|
||||
mps_arena_t arena,
|
||||
mps_rank_t mps_rank, mps_rm_t mps_rm,
|
||||
void *base, void *limit,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure)
|
||||
{
|
||||
Rank rank = (Rank)mps_rank;
|
||||
Root root;
|
||||
|
|
@ -1329,14 +1311,14 @@ mps_res_t mps_root_create_table_masked(mps_root_t *mps_root_o,
|
|||
|
||||
AVER(mps_root_o != NULL);
|
||||
AVER(base != NULL);
|
||||
AVER(size > 0);
|
||||
/* Can't check anything about mask */
|
||||
AVER(limit != NULL);
|
||||
AVER(base < limit);
|
||||
AVER(FUNCHECK(scan_area));
|
||||
/* Can't check anything about closure */
|
||||
|
||||
/* See .root.table-size. */
|
||||
|
||||
res = RootCreateTableMasked(&root, arena, rank, mode,
|
||||
(Addr *)base, (Addr *)base + size,
|
||||
mask);
|
||||
res = RootCreateArea(&root, arena, rank, mode,
|
||||
base, limit,
|
||||
scan_area, closure);
|
||||
|
||||
ArenaLeave(arena);
|
||||
|
||||
|
|
@ -1346,6 +1328,56 @@ mps_res_t mps_root_create_table_masked(mps_root_t *mps_root_o,
|
|||
return MPS_RES_OK;
|
||||
}
|
||||
|
||||
mps_res_t mps_root_create_area_tagged(mps_root_t *mps_root_o,
|
||||
mps_arena_t arena,
|
||||
mps_rank_t mps_rank,
|
||||
mps_rm_t mps_rm,
|
||||
void *base,
|
||||
void *limit,
|
||||
mps_area_scan_t scan_area,
|
||||
mps_word_t mask,
|
||||
mps_word_t pattern)
|
||||
{
|
||||
Rank rank = (Rank)mps_rank;
|
||||
Root root;
|
||||
RootMode mode = (RootMode)mps_rm;
|
||||
Res res;
|
||||
|
||||
ArenaEnter(arena);
|
||||
|
||||
AVER(mps_root_o != NULL);
|
||||
AVER(base != NULL);
|
||||
AVER(limit != NULL);
|
||||
AVER(base < limit);
|
||||
AVER(FUNCHECK(scan_area));
|
||||
/* Can't check anything about mask or pattern, as they could mean
|
||||
anything to scan_area. */
|
||||
|
||||
res = RootCreateAreaTagged(&root, arena, rank, mode,
|
||||
base, limit,
|
||||
scan_area, mask, pattern);
|
||||
|
||||
ArenaLeave(arena);
|
||||
|
||||
if (res != ResOK)
|
||||
return (mps_res_t)res;
|
||||
*mps_root_o = (mps_root_t)root;
|
||||
return MPS_RES_OK;
|
||||
}
|
||||
|
||||
|
||||
mps_res_t mps_root_create_table_masked(mps_root_t *mps_root_o,
|
||||
mps_arena_t arena,
|
||||
mps_rank_t mps_rank, mps_rm_t mps_rm,
|
||||
mps_addr_t *base, size_t size,
|
||||
mps_word_t mask)
|
||||
{
|
||||
return mps_root_create_area_tagged(mps_root_o, arena, mps_rank, mps_rm,
|
||||
base, base + size,
|
||||
mps_scan_area_tagged,
|
||||
mask, 0);
|
||||
}
|
||||
|
||||
mps_res_t mps_root_create_fmt(mps_root_t *mps_root_o, mps_arena_t arena,
|
||||
mps_rank_t mps_rank, mps_rm_t mps_rm,
|
||||
mps_fmt_scan_t scan,
|
||||
|
|
@ -1372,7 +1404,7 @@ mps_res_t mps_root_create_fmt(mps_root_t *mps_root_o, mps_arena_t arena,
|
|||
mps_res_t mps_root_create_reg(mps_root_t *mps_root_o, mps_arena_t arena,
|
||||
mps_rank_t mps_rank, mps_rm_t mps_rm,
|
||||
mps_thr_t thread, mps_reg_scan_t mps_reg_scan,
|
||||
void *reg_scan_p, size_t mps_size)
|
||||
void *cold, size_t mps_size)
|
||||
{
|
||||
Rank rank = (Rank)mps_rank;
|
||||
Root root;
|
||||
|
|
@ -1383,14 +1415,111 @@ mps_res_t mps_root_create_reg(mps_root_t *mps_root_o, mps_arena_t arena,
|
|||
AVER(mps_root_o != NULL);
|
||||
AVER(mps_reg_scan != NULL);
|
||||
AVER(mps_reg_scan == mps_stack_scan_ambig); /* .reg.scan */
|
||||
AVER(reg_scan_p != NULL); /* stackBot */
|
||||
AVER(AddrIsAligned(reg_scan_p, sizeof(Word)));
|
||||
AVER(cold != NULL);
|
||||
AVER(AddrIsAligned(cold, sizeof(Word)));
|
||||
AVER(rank == mps_rank_ambig());
|
||||
AVER(mps_rm == (mps_rm_t)0);
|
||||
|
||||
UNUSED(mps_size);
|
||||
|
||||
/* See .root-mode. */
|
||||
res = RootCreateReg(&root, arena, rank, thread,
|
||||
mps_reg_scan, reg_scan_p, mps_size);
|
||||
res = RootCreateThreadTagged(&root, arena, rank, thread,
|
||||
mps_scan_area_tagged,
|
||||
sizeof(mps_word_t) - 1, 0,
|
||||
(Word *)cold);
|
||||
|
||||
ArenaLeave(arena);
|
||||
|
||||
if (res != ResOK)
|
||||
return (mps_res_t)res;
|
||||
*mps_root_o = (mps_root_t)root;
|
||||
return MPS_RES_OK;
|
||||
}
|
||||
|
||||
|
||||
mps_res_t mps_root_create_thread(mps_root_t *mps_root_o,
|
||||
mps_arena_t arena,
|
||||
mps_thr_t thread,
|
||||
void *stack)
|
||||
{
|
||||
return mps_root_create_thread_tagged(mps_root_o,
|
||||
arena,
|
||||
mps_rank_ambig(),
|
||||
(mps_rm_t)0,
|
||||
thread,
|
||||
mps_scan_area_tagged,
|
||||
sizeof(mps_word_t) - 1,
|
||||
0,
|
||||
stack);
|
||||
}
|
||||
|
||||
|
||||
mps_res_t mps_root_create_thread_scanned(mps_root_t *mps_root_o,
|
||||
mps_arena_t arena,
|
||||
mps_rank_t mps_rank,
|
||||
mps_rm_t mps_rm,
|
||||
mps_thr_t thread,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure,
|
||||
void *cold)
|
||||
{
|
||||
Rank rank = (Rank)mps_rank;
|
||||
Root root;
|
||||
Res res;
|
||||
|
||||
ArenaEnter(arena);
|
||||
|
||||
AVER(mps_root_o != NULL);
|
||||
AVER(cold != NULL);
|
||||
AVER(AddrIsAligned(cold, sizeof(Word)));
|
||||
AVER(rank == mps_rank_ambig());
|
||||
AVER(mps_rm == (mps_rm_t)0);
|
||||
AVER(FUNCHECK(scan_area));
|
||||
/* Can't check anything about closure. */
|
||||
|
||||
/* See .root-mode. */
|
||||
res = RootCreateThread(&root, arena, rank, thread,
|
||||
scan_area, closure,
|
||||
(Word *)cold);
|
||||
|
||||
ArenaLeave(arena);
|
||||
|
||||
if (res != ResOK)
|
||||
return (mps_res_t)res;
|
||||
*mps_root_o = (mps_root_t)root;
|
||||
return MPS_RES_OK;
|
||||
}
|
||||
|
||||
|
||||
mps_res_t mps_root_create_thread_tagged(mps_root_t *mps_root_o,
|
||||
mps_arena_t arena,
|
||||
mps_rank_t mps_rank,
|
||||
mps_rm_t mps_rm,
|
||||
mps_thr_t thread,
|
||||
mps_area_scan_t scan_area,
|
||||
mps_word_t mask,
|
||||
mps_word_t pattern,
|
||||
void *cold)
|
||||
{
|
||||
Rank rank = (Rank)mps_rank;
|
||||
Root root;
|
||||
Res res;
|
||||
|
||||
ArenaEnter(arena);
|
||||
|
||||
AVER(mps_root_o != NULL);
|
||||
AVER(cold != NULL);
|
||||
AVER(AddrIsAligned(cold, sizeof(Word)));
|
||||
AVER(rank == mps_rank_ambig());
|
||||
AVER(mps_rm == (mps_rm_t)0);
|
||||
AVER(FUNCHECK(scan_area));
|
||||
/* Can't check anything about mask or pattern, as they could mean
|
||||
anything to scan_area. */
|
||||
|
||||
/* See .root-mode. */
|
||||
res = RootCreateThreadTagged(&root, arena, rank, thread,
|
||||
scan_area, mask, pattern,
|
||||
(Word *)cold);
|
||||
|
||||
ArenaLeave(arena);
|
||||
|
||||
|
|
@ -1403,14 +1532,22 @@ mps_res_t mps_root_create_reg(mps_root_t *mps_root_o, mps_arena_t arena,
|
|||
|
||||
/* mps_stack_scan_ambig -- scan the thread state ambiguously
|
||||
*
|
||||
* See .reg-scan. */
|
||||
* This is a helper function for the deprecated mps_root_create_reg
|
||||
* and should no longer be reached since that has been reimplemented
|
||||
* in terms of the more general RootCreateThreadTagged.
|
||||
*/
|
||||
|
||||
mps_res_t mps_stack_scan_ambig(mps_ss_t mps_ss,
|
||||
mps_thr_t thread, void *p, size_t s)
|
||||
{
|
||||
ScanState ss = PARENT(ScanStateStruct, ss_s, mps_ss);
|
||||
UNUSED(mps_ss);
|
||||
UNUSED(thread);
|
||||
UNUSED(p);
|
||||
UNUSED(s);
|
||||
return ThreadScan(ss, thread, p);
|
||||
|
||||
NOTREACHED;
|
||||
|
||||
return ResUNIMPL;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1904,16 +2041,16 @@ mps_res_t mps_ap_alloc_pattern_reset(mps_ap_t mps_ap)
|
|||
}
|
||||
|
||||
|
||||
/* Low memory reservoir */
|
||||
/* Low memory reservoir (deprecated -- see job003985) */
|
||||
|
||||
|
||||
/* mps_reservoir_limit_set -- set the reservoir size */
|
||||
|
||||
void mps_reservoir_limit_set(mps_arena_t arena, size_t size)
|
||||
{
|
||||
ArenaEnter(arena);
|
||||
ReservoirSetLimit(ArenaReservoir(arena), size);
|
||||
ArenaLeave(arena);
|
||||
UNUSED(arena);
|
||||
UNUSED(size);
|
||||
NOOP;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1921,14 +2058,8 @@ void mps_reservoir_limit_set(mps_arena_t arena, size_t size)
|
|||
|
||||
size_t mps_reservoir_limit(mps_arena_t arena)
|
||||
{
|
||||
Size size;
|
||||
|
||||
ArenaEnter(arena);
|
||||
|
||||
size = ReservoirLimit(ArenaReservoir(arena));
|
||||
|
||||
ArenaLeave(arena);
|
||||
return size;
|
||||
UNUSED(arena);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1936,14 +2067,8 @@ size_t mps_reservoir_limit(mps_arena_t arena)
|
|||
|
||||
size_t mps_reservoir_available(mps_arena_t arena)
|
||||
{
|
||||
Size size;
|
||||
|
||||
ArenaEnter(arena);
|
||||
|
||||
size = ReservoirAvailable(ArenaReservoir(arena));
|
||||
|
||||
ArenaLeave(arena);
|
||||
return size;
|
||||
UNUSED(arena);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -143,31 +143,6 @@ static mps_addr_t make(void)
|
|||
}
|
||||
|
||||
|
||||
/* make_with_permit -- allocate an object, with reservoir permit */
|
||||
|
||||
static mps_addr_t make_with_permit(void)
|
||||
{
|
||||
size_t length = rnd() % 20;
|
||||
size_t sizeCli = (length+2)*sizeof(mps_word_t);
|
||||
size_t sizeMps = SizeCli2Mps(sizeCli);
|
||||
mps_addr_t pMps, pCli;
|
||||
mps_res_t res;
|
||||
|
||||
do {
|
||||
MPS_RESERVE_WITH_RESERVOIR_PERMIT_BLOCK(res, pMps, ap, sizeMps);
|
||||
if (res != MPS_RES_OK)
|
||||
die(res, "MPS_RESERVE_WITH_RESERVOIR_PERMIT_BLOCK");
|
||||
HeaderInit(pMps);
|
||||
pCli = PtrMps2Cli(pMps);
|
||||
res = dylan_init(pCli, sizeCli, exactRoots, exactRootsCOUNT);
|
||||
if (res != MPS_RES_OK)
|
||||
die(res, "dylan_init");
|
||||
} while(!mps_commit(ap, pMps, sizeMps));
|
||||
|
||||
return pCli;
|
||||
}
|
||||
|
||||
|
||||
/* make_no_inline -- allocate an object, using non-inlined interface */
|
||||
|
||||
static mps_addr_t make_no_inline(void)
|
||||
|
|
@ -233,6 +208,7 @@ static void ap_create_v_test(mps_pool_t pool, ...)
|
|||
/* addr_pool_test
|
||||
*
|
||||
* intended to test:
|
||||
* mps_arena_has_addr
|
||||
* mps_addr_pool
|
||||
* mps_addr_fmt
|
||||
*/
|
||||
|
|
@ -270,6 +246,7 @@ static void addr_pool_test(mps_arena_t arena,
|
|||
addr = obj1;
|
||||
pool = poolDistinguished;
|
||||
fmt = fmtDistinguished;
|
||||
cdie(mps_arena_has_addr(arena, addr), "mps_arena_has_addr 0a");
|
||||
b = mps_addr_pool(&pool, arena, addr);
|
||||
/* printf("b %d; pool %p; sig %lx\n", b, (void *)pool,
|
||||
b ? ((mps_word_t*)pool)[0] : (mps_word_t)0); */
|
||||
|
|
@ -283,6 +260,7 @@ static void addr_pool_test(mps_arena_t arena,
|
|||
addr = obj2;
|
||||
pool = poolDistinguished;
|
||||
fmt = fmtDistinguished;
|
||||
cdie(mps_arena_has_addr(arena, addr), "mps_arena_has_addr 0b");
|
||||
b = mps_addr_pool(&pool, arena, addr);
|
||||
/* printf("b %d; pool %p; sig %lx\n", b, (void *)pool,
|
||||
b ? ((mps_word_t*)pool)[0] : (mps_word_t)0); */
|
||||
|
|
@ -296,6 +274,7 @@ static void addr_pool_test(mps_arena_t arena,
|
|||
addr = &pool; /* point at stack, not in any chunk */
|
||||
pool = poolDistinguished;
|
||||
fmt = fmtDistinguished;
|
||||
cdie(mps_arena_has_addr(arena, addr) == FALSE, "mps_arena_has_addr 5");
|
||||
b = mps_addr_pool(&pool, arena, addr);
|
||||
cdie(b == FALSE && pool == poolDistinguished, "mps_addr_pool 5");
|
||||
b = mps_addr_fmt(&fmt, arena, addr);
|
||||
|
|
@ -320,6 +299,7 @@ static mps_res_t root_single(mps_ss_t ss, void *p, size_t s)
|
|||
* mps_arena_reserved
|
||||
* incidentally tests:
|
||||
* mps_alloc
|
||||
* mps_arena_commit_limit_set
|
||||
* mps_class_mv
|
||||
* mps_pool_create
|
||||
* mps_pool_destroy
|
||||
|
|
@ -353,30 +333,6 @@ static void arena_commit_test(mps_arena_t arena)
|
|||
}
|
||||
|
||||
|
||||
/* reservoir_test -- Test the reservoir interface
|
||||
*
|
||||
* This has not been tuned to actually dip into the reservoir. See
|
||||
* QA test 132 for that.
|
||||
*/
|
||||
|
||||
#define reservoirSIZE ((size_t)128 * 1024)
|
||||
|
||||
static void reservoir_test(mps_arena_t arena)
|
||||
{
|
||||
(void)make_with_permit();
|
||||
cdie(mps_reservoir_available(arena) == 0, "empty reservoir");
|
||||
cdie(mps_reservoir_limit(arena) == 0, "no reservoir");
|
||||
mps_reservoir_limit_set(arena, reservoirSIZE);
|
||||
cdie(mps_reservoir_limit(arena) >= reservoirSIZE, "reservoir limit set");
|
||||
cdie(mps_reservoir_available(arena) >= reservoirSIZE, "got reservoir");
|
||||
(void)make_with_permit();
|
||||
mps_reservoir_limit_set(arena, 0);
|
||||
cdie(mps_reservoir_available(arena) == 0, "empty reservoir");
|
||||
cdie(mps_reservoir_limit(arena) == 0, "no reservoir");
|
||||
(void)make_with_permit();
|
||||
}
|
||||
|
||||
|
||||
static void *test(void *arg, size_t s)
|
||||
{
|
||||
mps_arena_t arena;
|
||||
|
|
@ -550,7 +506,6 @@ static void *test(void *arg, size_t s)
|
|||
}
|
||||
|
||||
arena_commit_test(arena);
|
||||
reservoir_test(arena);
|
||||
alignmentTest(arena);
|
||||
|
||||
die(mps_arena_collect(arena), "collect");
|
||||
|
|
@ -591,11 +546,16 @@ int main(int argc, char *argv[])
|
|||
"arena_create");
|
||||
die(mps_thread_reg(&thread, arena), "thread_reg");
|
||||
|
||||
die(mps_root_create_reg(®_root, arena,
|
||||
mps_rank_ambig(), (mps_rm_t)0,
|
||||
thread, &mps_stack_scan_ambig,
|
||||
marker, (size_t)0),
|
||||
"root_create_reg");
|
||||
if (rnd() % 2) {
|
||||
die(mps_root_create_reg(®_root, arena,
|
||||
mps_rank_ambig(), (mps_rm_t)0,
|
||||
thread, &mps_stack_scan_ambig,
|
||||
marker, (size_t)0),
|
||||
"root_create_reg");
|
||||
} else {
|
||||
die(mps_root_create_thread(®_root, arena, thread, marker),
|
||||
"root_create_thread");
|
||||
}
|
||||
|
||||
mps_tramp(&r, test, arena, 0);
|
||||
mps_root_destroy(reg_root);
|
||||
|
|
|
|||
|
|
@ -261,6 +261,23 @@
|
|||
#define MPS_PF_ALIGN 4
|
||||
|
||||
|
||||
#elif defined(__FreeBSD__) && defined (__i386__) && defined (__GNUC__) \
|
||||
&& defined(__clang__)
|
||||
#if defined(CONFIG_PF_STRING) && ! defined(CONFIG_PF_FRI3LL)
|
||||
#error "specified CONFIG_PF_... inconsistent with detected fri3ll"
|
||||
#endif
|
||||
#define MPS_PF_FRI3LL
|
||||
#define MPS_PF_STRING "fri3ll"
|
||||
#define MPS_OS_FR
|
||||
#define MPS_ARCH_I3
|
||||
#define MPS_BUILD_LL
|
||||
#define MPS_T_WORD unsigned long
|
||||
#define MPS_T_ULONGEST unsigned long
|
||||
#define MPS_WORD_WIDTH 32
|
||||
#define MPS_WORD_SHIFT 5
|
||||
#define MPS_PF_ALIGN 4
|
||||
|
||||
|
||||
#elif defined(__FreeBSD__) && defined (__x86_64__) && defined (__GNUC__) \
|
||||
&& !defined(__clang__)
|
||||
#if defined(CONFIG_PF_STRING) && ! defined(CONFIG_PF_FRI6GC)
|
||||
|
|
@ -278,6 +295,23 @@
|
|||
#define MPS_PF_ALIGN 8
|
||||
|
||||
|
||||
#elif defined(__FreeBSD__) && defined (__x86_64__) && defined (__GNUC__) \
|
||||
&& defined(__clang__)
|
||||
#if defined(CONFIG_PF_STRING) && ! defined(CONFIG_PF_FRI6LL)
|
||||
#error "specified CONFIG_PF_... inconsistent with detected fri6ll"
|
||||
#endif
|
||||
#define MPS_PF_FRI6LL
|
||||
#define MPS_PF_STRING "fri6ll"
|
||||
#define MPS_OS_FR
|
||||
#define MPS_ARCH_I6
|
||||
#define MPS_BUILD_LL
|
||||
#define MPS_T_WORD unsigned long
|
||||
#define MPS_T_ULONGEST unsigned long /* FIXME: Check this for Clang */
|
||||
#define MPS_WORD_WIDTH 64
|
||||
#define MPS_WORD_SHIFT 6
|
||||
#define MPS_PF_ALIGN 8
|
||||
|
||||
|
||||
#else
|
||||
#error "The MPS Kit does not have a configuration for this platform out of the box; see manual/build.txt"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
#
|
||||
# This file is included by platform nmake files that use the Microsoft
|
||||
# Visual C/C+ compiler. It defines the compiler-specific variables
|
||||
# that the common nmake fragment (comm.nmk) requires.
|
||||
# that the common nmake file fragment (<code/commpost.nmk>) requires.
|
||||
|
||||
CC = cl
|
||||
LIBMAN = lib
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ Res NailboardCreate(Nailboard *boardReturn, Arena arena, Align alignment,
|
|||
alignShift = SizeLog2((Size)alignment);
|
||||
nails = AddrOffset(base, limit) >> alignShift;
|
||||
levels = nailboardLevels(nails);
|
||||
res = ControlAlloc(&p, arena, nailboardSize(nails, levels), FALSE);
|
||||
res = ControlAlloc(&p, arena, nailboardSize(nails, levels));
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* nailboardtest.c: NAILBOARD TEST
|
||||
*
|
||||
* $Id: //info.ravenbrook.com/project/mps/branch/2014-01-15/nailboard/code/fotest.c#1 $
|
||||
* Copyright (c) 2014 Ravenbrook Limited. See end of file for license.
|
||||
* $Id$
|
||||
* Copyright (c) 2014-2016 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -73,7 +73,7 @@ int main(int argc, char **argv)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (c) 2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (c) 2014-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
#
|
||||
# This file is included by platform nmake files that use the Pelles C
|
||||
# compiler. It defines the compiler-specific variables that the common
|
||||
# nmake fragment (comm.nmk) requires.
|
||||
# nmake file fragment (<code/commpost.nmk>) requires.
|
||||
|
||||
CC = pocc
|
||||
LIBMAN = polib
|
||||
|
|
|
|||
449
mps/code/policy.c
Normal file
449
mps/code/policy.c
Normal file
|
|
@ -0,0 +1,449 @@
|
|||
/* policy.c: POLICY DECISIONS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* This module collects the decision-making code for the MPS, so that
|
||||
* policy can be maintained and adjusted.
|
||||
*
|
||||
* .sources: <design/strategy/>.
|
||||
*/
|
||||
|
||||
#include "locus.h"
|
||||
#include "mpm.h"
|
||||
|
||||
SRCID(policy, "$Id$");
|
||||
|
||||
|
||||
/* PolicyAlloc -- allocation policy
|
||||
*
|
||||
* This is the code responsible for making decisions about where to allocate
|
||||
* memory.
|
||||
*
|
||||
* pref describes the address space preferences for the allocation.
|
||||
* size is the amount of memory requested to be allocated, in bytes.
|
||||
* pool is the pool that is requresting the memory.
|
||||
*
|
||||
* If successful, update *tractReturn to point to the initial tract of
|
||||
* the allocated memory and return ResOK. Otherwise return a result
|
||||
* code describing the problem.
|
||||
*/
|
||||
|
||||
Res PolicyAlloc(Tract *tractReturn, Arena arena, LocusPref pref,
|
||||
Size size, Pool pool)
|
||||
{
|
||||
Res res;
|
||||
Tract tract;
|
||||
ZoneSet zones, moreZones, evenMoreZones;
|
||||
|
||||
AVER(tractReturn != NULL);
|
||||
AVERT(Arena, arena);
|
||||
AVERT(LocusPref, pref);
|
||||
AVER(size > (Size)0);
|
||||
AVER(SizeIsArenaGrains(size, arena));
|
||||
AVERT(Pool, pool);
|
||||
AVER(arena == PoolArena(pool));
|
||||
|
||||
/* Don't attempt to allocate if doing so would definitely exceed the
|
||||
* commit limit. */
|
||||
if (arena->spareCommitted < size) {
|
||||
Size necessaryCommitIncrease = size - arena->spareCommitted;
|
||||
if (arena->committed + necessaryCommitIncrease > arena->commitLimit
|
||||
|| arena->committed + necessaryCommitIncrease < arena->committed) {
|
||||
return ResCOMMIT_LIMIT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Plan A: allocate from the free land in the requested zones */
|
||||
zones = ZoneSetDiff(pref->zones, pref->avoid);
|
||||
if (zones != ZoneSetEMPTY) {
|
||||
res = ArenaFreeLandAlloc(&tract, arena, zones, pref->high, size, pool);
|
||||
if (res == ResOK)
|
||||
goto found;
|
||||
}
|
||||
|
||||
/* Plan B: add free zones that aren't blacklisted */
|
||||
/* TODO: Pools without ambiguous roots might not care about the blacklist. */
|
||||
/* TODO: zones are precious and (currently) never deallocated, so we
|
||||
* should consider extending the arena first if address space is plentiful.
|
||||
* See also job003384. */
|
||||
moreZones = ZoneSetUnion(pref->zones, ZoneSetDiff(arena->freeZones, pref->avoid));
|
||||
if (moreZones != zones) {
|
||||
res = ArenaFreeLandAlloc(&tract, arena, moreZones, pref->high, size, pool);
|
||||
if (res == ResOK)
|
||||
goto found;
|
||||
}
|
||||
|
||||
/* Plan C: Extend the arena, then try A and B again. */
|
||||
if (moreZones != ZoneSetEMPTY) {
|
||||
res = arena->class->grow(arena, pref, size);
|
||||
/* If we can't extend because we hit the commit limit, try purging
|
||||
some spare committed memory and try again.*/
|
||||
/* TODO: This would be a good time to *remap* VM instead of
|
||||
returning it to the OS. */
|
||||
if (res == ResCOMMIT_LIMIT) {
|
||||
if (arena->class->purgeSpare(arena, size) >= size)
|
||||
res = arena->class->grow(arena, pref, size);
|
||||
}
|
||||
if (res == ResOK) {
|
||||
if (zones != ZoneSetEMPTY) {
|
||||
res = ArenaFreeLandAlloc(&tract, arena, zones, pref->high, size, pool);
|
||||
if (res == ResOK)
|
||||
goto found;
|
||||
}
|
||||
if (moreZones != zones) {
|
||||
res = ArenaFreeLandAlloc(&tract, arena, moreZones, pref->high,
|
||||
size, pool);
|
||||
if (res == ResOK)
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
/* TODO: Log an event here, since something went wrong, before
|
||||
trying the next plan anyway. */
|
||||
}
|
||||
|
||||
/* Plan D: add every zone that isn't blacklisted. This might mix GC'd
|
||||
* objects with those from other generations, causing the zone check
|
||||
* to give false positives and slowing down the collector. */
|
||||
/* TODO: log an event for this */
|
||||
evenMoreZones = ZoneSetDiff(ZoneSetUNIV, pref->avoid);
|
||||
if (evenMoreZones != moreZones) {
|
||||
res = ArenaFreeLandAlloc(&tract, arena, evenMoreZones, pref->high,
|
||||
size, pool);
|
||||
if (res == ResOK)
|
||||
goto found;
|
||||
}
|
||||
|
||||
/* Last resort: try anywhere. This might put GC'd objects in zones where
|
||||
* common ambiguous bit patterns pin them down, causing the zone check
|
||||
* to give even more false positives permanently, and possibly retaining
|
||||
* garbage indefinitely. */
|
||||
res = ArenaFreeLandAlloc(&tract, arena, ZoneSetUNIV, pref->high, size, pool);
|
||||
if (res == ResOK)
|
||||
goto found;
|
||||
|
||||
/* Uh oh. */
|
||||
return res;
|
||||
|
||||
found:
|
||||
*tractReturn = tract;
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
||||
/* policyCollectionTime -- estimate time to collect the world, in seconds */
|
||||
|
||||
static double policyCollectionTime(Arena arena)
|
||||
{
|
||||
Size collectableSize;
|
||||
double collectionRate;
|
||||
double collectionTime;
|
||||
|
||||
AVERT(Arena, arena);
|
||||
|
||||
collectableSize = ArenaCollectable(arena);
|
||||
/* The condition arena->tracedTime >= 1.0 ensures that the division
|
||||
* can't overflow. */
|
||||
if (arena->tracedTime >= 1.0)
|
||||
collectionRate = arena->tracedWork / arena->tracedTime;
|
||||
else
|
||||
collectionRate = ARENA_DEFAULT_COLLECTION_RATE;
|
||||
collectionTime = collectableSize / collectionRate;
|
||||
collectionTime += ARENA_DEFAULT_COLLECTION_OVERHEAD;
|
||||
|
||||
return collectionTime;
|
||||
}
|
||||
|
||||
|
||||
/* PolicyShouldCollectWorld -- should we collect the world now?
|
||||
*
|
||||
* Return TRUE if we should try collecting the world now, FALSE if
|
||||
* not.
|
||||
*
|
||||
* This is the policy behind mps_arena_step, and so the client
|
||||
* must have provided us with enough time to collect the world, and
|
||||
* enough time must have passed since the last time we did that
|
||||
* opportunistically.
|
||||
*/
|
||||
|
||||
Bool PolicyShouldCollectWorld(Arena arena, double availableTime,
|
||||
Clock now, Clock clocks_per_sec)
|
||||
{
|
||||
Size collectableSize;
|
||||
double collectionTime, sinceLastWorldCollect;
|
||||
|
||||
AVERT(Arena, arena);
|
||||
/* Can't collect the world if we're already collecting. */
|
||||
AVER(arena->busyTraces == TraceSetEMPTY);
|
||||
|
||||
if (availableTime <= 0.0)
|
||||
/* Can't collect the world if we're not given any time. */
|
||||
return FALSE;
|
||||
|
||||
/* Don't collect the world if it's very small. */
|
||||
collectableSize = ArenaCollectable(arena);
|
||||
if (collectableSize < ARENA_MINIMUM_COLLECTABLE_SIZE)
|
||||
return FALSE;
|
||||
|
||||
/* How long would it take to collect the world? */
|
||||
collectionTime = policyCollectionTime(arena);
|
||||
|
||||
/* How long since we last collected the world? */
|
||||
sinceLastWorldCollect = ((now - arena->lastWorldCollect) /
|
||||
(double) clocks_per_sec);
|
||||
|
||||
/* Offered enough time, and long enough since we last did it? */
|
||||
return availableTime > collectionTime
|
||||
&& sinceLastWorldCollect > collectionTime / ARENA_MAX_COLLECT_FRACTION;
|
||||
}
|
||||
|
||||
|
||||
/* policyCondemnChain -- condemn approriate parts of this chain
|
||||
*
|
||||
* If successful, set *mortalityReturn to an estimate of the mortality
|
||||
* of the condemned parts of this chain and return ResOK.
|
||||
*
|
||||
* This is only called if ChainDeferral returned a value sufficiently
|
||||
* low that we decided to start the collection. (Usually such values
|
||||
* are less than zero; see <design/strategy/#policy.start.chain>.)
|
||||
*/
|
||||
|
||||
static Res policyCondemnChain(double *mortalityReturn, Chain chain, Trace trace)
|
||||
{
|
||||
Res res;
|
||||
size_t topCondemnedGen, i;
|
||||
GenDesc gen;
|
||||
ZoneSet condemnedSet = ZoneSetEMPTY;
|
||||
Size condemnedSize = 0, survivorSize = 0, genNewSize, genTotalSize;
|
||||
|
||||
AVERT(Chain, chain);
|
||||
AVERT(Trace, trace);
|
||||
|
||||
/* Find the highest generation that's over capacity. We will condemn
|
||||
* this and all lower generations in the chain. */
|
||||
topCondemnedGen = chain->genCount;
|
||||
for (;;) {
|
||||
/* It's an error to call this function unless some generation is
|
||||
* over capacity as reported by ChainDeferral. */
|
||||
AVER(topCondemnedGen > 0);
|
||||
if (topCondemnedGen == 0)
|
||||
return ResFAIL;
|
||||
-- topCondemnedGen;
|
||||
gen = &chain->gens[topCondemnedGen];
|
||||
AVERT(GenDesc, gen);
|
||||
genNewSize = GenDescNewSize(gen);
|
||||
if (genNewSize >= gen->capacity * (Size)1024)
|
||||
break;
|
||||
}
|
||||
|
||||
/* At this point, we've decided to condemn topCondemnedGen and all
|
||||
* lower generations. */
|
||||
for (i = 0; i <= topCondemnedGen; ++i) {
|
||||
gen = &chain->gens[i];
|
||||
AVERT(GenDesc, gen);
|
||||
condemnedSet = ZoneSetUnion(condemnedSet, gen->zones);
|
||||
genTotalSize = GenDescTotalSize(gen);
|
||||
genNewSize = GenDescNewSize(gen);
|
||||
condemnedSize += genTotalSize;
|
||||
survivorSize += (Size)(genNewSize * (1.0 - gen->mortality))
|
||||
/* predict survivors will survive again */
|
||||
+ (genTotalSize - genNewSize);
|
||||
}
|
||||
|
||||
AVER(condemnedSet != ZoneSetEMPTY || condemnedSize == 0);
|
||||
EVENT3(ChainCondemnAuto, chain, topCondemnedGen, chain->genCount);
|
||||
|
||||
/* Condemn everything in these zones. */
|
||||
if (condemnedSet != ZoneSetEMPTY) {
|
||||
res = TraceCondemnZones(trace, condemnedSet);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
}
|
||||
|
||||
*mortalityReturn = 1.0 - (double)survivorSize / condemnedSize;
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
||||
/* PolicyStartTrace -- consider starting a trace
|
||||
*
|
||||
* If a trace was started, update *traceReturn and return TRUE.
|
||||
* Otherwise, leave *traceReturn unchanged and return FALSE.
|
||||
*/
|
||||
|
||||
Bool PolicyStartTrace(Trace *traceReturn, Arena arena)
|
||||
{
|
||||
Res res;
|
||||
Trace trace;
|
||||
Size sFoundation, sCondemned, sSurvivors, sConsTrace;
|
||||
double tTracePerScan; /* tTrace/cScan */
|
||||
double dynamicDeferral;
|
||||
|
||||
/* Compute dynamic criterion. See strategy.lisp-machine. */
|
||||
AVER(arena->topGen.mortality >= 0.0);
|
||||
AVER(arena->topGen.mortality <= 1.0);
|
||||
sFoundation = (Size)0; /* condemning everything, only roots @@@@ */
|
||||
/* @@@@ sCondemned should be scannable only */
|
||||
sCondemned = ArenaCommitted(arena) - ArenaSpareCommitted(arena);
|
||||
sSurvivors = (Size)(sCondemned * (1 - arena->topGen.mortality));
|
||||
tTracePerScan = sFoundation + (sSurvivors * (1 + TraceCopyScanRATIO));
|
||||
AVER(TraceWorkFactor >= 0);
|
||||
AVER(sSurvivors + tTracePerScan * TraceWorkFactor <= (double)SizeMAX);
|
||||
sConsTrace = (Size)(sSurvivors + tTracePerScan * TraceWorkFactor);
|
||||
dynamicDeferral = (double)ArenaAvail(arena) - (double)sConsTrace;
|
||||
|
||||
if (dynamicDeferral < 0.0) {
|
||||
/* Start full collection. */
|
||||
res = TraceStartCollectAll(&trace, arena, TraceStartWhyDYNAMICCRITERION);
|
||||
if (res != ResOK)
|
||||
goto failStart;
|
||||
*traceReturn = trace;
|
||||
return TRUE;
|
||||
} else {
|
||||
/* Find the chain most over its capacity. */
|
||||
Ring node, nextNode;
|
||||
double firstTime = 0.0;
|
||||
Chain firstChain = NULL;
|
||||
|
||||
RING_FOR(node, &arena->chainRing, nextNode) {
|
||||
Chain chain = RING_ELT(Chain, chainRing, node);
|
||||
double time;
|
||||
|
||||
AVERT(Chain, chain);
|
||||
time = ChainDeferral(chain);
|
||||
if (time < firstTime) {
|
||||
firstTime = time; firstChain = chain;
|
||||
}
|
||||
}
|
||||
|
||||
/* If one was found, start collection on that chain. */
|
||||
if(firstTime < 0) {
|
||||
double mortality;
|
||||
|
||||
res = TraceCreate(&trace, arena, TraceStartWhyCHAIN_GEN0CAP);
|
||||
AVER(res == ResOK);
|
||||
res = policyCondemnChain(&mortality, firstChain, trace);
|
||||
if (res != ResOK) /* should try some other trace, really @@@@ */
|
||||
goto failCondemn;
|
||||
if (TraceIsEmpty(trace))
|
||||
goto nothingCondemned;
|
||||
trace->chain = firstChain;
|
||||
ChainStartGC(firstChain, trace);
|
||||
res = TraceStart(trace, mortality, trace->condemned * TraceWorkFactor);
|
||||
/* We don't expect normal GC traces to fail to start. */
|
||||
AVER(res == ResOK);
|
||||
*traceReturn = trace;
|
||||
return TRUE;
|
||||
}
|
||||
} /* (dynamicDeferral > 0.0) */
|
||||
return FALSE;
|
||||
|
||||
nothingCondemned:
|
||||
failCondemn:
|
||||
TraceDestroyInit(trace);
|
||||
failStart:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* PolicyPoll -- do some tracing work?
|
||||
*
|
||||
* Return TRUE if the MPS should do some tracing work; FALSE if it
|
||||
* should return to the mutator.
|
||||
*/
|
||||
|
||||
Bool PolicyPoll(Arena arena)
|
||||
{
|
||||
Globals globals;
|
||||
AVERT(Arena, arena);
|
||||
globals = ArenaGlobals(arena);
|
||||
return globals->pollThreshold <= globals->fillMutatorSize;
|
||||
}
|
||||
|
||||
|
||||
/* PolicyPollAgain -- do another unit of work?
|
||||
*
|
||||
* Return TRUE if the MPS should do another unit of work; FALSE if it
|
||||
* should return to the mutator.
|
||||
*
|
||||
* start is the clock time when the MPS was entered.
|
||||
* moreWork and tracedWork are the results of the last call to TracePoll.
|
||||
*/
|
||||
|
||||
Bool PolicyPollAgain(Arena arena, Clock start, Bool moreWork, Work tracedWork)
|
||||
{
|
||||
Bool moreTime;
|
||||
Globals globals;
|
||||
double nextPollThreshold;
|
||||
|
||||
AVERT(Arena, arena);
|
||||
UNUSED(tracedWork);
|
||||
|
||||
if (ArenaEmergency(arena))
|
||||
return TRUE;
|
||||
|
||||
/* Is there more work to do and more time to do it in? */
|
||||
moreTime = (ClockNow() - start) < ArenaPauseTime(arena) * ClocksPerSec();
|
||||
if (moreWork && moreTime)
|
||||
return TRUE;
|
||||
|
||||
/* We're not going to do more work now, so calculate when to come back. */
|
||||
|
||||
globals = ArenaGlobals(arena);
|
||||
|
||||
if (moreWork) {
|
||||
/* We did one quantum of work; consume one unit of 'time'. */
|
||||
nextPollThreshold = globals->pollThreshold + ArenaPollALLOCTIME;
|
||||
} else {
|
||||
/* No more work to do. Sleep until NOW + a bit. */
|
||||
nextPollThreshold = globals->fillMutatorSize + ArenaPollALLOCTIME;
|
||||
}
|
||||
|
||||
/* Advance pollThreshold; check: enough precision? */
|
||||
AVER(nextPollThreshold > globals->pollThreshold);
|
||||
globals->pollThreshold = nextPollThreshold;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2016 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.
|
||||
*/
|
||||
|
|
@ -169,6 +169,11 @@ Res PoolInit(Pool pool, Arena arena, PoolClass class, ArgList args)
|
|||
/* Add initialized pool to list of pools in arena. */
|
||||
RingAppend(&globals->poolRing, &pool->arenaRing);
|
||||
|
||||
/* Add initialized pool to list of pools using format. */
|
||||
if (pool->format) {
|
||||
++ pool->format->poolCount;
|
||||
}
|
||||
|
||||
return ResOK;
|
||||
|
||||
failInit:
|
||||
|
|
@ -195,8 +200,7 @@ Res PoolCreate(Pool *poolReturn, Arena arena,
|
|||
|
||||
/* .space.alloc: Allocate the pool instance structure with the size */
|
||||
/* requested in the pool class. See .space.free */
|
||||
res = ControlAlloc(&base, arena, class->size,
|
||||
/* withReservoirPermit */ FALSE);
|
||||
res = ControlAlloc(&base, arena, class->size);
|
||||
if (res != ResOK)
|
||||
goto failControlAlloc;
|
||||
|
||||
|
|
@ -229,8 +233,12 @@ void PoolFinish(Pool pool)
|
|||
/* Do any class-specific finishing. */
|
||||
(*pool->class->finish)(pool);
|
||||
|
||||
/* Detach the pool from the arena, and unsig it. */
|
||||
/* Detach the pool from the arena and format, and unsig it. */
|
||||
RingRemove(&pool->arenaRing);
|
||||
if (pool->format) {
|
||||
AVER(pool->format->poolCount > 0);
|
||||
-- pool->format->poolCount;
|
||||
}
|
||||
pool->sig = SigInvalid;
|
||||
|
||||
RingFinish(&pool->segRing);
|
||||
|
|
@ -274,17 +282,15 @@ BufferClass PoolDefaultBufferClass(Pool pool)
|
|||
|
||||
/* PoolAlloc -- allocate a block of memory from a pool */
|
||||
|
||||
Res PoolAlloc(Addr *pReturn, Pool pool, Size size,
|
||||
Bool withReservoirPermit)
|
||||
Res PoolAlloc(Addr *pReturn, Pool pool, Size size)
|
||||
{
|
||||
Res res;
|
||||
|
||||
AVER(pReturn != NULL);
|
||||
AVERT(Pool, pool);
|
||||
AVER(size > 0);
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
res = (*pool->class->alloc)(pReturn, pool, size, withReservoirPermit);
|
||||
res = (*pool->class->alloc)(pReturn, pool, size);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
/* Make sure that the allocated address was in the pool's memory. */
|
||||
|
|
|
|||
|
|
@ -196,24 +196,20 @@ Res PoolTrivInit(Pool pool, ArgList args)
|
|||
return ResOK;
|
||||
}
|
||||
|
||||
Res PoolNoAlloc(Addr *pReturn, Pool pool, Size size,
|
||||
Bool withReservoirPermit)
|
||||
Res PoolNoAlloc(Addr *pReturn, Pool pool, Size size)
|
||||
{
|
||||
AVER(pReturn != NULL);
|
||||
AVERT(Pool, pool);
|
||||
AVER(size > 0);
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
NOTREACHED;
|
||||
return ResUNIMPL;
|
||||
}
|
||||
|
||||
Res PoolTrivAlloc(Addr *pReturn, Pool pool, Size size,
|
||||
Bool withReservoirPermit)
|
||||
Res PoolTrivAlloc(Addr *pReturn, Pool pool, Size size)
|
||||
{
|
||||
AVER(pReturn != NULL);
|
||||
AVERT(Pool, pool);
|
||||
AVER(size > 0);
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
return ResLIMIT;
|
||||
}
|
||||
|
||||
|
|
@ -235,22 +231,19 @@ void PoolTrivFree(Pool pool, Addr old, Size size)
|
|||
|
||||
|
||||
Res PoolNoBufferFill(Addr *baseReturn, Addr *limitReturn,
|
||||
Pool pool, Buffer buffer, Size size,
|
||||
Bool withReservoirPermit)
|
||||
Pool pool, Buffer buffer, Size size)
|
||||
{
|
||||
AVER(baseReturn != NULL);
|
||||
AVER(limitReturn != NULL);
|
||||
AVERT(Pool, pool);
|
||||
AVERT(Buffer, buffer);
|
||||
AVER(size > 0);
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
NOTREACHED;
|
||||
return ResUNIMPL;
|
||||
}
|
||||
|
||||
Res PoolTrivBufferFill(Addr *baseReturn, Addr *limitReturn,
|
||||
Pool pool, Buffer buffer, Size size,
|
||||
Bool withReservoirPermit)
|
||||
Pool pool, Buffer buffer, Size size)
|
||||
{
|
||||
Res res;
|
||||
Addr p;
|
||||
|
|
@ -260,9 +253,8 @@ Res PoolTrivBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
AVERT(Pool, pool);
|
||||
AVERT(Buffer, buffer);
|
||||
AVER(size > 0);
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
res = PoolAlloc(&p, pool, size, withReservoirPermit);
|
||||
res = PoolAlloc(&p, pool, size);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
/* poolamc.c: AUTOMATIC MOSTLY-COPYING MEMORY POOL CLASS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (C) 2002 Global Graphics Software.
|
||||
*
|
||||
* .sources: <design/poolamc/>.
|
||||
*/
|
||||
|
||||
#include "mpscamc.h"
|
||||
#include "chain.h"
|
||||
#include "locus.h"
|
||||
#include "bt.h"
|
||||
#include "mpm.h"
|
||||
#include "nailboard.h"
|
||||
|
|
@ -123,8 +123,7 @@ static Bool amcSegCheck(amcSeg amcseg)
|
|||
ARG_DEFINE_KEY(amc_seg_gen, Pointer);
|
||||
#define amcKeySegGen (&_mps_key_amc_seg_gen)
|
||||
|
||||
static Res AMCSegInit(Seg seg, Pool pool, Addr base, Size size,
|
||||
Bool reservoirPermit, ArgList args)
|
||||
static Res AMCSegInit(Seg seg, Pool pool, Addr base, Size size, ArgList args)
|
||||
{
|
||||
amcGen amcgen;
|
||||
SegClass super;
|
||||
|
|
@ -138,11 +137,10 @@ static Res AMCSegInit(Seg seg, Pool pool, Addr base, Size size,
|
|||
AVERT(Seg, seg);
|
||||
amcseg = Seg2amcSeg(seg);
|
||||
/* no useful checks for base and size */
|
||||
AVERT(Bool, reservoirPermit);
|
||||
|
||||
/* Initialize the superclass fields first via next-method call */
|
||||
super = SEG_SUPERCLASS(amcSegClass);
|
||||
res = super->init(seg, pool, base, size, reservoirPermit, args);
|
||||
res = super->init(seg, pool, base, size, args);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
|
||||
|
|
@ -592,7 +590,7 @@ static Res amcGenCreate(amcGen *genReturn, AMC amc, GenDesc gen)
|
|||
pool = AMCPool(amc);
|
||||
arena = pool->arena;
|
||||
|
||||
res = ControlAlloc(&p, arena, sizeof(amcGenStruct), FALSE);
|
||||
res = ControlAlloc(&p, arena, sizeof(amcGenStruct));
|
||||
if(res != ResOK)
|
||||
goto failControlAlloc;
|
||||
amcgen = (amcGen)p;
|
||||
|
|
@ -807,7 +805,7 @@ static Res amcInitComm(Pool pool, RankSet rankSet, ArgList args)
|
|||
|
||||
/* One gen for each one in the chain plus dynamic gen. */
|
||||
genArraySize = sizeof(amcGen) * (genCount + 1);
|
||||
res = ControlAlloc(&p, arena, genArraySize, FALSE);
|
||||
res = ControlAlloc(&p, arena, genArraySize);
|
||||
if(res != ResOK)
|
||||
goto failGensAlloc;
|
||||
amc->gen = p;
|
||||
|
|
@ -916,8 +914,7 @@ static void AMCFinish(Pool pool)
|
|||
* See <design/poolamc/#fill>.
|
||||
*/
|
||||
static Res AMCBufferFill(Addr *baseReturn, Addr *limitReturn,
|
||||
Pool pool, Buffer buffer, Size size,
|
||||
Bool withReservoirPermit)
|
||||
Pool pool, Buffer buffer, Size size)
|
||||
{
|
||||
Seg seg;
|
||||
AMC amc;
|
||||
|
|
@ -938,7 +935,6 @@ static Res AMCBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
AVER(BufferIsReset(buffer));
|
||||
AVER(size > 0);
|
||||
AVER(SizeIsAligned(size, PoolAlignment(pool)));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
arena = PoolArena(pool);
|
||||
gen = amcBufGen(buffer);
|
||||
|
|
@ -957,8 +953,7 @@ static Res AMCBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
}
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD_FIELD(args, amcKeySegGen, p, gen);
|
||||
res = PoolGenAlloc(&seg, pgen, amcSegClassGet(), grainsSize,
|
||||
withReservoirPermit, args);
|
||||
res = PoolGenAlloc(&seg, pgen, amcSegClassGet(), grainsSize, args);
|
||||
} MPS_ARGS_END(args);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
|
|
@ -1247,9 +1242,12 @@ static Res AMCWhiten(Pool pool, Trace trace, Seg seg)
|
|||
|
||||
/* amcScanNailedRange -- make one scanning pass over a range of
|
||||
* addresses in a nailed segment.
|
||||
*
|
||||
* *totalReturn is set to FALSE if not all the objects between base and
|
||||
* limit have been scanned. It is not touched otherwise.
|
||||
*/
|
||||
static Res amcScanNailedRange(Bool *totalReturn, Bool *moreReturn,
|
||||
Size *bytesScanned, ScanState ss,
|
||||
ScanState ss,
|
||||
AMC amc, Nailboard board,
|
||||
Addr base, Addr limit)
|
||||
{
|
||||
|
|
@ -1265,14 +1263,12 @@ static Res amcScanNailedRange(Bool *totalReturn, Bool *moreReturn,
|
|||
Addr q;
|
||||
q = (*format->skip)(p);
|
||||
if ((*amc->pinned)(amc, board, p, q)) {
|
||||
Res res;
|
||||
res = (*format->scan)(&ss->ss_s, p, q);
|
||||
Res res = FormatScan(format, ss, p, q);
|
||||
if(res != ResOK) {
|
||||
*totalReturn = FALSE;
|
||||
*moreReturn = TRUE;
|
||||
return res;
|
||||
}
|
||||
*bytesScanned += AddrOffset(p, q);
|
||||
} else {
|
||||
*totalReturn = FALSE;
|
||||
}
|
||||
|
|
@ -1297,7 +1293,6 @@ static Res amcScanNailedOnce(Bool *totalReturn, Bool *moreReturn,
|
|||
ScanState ss, Seg seg, AMC amc)
|
||||
{
|
||||
Addr p, limit;
|
||||
Size bytesScanned = 0;
|
||||
Nailboard board;
|
||||
Res res;
|
||||
|
||||
|
|
@ -1314,7 +1309,7 @@ static Res amcScanNailedOnce(Bool *totalReturn, Bool *moreReturn,
|
|||
AVER(p == limit);
|
||||
goto returnGood;
|
||||
}
|
||||
res = amcScanNailedRange(totalReturn, moreReturn, &bytesScanned,
|
||||
res = amcScanNailedRange(totalReturn, moreReturn,
|
||||
ss, amc, board, p, limit);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
|
@ -1323,7 +1318,7 @@ static Res amcScanNailedOnce(Bool *totalReturn, Bool *moreReturn,
|
|||
|
||||
limit = SegLimit(seg);
|
||||
/* @@@@ Shouldn't p be set to BufferLimit here?! */
|
||||
res = amcScanNailedRange(totalReturn, moreReturn, &bytesScanned,
|
||||
res = amcScanNailedRange(totalReturn, moreReturn,
|
||||
ss, amc, board, p, limit);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
|
@ -1331,8 +1326,6 @@ static Res amcScanNailedOnce(Bool *totalReturn, Bool *moreReturn,
|
|||
returnGood:
|
||||
EVENT3(AMCScanEnd, amc, seg, ss); /* TODO: consider using own event */
|
||||
|
||||
AVER(bytesScanned <= SegSize(seg));
|
||||
ss->scannedSize += bytesScanned;
|
||||
*moreReturn = NailboardNewNails(board);
|
||||
return ResOK;
|
||||
}
|
||||
|
|
@ -1423,12 +1416,11 @@ static Res AMCScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg)
|
|||
*totalReturn = TRUE;
|
||||
return ResOK;
|
||||
}
|
||||
res = (*format->scan)(&ss->ss_s, base, limit);
|
||||
res = FormatScan(format, ss, base, limit);
|
||||
if(res != ResOK) {
|
||||
*totalReturn = FALSE;
|
||||
return res;
|
||||
}
|
||||
ss->scannedSize += AddrOffset(base, limit);
|
||||
base = limit;
|
||||
}
|
||||
|
||||
|
|
@ -1437,14 +1429,13 @@ static Res AMCScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg)
|
|||
AVER(SegBase(seg) <= base);
|
||||
AVER(base <= AddrAdd(SegLimit(seg), format->headerSize));
|
||||
if(base < limit) {
|
||||
res = (*format->scan)(&ss->ss_s, base, limit);
|
||||
res = FormatScan(format, ss, base, limit);
|
||||
if(res != ResOK) {
|
||||
*totalReturn = FALSE;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
ss->scannedSize += AddrOffset(base, limit);
|
||||
EVENT3(AMCScanEnd, amc, seg, ss);
|
||||
|
||||
*totalReturn = TRUE;
|
||||
|
|
@ -1646,7 +1637,7 @@ static Res AMCFix(Pool pool, ScanState ss, Seg seg, Ref *refIO)
|
|||
STATISTIC_STAT(++ss->forwardedCount);
|
||||
ss->forwardedSize += length;
|
||||
do {
|
||||
res = BUFFER_RESERVE(&newBase, buffer, length, FALSE);
|
||||
res = BUFFER_RESERVE(&newBase, buffer, length);
|
||||
if (res != ResOK)
|
||||
goto returnRes;
|
||||
newRef = AddrAdd(newBase, headerSize);
|
||||
|
|
@ -2258,7 +2249,7 @@ static Bool AMCCheck(AMC amc)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 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-2014 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
* Portions copyright (c) 2002 Global Graphics Software.
|
||||
*
|
||||
*
|
||||
|
|
@ -215,8 +215,7 @@ static void amsDestroyTables(AMS ams, BT allocTable,
|
|||
|
||||
/* AMSSegInit -- Init method for AMS segments */
|
||||
|
||||
static Res AMSSegInit(Seg seg, Pool pool, Addr base, Size size,
|
||||
Bool reservoirPermit, ArgList args)
|
||||
static Res AMSSegInit(Seg seg, Pool pool, Addr base, Size size, ArgList args)
|
||||
{
|
||||
SegClass super;
|
||||
AMSSeg amsseg;
|
||||
|
|
@ -231,11 +230,10 @@ static Res AMSSegInit(Seg seg, Pool pool, Addr base, Size size,
|
|||
AVERT(AMS, ams);
|
||||
arena = PoolArena(pool);
|
||||
/* no useful checks for base and size */
|
||||
AVERT(Bool, reservoirPermit);
|
||||
|
||||
/* Initialize the superclass fields first via next-method call */
|
||||
super = SEG_SUPERCLASS(AMSSegClass);
|
||||
res = super->init(seg, pool, base, size, reservoirPermit, args);
|
||||
res = super->init(seg, pool, base, size, args);
|
||||
if (res != ResOK)
|
||||
goto failNextMethod;
|
||||
|
||||
|
|
@ -328,8 +326,7 @@ static void AMSSegFinish(Seg seg)
|
|||
*/
|
||||
|
||||
static Res AMSSegMerge(Seg seg, Seg segHi,
|
||||
Addr base, Addr mid, Addr limit,
|
||||
Bool withReservoirPermit)
|
||||
Addr base, Addr mid, Addr limit)
|
||||
{
|
||||
SegClass super;
|
||||
Count loGrains, hiGrains, allGrains;
|
||||
|
|
@ -367,8 +364,7 @@ static Res AMSSegMerge(Seg seg, Seg segHi,
|
|||
|
||||
/* Merge the superclass fields via next-method call */
|
||||
super = SEG_SUPERCLASS(AMSSegClass);
|
||||
res = super->merge(seg, segHi, base, mid, limit,
|
||||
withReservoirPermit);
|
||||
res = super->merge(seg, segHi, base, mid, limit);
|
||||
if (res != ResOK)
|
||||
goto failSuper;
|
||||
|
||||
|
|
@ -414,8 +410,7 @@ static Res AMSSegMerge(Seg seg, Seg segHi,
|
|||
|
||||
|
||||
static Res AMSSegSplit(Seg seg, Seg segHi,
|
||||
Addr base, Addr mid, Addr limit,
|
||||
Bool withReservoirPermit)
|
||||
Addr base, Addr mid, Addr limit)
|
||||
{
|
||||
SegClass super;
|
||||
Count loGrains, hiGrains, allGrains;
|
||||
|
|
@ -462,7 +457,7 @@ static Res AMSSegSplit(Seg seg, Seg segHi,
|
|||
|
||||
/* Split the superclass fields via next-method call */
|
||||
super = SEG_SUPERCLASS(AMSSegClass);
|
||||
res = super->split(seg, segHi, base, mid, limit, withReservoirPermit);
|
||||
res = super->split(seg, segHi, base, mid, limit);
|
||||
if (res != ResOK)
|
||||
goto failSuper;
|
||||
|
||||
|
|
@ -682,7 +677,7 @@ static Res AMSSegSizePolicy(Size *sizeReturn,
|
|||
/* AMSSegCreate -- create a single AMSSeg */
|
||||
|
||||
static Res AMSSegCreate(Seg *segReturn, Pool pool, Size size,
|
||||
RankSet rankSet, Bool withReservoirPermit)
|
||||
RankSet rankSet)
|
||||
{
|
||||
Seg seg;
|
||||
AMS ams;
|
||||
|
|
@ -694,7 +689,6 @@ static Res AMSSegCreate(Seg *segReturn, Pool pool, Size size,
|
|||
AVERT(Pool, pool);
|
||||
AVER(size > 0);
|
||||
AVERT(RankSet, rankSet);
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
ams = PoolAMS(pool);
|
||||
AVERT(AMS,ams);
|
||||
|
|
@ -705,13 +699,13 @@ static Res AMSSegCreate(Seg *segReturn, Pool pool, Size size,
|
|||
goto failSize;
|
||||
|
||||
res = PoolGenAlloc(&seg, &ams->pgen, (*ams->segClass)(), prefSize,
|
||||
withReservoirPermit, argsNone);
|
||||
argsNone);
|
||||
if (res != ResOK) { /* try to allocate one that's just large enough */
|
||||
Size minSize = SizeArenaGrains(size, arena);
|
||||
if (minSize == prefSize)
|
||||
goto failSeg;
|
||||
res = PoolGenAlloc(&seg, &ams->pgen, (*ams->segClass)(), prefSize,
|
||||
withReservoirPermit, argsNone);
|
||||
argsNone);
|
||||
if (res != ResOK)
|
||||
goto failSeg;
|
||||
}
|
||||
|
|
@ -946,8 +940,7 @@ static Bool amsSegAlloc(Index *baseReturn, Index *limitReturn,
|
|||
* <design/poolams/#fill>.
|
||||
*/
|
||||
static Res AMSBufferFill(Addr *baseReturn, Addr *limitReturn,
|
||||
Pool pool, Buffer buffer, Size size,
|
||||
Bool withReservoirPermit)
|
||||
Pool pool, Buffer buffer, Size size)
|
||||
{
|
||||
Res res;
|
||||
AMS ams;
|
||||
|
|
@ -967,7 +960,6 @@ static Res AMSBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
AVERT(Buffer, buffer);
|
||||
AVER(size > 0);
|
||||
AVER(SizeIsAligned(size, PoolAlignment(pool)));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
/* Check that we're not in the grey mutator phase (see */
|
||||
/* <design/poolams/#fill.colour>). */
|
||||
|
|
@ -996,8 +988,7 @@ static Res AMSBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
}
|
||||
|
||||
/* No suitable segment found; make a new one. */
|
||||
res = AMSSegCreate(&seg, pool, size, rankSet,
|
||||
withReservoirPermit);
|
||||
res = AMSSegCreate(&seg, pool, size, rankSet);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
b = amsSegAlloc(&base, &limit, seg, size);
|
||||
|
|
@ -1179,9 +1170,13 @@ static Res AMSWhiten(Pool pool, Trace trace, Seg seg)
|
|||
amsseg->newGrains = uncondemned;
|
||||
amsseg->marksChanged = FALSE; /* <design/poolams/#marked.condemn> */
|
||||
amsseg->ambiguousFixes = FALSE;
|
||||
trace->condemned += AMSGrainsSize(ams, amsseg->oldGrains);
|
||||
|
||||
SegSetWhite(seg, TraceSetAdd(SegWhite(seg), trace));
|
||||
if (amsseg->oldGrains > 0) {
|
||||
trace->condemned += AMSGrainsSize(ams, amsseg->oldGrains);
|
||||
SegSetWhite(seg, TraceSetAdd(SegWhite(seg), trace));
|
||||
} else {
|
||||
amsseg->colourTablesInUse = FALSE;
|
||||
}
|
||||
|
||||
return ResOK;
|
||||
}
|
||||
|
|
@ -1318,12 +1313,12 @@ static Res amsScanObject(Seg seg, Index i, Addr p, Addr next, void *clos)
|
|||
|
||||
/* @@@@ This isn't quite right for multiple traces. */
|
||||
if (closure->scanAllObjects || AMS_IS_GREY(seg, i)) {
|
||||
res = (*format->scan)(&closure->ss->ss_s,
|
||||
AddrAdd(p, format->headerSize),
|
||||
AddrAdd(next, format->headerSize));
|
||||
res = FormatScan(format,
|
||||
closure->ss,
|
||||
AddrAdd(p, format->headerSize),
|
||||
AddrAdd(next, format->headerSize));
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
closure->ss->scannedSize += AddrOffset(p, next);
|
||||
if (!closure->scanAllObjects) {
|
||||
Index j = AMS_ADDR_INDEX(seg, next);
|
||||
AVER(!AMS_IS_INVALID_COLOUR(seg, i));
|
||||
|
|
@ -1412,7 +1407,7 @@ Res AMSScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg)
|
|||
next = AddrAdd(p, alignment);
|
||||
}
|
||||
j = AMS_ADDR_INDEX(seg, next);
|
||||
res = (*format->scan)(&ss->ss_s, clientP, clientNext);
|
||||
res = FormatScan(format, ss, clientP, clientNext);
|
||||
if (res != ResOK) {
|
||||
/* <design/poolams/#marked.scan.fail> */
|
||||
amsseg->marksChanged = TRUE;
|
||||
|
|
@ -1422,7 +1417,6 @@ Res AMSScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg)
|
|||
/* Check that there haven't been any ambiguous fixes during the */
|
||||
/* scan, because AMSFindGrey won't work otherwise. */
|
||||
AVER_CRITICAL(!amsseg->ambiguousFixes);
|
||||
ss->scannedSize += AddrOffset(p, next);
|
||||
AMS_GREY_BLACKEN(seg, i);
|
||||
if (i+1 < j)
|
||||
AMS_RANGE_WHITE_BLACKEN(seg, i+1, j);
|
||||
|
|
@ -1809,6 +1803,22 @@ DEFINE_POOL_CLASS(AMSDebugPoolClass, this)
|
|||
}
|
||||
|
||||
|
||||
/* mps_class_ams -- return the AMS pool class descriptor */
|
||||
|
||||
mps_pool_class_t mps_class_ams(void)
|
||||
{
|
||||
return (mps_pool_class_t)AMSPoolClassGet();
|
||||
}
|
||||
|
||||
|
||||
/* mps_class_ams_debug -- return the AMS (debug) pool class descriptor */
|
||||
|
||||
mps_pool_class_t mps_class_ams_debug(void)
|
||||
{
|
||||
return (mps_pool_class_t)AMSDebugPoolClassGet();
|
||||
}
|
||||
|
||||
|
||||
/* AMSCheck -- the check method for an AMS */
|
||||
|
||||
Bool AMSCheck(AMS ams)
|
||||
|
|
@ -1831,7 +1841,7 @@ Bool AMSCheck(AMS ams)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,69 +0,0 @@
|
|||
/* poolamsi.c: AUTOMATIC MARK & SWEEP POOL CLASS C INTERFACE
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*/
|
||||
|
||||
#include "mpscams.h"
|
||||
#include "mps.h"
|
||||
#include "poolams.h"
|
||||
|
||||
SRCID(poolamsi, "$Id$");
|
||||
|
||||
|
||||
/* mps_class_ams -- return the AMS pool class descriptor */
|
||||
|
||||
mps_pool_class_t mps_class_ams(void)
|
||||
{
|
||||
return (mps_pool_class_t)AMSPoolClassGet();
|
||||
}
|
||||
|
||||
|
||||
/* mps_class_ams_debug -- return the AMS (debug) pool class descriptor */
|
||||
|
||||
mps_pool_class_t mps_class_ams_debug(void)
|
||||
{
|
||||
return (mps_pool_class_t)AMSDebugPoolClassGet();
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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,7 +1,7 @@
|
|||
/* poolawl.c: AUTOMATIC WEAK LINKED POOL CLASS
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
*
|
||||
* DESIGN
|
||||
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
#include "mpscawl.h"
|
||||
#include "mpm.h"
|
||||
#include "chain.h"
|
||||
#include "locus.h"
|
||||
|
||||
SRCID(poolawl, "$Id$");
|
||||
|
||||
|
|
@ -172,8 +172,7 @@ static void awlStatTotalInit(AWL awl)
|
|||
ARG_DEFINE_KEY(awl_seg_rank_set, RankSet);
|
||||
#define awlKeySegRankSet (&_mps_key_awl_seg_rank_set)
|
||||
|
||||
static Res AWLSegInit(Seg seg, Pool pool, Addr base, Size size,
|
||||
Bool reservoirPermit, ArgList args)
|
||||
static Res AWLSegInit(Seg seg, Pool pool, Addr base, Size size, ArgList args)
|
||||
{
|
||||
SegClass super;
|
||||
AWLSeg awlseg;
|
||||
|
|
@ -191,7 +190,6 @@ static Res AWLSegInit(Seg seg, Pool pool, Addr base, Size size,
|
|||
AVERT(Pool, pool);
|
||||
arena = PoolArena(pool);
|
||||
/* no useful checks for base and size */
|
||||
AVERT(Bool, reservoirPermit);
|
||||
ArgRequire(&arg, args, awlKeySegRankSet);
|
||||
rankSet = arg.val.u;
|
||||
AVERT(RankSet, rankSet);
|
||||
|
|
@ -204,21 +202,21 @@ static Res AWLSegInit(Seg seg, Pool pool, Addr base, Size size,
|
|||
|
||||
/* Initialize the superclass fields first via next-method call */
|
||||
super = SEG_SUPERCLASS(AWLSegClass);
|
||||
res = super->init(seg, pool, base, size, reservoirPermit, args);
|
||||
res = super->init(seg, pool, base, size, args);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
bits = size >> awl->alignShift;
|
||||
tableSize = BTSize(bits);
|
||||
res = ControlAlloc(&v, arena, tableSize, reservoirPermit);
|
||||
res = ControlAlloc(&v, arena, tableSize);
|
||||
if (res != ResOK)
|
||||
goto failControlAllocMark;
|
||||
awlseg->mark = v;
|
||||
res = ControlAlloc(&v, arena, tableSize, reservoirPermit);
|
||||
res = ControlAlloc(&v, arena, tableSize);
|
||||
if (res != ResOK)
|
||||
goto failControlAllocScanned;
|
||||
awlseg->scanned = v;
|
||||
res = ControlAlloc(&v, arena, tableSize, reservoirPermit);
|
||||
res = ControlAlloc(&v, arena, tableSize);
|
||||
if (res != ResOK)
|
||||
goto failControlAllocAlloc;
|
||||
awlseg->alloc = v;
|
||||
|
|
@ -451,8 +449,7 @@ static void AWLNoteScan(AWL awl, Seg seg, ScanState ss)
|
|||
/* AWLSegCreate -- Create a new segment of at least given size */
|
||||
|
||||
static Res AWLSegCreate(AWLSeg *awlsegReturn,
|
||||
RankSet rankSet, Pool pool, Size size,
|
||||
Bool reservoirPermit)
|
||||
RankSet rankSet, Pool pool, Size size)
|
||||
{
|
||||
AWL awl;
|
||||
Seg seg;
|
||||
|
|
@ -464,7 +461,6 @@ static Res AWLSegCreate(AWLSeg *awlsegReturn,
|
|||
AVERT(RankSet, rankSet);
|
||||
AVERT(Pool, pool);
|
||||
AVER(size > 0);
|
||||
AVERT(Bool, reservoirPermit);
|
||||
|
||||
awl = PoolAWL(pool);
|
||||
AVERT(AWL, awl);
|
||||
|
|
@ -478,8 +474,7 @@ static Res AWLSegCreate(AWLSeg *awlsegReturn,
|
|||
return ResMEMORY;
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD_FIELD(args, awlKeySegRankSet, u, rankSet);
|
||||
res = PoolGenAlloc(&seg, &awl->pgen, AWLSegClassGet(), size,
|
||||
reservoirPermit, args);
|
||||
res = PoolGenAlloc(&seg, &awl->pgen, AWLSegClassGet(), size, args);
|
||||
} MPS_ARGS_END(args);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
|
@ -636,8 +631,7 @@ static void AWLFinish(Pool pool)
|
|||
/* AWLBufferFill -- BufferFill method for AWL */
|
||||
|
||||
static Res AWLBufferFill(Addr *baseReturn, Addr *limitReturn,
|
||||
Pool pool, Buffer buffer, Size size,
|
||||
Bool reservoirPermit)
|
||||
Pool pool, Buffer buffer, Size size)
|
||||
{
|
||||
Addr base, limit;
|
||||
AWLSeg awlseg;
|
||||
|
|
@ -650,7 +644,6 @@ static Res AWLBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
AVERT(Pool, pool);
|
||||
AVERT(Buffer, buffer);
|
||||
AVER(size > 0);
|
||||
AVERT(Bool, reservoirPermit);
|
||||
|
||||
awl = PoolAWL(pool);
|
||||
AVERT(AWL, awl);
|
||||
|
|
@ -674,8 +667,7 @@ static Res AWLBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
|
||||
/* No free space in existing awlsegs, so create new awlseg */
|
||||
|
||||
res = AWLSegCreate(&awlseg, BufferRankSet(buffer), pool, size,
|
||||
reservoirPermit);
|
||||
res = AWLSegCreate(&awlseg, BufferRankSet(buffer), pool, size);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
base = SegBase(AWLSeg2Seg(awlseg));
|
||||
|
|
@ -799,8 +791,12 @@ static Res AWLWhiten(Pool pool, Trace trace, Seg seg)
|
|||
PoolGenAccountForAge(&awl->pgen, AWLGrainsSize(awl, awlseg->newGrains - uncondemned), FALSE);
|
||||
awlseg->oldGrains += awlseg->newGrains - uncondemned;
|
||||
awlseg->newGrains = uncondemned;
|
||||
trace->condemned += AWLGrainsSize(awl, awlseg->oldGrains);
|
||||
SegSetWhite(seg, TraceSetAdd(SegWhite(seg), trace));
|
||||
|
||||
if (awlseg->oldGrains > 0) {
|
||||
trace->condemned += AWLGrainsSize(awl, awlseg->oldGrains);
|
||||
SegSetWhite(seg, TraceSetAdd(SegWhite(seg), trace));
|
||||
}
|
||||
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
|
@ -901,9 +897,7 @@ static Res awlScanObject(Arena arena, AWL awl, ScanState ss,
|
|||
SegSetSummary(dependentSeg, RefSetUNIV);
|
||||
}
|
||||
|
||||
res = (*format->scan)(&ss->ss_s, base, limit);
|
||||
if (res == ResOK)
|
||||
ss->scannedSize += AddrOffset(base, limit);
|
||||
res = FormatScan(format, ss, base, limit);
|
||||
|
||||
if (dependent)
|
||||
ShieldCover(arena, dependentSeg);
|
||||
|
|
@ -1376,7 +1370,7 @@ static Bool AWLCheck(AWL awl)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2015 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -59,8 +59,7 @@ typedef struct LOSegStruct {
|
|||
|
||||
|
||||
/* forward decls */
|
||||
static Res loSegInit(Seg seg, Pool pool, Addr base, Size size,
|
||||
Bool reservoirPermit, ArgList args);
|
||||
static Res loSegInit(Seg seg, Pool pool, Addr base, Size size, ArgList args);
|
||||
static void loSegFinish(Seg seg);
|
||||
static Count loSegGrains(LOSeg loseg);
|
||||
|
||||
|
|
@ -98,8 +97,7 @@ static Bool LOSegCheck(LOSeg loseg)
|
|||
|
||||
/* loSegInit -- Init method for LO segments */
|
||||
|
||||
static Res loSegInit(Seg seg, Pool pool, Addr base, Size size,
|
||||
Bool reservoirPermit, ArgList args)
|
||||
static Res loSegInit(Seg seg, Pool pool, Addr base, Size size, ArgList args)
|
||||
{
|
||||
SegClass super;
|
||||
LOSeg loseg;
|
||||
|
|
@ -116,13 +114,12 @@ static Res loSegInit(Seg seg, Pool pool, Addr base, Size size,
|
|||
AVERT(Pool, pool);
|
||||
arena = PoolArena(pool);
|
||||
/* no useful checks for base and size */
|
||||
AVERT(Bool, reservoirPermit);
|
||||
lo = PoolPoolLO(pool);
|
||||
AVERT(LO, lo);
|
||||
|
||||
/* Initialize the superclass fields first via next-method call */
|
||||
super = SEG_SUPERCLASS(LOSegClass);
|
||||
res = super->init(seg, pool, base, size, reservoirPermit, args);
|
||||
res = super->init(seg, pool, base, size, args);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
|
||||
|
|
@ -130,11 +127,11 @@ static Res loSegInit(Seg seg, Pool pool, Addr base, Size size,
|
|||
|
||||
grains = size >> lo->alignShift;
|
||||
tablebytes = BTSize(grains);
|
||||
res = ControlAlloc(&p, arena, tablebytes, reservoirPermit);
|
||||
res = ControlAlloc(&p, arena, tablebytes);
|
||||
if(res != ResOK)
|
||||
goto failMarkTable;
|
||||
loseg->mark = p;
|
||||
res = ControlAlloc(&p, arena, tablebytes, reservoirPermit);
|
||||
res = ControlAlloc(&p, arena, tablebytes);
|
||||
if(res != ResOK)
|
||||
goto failAllocTable;
|
||||
loseg->alloc = p;
|
||||
|
|
@ -280,8 +277,7 @@ static Bool loSegFindFree(Addr *bReturn, Addr *lReturn,
|
|||
* Segments will be multiples of ArenaGrainSize.
|
||||
*/
|
||||
|
||||
static Res loSegCreate(LOSeg *loSegReturn, Pool pool, Size size,
|
||||
Bool withReservoirPermit)
|
||||
static Res loSegCreate(LOSeg *loSegReturn, Pool pool, Size size)
|
||||
{
|
||||
LO lo;
|
||||
Seg seg;
|
||||
|
|
@ -290,13 +286,12 @@ static Res loSegCreate(LOSeg *loSegReturn, Pool pool, Size size,
|
|||
AVER(loSegReturn != NULL);
|
||||
AVERT(Pool, pool);
|
||||
AVER(size > 0);
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
lo = PoolPoolLO(pool);
|
||||
AVERT(LO, lo);
|
||||
|
||||
res = PoolGenAlloc(&seg, &lo->pgen, EnsureLOSegClass(),
|
||||
SizeArenaGrains(size, PoolArena(pool)),
|
||||
withReservoirPermit, argsNone);
|
||||
argsNone);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
|
|
@ -556,7 +551,7 @@ static void LOFinish(Pool pool)
|
|||
|
||||
static Res LOBufferFill(Addr *baseReturn, Addr *limitReturn,
|
||||
Pool pool, Buffer buffer,
|
||||
Size size, Bool withReservoirPermit)
|
||||
Size size)
|
||||
{
|
||||
Res res;
|
||||
Ring node, nextNode;
|
||||
|
|
@ -574,7 +569,6 @@ static Res LOBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
AVER(BufferRankSet(buffer) == RankSetEMPTY);
|
||||
AVER(size > 0);
|
||||
AVER(SizeIsAligned(size, PoolAlignment(pool)));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
/* Try to find a segment with enough space already. */
|
||||
RING_FOR(node, &pool->segRing, nextNode) {
|
||||
|
|
@ -587,7 +581,7 @@ static Res LOBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
}
|
||||
|
||||
/* No segment had enough space, so make a new one. */
|
||||
res = loSegCreate(&loseg, pool, size, withReservoirPermit);
|
||||
res = loSegCreate(&loseg, pool, size);
|
||||
if(res != ResOK) {
|
||||
goto failCreate;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ static Res MFSInit(Pool pool, ArgList args)
|
|||
|
||||
|
||||
void MFSFinishTracts(Pool pool, MFSTractVisitor visitor,
|
||||
void *closureP, Size closureS)
|
||||
void *closure)
|
||||
{
|
||||
MFS mfs;
|
||||
|
||||
|
|
@ -136,19 +136,17 @@ void MFSFinishTracts(Pool pool, MFSTractVisitor visitor,
|
|||
|
||||
while (mfs->tractList != NULL) {
|
||||
Tract nextTract = (Tract)TractP(mfs->tractList); /* .tract.chain */
|
||||
visitor(pool, TractBase(mfs->tractList), mfs->extendBy, closureP, closureS);
|
||||
visitor(pool, TractBase(mfs->tractList), mfs->extendBy, closure);
|
||||
mfs->tractList = nextTract;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void MFSTractFreeVisitor(Pool pool, Addr base, Size size,
|
||||
void *closureP, Size closureS)
|
||||
void *closure)
|
||||
{
|
||||
AVER(closureP == UNUSED_POINTER);
|
||||
AVER(closureS == UNUSED_SIZE);
|
||||
UNUSED(closureP);
|
||||
UNUSED(closureS);
|
||||
AVER(closure == UNUSED_POINTER);
|
||||
UNUSED(closure);
|
||||
ArenaFree(base, size, pool);
|
||||
}
|
||||
|
||||
|
|
@ -161,7 +159,7 @@ static void MFSFinish(Pool pool)
|
|||
mfs = PoolPoolMFS(pool);
|
||||
AVERT(MFS, mfs);
|
||||
|
||||
MFSFinishTracts(pool, MFSTractFreeVisitor, UNUSED_POINTER, UNUSED_SIZE);
|
||||
MFSFinishTracts(pool, MFSTractFreeVisitor, UNUSED_POINTER);
|
||||
|
||||
mfs->sig = SigInvalid;
|
||||
}
|
||||
|
|
@ -227,8 +225,7 @@ void MFSExtend(Pool pool, Addr base, Size size)
|
|||
* arena.
|
||||
*/
|
||||
|
||||
static Res MFSAlloc(Addr *pReturn, Pool pool, Size size,
|
||||
Bool withReservoirPermit)
|
||||
static Res MFSAlloc(Addr *pReturn, Pool pool, Size size)
|
||||
{
|
||||
Header f;
|
||||
Res res;
|
||||
|
|
@ -240,7 +237,6 @@ static Res MFSAlloc(Addr *pReturn, Pool pool, Size size,
|
|||
|
||||
AVER(pReturn != NULL);
|
||||
AVER(size == mfs->unroundedUnitSize);
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
f = mfs->freeList;
|
||||
|
||||
|
|
@ -249,13 +245,13 @@ static Res MFSAlloc(Addr *pReturn, Pool pool, Size size,
|
|||
if(f == NULL)
|
||||
{
|
||||
Addr base;
|
||||
|
||||
|
||||
/* See design.mps.bootstrap.land.sol.pool. */
|
||||
if (!mfs->extendSelf)
|
||||
return ResLIMIT;
|
||||
|
||||
/* Create a new region and attach it to the pool. */
|
||||
res = ArenaAlloc(&base, LocusPrefDefault(), mfs->extendBy, pool,
|
||||
withReservoirPermit);
|
||||
res = ArenaAlloc(&base, LocusPrefDefault(), mfs->extendBy, pool);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
|
||||
|
|
|
|||
|
|
@ -46,9 +46,9 @@ extern const struct mps_key_s _mps_key_MFSExtendSelf;
|
|||
extern void MFSExtend(Pool pool, Addr base, Size size);
|
||||
|
||||
typedef void MFSTractVisitor(Pool pool, Addr base, Size size,
|
||||
void *closureP, Size closureS);
|
||||
void *closure);
|
||||
extern void MFSFinishTracts(Pool pool, MFSTractVisitor visitor,
|
||||
void *closureP, Size closureS);
|
||||
void *closure);
|
||||
|
||||
#endif /* poolmfs_h */
|
||||
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ static Bool MRGRefSegCheck(MRGRefSeg refseg)
|
|||
/* MRGLinkSegInit -- initialise a link segment */
|
||||
|
||||
static Res MRGLinkSegInit(Seg seg, Pool pool, Addr base, Size size,
|
||||
Bool reservoirPermit, ArgList args)
|
||||
ArgList args)
|
||||
{
|
||||
SegClass super;
|
||||
MRGLinkSeg linkseg;
|
||||
|
|
@ -228,11 +228,10 @@ static Res MRGLinkSegInit(Seg seg, Pool pool, Addr base, Size size,
|
|||
mrg = PoolMRG(pool);
|
||||
AVERT(MRG, mrg);
|
||||
/* no useful checks for base and size */
|
||||
AVERT(Bool, reservoirPermit);
|
||||
|
||||
/* Initialize the superclass fields first via next-method call */
|
||||
super = SEG_SUPERCLASS(MRGLinkSegClass);
|
||||
res = super->init(seg, pool, base, size, reservoirPermit, args);
|
||||
res = super->init(seg, pool, base, size, args);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
linkseg->refSeg = NULL; /* .link.nullref */
|
||||
|
|
@ -248,8 +247,7 @@ static Res MRGLinkSegInit(Seg seg, Pool pool, Addr base, Size size,
|
|||
ARG_DEFINE_KEY(mrg_seg_link_seg, Pointer);
|
||||
#define mrgKeyLinkSeg (&_mps_key_mrg_seg_link_seg)
|
||||
|
||||
static Res MRGRefSegInit(Seg seg, Pool pool, Addr base, Size size,
|
||||
Bool reservoirPermit, ArgList args)
|
||||
static Res MRGRefSegInit(Seg seg, Pool pool, Addr base, Size size, ArgList args)
|
||||
{
|
||||
MRGLinkSeg linkseg;
|
||||
MRGRefSeg refseg;
|
||||
|
|
@ -271,12 +269,11 @@ static Res MRGRefSegInit(Seg seg, Pool pool, Addr base, Size size,
|
|||
mrg = PoolMRG(pool);
|
||||
AVERT(MRG, mrg);
|
||||
/* no useful checks for base and size */
|
||||
AVERT(Bool, reservoirPermit);
|
||||
AVERT(MRGLinkSeg, linkseg);
|
||||
|
||||
/* Initialize the superclass fields first via next-method call */
|
||||
super = SEG_SUPERCLASS(MRGRefSegClass);
|
||||
res = super->init(seg, pool, base, size, reservoirPermit, args);
|
||||
res = super->init(seg, pool, base, size, args);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
|
|
@ -499,8 +496,7 @@ static void MRGSegPairDestroy(MRGRefSeg refseg)
|
|||
|
||||
/* MRGSegPairCreate -- create a pair of segments (link & ref) */
|
||||
|
||||
static Res MRGSegPairCreate(MRGRefSeg *refSegReturn, MRG mrg,
|
||||
Bool withReservoirPermit)
|
||||
static Res MRGSegPairCreate(MRGRefSeg *refSegReturn, MRG mrg)
|
||||
{
|
||||
RefPart refPartBase;
|
||||
Count nGuardians; /* guardians per seg */
|
||||
|
|
@ -525,7 +521,7 @@ static Res MRGSegPairCreate(MRGRefSeg *refSegReturn, MRG mrg,
|
|||
|
||||
res = SegAlloc(&segLink, EnsureMRGLinkSegClass(),
|
||||
LocusPrefDefault(), linkSegSize, pool,
|
||||
withReservoirPermit, argsNone);
|
||||
argsNone);
|
||||
if (res != ResOK)
|
||||
goto failLinkSegAlloc;
|
||||
linkseg = Seg2LinkSeg(segLink);
|
||||
|
|
@ -534,7 +530,7 @@ static Res MRGSegPairCreate(MRGRefSeg *refSegReturn, MRG mrg,
|
|||
MPS_ARGS_ADD_FIELD(args, mrgKeyLinkSeg, p, linkseg); /* .ref.initarg */
|
||||
res = SegAlloc(&segRefPart, EnsureMRGRefSegClass(),
|
||||
LocusPrefDefault(), mrg->extendBy, pool,
|
||||
withReservoirPermit, args);
|
||||
args);
|
||||
} MPS_ARGS_END(args);
|
||||
if (res != ResOK)
|
||||
goto failRefPartSegAlloc;
|
||||
|
|
@ -620,6 +616,7 @@ static Res MRGRefSegScan(ScanState ss, MRGRefSeg refseg, MRG mrg)
|
|||
MRGFinalize(arena, linkseg, i);
|
||||
}
|
||||
}
|
||||
ss->scannedSize += sizeof *refPart;
|
||||
}
|
||||
}
|
||||
} TRACE_SCAN_END(ss);
|
||||
|
|
@ -722,8 +719,7 @@ Res MRGRegister(Pool pool, Ref ref)
|
|||
|
||||
/* <design/poolmrg/#alloc.grow> */
|
||||
if (RingIsSingle(&mrg->freeRing)) {
|
||||
/* @@@@ Should the client be able to use the reservoir for this? */
|
||||
res = MRGSegPairCreate(&junk, mrg, /* withReservoirPermit */ FALSE);
|
||||
res = MRGSegPairCreate(&junk, mrg);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
}
|
||||
|
|
@ -745,7 +741,12 @@ Res MRGRegister(Pool pool, Ref ref)
|
|||
}
|
||||
|
||||
|
||||
/* MRGDeregister -- deregister (once) an object for finalization */
|
||||
/* MRGDeregister -- deregister (once) an object for finalization
|
||||
*
|
||||
* TODO: Definalization loops over all finalizable objects in the heap,
|
||||
* and so using it could accidentally be disastrous for performance.
|
||||
* See job003953 and back out changelist 187123 if this is fixed.
|
||||
*/
|
||||
|
||||
Res MRGDeregister(Pool pool, Ref obj)
|
||||
{
|
||||
|
|
@ -820,7 +821,7 @@ static Res MRGDescribe(Pool pool, mps_lib_FILE *stream, Count depth)
|
|||
if (res != ResOK)
|
||||
return res;
|
||||
RING_FOR(node, &mrg->entryRing, nextNode) {
|
||||
Bool outsideShield = !arena->insideShield;
|
||||
Bool outsideShield = !ArenaShield(arena)->inside;
|
||||
refPart = MRGRefPartOfLink(linkOfRing(node), arena);
|
||||
if (outsideShield) {
|
||||
ShieldEnter(arena);
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "dbgpool.h"
|
||||
#include "poolmv.h"
|
||||
#include "poolmfs.h"
|
||||
#include "mpscmvff.h"
|
||||
#include "mpm.h"
|
||||
|
||||
SRCID(poolmv, "$Id$");
|
||||
|
|
@ -236,7 +237,10 @@ static Res MVInit(Pool pool, ArgList args)
|
|||
if (ArgPick(&arg, args, MPS_KEY_MAX_SIZE))
|
||||
maxSize = arg.val.size;
|
||||
|
||||
arena = PoolArena(pool);
|
||||
|
||||
AVERT(Align, align);
|
||||
AVER(align <= ArenaGrainSize(arena));
|
||||
AVER(extendBy > 0);
|
||||
AVER(avgSize > 0);
|
||||
AVER(avgSize <= extendBy);
|
||||
|
|
@ -245,7 +249,6 @@ static Res MVInit(Pool pool, ArgList args)
|
|||
|
||||
pool->alignment = align;
|
||||
mv = PoolMV(pool);
|
||||
arena = PoolArena(pool);
|
||||
|
||||
/* At 100% fragmentation we will need one block descriptor for every other */
|
||||
/* allocated block, or (extendBy/avgSize)/2 descriptors. See note 1. */
|
||||
|
|
@ -458,8 +461,7 @@ static Res MVSpanFree(MVSpan span, Addr base, Addr limit, Pool blockPool)
|
|||
|
||||
/* The freed area is buried in the middle of the block, so the */
|
||||
/* block must be split into two parts. */
|
||||
res = PoolAlloc(&addr, blockPool, sizeof(MVBlockStruct),
|
||||
/* withReservoirPermit */ FALSE);
|
||||
res = PoolAlloc(&addr, blockPool, sizeof(MVBlockStruct));
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
new = (MVBlock)addr;
|
||||
|
|
@ -513,8 +515,7 @@ static Res MVSpanFree(MVSpan span, Addr base, Addr limit, Pool blockPool)
|
|||
|
||||
/* MVAlloc -- allocate method for class MV */
|
||||
|
||||
static Res MVAlloc(Addr *pReturn, Pool pool, Size size,
|
||||
Bool withReservoirPermit)
|
||||
static Res MVAlloc(Addr *pReturn, Pool pool, Size size)
|
||||
{
|
||||
Res res;
|
||||
MVSpan span;
|
||||
|
|
@ -530,7 +531,6 @@ static Res MVAlloc(Addr *pReturn, Pool pool, Size size,
|
|||
mv = PoolMV(pool);
|
||||
AVERT(MV, mv);
|
||||
AVER(size > 0);
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
size = SizeAlignUp(size, pool->alignment);
|
||||
|
||||
|
|
@ -556,8 +556,7 @@ static Res MVAlloc(Addr *pReturn, Pool pool, Size size,
|
|||
/* pool with a new region which will hold the requested allocation. */
|
||||
/* Allocate a new span descriptor and initialize it to point at the */
|
||||
/* region. */
|
||||
res = PoolAlloc(&addr, mvSpanPool(mv), sizeof(MVSpanStruct),
|
||||
withReservoirPermit);
|
||||
res = PoolAlloc(&addr, mvSpanPool(mv), sizeof(MVSpanStruct));
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
span = (MVSpan)addr;
|
||||
|
|
@ -570,12 +569,10 @@ static Res MVAlloc(Addr *pReturn, Pool pool, Size size,
|
|||
arena = PoolArena(pool);
|
||||
regionSize = SizeArenaGrains(regionSize, arena);
|
||||
|
||||
res = ArenaAlloc(&base, LocusPrefDefault(), regionSize, pool,
|
||||
withReservoirPermit);
|
||||
res = ArenaAlloc(&base, LocusPrefDefault(), regionSize, pool);
|
||||
if(res != ResOK) { /* try again with a region big enough for this object */
|
||||
regionSize = SizeArenaGrains(size, arena);
|
||||
res = ArenaAlloc(&base, LocusPrefDefault(), regionSize, pool,
|
||||
withReservoirPermit);
|
||||
res = ArenaAlloc(&base, LocusPrefDefault(), regionSize, pool);
|
||||
if (res != ResOK) {
|
||||
PoolFree(mvSpanPool(mv), (Addr)span, sizeof(MVSpanStruct));
|
||||
return res;
|
||||
|
|
|
|||
|
|
@ -35,15 +35,13 @@ static Res MVTInit(Pool pool, ArgList arg);
|
|||
static Bool MVTCheck(MVT mvt);
|
||||
static void MVTFinish(Pool pool);
|
||||
static Res MVTBufferFill(Addr *baseReturn, Addr *limitReturn,
|
||||
Pool pool, Buffer buffer, Size minSize,
|
||||
Bool withReservoirPermit);
|
||||
Pool pool, Buffer buffer, Size minSize);
|
||||
static void MVTBufferEmpty(Pool pool, Buffer buffer, Addr base, Addr limit);
|
||||
static void MVTFree(Pool pool, Addr base, Size size);
|
||||
static Res MVTDescribe(Pool pool, mps_lib_FILE *stream, Count depth);
|
||||
static Size MVTTotalSize(Pool pool);
|
||||
static Size MVTFreeSize(Pool pool);
|
||||
static Res MVTSegAlloc(Seg *segReturn, MVT mvt, Size size,
|
||||
Bool withReservoirPermit);
|
||||
static Res MVTSegAlloc(Seg *segReturn, MVT mvt, Size size);
|
||||
|
||||
static void MVTSegFree(MVT mvt, Seg seg);
|
||||
static Bool MVTReturnSegs(MVT mvt, Range range, Arena arena);
|
||||
|
|
@ -261,10 +259,10 @@ static Res MVTInit(Pool pool, ArgList args)
|
|||
|
||||
AVERT(Align, align);
|
||||
/* This restriction on the alignment is necessary because of the use
|
||||
* of a Freelist to store the free address ranges in low-memory
|
||||
* situations. See <design/freelist/#impl.grain.align>.
|
||||
*/
|
||||
of a Freelist to store the free address ranges in low-memory
|
||||
situations. See <design/freelist/#impl.grain.align>. */
|
||||
AVER(AlignIsAligned(align, FreelistMinimumAlignment));
|
||||
AVER(align <= ArenaGrainSize(arena));
|
||||
AVER(0 < minSize);
|
||||
AVER(minSize <= meanSize);
|
||||
AVER(meanSize <= maxSize);
|
||||
|
|
@ -491,8 +489,7 @@ static void MVTNoteFill(MVT mvt, Addr base, Addr limit, Size minSize) {
|
|||
static Res MVTOversizeFill(Addr *baseReturn,
|
||||
Addr *limitReturn,
|
||||
MVT mvt,
|
||||
Size minSize,
|
||||
Bool withReservoirPermit)
|
||||
Size minSize)
|
||||
{
|
||||
Res res;
|
||||
Seg seg;
|
||||
|
|
@ -501,7 +498,7 @@ static Res MVTOversizeFill(Addr *baseReturn,
|
|||
|
||||
alignedSize = SizeArenaGrains(minSize, PoolArena(MVTPool(mvt)));
|
||||
|
||||
res = MVTSegAlloc(&seg, mvt, alignedSize, withReservoirPermit);
|
||||
res = MVTSegAlloc(&seg, mvt, alignedSize);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
|
|
@ -660,14 +657,13 @@ static Bool MVTContingencyFill(Addr *baseReturn, Addr *limitReturn,
|
|||
|
||||
static Res MVTSegFill(Addr *baseReturn, Addr *limitReturn,
|
||||
MVT mvt, Size fillSize,
|
||||
Size minSize,
|
||||
Bool withReservoirPermit)
|
||||
Size minSize)
|
||||
{
|
||||
Res res;
|
||||
Seg seg;
|
||||
Addr base, limit;
|
||||
|
||||
res = MVTSegAlloc(&seg, mvt, fillSize, withReservoirPermit);
|
||||
res = MVTSegAlloc(&seg, mvt, fillSize);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
|
|
@ -686,8 +682,7 @@ static Res MVTSegFill(Addr *baseReturn, Addr *limitReturn,
|
|||
* See <design/poolmvt/#impl.c.ap.fill>
|
||||
*/
|
||||
static Res MVTBufferFill(Addr *baseReturn, Addr *limitReturn,
|
||||
Pool pool, Buffer buffer, Size minSize,
|
||||
Bool withReservoirPermit)
|
||||
Pool pool, Buffer buffer, Size minSize)
|
||||
{
|
||||
MVT mvt;
|
||||
Res res;
|
||||
|
|
@ -701,13 +696,12 @@ static Res MVTBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
AVER(BufferIsReset(buffer));
|
||||
AVER(minSize > 0);
|
||||
AVER(SizeIsAligned(minSize, pool->alignment));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
/* 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);
|
||||
minSize);
|
||||
}
|
||||
|
||||
/* Use any splinter, if available.
|
||||
|
|
@ -732,7 +726,7 @@ static Res MVTBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
/* Attempt to request a block from the arena.
|
||||
<design/poolmvt/#impl.c.free.merge.segment> */
|
||||
res = MVTSegFill(baseReturn, limitReturn,
|
||||
mvt, mvt->fillSize, minSize, withReservoirPermit);
|
||||
mvt, mvt->fillSize, minSize);
|
||||
if (res == ResOK)
|
||||
return ResOK;
|
||||
|
||||
|
|
@ -751,23 +745,21 @@ static Res MVTBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
|
||||
|
||||
/* MVTDeleteOverlapping -- ABQIterate callback used by MVTInsert and
|
||||
* MVTDelete. It receives a Range in its closureP argument, and sets
|
||||
* MVTDelete. It receives a Range in its closure argument, and sets
|
||||
* *deleteReturn to TRUE for ranges in the ABQ that overlap with it,
|
||||
* and FALSE for ranges that do not.
|
||||
*/
|
||||
static Bool MVTDeleteOverlapping(Bool *deleteReturn, void *element,
|
||||
void *closureP, Size closureS)
|
||||
void *closure)
|
||||
{
|
||||
Range oldRange, newRange;
|
||||
|
||||
AVER(deleteReturn != NULL);
|
||||
AVER(element != NULL);
|
||||
AVER(closureP != NULL);
|
||||
AVER(closureS == UNUSED_SIZE);
|
||||
UNUSED(closureS);
|
||||
AVER(closure != NULL);
|
||||
|
||||
oldRange = element;
|
||||
newRange = closureP;
|
||||
newRange = closure;
|
||||
|
||||
*deleteReturn = RangesOverlap(oldRange, newRange);
|
||||
return TRUE;
|
||||
|
|
@ -830,7 +822,7 @@ static Res MVTInsert(MVT mvt, Addr base, Addr limit)
|
|||
* with ranges on the ABQ, so ensure that the corresponding ranges
|
||||
* are coalesced on the ABQ.
|
||||
*/
|
||||
ABQIterate(MVTABQ(mvt), MVTDeleteOverlapping, &newRange, UNUSED_SIZE);
|
||||
ABQIterate(MVTABQ(mvt), MVTDeleteOverlapping, &newRange);
|
||||
(void)MVTReserve(mvt, &newRange);
|
||||
}
|
||||
|
||||
|
|
@ -859,7 +851,7 @@ static Res MVTDelete(MVT mvt, Addr base, Addr limit)
|
|||
* might be on the ABQ, so ensure it is removed.
|
||||
*/
|
||||
if (RangeSize(&rangeOld) >= mvt->reuseSize)
|
||||
ABQIterate(MVTABQ(mvt), MVTDeleteOverlapping, &rangeOld, UNUSED_SIZE);
|
||||
ABQIterate(MVTABQ(mvt), MVTDeleteOverlapping, &rangeOld);
|
||||
|
||||
/* There might be fragments at the left or the right of the deleted
|
||||
* range, and either might be big enough to go back on the ABQ.
|
||||
|
|
@ -1135,11 +1127,10 @@ mps_pool_class_t mps_class_mvt(void)
|
|||
/* MVTSegAlloc -- encapsulates SegAlloc with associated accounting and
|
||||
* metering
|
||||
*/
|
||||
static Res MVTSegAlloc(Seg *segReturn, MVT mvt, Size size,
|
||||
Bool withReservoirPermit)
|
||||
static Res MVTSegAlloc(Seg *segReturn, MVT mvt, Size size)
|
||||
{
|
||||
Res res = SegAlloc(segReturn, SegClassGet(), LocusPrefDefault(), size,
|
||||
MVTPool(mvt), withReservoirPermit, argsNone);
|
||||
MVTPool(mvt), argsNone);
|
||||
|
||||
if (res == ResOK) {
|
||||
Size segSize = SegSize(*segReturn);
|
||||
|
|
@ -1210,15 +1201,13 @@ static Bool MVTReturnSegs(MVT mvt, Range range, Arena arena)
|
|||
*/
|
||||
|
||||
static Bool MVTRefillVisitor(Land land, Range range,
|
||||
void *closureP, Size closureS)
|
||||
void *closure)
|
||||
{
|
||||
MVT mvt;
|
||||
|
||||
AVERT(Land, land);
|
||||
mvt = closureP;
|
||||
mvt = closure;
|
||||
AVERT(MVT, mvt);
|
||||
AVER(closureS == UNUSED_SIZE);
|
||||
UNUSED(closureS);
|
||||
|
||||
if (RangeSize(range) < mvt->reuseSize)
|
||||
return TRUE;
|
||||
|
|
@ -1241,7 +1230,7 @@ static void MVTRefillABQIfEmpty(MVT mvt, Size size)
|
|||
mvt->abqOverflow = FALSE;
|
||||
METER_ACC(mvt->refills, size);
|
||||
/* The iteration stops if the ABQ overflows, so may finish or not. */
|
||||
(void)LandIterate(MVTFreeLand(mvt), MVTRefillVisitor, mvt, UNUSED_SIZE);
|
||||
(void)LandIterate(MVTFreeLand(mvt), MVTRefillVisitor, mvt);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1260,7 +1249,7 @@ typedef struct MVTContigencyClosureStruct
|
|||
} MVTContigencyClosureStruct, *MVTContigencyClosure;
|
||||
|
||||
static Bool MVTContingencyVisitor(Land land, Range range,
|
||||
void *closureP, Size closureS)
|
||||
void *closure)
|
||||
{
|
||||
MVT mvt;
|
||||
Size size;
|
||||
|
|
@ -1269,12 +1258,10 @@ static Bool MVTContingencyVisitor(Land land, Range range,
|
|||
|
||||
AVERT(Land, land);
|
||||
AVERT(Range, range);
|
||||
AVER(closureP != NULL);
|
||||
cl = closureP;
|
||||
AVER(closure != NULL);
|
||||
cl = closure;
|
||||
mvt = cl->mvt;
|
||||
AVERT(MVT, mvt);
|
||||
AVER(closureS == UNUSED_SIZE);
|
||||
UNUSED(closureS);
|
||||
|
||||
base = RangeBase(range);
|
||||
limit = RangeLimit(range);
|
||||
|
|
@ -1312,7 +1299,7 @@ static Bool MVTContingencySearch(Addr *baseReturn, Addr *limitReturn,
|
|||
cls.steps = 0;
|
||||
cls.hardSteps = 0;
|
||||
|
||||
if (LandIterate(MVTFreeLand(mvt), MVTContingencyVisitor, &cls, UNUSED_SIZE))
|
||||
if (LandIterate(MVTFreeLand(mvt), MVTContingencyVisitor, &cls))
|
||||
return FALSE;
|
||||
|
||||
AVER(RangeSize(&cls.range) >= min);
|
||||
|
|
|
|||
|
|
@ -189,13 +189,11 @@ static void MVFFReduce(MVFF mvff)
|
|||
|
||||
/* MVFFExtend -- allocate a new range from the arena
|
||||
*
|
||||
* Allocate a new range from the arena (with the given
|
||||
* withReservoirPermit flag) of at least the specified size. The
|
||||
* specified size should be pool-aligned. Add it to the allocated and
|
||||
* free lists.
|
||||
* Allocate a new range from the arena of at least the specified
|
||||
* size. The specified size should be pool-aligned. Add it to the
|
||||
* allocated and free lists.
|
||||
*/
|
||||
static Res MVFFExtend(Range rangeReturn, MVFF mvff, Size size,
|
||||
Bool withReservoirPermit)
|
||||
static Res MVFFExtend(Range rangeReturn, MVFF mvff, Size size)
|
||||
{
|
||||
Pool pool;
|
||||
Arena arena;
|
||||
|
|
@ -206,7 +204,6 @@ static Res MVFFExtend(Range rangeReturn, MVFF mvff, Size size,
|
|||
|
||||
AVERT(MVFF, mvff);
|
||||
AVER(size > 0);
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
pool = MVFFPool(mvff);
|
||||
arena = PoolArena(pool);
|
||||
|
|
@ -222,14 +219,12 @@ static Res MVFFExtend(Range rangeReturn, MVFF mvff, Size size,
|
|||
|
||||
allocSize = SizeArenaGrains(allocSize, arena);
|
||||
|
||||
res = ArenaAlloc(&base, MVFFLocusPref(mvff), allocSize, pool,
|
||||
withReservoirPermit);
|
||||
res = ArenaAlloc(&base, MVFFLocusPref(mvff), allocSize, pool);
|
||||
if (res != ResOK) {
|
||||
/* try again with a range just large enough for object */
|
||||
/* see <design/poolmvff/#design.seg-fail> */
|
||||
allocSize = SizeArenaGrains(size, arena);
|
||||
res = ArenaAlloc(&base, MVFFLocusPref(mvff), allocSize, pool,
|
||||
withReservoirPermit);
|
||||
res = ArenaAlloc(&base, MVFFLocusPref(mvff), allocSize, pool);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
}
|
||||
|
|
@ -262,8 +257,7 @@ static Res MVFFExtend(Range rangeReturn, MVFF mvff, Size size,
|
|||
* If there is no suitable free block, try extending the pool.
|
||||
*/
|
||||
static Res mvffFindFree(Range rangeReturn, MVFF mvff, Size size,
|
||||
LandFindMethod findMethod, FindDelete findDelete,
|
||||
Bool withReservoirPermit)
|
||||
LandFindMethod findMethod, FindDelete findDelete)
|
||||
{
|
||||
Bool found;
|
||||
RangeStruct oldRange;
|
||||
|
|
@ -275,14 +269,13 @@ static Res mvffFindFree(Range rangeReturn, MVFF mvff, Size size,
|
|||
AVER(SizeIsAligned(size, PoolAlignment(MVFFPool(mvff))));
|
||||
AVER(FUNCHECK(findMethod));
|
||||
AVERT(FindDelete, findDelete);
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
land = MVFFFreeLand(mvff);
|
||||
found = (*findMethod)(rangeReturn, &oldRange, land, size, findDelete);
|
||||
if (!found) {
|
||||
RangeStruct newRange;
|
||||
Res res;
|
||||
res = MVFFExtend(&newRange, mvff, size, withReservoirPermit);
|
||||
res = MVFFExtend(&newRange, mvff, size);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
found = (*findMethod)(rangeReturn, &oldRange, land, size, findDelete);
|
||||
|
|
@ -300,8 +293,7 @@ static Res mvffFindFree(Range rangeReturn, MVFF mvff, Size size,
|
|||
|
||||
/* MVFFAlloc -- Allocate a block */
|
||||
|
||||
static Res MVFFAlloc(Addr *aReturn, Pool pool, Size size,
|
||||
Bool withReservoirPermit)
|
||||
static Res MVFFAlloc(Addr *aReturn, Pool pool, Size size)
|
||||
{
|
||||
Res res;
|
||||
MVFF mvff;
|
||||
|
|
@ -314,14 +306,12 @@ static Res MVFFAlloc(Addr *aReturn, Pool pool, Size size,
|
|||
mvff = PoolMVFF(pool);
|
||||
AVERT(MVFF, mvff);
|
||||
AVER(size > 0);
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
size = SizeAlignUp(size, PoolAlignment(pool));
|
||||
findMethod = mvff->firstFit ? LandFindFirst : LandFindLast;
|
||||
findDelete = mvff->slotHigh ? FindDeleteHIGH : FindDeleteLOW;
|
||||
|
||||
res = mvffFindFree(&range, mvff, size, findMethod, findDelete,
|
||||
withReservoirPermit);
|
||||
res = mvffFindFree(&range, mvff, size, findMethod, findDelete);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
|
|
@ -361,8 +351,7 @@ static void MVFFFree(Pool pool, Addr old, Size size)
|
|||
* allocation policy; see <design/poolmvff/#over.buffer>.
|
||||
*/
|
||||
static Res MVFFBufferFill(Addr *baseReturn, Addr *limitReturn,
|
||||
Pool pool, Buffer buffer, Size size,
|
||||
Bool withReservoirPermit)
|
||||
Pool pool, Buffer buffer, Size size)
|
||||
{
|
||||
Res res;
|
||||
MVFF mvff;
|
||||
|
|
@ -376,10 +365,8 @@ static Res MVFFBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
AVERT(Buffer, buffer);
|
||||
AVER(size > 0);
|
||||
AVER(SizeIsAligned(size, PoolAlignment(pool)));
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
res = mvffFindFree(&range, mvff, size, LandFindLargest, FindDeleteENTIRE,
|
||||
withReservoirPermit);
|
||||
res = mvffFindFree(&range, mvff, size, LandFindLargest, FindDeleteENTIRE);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
AVER(RangeSize(&range) >= size);
|
||||
|
|
@ -499,10 +486,10 @@ static Res MVFFInit(Pool pool, ArgList args)
|
|||
AVER(spare <= 1.0); /* .arg.check */
|
||||
AVERT(Align, align);
|
||||
/* This restriction on the alignment is necessary because of the use
|
||||
* of a Freelist to store the free address ranges in low-memory
|
||||
* situations. <design/freelist/#impl.grain.align>.
|
||||
*/
|
||||
of a Freelist to store the free address ranges in low-memory
|
||||
situations. <design/freelist/#impl.grain.align>. */
|
||||
AVER(AlignIsAligned(align, FreelistMinimumAlignment));
|
||||
AVER(align <= ArenaGrainSize(arena));
|
||||
AVERT(Bool, slotHigh);
|
||||
AVERT(Bool, arenaHigh);
|
||||
AVERT(Bool, firstFit);
|
||||
|
|
@ -585,18 +572,16 @@ static Res MVFFInit(Pool pool, ArgList args)
|
|||
/* MVFFFinish -- finish method for MVFF */
|
||||
|
||||
static Bool mvffFinishVisitor(Bool *deleteReturn, Land land, Range range,
|
||||
void *closureP, Size closureS)
|
||||
void *closure)
|
||||
{
|
||||
Pool pool;
|
||||
|
||||
AVER(deleteReturn != NULL);
|
||||
AVERT(Land, land);
|
||||
AVERT(Range, range);
|
||||
AVER(closureP != NULL);
|
||||
pool = closureP;
|
||||
AVER(closure != NULL);
|
||||
pool = closure;
|
||||
AVERT(Pool, pool);
|
||||
AVER(closureS == UNUSED_SIZE);
|
||||
UNUSED(closureS);
|
||||
|
||||
ArenaFree(RangeBase(range), RangeSize(range), pool);
|
||||
*deleteReturn = TRUE;
|
||||
|
|
@ -613,8 +598,7 @@ static void MVFFFinish(Pool pool)
|
|||
AVERT(MVFF, mvff);
|
||||
mvff->sig = SigInvalid;
|
||||
|
||||
b = LandIterateAndDelete(MVFFTotalLand(mvff), mvffFinishVisitor, pool,
|
||||
UNUSED_SIZE);
|
||||
b = LandIterateAndDelete(MVFFTotalLand(mvff), mvffFinishVisitor, pool);
|
||||
AVER(b);
|
||||
AVER(LandSize(MVFFTotalLand(mvff)) == 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -60,8 +60,7 @@ static void NFinish(Pool pool)
|
|||
|
||||
/* NAlloc -- alloc method for class N */
|
||||
|
||||
static Res NAlloc(Addr *pReturn, Pool pool, Size size,
|
||||
Bool withReservoirPermit)
|
||||
static Res NAlloc(Addr *pReturn, Pool pool, Size size)
|
||||
{
|
||||
PoolN poolN;
|
||||
|
||||
|
|
@ -71,7 +70,6 @@ static Res NAlloc(Addr *pReturn, Pool pool, Size size,
|
|||
|
||||
AVER(pReturn != NULL);
|
||||
AVER(size > 0);
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
return ResLIMIT; /* limit of nil blocks exceeded */
|
||||
}
|
||||
|
|
@ -97,8 +95,7 @@ static void NFree(Pool pool, Addr old, Size size)
|
|||
/* NBufferFill -- buffer fill method for class N */
|
||||
|
||||
static Res NBufferFill(Addr *baseReturn, Addr *limitReturn,
|
||||
Pool pool, Buffer buffer, Size size,
|
||||
Bool withReservoirPermit)
|
||||
Pool pool, Buffer buffer, Size size)
|
||||
{
|
||||
PoolN poolN;
|
||||
|
||||
|
|
@ -110,7 +107,6 @@ static Res NBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
AVERT(Buffer, buffer);
|
||||
AVER(BufferIsReset(buffer));
|
||||
AVER(size > 0);
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
|
||||
NOTREACHED; /* can't create buffers, so shouldn't fill them */
|
||||
return ResUNIMPL;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ static void testit(ArenaClass class, ArgList args)
|
|||
die(ArenaCreate(&arena, class, args), "ArenaCreate");
|
||||
|
||||
die(PoolCreate(&pool, arena, PoolClassN(), argsNone), "PoolNCreate");
|
||||
res = PoolAlloc(&p, pool, 1, /* withReservoirPermit */ FALSE);
|
||||
res = PoolAlloc(&p, pool, 1);
|
||||
if (res == ResOK) {
|
||||
error("Error: Unexpectedly succeeded in"
|
||||
"allocating block from PoolN\n");
|
||||
|
|
|
|||
|
|
@ -226,8 +226,7 @@ static Bool SNCSegCheck(SNCSeg sncseg)
|
|||
|
||||
/* sncSegInit -- Init method for SNC segments */
|
||||
|
||||
static Res sncSegInit(Seg seg, Pool pool, Addr base, Size size,
|
||||
Bool reservoirPermit, ArgList args)
|
||||
static Res sncSegInit(Seg seg, Pool pool, Addr base, Size size, ArgList args)
|
||||
{
|
||||
SegClass super;
|
||||
SNCSeg sncseg;
|
||||
|
|
@ -237,11 +236,10 @@ static Res sncSegInit(Seg seg, Pool pool, Addr base, Size size,
|
|||
sncseg = SegSNCSeg(seg);
|
||||
AVERT(Pool, pool);
|
||||
/* no useful checks for base and size */
|
||||
AVERT(Bool, reservoirPermit);
|
||||
|
||||
/* Initialize the superclass fields first via next-method call */
|
||||
super = SEG_SUPERCLASS(SNCSegClass);
|
||||
res = super->init(seg, pool, base, size, reservoirPermit, args);
|
||||
res = super->init(seg, pool, base, size, args);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
|
|
@ -419,8 +417,7 @@ static void SNCFinish(Pool pool)
|
|||
|
||||
|
||||
static Res SNCBufferFill(Addr *baseReturn, Addr *limitReturn,
|
||||
Pool pool, Buffer buffer, Size size,
|
||||
Bool withReservoirPermit)
|
||||
Pool pool, Buffer buffer, Size size)
|
||||
{
|
||||
SNC snc;
|
||||
Arena arena;
|
||||
|
|
@ -433,7 +430,6 @@ static Res SNCBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
AVERT(Pool, pool);
|
||||
AVERT(Buffer, buffer);
|
||||
AVER(size > 0);
|
||||
AVERT(Bool, withReservoirPermit);
|
||||
AVER(BufferIsReset(buffer));
|
||||
|
||||
snc = PoolSNC(pool);
|
||||
|
|
@ -448,7 +444,7 @@ static Res SNCBufferFill(Addr *baseReturn, Addr *limitReturn,
|
|||
arena = PoolArena(pool);
|
||||
asize = SizeArenaGrains(size, arena);
|
||||
res = SegAlloc(&seg, SNCSegClassGet(), LocusPrefDefault(),
|
||||
asize, pool, withReservoirPermit, argsNone);
|
||||
asize, pool, argsNone);
|
||||
if (res != ResOK)
|
||||
return res;
|
||||
|
||||
|
|
@ -527,7 +523,7 @@ static Res SNCScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg)
|
|||
}
|
||||
|
||||
if (base < limit) {
|
||||
res = (*format->scan)(&ss->ss_s, base, limit);
|
||||
res = FormatScan(format, ss, base, limit);
|
||||
if (res != ResOK) {
|
||||
*totalReturn = FALSE;
|
||||
return res;
|
||||
|
|
@ -536,8 +532,6 @@ static Res SNCScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg)
|
|||
AVER(base == limit);
|
||||
}
|
||||
|
||||
ss->scannedSize += AddrOffset(base, limit);
|
||||
|
||||
*totalReturn = TRUE;
|
||||
return ResOK;
|
||||
}
|
||||
|
|
@ -664,6 +658,52 @@ static void SNCWalk(Pool pool, Seg seg, FormattedObjectsVisitor f,
|
|||
}
|
||||
|
||||
|
||||
/* SNCTotalSize -- total memory allocated from the arena */
|
||||
|
||||
static Size SNCTotalSize(Pool pool)
|
||||
{
|
||||
SNC snc;
|
||||
Ring ring, node, nextNode;
|
||||
Size total = 0;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
snc = PoolSNC(pool);
|
||||
AVERT(SNC, snc);
|
||||
|
||||
ring = &pool->segRing;
|
||||
RING_FOR(node, ring, nextNode) {
|
||||
Seg seg = SegOfPoolRing(node);
|
||||
AVERT(Seg, seg);
|
||||
total += SegSize(seg);
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
|
||||
/* SNCFreeSize -- free memory (unused by client program) */
|
||||
|
||||
static Size SNCFreeSize(Pool pool)
|
||||
{
|
||||
SNC snc;
|
||||
Seg seg;
|
||||
Size free = 0;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
snc = PoolSNC(pool);
|
||||
AVERT(SNC, snc);
|
||||
|
||||
seg = snc->freeSegs;
|
||||
while (seg != NULL) {
|
||||
AVERT(Seg, seg);
|
||||
free += SegSize(seg);
|
||||
seg = sncSegNext(seg);
|
||||
}
|
||||
|
||||
return free;
|
||||
}
|
||||
|
||||
|
||||
/* SNCPoolClass -- the class definition */
|
||||
|
||||
DEFINE_POOL_CLASS(SNCPoolClass, this)
|
||||
|
|
@ -684,6 +724,8 @@ DEFINE_POOL_CLASS(SNCPoolClass, this)
|
|||
this->framePopPending = SNCFramePopPending;
|
||||
this->walk = SNCWalk;
|
||||
this->bufferClass = SNCBufClassGet;
|
||||
this->totalSize = SNCTotalSize;
|
||||
this->freeSize = SNCFreeSize;
|
||||
AVERT(PoolClass, this);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,17 +38,20 @@ Addr MutatorFaultContextSP(MutatorFaultContext mfc)
|
|||
}
|
||||
|
||||
|
||||
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
|
||||
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure)
|
||||
{
|
||||
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. */
|
||||
res = TraceScanAreaTagged(
|
||||
res = TraceScanArea(
|
||||
ss,
|
||||
(Addr *)mfc->ucontext,
|
||||
(Addr *)((char *)mfc->ucontext + sizeof(*(mfc->ucontext)))
|
||||
(Word *)mfc->ucontext,
|
||||
(Word *)((char *)mfc->ucontext + sizeof(*(mfc->ucontext))),
|
||||
scan_area, closure
|
||||
);
|
||||
|
||||
return res;
|
||||
|
|
|
|||
|
|
@ -101,7 +101,9 @@ Addr MutatorFaultContextSP(MutatorFaultContext mfc)
|
|||
}
|
||||
|
||||
|
||||
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
|
||||
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure)
|
||||
{
|
||||
mcontext_t *mc;
|
||||
Res res;
|
||||
|
|
@ -110,9 +112,10 @@ Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
|
|||
unnecessarily scans the rest of the context. The optimisation
|
||||
to scan only relevant parts would be machine dependent. */
|
||||
mc = &mfc->ucontext->uc_mcontext;
|
||||
res = TraceScanAreaTagged(ss,
|
||||
(Addr *)mc,
|
||||
(Addr *)((char *)mc + sizeof(*mc)));
|
||||
res = TraceScanArea(ss,
|
||||
(Word *)mc,
|
||||
(Word *)((char *)mc + sizeof(*mc)),
|
||||
scan_area, closure);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -96,7 +96,9 @@ Addr MutatorFaultContextSP(MutatorFaultContext mfc)
|
|||
}
|
||||
|
||||
|
||||
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
|
||||
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure)
|
||||
{
|
||||
x86_thread_state32_t *mc;
|
||||
Res res;
|
||||
|
|
@ -105,9 +107,10 @@ Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
|
|||
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)));
|
||||
res = TraceScanArea(ss,
|
||||
(Word *)mc,
|
||||
(Word *)((char *)mc + sizeof(*mc)),
|
||||
scan_area, closure);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,17 +32,20 @@ Addr MutatorFaultContextSP(MutatorFaultContext mfc)
|
|||
}
|
||||
|
||||
|
||||
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
|
||||
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure)
|
||||
{
|
||||
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. */
|
||||
res = TraceScanAreaTagged(
|
||||
res = TraceScanArea(
|
||||
ss,
|
||||
(Addr *)mfc->ucontext,
|
||||
(Addr *)((char *)mfc->ucontext + sizeof(*(mfc->ucontext)))
|
||||
(Word *)mfc->ucontext,
|
||||
(Word *)((char *)mfc->ucontext + sizeof(*(mfc->ucontext))),
|
||||
scan_area, closure
|
||||
);
|
||||
|
||||
return res;
|
||||
|
|
|
|||
|
|
@ -105,7 +105,9 @@ Addr MutatorFaultContextSP(MutatorFaultContext mfc)
|
|||
}
|
||||
|
||||
|
||||
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
|
||||
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure)
|
||||
{
|
||||
mcontext_t *mc;
|
||||
Res res;
|
||||
|
|
@ -114,9 +116,10 @@ Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
|
|||
unnecessarily scans the rest of the context. The optimisation
|
||||
to scan only relevant parts would be machine dependent. */
|
||||
mc = &mfc->ucontext->uc_mcontext;
|
||||
res = TraceScanAreaTagged(ss,
|
||||
(Addr *)mc,
|
||||
(Addr *)((char *)mc + sizeof(*mc)));
|
||||
res = TraceScanArea(ss,
|
||||
(Word *)mc,
|
||||
(Word *)((char *)mc + sizeof(*mc)),
|
||||
scan_area, closure);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -99,7 +99,9 @@ Addr MutatorFaultContextSP(MutatorFaultContext mfc)
|
|||
}
|
||||
|
||||
|
||||
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
|
||||
Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc,
|
||||
mps_area_scan_t scan_area,
|
||||
void *closure)
|
||||
{
|
||||
x86_thread_state64_t *mc;
|
||||
Res res;
|
||||
|
|
@ -108,9 +110,10 @@ Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc)
|
|||
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)));
|
||||
res = TraceScanArea(ss,
|
||||
(Word *)mc,
|
||||
(Word *)((char *)mc + sizeof(*mc)),
|
||||
scan_area, closure);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* prot.h: MEMORY PROTECTION INTERFACE
|
||||
*
|
||||
* $Id: //info.ravenbrook.com/project/mps/master/code/prot.h#1 $
|
||||
* Copyright (c) 2014 Ravenbrook Limited. See end of file for license.
|
||||
* $Id$
|
||||
* Copyright (c) 2014-2016 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* See <design/prot/> for the design of the generic interface including
|
||||
* the contracts for these functions.
|
||||
|
|
@ -30,7 +30,9 @@ extern void ProtSync(Arena arena);
|
|||
extern Bool ProtCanStepInstruction(MutatorFaultContext context);
|
||||
extern Res ProtStepInstruction(MutatorFaultContext context);
|
||||
extern Addr MutatorFaultContextSP(MutatorFaultContext mfc);
|
||||
extern Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc);
|
||||
extern Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc,
|
||||
mps_area_scan_t scan,
|
||||
void *closure);
|
||||
|
||||
|
||||
#endif /* prot_h */
|
||||
|
|
@ -38,7 +40,7 @@ extern Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc);
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2014-2016 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 @@
|
|||
/* ref.c: REFERENCES
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
|
||||
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .purpose: Implement operations on Ref, RefSet, ZoneSet, and Rank.
|
||||
*
|
||||
|
|
@ -35,7 +35,7 @@ Bool RankSetCheck(RankSet rankSet)
|
|||
|
||||
/* ZoneSetOfRange -- calculate the zone set of a range of addresses */
|
||||
|
||||
RefSet ZoneSetOfRange(Arena arena, Addr base, Addr limit)
|
||||
ZoneSet ZoneSetOfRange(Arena arena, Addr base, Addr limit)
|
||||
{
|
||||
Word zbase, zlimit;
|
||||
|
||||
|
|
@ -292,13 +292,9 @@ ZoneSet ZoneSetBlacklist(Arena arena)
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,458 +0,0 @@
|
|||
/* reserv.c: ARENA RESERVOIR
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* IMPROVEMENTS
|
||||
*
|
||||
* .improve.contiguous: There should be a means of grouping contiguous
|
||||
* tracts together so that there's a likelihood of being able to meet
|
||||
* requests for regions larger than the arena grain size. */
|
||||
|
||||
#include "mpm.h"
|
||||
|
||||
SRCID(reserv, "$Id$");
|
||||
|
||||
|
||||
/* The reservoir pool is defined here. See <design/reservoir/> */
|
||||
|
||||
#define PoolReservoir(pool) PARENT(ReservoirStruct, poolStruct, pool)
|
||||
|
||||
|
||||
/* Management of tracts
|
||||
*
|
||||
* The reservoir maintains a linked list of tracts in arbitrary order.
|
||||
* (see .improve.contiguous)
|
||||
*
|
||||
* Tracts are chained using the TractP field. */
|
||||
|
||||
#define resTractNext(tract) ((Tract)TractP((tract)))
|
||||
#define resTractSetNext(tract, next) (TractSetP((tract), (void*)(next)))
|
||||
|
||||
|
||||
#define reservoirArena(reservoir) (PoolArena(ReservoirPool(reservoir)))
|
||||
|
||||
|
||||
/* ResPoolInit -- Reservoir pool init method */
|
||||
|
||||
static Res ResPoolInit(Pool pool, ArgList arg)
|
||||
{
|
||||
AVER(pool != NULL);
|
||||
|
||||
UNUSED(arg);
|
||||
/* Caller will set sig and AVERT. */
|
||||
EVENT3(PoolInit, pool, PoolArena(pool), ClassOfPool(pool));
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
||||
/* ResPoolFinish -- Reservoir pool finish method
|
||||
*
|
||||
* .reservoir.finish: This might be called from ArenaFinish, so the
|
||||
* arena cannot be checked at this time. In order to avoid the check,
|
||||
* insist that the reservoir is empty, by AVERing that the reserve list
|
||||
* is NULL. */
|
||||
|
||||
static void ResPoolFinish(Pool pool)
|
||||
{
|
||||
Reservoir reservoir;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
reservoir = PoolReservoir(pool);
|
||||
AVERT(Reservoir, reservoir);
|
||||
AVER(reservoir->reserve == NULL); /* .reservoir.finish */
|
||||
}
|
||||
|
||||
|
||||
/* ReservoirPoolClass -- Class definition */
|
||||
|
||||
DEFINE_POOL_CLASS(ReservoirPoolClass, this)
|
||||
{
|
||||
INHERIT_CLASS(this, AbstractPoolClass);
|
||||
this->name = "Reservoir";
|
||||
this->size = sizeof(ReservoirStruct);
|
||||
this->offset = offsetof(ReservoirStruct, poolStruct);
|
||||
this->init = ResPoolInit;
|
||||
this->finish = ResPoolFinish;
|
||||
AVERT(PoolClass, this);
|
||||
}
|
||||
|
||||
|
||||
/* ReservoirCheck -- Reservoir check method */
|
||||
|
||||
Bool ReservoirCheck(Reservoir reservoir)
|
||||
{
|
||||
ReservoirPoolClass reservoircl = EnsureReservoirPoolClass();
|
||||
Arena arena;
|
||||
Tract tract;
|
||||
|
||||
CHECKS(Reservoir, reservoir);
|
||||
CHECKD(Pool, ReservoirPool(reservoir));
|
||||
CHECKL(ReservoirPool(reservoir)->class == reservoircl);
|
||||
UNUSED(reservoircl); /* <code/mpm.c#check.unused> */
|
||||
arena = reservoirArena(reservoir);
|
||||
CHECKU(Arena, arena);
|
||||
/* could call ReservoirIsConsistent, but it's costly. */
|
||||
tract = reservoir->reserve;
|
||||
if (tract != NULL) {
|
||||
CHECKD_NOSIG(Tract, tract);
|
||||
CHECKL(TractPool(tract) == ReservoirPool(reservoir));
|
||||
}
|
||||
CHECKL(SizeIsArenaGrains(reservoir->reservoirLimit, arena));
|
||||
CHECKL(SizeIsArenaGrains(reservoir->reservoirSize, arena));
|
||||
CHECKL(reservoir->reservoirSize <= reservoir->reservoirLimit);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* reservoirIsConsistent -- returns FALSE if the reservoir is corrupt */
|
||||
|
||||
ATTRIBUTE_UNUSED
|
||||
static Bool reservoirIsConsistent(Reservoir reservoir)
|
||||
{
|
||||
Size grainSize, size = 0;
|
||||
Tract tract;
|
||||
Pool pool;
|
||||
Arena arena;
|
||||
|
||||
arena = reservoirArena(reservoir);
|
||||
pool = ReservoirPool(reservoir);
|
||||
|
||||
/* Check that the size of the tracts matches reservoirSize */
|
||||
grainSize = ArenaGrainSize(arena);
|
||||
tract = reservoir->reserve;
|
||||
while (tract != NULL) {
|
||||
AVERT(Tract, tract);
|
||||
AVER(TractPool(tract) == pool);
|
||||
tract = resTractNext(tract);
|
||||
size += grainSize;
|
||||
}
|
||||
|
||||
if (size != reservoir->reservoirSize)
|
||||
return FALSE;
|
||||
|
||||
/* <design/reservoir/#align> */
|
||||
return SizeIsAligned(reservoir->reservoirLimit, grainSize)
|
||||
&& SizeIsAligned(reservoir->reservoirSize, grainSize)
|
||||
&& (reservoir->reservoirLimit >= reservoir->reservoirSize);
|
||||
}
|
||||
|
||||
|
||||
/* ReservoirEnsureFull
|
||||
*
|
||||
* Ensures that the reservoir is the right size, by topping it up with
|
||||
* fresh memory from the arena if possible. */
|
||||
|
||||
Res ReservoirEnsureFull(Reservoir reservoir)
|
||||
{
|
||||
Size limit, size;
|
||||
Pool pool;
|
||||
Arena arena;
|
||||
AVERT(Reservoir, reservoir);
|
||||
arena = reservoirArena(reservoir);
|
||||
|
||||
AVERT(Arena, arena);
|
||||
size = ArenaGrainSize(arena);
|
||||
limit = reservoir->reservoirLimit;
|
||||
|
||||
/* optimize the common case of a full reservoir */
|
||||
if (reservoir->reservoirSize == limit)
|
||||
return ResOK;
|
||||
|
||||
pool = ReservoirPool(reservoir);
|
||||
|
||||
/* really ought to try hard to allocate contiguous tracts */
|
||||
/* see .improve.contiguous */
|
||||
while (reservoir->reservoirSize < limit) {
|
||||
Res res;
|
||||
Addr base;
|
||||
Tract tract;
|
||||
res = ArenaAlloc(&base, LocusPrefDefault(), size, pool, FALSE);
|
||||
if (res != ResOK) {
|
||||
AVER(reservoirIsConsistent(reservoir));
|
||||
return res;
|
||||
}
|
||||
tract = TractOfBaseAddr(arena, base);
|
||||
reservoir->reservoirSize += size;
|
||||
resTractSetNext(tract, reservoir->reserve);
|
||||
reservoir->reserve = tract;
|
||||
}
|
||||
AVER(reservoirIsConsistent(reservoir));
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
||||
/* reservoirShrink -- Reduce the size of the reservoir */
|
||||
|
||||
static void reservoirShrink(Reservoir reservoir, Size want)
|
||||
{
|
||||
Arena arena;
|
||||
Pool pool;
|
||||
Size size;
|
||||
|
||||
pool = ReservoirPool(reservoir);
|
||||
arena = reservoirArena(reservoir);
|
||||
AVER(SizeIsArenaGrains(want, arena));
|
||||
AVER(reservoir->reservoirSize >= want);
|
||||
|
||||
if (reservoir->reservoirSize == want)
|
||||
return;
|
||||
|
||||
/* Iterate over tracts, freeing them while reservoir is too big */
|
||||
size = ArenaGrainSize(arena);
|
||||
while (reservoir->reservoirSize > want) {
|
||||
Tract tract = reservoir->reserve;
|
||||
AVER(tract != NULL);
|
||||
reservoir->reserve = resTractNext(tract);
|
||||
ArenaFree(TractBase(tract), size, pool);
|
||||
reservoir->reservoirSize -= size;
|
||||
}
|
||||
AVER(reservoir->reservoirSize == want);
|
||||
AVER(reservoirIsConsistent(reservoir));
|
||||
}
|
||||
|
||||
|
||||
/* ReservoirWithdraw -- Attempt to supply memory from the reservoir */
|
||||
|
||||
Res ReservoirWithdraw(Addr *baseReturn, Tract *baseTractReturn,
|
||||
Reservoir reservoir, Size size, Pool pool)
|
||||
{
|
||||
Arena arena;
|
||||
|
||||
AVER(baseReturn != NULL);
|
||||
AVER(baseTractReturn != NULL);
|
||||
AVERT(Reservoir, reservoir);
|
||||
arena = reservoirArena(reservoir);
|
||||
AVERT(Arena, arena);
|
||||
AVER(SizeIsArenaGrains(size, arena));
|
||||
AVER(size > 0);
|
||||
AVERT(Pool, pool);
|
||||
|
||||
/* @@@@ As a short-term measure, we only permit the reservoir to */
|
||||
/* allocate single-page regions. */
|
||||
/* See .improve.contiguous & change.dylan.jackdaw.160125 */
|
||||
if (size != ArenaGrainSize(arena))
|
||||
return ResMEMORY;
|
||||
|
||||
if (size <= reservoir->reservoirSize) {
|
||||
/* Return the first tract */
|
||||
Tract tract = reservoir->reserve;
|
||||
Addr base;
|
||||
AVER(tract != NULL);
|
||||
base = TractBase(tract);
|
||||
reservoir->reserve = resTractNext(tract);
|
||||
reservoir->reservoirSize -= ArenaGrainSize(arena);
|
||||
TractFinish(tract);
|
||||
TractInit(tract, pool, base);
|
||||
AVER(reservoirIsConsistent(reservoir));
|
||||
*baseReturn = base;
|
||||
*baseTractReturn = tract;
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
AVER(reservoirIsConsistent(reservoir));
|
||||
return ResMEMORY; /* no suitable region in the reservoir */
|
||||
}
|
||||
|
||||
|
||||
/* ReservoirDeposit -- Top up the reservoir */
|
||||
|
||||
Bool ReservoirDeposit(Reservoir reservoir, Addr *baseIO, Size *sizeIO)
|
||||
{
|
||||
Pool respool;
|
||||
Addr addr, limit;
|
||||
Size reslimit;
|
||||
Arena arena;
|
||||
Tract tract;
|
||||
Addr base;
|
||||
Size size;
|
||||
|
||||
AVERT(Reservoir, reservoir);
|
||||
arena = reservoirArena(reservoir);
|
||||
AVERT(Arena, arena);
|
||||
respool = ReservoirPool(reservoir);
|
||||
AVER(baseIO != NULL);
|
||||
AVER(sizeIO != NULL);
|
||||
base = *baseIO;
|
||||
size = *sizeIO;
|
||||
AVER(AddrIsArenaGrain(base, arena));
|
||||
AVER(SizeIsArenaGrains(size, arena));
|
||||
limit = AddrAdd(base, size);
|
||||
reslimit = reservoir->reservoirLimit;
|
||||
|
||||
/* put as many pages as necessary into the reserve & free the rest */
|
||||
TRACT_FOR(tract, addr, arena, base, limit) {
|
||||
AVERT(Tract, tract);
|
||||
if (reservoir->reservoirSize < reslimit) {
|
||||
/* Reassign the tract to the reservoir pool */
|
||||
TractFinish(tract);
|
||||
TractInit(tract, respool, addr);
|
||||
reservoir->reservoirSize += ArenaGrainSize(arena);
|
||||
resTractSetNext(tract, reservoir->reserve);
|
||||
reservoir->reserve = tract;
|
||||
} else {
|
||||
*baseIO = addr;
|
||||
*sizeIO = AddrOffset(base, limit);
|
||||
AVER(reservoirIsConsistent(reservoir));
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
AVER(addr == limit);
|
||||
AVER(reservoirIsConsistent(reservoir));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* mutatorBufferCount -- returns the number of mutator buffers for the arena
|
||||
*
|
||||
* This should probably be in the pool module, but it's only used here. */
|
||||
|
||||
static Count mutatorBufferCount(Globals arena)
|
||||
{
|
||||
Ring nodep, nextp;
|
||||
Count count = 0;
|
||||
|
||||
/* Iterate over all pools, and count the mutator buffers in each */
|
||||
RING_FOR(nodep, &arena->poolRing, nextp) {
|
||||
Pool pool = RING_ELT(Pool, arenaRing, nodep);
|
||||
Ring nodeb, nextb;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
RING_FOR(nodeb, &pool->bufferRing, nextb) {
|
||||
Buffer buff = RING_ELT(Buffer, poolRing, nodeb);
|
||||
if (buff->isMutator)
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/* ReservoirSetLimit -- Set the reservoir limit */
|
||||
|
||||
void ReservoirSetLimit(Reservoir reservoir, Size size)
|
||||
{
|
||||
Size needed;
|
||||
Arena arena;
|
||||
AVERT(Reservoir, reservoir);
|
||||
arena = reservoirArena(reservoir);
|
||||
AVERT(Arena, arena);
|
||||
|
||||
if (size > 0) {
|
||||
Size wastage;
|
||||
/* <design/reservoir/#wastage> */
|
||||
wastage = ArenaGrainSize(arena) * mutatorBufferCount(ArenaGlobals(arena));
|
||||
/* <design/reservoir/#align> */
|
||||
needed = SizeArenaGrains(size, arena) + wastage;
|
||||
} else {
|
||||
needed = 0; /* <design/reservoir/#really-empty> */
|
||||
}
|
||||
|
||||
AVER(SizeIsArenaGrains(needed, arena));
|
||||
/* Emit event now, so subsequent change can be ascribed to it. */
|
||||
EVENT2(ReservoirLimitSet, arena, size);
|
||||
|
||||
if (needed > reservoir->reservoirSize) {
|
||||
/* Try to grow the reservoir */
|
||||
reservoir->reservoirLimit = needed;
|
||||
(void)ReservoirEnsureFull(reservoir);
|
||||
} else {
|
||||
/* Shrink the reservoir */
|
||||
reservoirShrink(reservoir, needed);
|
||||
reservoir->reservoirLimit = needed;
|
||||
AVER(reservoirIsConsistent(reservoir));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ReservoirLimit -- Return the reservoir limit */
|
||||
|
||||
Size ReservoirLimit(Reservoir reservoir)
|
||||
{
|
||||
AVERT(Reservoir, reservoir);
|
||||
AVER(reservoirIsConsistent(reservoir));
|
||||
return reservoir->reservoirLimit;
|
||||
}
|
||||
|
||||
|
||||
/* ReservoirAvailable -- Return the amount in the reservoir */
|
||||
|
||||
Size ReservoirAvailable(Reservoir reservoir)
|
||||
{
|
||||
AVERT(Reservoir, reservoir);
|
||||
(void)ReservoirEnsureFull(reservoir);
|
||||
return reservoir->reservoirSize;
|
||||
}
|
||||
|
||||
|
||||
/* ReservoirInit -- Initialize a reservoir */
|
||||
|
||||
Res ReservoirInit(Reservoir reservoir, Arena arena)
|
||||
{
|
||||
Res res;
|
||||
|
||||
/* reservoir and arena are not initialized and can't be checked */
|
||||
reservoir->reservoirLimit = (Size)0;
|
||||
reservoir->reservoirSize = (Size)0;
|
||||
reservoir->reserve = NULL;
|
||||
reservoir->sig = ReservoirSig;
|
||||
/* initialize the reservoir pool, <design/reservoir/> */
|
||||
res = PoolInit(ReservoirPool(reservoir),
|
||||
arena, EnsureReservoirPoolClass(), argsNone);
|
||||
if (res == ResOK) {
|
||||
AVERT(Reservoir, reservoir);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* ReservoirFinish -- Finish a reservoir */
|
||||
|
||||
void ReservoirFinish (Reservoir reservoir)
|
||||
{
|
||||
PoolFinish(ReservoirPool(reservoir));
|
||||
reservoir->sig = SigInvalid;
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue