-- Event Logging Common Definitions
*
- * Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
+ * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* $Id$
*
* .sources: mps.design.telemetry
@@ -56,7 +56,8 @@ ENUM_DECLARE(EventKind)
enum EventDefinitionsEnum {
EVENT_LIST(EVENT_ENUM, X)
- EventEnumWarningSuppressor /* suppress comma-at-end-of-enum warning */
+ /* suppress comma-at-end-of-enum warning */
+ EventEnumWarningSuppressor = USHRT_MAX
};
@@ -89,7 +90,11 @@ typedef Word EventFW; /* word */
typedef unsigned EventFU; /* unsigned integer */
typedef char EventFS[EventStringLengthMAX + sizeof('\0')]; /* string */
typedef double EventFD; /* double */
-typedef int EventFB; /* boolean */
+/* EventFB must be unsigned (even though Bool is a typedef for int)
+ * because it used as the type of a bitfield with width 1, and we need
+ * the legals values of the field to be 0 and 1 (not 0 and -1 which
+ * would be the case for int : 1). */
+typedef unsigned EventFB; /* Boolean */
/* Event packing bitfield specifiers */
#define EventFP_BITFIELD
@@ -133,7 +138,7 @@ typedef union EventUnion {
/* C. COPYRIGHT AND LICENSE
*
- * Copyright (C) 2001-2002 Ravenbrook Limited .
+ * Copyright (C) 2001-2014 Ravenbrook Limited .
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*
diff --git a/mps/code/eventsql.c b/mps/code/eventsql.c
index 46bfa688a9b..e1c9ea22381 100644
--- a/mps/code/eventsql.c
+++ b/mps/code/eventsql.c
@@ -102,7 +102,7 @@ typedef sqlite3_int64 int64;
* and for reporting errors.
*/
-unsigned int verbosity = 0;
+static unsigned int verbosity = 0;
#define LOG_ALWAYS 0
#define LOG_OFTEN 1
@@ -533,7 +533,7 @@ static void logFileCompleted(sqlite3 *db,
/* An array of table-creation statement strings. */
-const char *createStatements[] = {
+static const char *createStatements[] = {
"CREATE TABLE IF NOT EXISTS event_kind (name TEXT,"
" description TEXT,"
" enum INTEGER PRIMARY KEY)",
@@ -571,7 +571,7 @@ static void makeTables(sqlite3 *db)
}
}
-const char *glueTables[] = {
+static const char *glueTables[] = {
"event_kind",
"event_type",
"event_param",
diff --git a/mps/code/eventtxt.c b/mps/code/eventtxt.c
index 5b7f7ab1312..4c50ac994f9 100644
--- a/mps/code/eventtxt.c
+++ b/mps/code/eventtxt.c
@@ -29,15 +29,20 @@
* $Id$
*/
+#include "mps.h"
+#include "mpsavm.h"
+#include "mpscmvff.h"
+#include "check.h"
#include "config.h"
#include "eventdef.h"
#include "eventcom.h"
#include "table.h"
#include "testlib.h" /* for ulongest_t and associated print formats */
+#include
#include
-#include
-#include
+#include /* exit, EXIT_FAILURE, EXIT_SUCCESS */
+#include /* strcpy, strlen */
static const char *prog; /* program name */
static const char *logFileName = NULL;
@@ -106,15 +111,19 @@ static void parseArgs(int argc, char *argv[])
static void *tableAlloc(void *closure, size_t size)
{
- UNUSED(closure);
- return malloc(size);
+ mps_pool_t pool = closure;
+ mps_addr_t p;
+ mps_res_t res;
+ res = mps_alloc(&p, pool, size);
+ if (res != MPS_RES_OK)
+ everror("allocation failed: %d", res);
+ return p;
}
static void tableFree(void *closure, void *p, size_t size)
{
- UNUSED(closure);
- UNUSED(size);
- free(p);
+ mps_pool_t pool = closure;
+ mps_free(pool, p, size);
}
/* Printing routines */
@@ -171,7 +180,7 @@ static double parseDouble(char **pInOut)
#define MAX_STRING_LENGTH 1024
-char strBuf[MAX_STRING_LENGTH];
+static char strBuf[MAX_STRING_LENGTH];
static char *parseString(char **pInOut)
{
@@ -215,21 +224,21 @@ static Table internTable; /* dictionary of intern ids to strings */
static Table labelTable; /* dictionary of addrs to intern ids */
-static void createTables(void)
+static void createTables(mps_pool_t pool)
{
Res res;
/* MPS intern IDs are serials from zero up, so we can use -1
* and -2 as specials. */
res = TableCreate(&internTable,
(size_t)1<<4,
- tableAlloc, tableFree, NULL,
+ tableAlloc, tableFree, pool,
(Word)-1, (Word)-2);
if (res != ResOK)
everror("Couldn't make intern table.");
/* We assume that 0 and 1 are invalid as Addrs. */
res = TableCreate(&labelTable, (size_t)1<<7,
- tableAlloc, tableFree, NULL,
+ tableAlloc, tableFree, pool,
0, 1);
if (res != ResOK)
everror("Couldn't make label table.");
@@ -238,19 +247,19 @@ static void createTables(void)
/* recordIntern -- record an interned string in the table. a copy of
* the string from the parsed buffer into a newly-allocated block. */
-static void recordIntern(char *p)
+static void recordIntern(mps_pool_t pool, char *p)
{
ulongest_t stringId;
char *string;
- char *copy;
+ mps_addr_t copy;
size_t len;
Res res;
stringId = parseHex(&p);
string = parseString(&p);
len = strlen(string);
- copy = malloc(len+1);
- if (copy == NULL)
+ res = mps_alloc(©, pool, len + 1);
+ if (res != MPS_RES_OK)
everror("Couldn't allocate space for a string.");
(void)strcpy(copy, string);
res = TableDefine(internTable, (Word)stringId, (void *)copy);
@@ -258,12 +267,55 @@ static void recordIntern(char *p)
everror("Couldn't create an intern mapping.");
}
-/* recordLabel records a label (an association between an address and
- * a string ID). Note that the event log may have been generated on a
- * platform with addresses larger than Word on the current platform.
- * If that happens then we are scuppered because our Table code uses
- * Word as the key type: there's nothing we can do except detect this
- * bad case (see also the EventInit handling and warning code).
+/* Over time there may be multiple labels associated with an address,
+ * so we keep a list, recording for each label the clock when the
+ * association was made. This means that printAddr can select the
+ * label that was in force at the time of the event.
+ */
+
+typedef struct LabelStruct *Label;
+typedef struct LabelStruct {
+ ulongest_t clock; /* clock of this label */
+ ulongest_t id; /* string id of this label */
+} LabelStruct;
+
+typedef struct LabelListStruct *LabelList;
+typedef struct LabelListStruct {
+ size_t n; /* number of labels in array */
+ Label labels; /* labels, sorted in order by clock */
+} LabelListStruct;
+
+/* labelFind returns the index of the first entry in list with a clock
+ * value that's greater than 'clock', or list->n if there is no such
+ * label. The list is assumed to be sorted.
+ */
+
+static size_t labelFind(LabelList list, ulongest_t clock)
+{
+ size_t low = 0, high = list->n;
+ while (low < high) {
+ size_t mid = (low + high) / 2;
+ assert(NONNEGATIVE(mid) && mid < list->n);
+ if (list->labels[mid].clock > clock) {
+ high = mid;
+ } else {
+ low = mid + 1;
+ }
+ }
+ assert(NONNEGATIVE(low) && low <= list->n);
+ assert(low == list->n || list->labels[low].clock > clock);
+ return low;
+}
+
+/* recordLabel records a label: an association (made at the time given
+ * by 'clock') between an address and a string ID. These are encoded
+ * as two hexadecimal numbers in the string pointed to by 'p'.
+ *
+ * Note that the event log may have been generated on a platform with
+ * addresses larger than Word on the current platform. If that happens
+ * then we are scuppered because our Table code uses Word as the key
+ * type: there's nothing we can do except detect this bad case (see
+ * also the EventInit handling and warning code).
*
* We can and do handle the case where string IDs (which are Words on
* the MPS platform) are larger than void* on the current platform.
@@ -274,25 +326,50 @@ static void recordIntern(char *p)
* probably a bad idea and maybe doomed to failure.
*/
-static void recordLabel(char *p)
+static void recordLabel(mps_pool_t pool, ulongest_t clock, char *p)
{
ulongest_t address;
- ulongest_t *stringIdP;
+ LabelList list;
+ Label newlabels;
+ mps_addr_t tmp;
+ size_t pos;
Res res;
-
+
address = parseHex(&p);
if (address > (Word)-1) {
(void)printf("label address too large!");
return;
}
-
- stringIdP = malloc(sizeof(ulongest_t));
- if (stringIdP == NULL)
- everror("Can't allocate space for a string's ID");
- *stringIdP = parseHex(&p);
- res = TableDefine(labelTable, (Word)address, (void *)stringIdP);
+
+ if (TableLookup(&tmp, labelTable, address)) {
+ list = tmp;
+ } else {
+ /* First label for this address */
+ res = mps_alloc(&tmp, pool, sizeof(LabelListStruct));
+ if (res != MPS_RES_OK)
+ everror("Can't allocate space for a label list");
+ list = tmp;
+ list->n = 0;
+ res = TableDefine(labelTable, (Word)address, list);
+ if (res != ResOK)
+ everror("Couldn't create a label mapping.");
+ }
+
+ res = mps_alloc(&tmp, pool, sizeof(LabelStruct) * (list->n + 1));
if (res != ResOK)
- everror("Couldn't create an intern mapping.");
+ everror("Couldn't allocate space for list of labels.");
+ newlabels = tmp;
+
+ pos = labelFind(list, clock);
+ memcpy(newlabels, list->labels, sizeof(LabelStruct) * pos);
+ newlabels[pos].clock = clock;
+ newlabels[pos].id = parseHex(&p);
+ memcpy(newlabels + pos + 1, list->labels + pos,
+ sizeof(LabelStruct) * (list->n - pos));
+ if (list->n > 0)
+ mps_free(pool, list->labels, sizeof(LabelStruct) * list->n);
+ list->labels = newlabels;
+ ++ list->n;
}
/* output code */
@@ -308,20 +385,23 @@ static int hexWordWidth = (MPS_WORD_WIDTH+3)/4;
/* printAddr -- output a ulongest_t in hex, with the interned string
* if the value is in the label table */
-static void printAddr(ulongest_t addr, const char *ident)
+static void printAddr(ulongest_t clock, ulongest_t addr, const char *ident)
{
- ulongest_t label;
- void *alias;
+ void *tmp;
printf("%s:%0*" PRIXLONGEST, ident, hexWordWidth, addr);
- if (TableLookup(&alias, labelTable, addr)) {
- label = *(ulongest_t*)alias;
- putchar('[');
- if (TableLookup(&alias, internTable, label))
- printStr((char *)alias);
- else
- printf("unknown label %" PRIuLONGEST, label);
- putchar(']');
+ if (TableLookup(&tmp, labelTable, addr)) {
+ LabelList list = tmp;
+ size_t pos = labelFind(list, clock);
+ if (pos > 0) {
+ ulongest_t id = list->labels[pos - 1].id;
+ putchar('[');
+ if (TableLookup(&tmp, internTable, id))
+ printStr((char *)tmp);
+ else
+ printf("unknown label %" PRIXLONGEST, id);
+ putchar(']');
+ }
}
putchar(' ');
}
@@ -332,7 +412,7 @@ static void printAddr(ulongest_t addr, const char *ident)
#define processParamA(ident) \
val_hex = parseHex(&p); \
- printAddr(val_hex, #ident);
+ printAddr(clock, val_hex, #ident);
#define processParamP processParamA
#define processParamW processParamA
@@ -375,7 +455,7 @@ static const char *eventName[EventCodeMAX+EventCodeMAX];
/* readLog -- read and parse log. Returns the number of events written. */
-static void readLog(FILE *input)
+static void readLog(mps_pool_t pool, FILE *input)
{
int i;
@@ -415,9 +495,9 @@ static void readLog(FILE *input)
/* for a few particular codes, we do local processing. */
if (code == EventInternCode) {
- recordIntern(q);
+ recordIntern(pool, q);
} else if (code == EventLabelCode) {
- recordLabel(q);
+ recordLabel(pool, clock, q);
} else if (code == EventEventInitCode) {
ulongest_t major, median, minor, maxCode, maxNameLen, wordWidth, clocksPerSec;
major = parseHex(&q); /* EVENT_VERSION_MAJOR */
@@ -476,6 +556,9 @@ static void readLog(FILE *input)
int main(int argc, char *argv[])
{
+ mps_arena_t arena;
+ mps_pool_t pool;
+ mps_res_t res;
FILE *input;
parseArgs(argc, argv);
@@ -488,8 +571,20 @@ int main(int argc, char *argv[])
everror("unable to open %s", logFileName);
}
- createTables();
- readLog(input);
+ res = mps_arena_create_k(&arena, mps_arena_class_vm(), mps_args_none);
+ if (res != MPS_RES_OK)
+ everror("failed to create arena: %d", res);
+
+ res = mps_pool_create_k(&pool, arena, mps_class_mvff(), mps_args_none);
+ if (res != MPS_RES_OK)
+ everror("failed to create pool: %d", res);
+
+ createTables(pool);
+ readLog(pool, input);
+
+ mps_pool_destroy(pool);
+ mps_arena_destroy(arena);
+
(void)fclose(input);
return 0;
}
diff --git a/mps/code/exposet0.c b/mps/code/exposet0.c
index 11e78ad29cb..21f2567cbaa 100644
--- a/mps/code/exposet0.c
+++ b/mps/code/exposet0.c
@@ -19,12 +19,9 @@
#include "mpscamc.h"
#include "mpsavm.h"
#include "mpstd.h"
-#ifdef MPS_OS_W3
-#include "mpsw3.h"
-#endif
#include "mps.h"
-#include
-#include
+
+#include /* fflush, printf, puts, stdout */
/* These values have been tuned in the hope of getting one dynamic collection. */
@@ -75,12 +72,6 @@ static void report(mps_arena_t arena)
printf("not_condemned %"PRIuLONGEST"\n", (ulongest_t)not_condemned);
mps_message_discard(arena, message);
-
- if (condemned > (gen1SIZE + gen2SIZE + (size_t)128) * 1024)
- /* When condemned size is larger than could happen in a gen 2
- * collection (discounting ramps, natch), guess that was a dynamic
- * collection, and reset the commit limit, so it doesn't run out. */
- die(mps_arena_commit_limit_set(arena, 2 * testArenaSIZE), "set limit");
}
}
@@ -115,15 +106,7 @@ static void test_stepper(mps_addr_t object, mps_fmt_t fmt, mps_pool_t pool,
testlib_unused(fmt);
testlib_unused(pool);
testlib_unused(s);
-#ifdef MPS_OS_W3
- __try {
- dylan_mutate(object);
- } __except(EXCEPTION_EXECUTE_HANDLER) {
- error("Unexpected exception.\n");
- }
-#else
dylan_mutate(object);
-#endif
(*(unsigned long *)p)++;
}
diff --git a/mps/code/expt825.c b/mps/code/expt825.c
index 5947a0cff68..5e775455909 100644
--- a/mps/code/expt825.c
+++ b/mps/code/expt825.c
@@ -34,10 +34,8 @@
#include "fmtdy.h"
#include "fmtdytst.h"
#include "mpstd.h"
-#ifdef MPS_OS_W3
-#include "mpsw3.h"
-#endif
-#include
+
+#include /* printf, fflush, stdout */
#define testArenaSIZE ((size_t)16<<20)
diff --git a/mps/code/finalcv.c b/mps/code/finalcv.c
index e8f7e251a6e..1466e514ff8 100644
--- a/mps/code/finalcv.c
+++ b/mps/code/finalcv.c
@@ -26,10 +26,8 @@
#include "fmtdy.h"
#include "fmtdytst.h"
#include "mpstd.h"
-#ifdef MPS_OS_W3
-#include "mpsw3.h"
-#endif
-#include
+
+#include /* printf */
#define testArenaSIZE ((size_t)16<<20)
diff --git a/mps/code/finaltest.c b/mps/code/finaltest.c
index dd6146851df..88895027286 100644
--- a/mps/code/finaltest.c
+++ b/mps/code/finaltest.c
@@ -22,14 +22,13 @@
#include "mpscamc.h"
#include "mpscams.h"
#include "mpscawl.h"
+#include "mpsclo.h"
#include "mpsavm.h"
#include "fmtdy.h"
#include "fmtdytst.h"
#include "mpstd.h"
-#ifdef MPS_OS_W3
-#include "mpsw3.h"
-#endif
-#include
+
+#include /* fflush, printf, stdout */
#define testArenaSIZE ((size_t)16<<20)
@@ -160,16 +159,16 @@ static void test_trees(const char *name, mps_arena_t arena, mps_ap_t ap,
while (mps_message_poll(arena)) {
mps_message_t message;
mps_addr_t objaddr;
- cdie(mps_message_get(&message, arena,
- mps_message_type_finalization()),
- "get");
+ cdie(mps_message_get(&message, arena, mps_message_type_finalization()),
+ "message_get");
mps_message_finalization_ref(&objaddr, arena, message);
mps_message_discard(arena, message);
++ final_this_time;
}
finals += final_this_time;
printf("%"PRIuLONGEST" objects finalized: total %"PRIuLONGEST
- " of %"PRIuLONGEST"\n", final_this_time, finals, object_count);
+ " of %"PRIuLONGEST"\n", (ulongest_t)final_this_time,
+ (ulongest_t)finals, (ulongest_t)object_count);
}
cdie(finals == object_count, "Not all objects were finalized.");
}
@@ -183,6 +182,8 @@ static void *test(mps_arena_t arena, mps_class_t pool_class)
die(mps_fmt_create_A(&fmt, arena, dylan_fmt_A()), "fmt_create\n");
MPS_ARGS_BEGIN(args) {
+ /* Allocate into generation 0 so that they get finalized quickly. */
+ MPS_ARGS_ADD(args, MPS_KEY_GEN, 0);
MPS_ARGS_ADD(args, MPS_KEY_FORMAT, fmt);
MPS_ARGS_ADD(args, MPS_KEY_AWL_FIND_DEPENDENT, test_awl_find_dependent);
die(mps_pool_create_k(&pool, arena, pool_class, args),
@@ -221,8 +222,10 @@ int main(int argc, char *argv[])
die(mps_thread_reg(&thread, arena), "thread_reg\n");
test(arena, mps_class_amc());
- /* TODO: test(arena, mps_class_ams()); */
- /* TODO: test(arena, mps_class_awl()); */
+ test(arena, mps_class_amcz());
+ test(arena, mps_class_ams());
+ test(arena, mps_class_awl());
+ /* TODO: test(arena, mps_class_lo()); */
mps_thread_dereg(thread);
mps_arena_destroy(arena);
diff --git a/mps/code/fmtdytst.c b/mps/code/fmtdytst.c
index 376c43aa7df..c7971098704 100644
--- a/mps/code/fmtdytst.c
+++ b/mps/code/fmtdytst.c
@@ -73,8 +73,12 @@ mps_res_t dylan_make_wrappers(void)
* If the raw memory is large enough, initialises it to a dylan-vector,
* whose slots are initialised to either dylan-ints, or valid refs, at
* random.
- * Caller must supply an array of (at least 1) valid refs to copy, via
- * the "refs" and "nr_refs" arguments.
+ *
+ * Caller must supply an array of valid refs to copy, via the "refs"
+ * and "nr_refs" arguments. If "nr_refs" is 0, all slots are
+ * initialized to dylan-ints: this may be useful for making leaf
+ * objects.
+ *
* (Makes a pad if the raw memory is too small to hold a dylan-vector)
*/
@@ -100,7 +104,7 @@ mps_res_t dylan_init(mps_addr_t addr, size_t size,
for(i = 0; i < t; ++i) {
mps_word_t r = rnd();
- if(r & 1)
+ if(nr_refs == 0 || (r & 1))
p[2+i] = ((r & ~(mps_word_t)3) | 1); /* random int */
else
p[2+i] = (mps_word_t)refs[(r >> 1) % nr_refs]; /* random ptr */
diff --git a/mps/code/fmtscheme.c b/mps/code/fmtscheme.c
index 5299c8f3525..11900130a71 100644
--- a/mps/code/fmtscheme.c
+++ b/mps/code/fmtscheme.c
@@ -12,14 +12,8 @@
/* special objects */
-obj_t obj_empty; /* (), the empty list */
-obj_t obj_eof; /* end of file */
-obj_t obj_error; /* error indicator */
-obj_t obj_true; /* #t, boolean true */
-obj_t obj_false; /* #f, boolean false */
-obj_t obj_undefined; /* undefined result indicator */
-obj_t obj_tail; /* tail recursion indicator */
-obj_t obj_deleted; /* deleted key in hashtable */
+static obj_t obj_true; /* #t, boolean true */
+static obj_t obj_false; /* #f, boolean false */
/* MPS globals */
diff --git a/mps/code/fotest.c b/mps/code/fotest.c
index f3d683cf674..2729395c0df 100644
--- a/mps/code/fotest.c
+++ b/mps/code/fotest.c
@@ -28,7 +28,7 @@
#include "mpmtypes.h"
#include "poolmfs.h"
-#include
+#include /* printf */
#define testArenaSIZE ((((size_t)3)<<24) - 4)
@@ -181,7 +181,7 @@ int main(int argc, char *argv[])
die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE),
"mps_arena_create");
- alignment = (1 << (rnd() % 4)) * MPS_PF_ALIGN;
+ alignment = sizeof(void *) << (rnd() % 4);
MPS_ARGS_BEGIN(args) {
MPS_ARGS_ADD(args, MPS_KEY_EXTEND_BY, (64 + rnd() % 64) * 1024);
MPS_ARGS_ADD(args, MPS_KEY_MEAN_SIZE, (1 + rnd() % 8) * 8);
@@ -200,7 +200,7 @@ int main(int argc, char *argv[])
die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE),
"mps_arena_create");
- alignment = (1 << (rnd() % 4)) * MPS_PF_ALIGN;
+ alignment = sizeof(void *) << (rnd() % 4);
MPS_ARGS_BEGIN(args) {
MPS_ARGS_ADD(args, MPS_KEY_ALIGN, alignment);
MPS_ARGS_ADD(args, MPS_KEY_MIN_SIZE, (1 + rnd() % 4) * 4);
diff --git a/mps/code/gcbench.c b/mps/code/gcbench.c
index 61b6e925e94..2a18d1a7d10 100644
--- a/mps/code/gcbench.c
+++ b/mps/code/gcbench.c
@@ -7,18 +7,16 @@
*/
#include "mps.c"
-
-#include
-#include
-#include
-#include
-#include
#include "getopt.h"
#include "testlib.h"
-
+#include "testthr.h"
#include "fmtdy.h"
#include "fmtdytst.h"
+#include /* fprintf, printf, putchars, sscanf, stderr, stdout */
+#include /* alloca, exit, EXIT_FAILURE, EXIT_SUCCESS, strtoul */
+#include /* clock, CLOCKS_PER_SEC */
+
#define RESMUST(expr) \
do { \
mps_res_t res = (expr); \
@@ -56,7 +54,7 @@ typedef struct gcthread_s *gcthread_t;
typedef void *(*gcthread_fn_t)(gcthread_t thread);
struct gcthread_s {
- pthread_t pthread;
+ testthr_t thread;
mps_thr_t mps_thread;
mps_root_t reg_root;
mps_ap_t ap;
@@ -189,23 +187,12 @@ static void weave(gcthread_fn_t fn)
for (t = 0; t < nthreads; ++t) {
gcthread_t thread = &threads[t];
- int err;
thread->fn = fn;
- err = pthread_create(&thread->pthread, NULL, start, thread);
- if (err != 0) {
- fprintf(stderr, "Unable to create thread: %d\n", err);
- exit(EXIT_FAILURE);
- }
+ testthr_create(&thread->thread, start, thread);
}
- for (t = 0; t < nthreads; ++t) {
- gcthread_t thread = &threads[t];
- int err = pthread_join(thread->pthread, NULL);
- if (err != 0) {
- fprintf(stderr, "Unable to join thread: %d\n", err);
- exit(EXIT_FAILURE);
- }
- }
+ for (t = 0; t < nthreads; ++t)
+ testthr_join(&threads[t].thread, NULL);
}
static void weave1(gcthread_fn_t fn)
@@ -331,8 +318,8 @@ int main(int argc, char *argv[]) {
double mort = 0.0;
cap = (size_t)strtoul(optarg, &p, 10);
switch(toupper(*p)) {
- case 'G': cap *= 1024; /* fall through */
- case 'M': cap *= 1024; /* fall through */
+ case 'G': cap <<= 20; p++; break;
+ case 'M': cap <<= 10; p++; break;
case 'K': p++; break;
default: cap = 0; break;
}
@@ -353,9 +340,9 @@ int main(int argc, char *argv[]) {
char *p;
arenasize = (unsigned)strtoul(optarg, &p, 10);
switch(toupper(*p)) {
- case 'G': arenasize *= 1024;
- case 'M': arenasize *= 1024;
- case 'K': arenasize *= 1024; break;
+ case 'G': arenasize <<= 30; break;
+ case 'M': arenasize <<= 20; break;
+ case 'K': arenasize <<= 10; break;
case '\0': break;
default:
fprintf(stderr, "Bad arena size %s\n", optarg);
@@ -432,7 +419,8 @@ int main(int argc, char *argv[]) {
argv += optind;
printf("seed: %lu\n", seed);
-
+ (void)fflush(stdout);
+
while (argc > 0) {
for (i = 0; i < sizeof(pools) / sizeof(pools[0]); ++i)
if (strcmp(argv[0], pools[i].name) == 0)
diff --git a/mps/code/getopt.h b/mps/code/getopt.h
index ad2a956608c..fb9c789d235 100644
--- a/mps/code/getopt.h
+++ b/mps/code/getopt.h
@@ -48,8 +48,6 @@
#ifndef _GETOPT_H_
#define _GETOPT_H_
-#include
-
/*
* GNU-like getopt_long()/getopt_long_only() with 4.4BSD optreset extension.
* getopt() is declared here too for GNU programs.
@@ -72,7 +70,6 @@ struct option {
int val;
};
-__BEGIN_DECLS
int getopt_long(int, char * const *, const char *,
const struct option *, int *);
int getopt_long_only(int, char * const *, const char *,
@@ -88,6 +85,5 @@ extern int optind, opterr, optopt;
#define _OPTRESET_DECLARED
extern int optreset; /* getopt(3) external variable */
#endif
-__END_DECLS
#endif /* !_GETOPT_H_ */
diff --git a/mps/code/global.c b/mps/code/global.c
index 22326aa391f..5f635206bd9 100644
--- a/mps/code/global.c
+++ b/mps/code/global.c
@@ -397,25 +397,7 @@ void GlobalsFinish(Globals arenaGlobals)
Arena arena;
Rank rank;
- /* Check that the tear-down is complete: that the client has
- * destroyed all data structures associated with the arena. We do
- * this *before* calling AVERT(Globals, arenaGlobals) because the
- * AVERT will crash if there are any remaining data structures, and
- * it is politer to assert than to crash. (The crash would happen
- * because by this point in the code the control pool has been
- * destroyed and so the address space containing all these rings has
- * potentially been unmapped, and so RingCheck dereferences a
- * pointer into that unmapped memory.) See job000652. */
arena = GlobalsArena(arenaGlobals);
- AVER(RingIsSingle(&arena->formatRing));
- AVER(RingIsSingle(&arena->chainRing));
- AVER(RingIsSingle(&arena->messageRing));
- AVER(RingIsSingle(&arena->threadRing));
- for(rank = 0; rank < RankLIMIT; ++rank)
- AVER(RingIsSingle(&arena->greyRing[rank]));
- AVER(RingIsSingle(&arenaGlobals->poolRing));
- AVER(RingIsSingle(&arenaGlobals->rootRing));
-
AVERT(Globals, arenaGlobals);
STATISTIC_STAT(EVENT2(ArenaWriteFaults, arena,
@@ -445,6 +427,7 @@ void GlobalsPrepareToDestroy(Globals arenaGlobals)
TraceId ti;
Trace trace;
Chain defaultChain;
+ Rank rank;
AVERT(Globals, arenaGlobals);
@@ -499,6 +482,31 @@ void GlobalsPrepareToDestroy(Globals arenaGlobals)
arena->finalPool = NULL;
PoolDestroy(pool);
}
+
+ /* Check that the tear-down is complete: that the client has
+ * destroyed all data structures associated with the arena. We do
+ * this here rather than in GlobalsFinish because by the time that
+ * is called, the control pool has been destroyed and so the address
+ * space containing all these rings has potentially been unmapped,
+ * and so RingCheck dereferences a pointer into that unmapped memory
+ * and we get a crash instead of an assertion. See job000652.
+ */
+ AVER(RingIsSingle(&arena->formatRing));
+ AVER(RingIsSingle(&arena->chainRing));
+ AVER(RingIsSingle(&arena->messageRing));
+ AVER(RingIsSingle(&arena->threadRing));
+ AVER(RingIsSingle(&arenaGlobals->rootRing));
+ for(rank = 0; rank < RankLIMIT; ++rank)
+ AVER(RingIsSingle(&arena->greyRing[rank]));
+
+ /* At this point the following pools still exist:
+ * 0. arena->freeCBSBlockPoolStruct
+ * 1. arena->reservoirStruct
+ * 2. arena->controlPoolStruct
+ * 3. arena->controlPoolStruct.blockPoolStruct
+ * 4. arena->controlPoolStruct.spanPoolStruct
+ */
+ AVER(RingLength(&arenaGlobals->poolRing) == 5);
}
@@ -617,6 +625,7 @@ void ArenaLeaveRecursive(Arena arena)
* version. The format is platform-specific. We won't necessarily
* publish this. */
+extern MutatorFaultContext mps_exception_info;
MutatorFaultContext mps_exception_info = NULL;
@@ -1131,7 +1140,7 @@ void ArenaSetEmergency(Arena arena, Bool emergency)
AVERT(Arena, arena);
AVERT(Bool, emergency);
- EVENT2(ArenaSetEmergency, arena, emergency);
+ EVENT2(ArenaSetEmergency, arena, BOOL(emergency));
arena->emergency = emergency;
}
diff --git a/mps/code/landtest.c b/mps/code/landtest.c
index b3f91eb0cc4..ef13e196600 100644
--- a/mps/code/landtest.c
+++ b/mps/code/landtest.c
@@ -26,9 +26,7 @@
#include "poolmfs.h"
#include "testlib.h"
-#include
-#include
-#include
+#include /* printf */
SRCID(landtest, "$Id$");
diff --git a/mps/code/ll.gmk b/mps/code/ll.gmk
index dc2595c511f..24dd32b9efe 100644
--- a/mps/code/ll.gmk
+++ b/mps/code/ll.gmk
@@ -17,10 +17,13 @@ CFLAGSCOMPILER := \
-Waggregate-return \
-Wall \
-Wcast-qual \
+ -Wconversion \
+ -Wduplicate-enum \
-Werror \
-Wextra \
-Winline \
-Wmissing-prototypes \
+ -Wmissing-variable-declarations \
-Wnested-externs \
-Wno-extended-offsetof \
-Wpointer-arith \
diff --git a/mps/code/locbwcss.c b/mps/code/locbwcss.c
index 0e40c254635..dbf54e7e881 100644
--- a/mps/code/locbwcss.c
+++ b/mps/code/locbwcss.c
@@ -11,8 +11,7 @@
#include "mpslib.h"
#include "mps.h"
-#include
-#include
+#include /* printf */
/* some constants */
diff --git a/mps/code/lockcov.c b/mps/code/lockcov.c
index a8237f7de72..75ded6f202a 100644
--- a/mps/code/lockcov.c
+++ b/mps/code/lockcov.c
@@ -4,19 +4,37 @@
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
*/
+#include "mps.h"
+#include "mpsavm.h"
+#include "mpscmfs.h"
#include "mpm.h"
#include "testlib.h"
#include "mpslib.h"
-#include /* for malloc & free */
+
+#include /* printf */
int main(int argc, char *argv[])
{
- Lock a = malloc(LockSize());
- Lock b = malloc(LockSize());
+ mps_arena_t arena;
+ mps_pool_t pool;
+ mps_addr_t p;
+ Lock a, b;
testlib_init(argc, argv);
+ die(mps_arena_create_k(&arena, mps_arena_class_vm(), mps_args_none),
+ "arena_create");
+ MPS_ARGS_BEGIN(args) {
+ MPS_ARGS_ADD(args, MPS_KEY_MFS_UNIT_SIZE, LockSize());
+ die(mps_pool_create_k(&pool, arena, mps_class_mfs(), args), "pool_create");
+ } MPS_ARGS_END(args);
+
+ die(mps_alloc(&p, pool, LockSize()), "alloc a");
+ a = p;
+ die(mps_alloc(&p, pool, LockSize()), "alloc b");
+ b = p;
+
Insist(a != NULL);
Insist(b != NULL);
@@ -44,8 +62,11 @@ int main(int argc, char *argv[])
LockReleaseMPM(a);
LockFinish(a);
LockReleaseGlobalRecursive();
- free(a);
- free(b);
+
+ mps_free(pool, a, LockSize());
+ mps_free(pool, b, LockSize());
+ mps_pool_destroy(pool);
+ mps_arena_destroy(arena);
printf("%s: Conclusion: Failed to find any defects.\n", argv[0]);
return 0;
diff --git a/mps/code/lockutw3.c b/mps/code/lockut.c
similarity index 77%
rename from mps/code/lockutw3.c
rename to mps/code/lockut.c
index 43f486799df..e93bdea6815 100644
--- a/mps/code/lockutw3.c
+++ b/mps/code/lockut.c
@@ -1,30 +1,26 @@
-/* lockutw3.c: LOCK UTILIZATION TEST
+/* lockut.c: LOCK UTILIZATION TEST
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
*/
-#include /* malloc */
-
+#include "mps.h"
+#include "mpsavm.h"
+#include "mpscmfs.h"
#include "mpm.h"
#include "testlib.h"
-#include "mpslib.h"
+#include "testthr.h"
-#include "mpswin.h"
-
-
-#ifndef MPS_OS_W3
-#error "Relies on Win32 threads"
-#endif
+#include /* printf */
#define nTHREADS 4
static Lock lock;
-unsigned long shared, tmp;
+static unsigned long shared, tmp;
-void incR(unsigned long i)
+static void incR(unsigned long i)
{
LockClaimRecursive(lock);
if (i < 100) {
@@ -40,7 +36,7 @@ void incR(unsigned long i)
}
-void inc(unsigned long i)
+static void inc(unsigned long i)
{
incR( (i+1) >>1);
i >>= 1;
@@ -59,23 +55,33 @@ void inc(unsigned long i)
#define COUNT 100000l
-DWORD WINAPI thread0(void *p)
+static void *thread0(void *p)
{
- (void)p;
+ testlib_unused(p);
inc(COUNT);
- return 0;
+ return NULL;
}
int main(int argc, char *argv[])
{
- DWORD id;
- HANDLE t[10];
+ mps_arena_t arena;
+ mps_pool_t pool;
+ mps_addr_t p;
+ testthr_t t[10];
unsigned i;
testlib_init(argc, argv);
- lock = malloc(LockSize());
+ die(mps_arena_create_k(&arena, mps_arena_class_vm(), mps_args_none),
+ "arena_create");
+ MPS_ARGS_BEGIN(args) {
+ MPS_ARGS_ADD(args, MPS_KEY_MFS_UNIT_SIZE, LockSize());
+ die(mps_pool_create_k(&pool, arena, mps_class_mfs(), args), "pool_create");
+ } MPS_ARGS_END(args);
+
+ die(mps_alloc(&p, pool, LockSize()), "alloc");
+ lock = p;
Insist(lock != NULL);
LockInit(lock);
@@ -84,17 +90,19 @@ int main(int argc, char *argv[])
shared = 0;
for(i = 0; i < nTHREADS; i++)
- t[i] = CreateThread(NULL, 0, thread0, NULL, 0, &id);
+ testthr_create(&t[i], thread0, NULL);
- for(i = 0; i < nTHREADS; i++) {
- cdie(WaitForSingleObject(t[i], INFINITE) == WAIT_OBJECT_0,
- "WaitForSingleObject");
- }
+ for(i = 0; i < nTHREADS; i++)
+ testthr_join(&t[i], NULL);
Insist(shared == nTHREADS*COUNT);
LockFinish(lock);
+ mps_free(pool, lock, LockSize());
+ mps_pool_destroy(pool);
+ mps_arena_destroy(arena);
+
printf("%s: Conclusion: Failed to find any defects.\n", argv[0]);
return 0;
}
diff --git a/mps/code/locusss.c b/mps/code/locusss.c
index 3dfbc78afe1..70cf313ed45 100644
--- a/mps/code/locusss.c
+++ b/mps/code/locusss.c
@@ -12,8 +12,7 @@
#include "mpslib.h"
#include "mps.h"
-#include
-#include
+#include /* printf */
/* some constants */
diff --git a/mps/code/locv.c b/mps/code/locv.c
index 56c9a46d2c5..06d2722dac3 100644
--- a/mps/code/locv.c
+++ b/mps/code/locv.c
@@ -13,6 +13,8 @@
#include "mpsclo.h"
#include "mpsavm.h"
+#include /* printf */
+
#define testArenaSIZE ((size_t)16<<20)
diff --git a/mps/code/messtest.c b/mps/code/messtest.c
index 7f96360f78e..96deeebfc58 100644
--- a/mps/code/messtest.c
+++ b/mps/code/messtest.c
@@ -10,8 +10,7 @@
#include "testlib.h"
#include "mpslib.h"
-#include
-#include
+#include /* printf */
SRCID(messtest, "$Id$");
diff --git a/mps/code/meter.h b/mps/code/meter.h
index 7a7f8266e87..f1731400e42 100644
--- a/mps/code/meter.h
+++ b/mps/code/meter.h
@@ -1,7 +1,7 @@
/* meter.h: METER INTERFACE
*
* $Id$
- * Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
+ * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
*
* .sources: mps.design.metrics.
*
@@ -45,9 +45,12 @@ extern void MeterEmit(Meter meter);
#define METER_ACC(meter, delta) \
STATISTIC(MeterAccumulate(&(meter), delta))
#if defined(STATISTICS)
-#define METER_WRITE(meter, stream) MeterWrite(&(meter), stream)
+#define METER_WRITE(meter, stream) BEGIN \
+ Res _res = MeterWrite(&(meter), (stream)); \
+ if (_res != ResOK) return _res; \
+ END
#elif defined(STATISTICS_NONE)
-#define METER_WRITE(meter, stream) (ResOK)
+#define METER_WRITE(meter, stream) NOOP
#else
#error "No statistics configured."
#endif
@@ -59,7 +62,7 @@ extern void MeterEmit(Meter meter);
/* C. COPYRIGHT AND LICENSE
*
- * Copyright (C) 2001-2013 Ravenbrook Limited .
+ * Copyright (C) 2001-2014 Ravenbrook Limited .
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*
diff --git a/mps/code/misc.h b/mps/code/misc.h
index 6ba4be5f49d..809fd7e954a 100644
--- a/mps/code/misc.h
+++ b/mps/code/misc.h
@@ -1,7 +1,7 @@
/* misc.h: MISCELLANEOUS DEFINITIONS
*
* $Id$
- * Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
+ * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Portions copyright (C) 2001 Global Graphics Software.
*
* Small general things which are useful for C but aren't part of the
@@ -50,6 +50,7 @@ typedef const struct SrcIdStruct {
#define SRCID(id, scmid) \
static SrcIdStruct id ## FileSrcIdStruct = \
{__FILE__, (scmid), __DATE__, __TIME__}; \
+ extern SrcId id ## SrcId; \
SrcId id ## SrcId = &id ## FileSrcIdStruct
@@ -170,6 +171,16 @@ typedef const struct SrcIdStruct {
((type *)(void *)((char *)(p) - offsetof(type, field)))
+/* BITFIELD -- coerce a value into a bitfield
+ *
+ * This coerces value to the given width and type in a way that avoids
+ * warnings from gcc -Wconversion about possible loss of data.
+ */
+
+#define BITFIELD(type, value, width) ((type)value & (((type)1 << (width)) - 1))
+#define BOOL(v) BITFIELD(unsigned, (v), 1)
+
+
/* Bit Sets -- sets of integers in [0,N-1].
*
* Can be used on any unsigned integral type, ty. These definitions
@@ -191,6 +202,7 @@ typedef const struct SrcIdStruct {
#define BS_SUB(s1, s2) BS_SUPER((s2), (s1))
#define BS_IS_SINGLE(s) ( ((s) != 0) && (((s) & ((s)-1)) == 0) )
#define BS_SYM_DIFF(s1, s2) ((s1) ^ (s2))
+#define BS_BITFIELD(ty, s) BITFIELD(ty ## Set, (s), ty ## LIMIT)
#endif /* misc_h */
@@ -198,7 +210,7 @@ typedef const struct SrcIdStruct {
/* C. COPYRIGHT AND LICENSE
*
- * Copyright (C) 2001-2002 Ravenbrook Limited .
+ * Copyright (C) 2001-2014 Ravenbrook Limited .
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*
diff --git a/mps/code/mpm.c b/mps/code/mpm.c
index f544acca401..a46fdf5fb10 100644
--- a/mps/code/mpm.c
+++ b/mps/code/mpm.c
@@ -174,16 +174,16 @@ Word (WordAlignDown)(Word word, Align alignment)
/* SizeIsP2 -- test whether a size is a power of two */
-Bool SizeIsP2(Size size)
+Bool (SizeIsP2)(Size size)
{
- return WordIsP2((Word)size);
+ return SizeIsP2(size);
}
/* WordIsP2 -- tests whether a word is a power of two */
-Bool WordIsP2(Word word)
+Bool (WordIsP2)(Word word)
{
- return word > 0 && (word & (word - 1)) == 0;
+ return WordIsP2(word);
}
diff --git a/mps/code/mpm.h b/mps/code/mpm.h
index 9b12eb6ccb5..422327453dc 100644
--- a/mps/code/mpm.h
+++ b/mps/code/mpm.h
@@ -143,11 +143,13 @@ extern Bool ResIsAllocFailure(Res res);
* SizeFloorLog2 returns the floor of the logarithm in base 2 of size.
* size can be any positive non-zero value. */
-extern Bool SizeIsP2(Size size);
+extern Bool (SizeIsP2)(Size size);
+#define SizeIsP2(size) WordIsP2((Word)size)
extern Shift SizeLog2(Size size);
extern Shift SizeFloorLog2(Size size);
-extern Bool WordIsP2(Word word);
+extern Bool (WordIsP2)(Word word);
+#define WordIsP2(word) ((word) > 0 && ((word) & ((word) - 1)) == 0)
/* Formatted Output -- see , */
@@ -709,10 +711,10 @@ extern Addr (SegLimit)(Seg seg);
#define SegSummary(seg) (((GCSeg)(seg))->summary)
-#define SegSetPM(seg, mode) ((void)((seg)->pm = (mode)))
-#define SegSetSM(seg, mode) ((void)((seg)->sm = (mode)))
-#define SegSetDepth(seg, d) ((void)((seg)->depth = (d)))
-#define SegSetNailed(seg, ts) ((void)((seg)->nailed = (ts)))
+#define SegSetPM(seg, mode) ((void)((seg)->pm = BS_BITFIELD(Access, (mode))))
+#define SegSetSM(seg, mode) ((void)((seg)->sm = BS_BITFIELD(Access, (mode))))
+#define SegSetDepth(seg, d) ((void)((seg)->depth = BITFIELD(unsigned, (d), ShieldDepthWIDTH)))
+#define SegSetNailed(seg, ts) ((void)((seg)->nailed = BS_BITFIELD(Trace, (ts))))
/* Buffer Interface -- see */
diff --git a/mps/code/mpmss.c b/mps/code/mpmss.c
index 9dd25574417..339ae5b54f4 100644
--- a/mps/code/mpmss.c
+++ b/mps/code/mpmss.c
@@ -7,19 +7,14 @@
#include "mpscmv.h"
#include "mpscmvff.h"
+#include "mpscmfs.h"
#include "mpslib.h"
#include "mpsavm.h"
#include "testlib.h"
#include "mpslib.h"
#include "mps.h"
-#include
-#include
-
-/* TODO: Decide whether we should support the MPS pool class externally,
- create mpscmfs.h, and replace this extern with proper use of its
- interface. */
-extern mps_class_t PoolClassMFS(void);
+#include /* printf */
#define testArenaSIZE ((((size_t)64)<<20) - 4)
@@ -156,8 +151,7 @@ static void testInArena(mps_arena_t arena, mps_pool_debug_option_s *options)
printf("MFS\n");
fixedSizeSize = 13;
- die(stress(PoolClassMFS(),
- fixedSize, arena, (size_t)100000, fixedSizeSize),
+ die(stress(mps_class_mfs(), fixedSize, arena, (size_t)100000, fixedSizeSize),
"stress MFS");
printf("MV\n");
diff --git a/mps/code/mpmst.h b/mps/code/mpmst.h
index 3dd920758f0..80bbd298090 100644
--- a/mps/code/mpmst.h
+++ b/mps/code/mpmst.h
@@ -1,7 +1,7 @@
/* mpmst.h: MEMORY POOL MANAGER DATA STRUCTURES
*
* $Id$
- * Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
+ * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Portions copyright (C) 2001 Global Graphics Software.
*
* .design: This header file crosses module boundaries. The relevant
@@ -275,8 +275,8 @@ typedef struct SegStruct { /* segment structure */
RingStruct poolRing; /* link in list of segs in pool */
Addr limit; /* limit of segment */
unsigned depth : ShieldDepthWIDTH; /* see */
- AccessSet pm : AccessSetWIDTH; /* protection mode, */
- AccessSet sm : AccessSetWIDTH; /* shield mode, */
+ AccessSet pm : AccessLIMIT; /* protection mode, */
+ AccessSet sm : AccessLIMIT; /* shield mode, */
TraceSet grey : TraceLIMIT; /* traces for which seg is grey */
TraceSet white : TraceLIMIT; /* traces for which seg is white */
TraceSet nailed : TraceLIMIT; /* traces for which seg has nailed objects */
@@ -817,7 +817,7 @@ typedef struct AllocPatternStruct {
/* C. COPYRIGHT AND LICENSE
*
- * Copyright (C) 2001-2013 Ravenbrook Limited .
+ * Copyright (C) 2001-2014 Ravenbrook Limited .
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*
diff --git a/mps/code/mpmtypes.h b/mps/code/mpmtypes.h
index 5d1a195fe45..d8eebb7bcd6 100644
--- a/mps/code/mpmtypes.h
+++ b/mps/code/mpmtypes.h
@@ -287,7 +287,7 @@ typedef Res (*LandDescribeMethod)(Land land, mps_lib_FILE *stream);
#define AccessSetEMPTY ((AccessSet)0) /* */
#define AccessREAD ((AccessSet)(1<<0))
#define AccessWRITE ((AccessSet)(1<<1))
-#define AccessSetWIDTH (2)
+#define AccessLIMIT (2)
#define RefSetEMPTY BS_EMPTY(RefSet)
#define RefSetUNIV BS_UNIV(RefSet)
#define ZoneSetEMPTY BS_EMPTY(ZoneSet)
diff --git a/mps/code/mps.xcodeproj/project.pbxproj b/mps/code/mps.xcodeproj/project.pbxproj
index 24381fa5c02..8b87dd9e7fc 100644
--- a/mps/code/mps.xcodeproj/project.pbxproj
+++ b/mps/code/mps.xcodeproj/project.pbxproj
@@ -50,6 +50,7 @@
3114A65B156E95B4001E0AA3 /* PBXTargetDependency */,
2231BB6D18CA986B002D6322 /* PBXTargetDependency */,
31D60034156D3D5A00337B26 /* PBXTargetDependency */,
+ 2286E4C918F4389E004111E2 /* PBXTargetDependency */,
2231BB6F18CA986D002D6322 /* PBXTargetDependency */,
3114A5A0156E915A001E0AA3 /* PBXTargetDependency */,
3114A6A7156E9739001E0AA3 /* PBXTargetDependency */,
@@ -88,6 +89,10 @@
224CC793175E1821002FF81B /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; };
224CC79F175E321C002FF81B /* mv2test.c in Sources */ = {isa = PBXBuildFile; fileRef = 3114A686156E9674001E0AA3 /* mv2test.c */; };
224CC7A0175E322C002FF81B /* fotest.c in Sources */ = {isa = PBXBuildFile; fileRef = 224CC79E175E3202002FF81B /* fotest.c */; };
+ 22561A9818F4265D00372C66 /* testthrix.c in Sources */ = {isa = PBXBuildFile; fileRef = 22561A9718F4263300372C66 /* testthrix.c */; };
+ 22561A9918F4266600372C66 /* testthrix.c in Sources */ = {isa = PBXBuildFile; fileRef = 22561A9718F4263300372C66 /* testthrix.c */; };
+ 22561A9A18F426BB00372C66 /* testthrix.c in Sources */ = {isa = PBXBuildFile; fileRef = 22561A9718F4263300372C66 /* testthrix.c */; };
+ 22561A9B18F426F300372C66 /* testthrix.c in Sources */ = {isa = PBXBuildFile; fileRef = 22561A9718F4263300372C66 /* testthrix.c */; };
2291A5B1175CAB2F001D4920 /* fmtdy.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC6156BE48D00753214 /* fmtdy.c */; };
2291A5B2175CAB2F001D4920 /* fmtdytst.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC7156BE48D00753214 /* fmtdytst.c */; };
2291A5B3175CAB2F001D4920 /* fmthe.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAE4156BE6D500753214 /* fmthe.c */; };
@@ -113,6 +118,10 @@
22C2ACA718BE400A006B3677 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; };
22C2ACA918BE400A006B3677 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; };
22C2ACB018BE4049006B3677 /* nailboardtest.c in Sources */ = {isa = PBXBuildFile; fileRef = 22C2ACA018BE3FEC006B3677 /* nailboardtest.c */; };
+ 22F846B518F437B900982BA7 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; };
+ 22F846B718F437B900982BA7 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; };
+ 22F846BE18F437D700982BA7 /* lockut.c in Sources */ = {isa = PBXBuildFile; fileRef = 22F846AF18F4379C00982BA7 /* lockut.c */; };
+ 22F846BF18F437E000982BA7 /* testthrix.c in Sources */ = {isa = PBXBuildFile; fileRef = 22561A9718F4263300372C66 /* testthrix.c */; };
22FA176916E8D6FC0098B23F /* fmtdy.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC6156BE48D00753214 /* fmtdy.c */; };
22FA176A16E8D6FC0098B23F /* fmtdytst.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC7156BE48D00753214 /* fmtdytst.c */; };
22FA176B16E8D6FC0098B23F /* fmthe.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAE4156BE6D500753214 /* fmthe.c */; };
@@ -327,6 +336,13 @@
remoteGlobalIDString = 2D604B9B16514B1A003AAF46;
remoteInfo = mpseventtxt;
};
+ 2286E4C818F4389E004111E2 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 22F846B018F437B900982BA7;
+ remoteInfo = lockut;
+ };
2291A5AE175CAB2F001D4920 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */;
@@ -418,6 +434,13 @@
remoteGlobalIDString = 3104AFF1156D37A0000A585A;
remoteInfo = all;
};
+ 22F846B218F437B900982BA7 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 31EEABFA156AAF9D00714D05;
+ remoteInfo = mps;
+ };
22FA176616E8D6FC0098B23F /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */;
@@ -955,6 +978,15 @@
);
runOnlyForDeploymentPostprocessing = 1;
};
+ 22F846B818F437B900982BA7 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
22FA177016E8D6FC0098B23F /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
@@ -1297,6 +1329,8 @@
2231BB6918CA983C002D6322 /* locusss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = locusss.c; sourceTree = ""; };
224CC799175E1821002FF81B /* fotest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fotest; sourceTree = BUILT_PRODUCTS_DIR; };
224CC79E175E3202002FF81B /* fotest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fotest.c; sourceTree = ""; };
+ 22561A9618F4263300372C66 /* testthr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = testthr.h; sourceTree = ""; };
+ 22561A9718F4263300372C66 /* testthrix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testthrix.c; sourceTree = ""; };
2291A5A8175CAA51001D4920 /* poolmv2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = poolmv2.h; sourceTree = ""; };
2291A5A9175CAA9B001D4920 /* awlutth.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = awlutth.c; sourceTree = ""; };
2291A5AA175CAA9B001D4920 /* exposet0.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = exposet0.c; sourceTree = ""; };
@@ -1317,6 +1351,8 @@
22C2ACAF18BE400A006B3677 /* nailboardtest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = nailboardtest; sourceTree = BUILT_PRODUCTS_DIR; };
22E30E821886FF1400D98EA9 /* nailboard.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nailboard.c; sourceTree = ""; };
22E30E831886FF1400D98EA9 /* nailboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nailboard.h; sourceTree = ""; };
+ 22F846AF18F4379C00982BA7 /* lockut.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lockut.c; sourceTree = ""; };
+ 22F846BD18F437B900982BA7 /* lockut */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = lockut; sourceTree = BUILT_PRODUCTS_DIR; };
22C5C99A18EC6AEC004C63D4 /* failover.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = failover.c; sourceTree = ""; };
22C5C99B18EC6AEC004C63D4 /* failover.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = failover.h; sourceTree = ""; };
22C5C99C18EC6AEC004C63D4 /* land.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = land.c; sourceTree = ""; };
@@ -1331,8 +1367,6 @@
22FACED5188807FF000FDBC1 /* fmtno.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fmtno.h; sourceTree = ""; };
22FACED6188807FF000FDBC1 /* fmtscheme.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fmtscheme.c; sourceTree = ""; };
22FACED7188807FF000FDBC1 /* fmtscheme.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fmtscheme.h; sourceTree = ""; };
- 22FACED8188807FF000FDBC1 /* locbwcss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = locbwcss.c; sourceTree = ""; };
- 22FACED9188807FF000FDBC1 /* locusss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = locusss.c; sourceTree = ""; };
22FACEDA1888088A000FDBC1 /* ss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ss.c; sourceTree = ""; };
22FACEDB188808D5000FDBC1 /* mpscmfs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mpscmfs.h; sourceTree = ""; };
22FACEDC18880933000FDBC1 /* poolmfs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = poolmfs.h; sourceTree = ""; };
@@ -1670,6 +1704,14 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 22F846B618F437B900982BA7 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 22F846B718F437B900982BA7 /* libmps.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
22FA176E16E8D6FC0098B23F /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@@ -2087,6 +2129,7 @@
3124CAB3156BE1B700753214 /* Tests */ = {
isa = PBXGroup;
children = (
+ 22F846AF18F4379C00982BA7 /* lockut.c */,
3114A63D156E94EA001E0AA3 /* abqtest.c */,
22FACED1188807FF000FDBC1 /* airtest.c */,
3124CAF5156BE81100753214 /* amcss.c */,
@@ -2134,6 +2177,8 @@
3114A628156E949A001E0AA3 /* teletest.c */,
31EEAC9E156AB73400714D05 /* testlib.c */,
2291A5F0175CB7A4001D4920 /* testlib.h */,
+ 22561A9618F4263300372C66 /* testthr.h */,
+ 22561A9718F4263300372C66 /* testthrix.c */,
3114A6BA156E9768001E0AA3 /* walkt0.c */,
31D6005E156D3F4A00337B26 /* zcoll.c */,
31D6007B156D3FCC00337B26 /* zmess.c */,
@@ -2227,6 +2272,7 @@
2231BB6718CA97DC002D6322 /* locusss */,
22FACEED18880983000FDBC1 /* airtest */,
22C2ACAF18BE400A006B3677 /* nailboardtest */,
+ 22F846BD18F437B900982BA7 /* lockut */,
);
name = Products;
sourceTree = "";
@@ -2558,6 +2604,24 @@
productReference = 22C2ACAF18BE400A006B3677 /* nailboardtest */;
productType = "com.apple.product-type.tool";
};
+ 22F846B018F437B900982BA7 /* lockut */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 22F846B918F437B900982BA7 /* Build configuration list for PBXNativeTarget "lockut" */;
+ buildPhases = (
+ 22F846B318F437B900982BA7 /* Sources */,
+ 22F846B618F437B900982BA7 /* Frameworks */,
+ 22F846B818F437B900982BA7 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 22F846B118F437B900982BA7 /* PBXTargetDependency */,
+ );
+ name = lockut;
+ productName = lockcov;
+ productReference = 22F846BD18F437B900982BA7 /* lockut */;
+ productType = "com.apple.product-type.tool";
+ };
22FA176416E8D6FC0098B23F /* amcssth */ = {
isa = PBXNativeTarget;
buildConfigurationList = 22FA177116E8D6FC0098B23F /* Build configuration list for PBXNativeTarget "amcssth" */;
@@ -3284,6 +3348,7 @@
2231BB4C18CA97D8002D6322 /* locbwcss */,
31D60026156D3D3E00337B26 /* lockcov */,
2231BB5A18CA97DC002D6322 /* locusss */,
+ 22F846B018F437B900982BA7 /* lockut */,
3114A58F156E913C001E0AA3 /* locv */,
3114A694156E971B001E0AA3 /* messtest */,
31EEAC64156AB52600714D05 /* mpmss */,
@@ -3363,6 +3428,7 @@
2291A5B3175CAB2F001D4920 /* fmthe.c in Sources */,
2291A5B4175CAB2F001D4920 /* fmtno.c in Sources */,
2291A5B5175CAB2F001D4920 /* testlib.c in Sources */,
+ 22561A9918F4266600372C66 /* testthrix.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -3408,6 +3474,16 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 22F846B318F437B900982BA7 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 22F846BE18F437D700982BA7 /* lockut.c in Sources */,
+ 22F846B518F437B900982BA7 /* testlib.c in Sources */,
+ 22F846BF18F437E000982BA7 /* testthrix.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
22FA176716E8D6FC0098B23F /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@@ -3418,6 +3494,7 @@
22FA176B16E8D6FC0098B23F /* fmthe.c in Sources */,
22FA176C16E8D6FC0098B23F /* fmtno.c in Sources */,
22FA176D16E8D6FC0098B23F /* testlib.c in Sources */,
+ 22561A9818F4265D00372C66 /* testthrix.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -3694,6 +3771,7 @@
318DA8D31892B27E0089718C /* testlib.c in Sources */,
6313D47318A4028E00EB03EF /* djbench.c in Sources */,
318DA8D21892B13B0089718C /* getoptl.c in Sources */,
+ 22561A9A18F426BB00372C66 /* testthrix.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -3801,6 +3879,7 @@
6313D47518A40C6300EB03EF /* fmtdytst.c in Sources */,
6313D47618A40C7B00EB03EF /* fmtdy.c in Sources */,
6313D46A18A400B200EB03EF /* getoptl.c in Sources */,
+ 22561A9B18F426F300372C66 /* testthrix.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -3842,6 +3921,11 @@
target = 2D604B9B16514B1A003AAF46 /* mpseventtxt */;
targetProxy = 2275798816C5422900B662B0 /* PBXContainerItemProxy */;
};
+ 2286E4C918F4389E004111E2 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 22F846B018F437B900982BA7 /* lockut */;
+ targetProxy = 2286E4C818F4389E004111E2 /* PBXContainerItemProxy */;
+ };
2291A5AD175CAB2F001D4920 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 31EEABFA156AAF9D00714D05 /* mps */;
@@ -3907,6 +3991,11 @@
target = 3104AFF1156D37A0000A585A /* all */;
targetProxy = 22CDE92D16E9EB9300366D0A /* PBXContainerItemProxy */;
};
+ 22F846B118F437B900982BA7 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 31EEABFA156AAF9D00714D05 /* mps */;
+ targetProxy = 22F846B218F437B900982BA7 /* PBXContainerItemProxy */;
+ };
22FA176516E8D6FC0098B23F /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 31EEABFA156AAF9D00714D05 /* mps */;
@@ -4410,6 +4499,27 @@
};
name = Release;
};
+ 22F846BA18F437B900982BA7 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = lockut;
+ };
+ name = Debug;
+ };
+ 22F846BB18F437B900982BA7 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = lockut;
+ };
+ name = Release;
+ };
+ 22F846BC18F437B900982BA7 /* RASH */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = lockut;
+ };
+ name = RASH;
+ };
22FA177216E8D6FC0098B23F /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -5547,6 +5657,16 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
+ 22F846B918F437B900982BA7 /* Build configuration list for PBXNativeTarget "lockut" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 22F846BA18F437B900982BA7 /* Debug */,
+ 22F846BB18F437B900982BA7 /* Release */,
+ 22F846BC18F437B900982BA7 /* RASH */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
22FA177116E8D6FC0098B23F /* Build configuration list for PBXNativeTarget "amcssth" */ = {
isa = XCConfigurationList;
buildConfigurations = (
diff --git a/mps/code/mpsicv.c b/mps/code/mpsicv.c
index a4d8c3750b5..55396aee3fe 100644
--- a/mps/code/mpsicv.c
+++ b/mps/code/mpsicv.c
@@ -15,13 +15,8 @@
#include "fmtdytst.h"
#include "mps.h"
#include "mpstd.h"
-#ifdef MPS_OS_W3
-# include "mpsw3.h"
-#endif
-#include
-#include
-#include
-#include
+
+#include /* printf */
#define exactRootsCOUNT 49
diff --git a/mps/code/mpswin.h b/mps/code/mpswin.h
index 0840f1371a3..2f88fc25c19 100644
--- a/mps/code/mpswin.h
+++ b/mps/code/mpswin.h
@@ -11,11 +11,15 @@
#ifndef mpswin_h
#define mpswin_h
+#ifndef WIN32_LEAN_AND_MEAN
/* Speed up the build process by excluding parts of windows.h that we
* don't use. See */
#define WIN32_LEAN_AND_MEAN
#include
#undef WIN32_LEAN_AND_MEAN
+#else
+#include
+#endif
#endif /* mpswin_h */
diff --git a/mps/code/nailboard.c b/mps/code/nailboard.c
index 8744514662b..852c98949e7 100644
--- a/mps/code/nailboard.c
+++ b/mps/code/nailboard.c
@@ -30,26 +30,36 @@ static Count nailboardLevels(Count nails)
}
+/* nailboardNails -- return the total number of nails in the board */
+
+static Count nailboardNails(Nailboard board)
+{
+ return RangeSize(&board->range) >> board->alignShift;
+}
+
+
/* nailboardLevelBits -- return the number of bits in the bit table
* for the given level.
*/
-static Count nailboardLevelBits(Nailboard board, Index level)
+static Count nailboardLevelBits(Count nails, Index level)
{
- /* Use <= rather than < because of .check.levels. */
- AVER(level <= board->levels);
- return RangeSize(&board->range) >> (board->alignShift + level * LEVEL_SHIFT);
+ Shift shift = (Shift)(level * LEVEL_SHIFT);
+ return (nails + ((Count)1 << shift) - 1) >> shift;
}
Bool NailboardCheck(Nailboard board)
{
Index i;
+ Count nails;
CHECKS(Nailboard, board);
CHECKL(RangeCheck(&board->range));
CHECKL(0 < board->levels);
- CHECKL(board->levels == nailboardLevels(nailboardLevelBits(board, 0)));
- CHECKL(nailboardLevelBits(board, board->levels - 1) != 0);
- CHECKL(nailboardLevelBits(board, board->levels) == 0); /* .check.levels */
+ nails = nailboardNails(board);
+ CHECKL(board->levels == nailboardLevels(nails));
+ CHECKL(nails == nailboardLevelBits(nails, 0));
+ CHECKL(nailboardLevelBits(nails, board->levels - 1) != 0);
+ CHECKL(nailboardLevelBits(nails, board->levels) == 1);
CHECKL(BoolCheck(board->newNails));
for (i = 0; i < board->levels; ++i) {
CHECKL(board->level[i] != NULL);
@@ -80,8 +90,7 @@ static Size nailboardSize(Count nails, Count levels)
Size size;
size = nailboardStructSize(levels);
for (i = 0; i < levels; ++i) {
- size += BTSize(nails);
- nails >>= LEVEL_SHIFT;
+ size += BTSize(nailboardLevelBits(nails, i));
}
return size;
}
@@ -130,11 +139,11 @@ Res NailboardCreate(Nailboard *boardReturn, Arena arena, Align alignment,
p = PointerAdd(p, nailboardStructSize(levels));
for (i = 0; i < levels; ++i) {
- AVER(nails > 0);
+ Count levelBits = nailboardLevelBits(nails, i);
+ AVER(levelBits > 0);
board->level[i] = p;
- BTResRange(board->level[i], 0, nails);
- p = PointerAdd(p, BTSize(nails));
- nails >>= LEVEL_SHIFT;
+ BTResRange(board->level[i], 0, levelBits);
+ p = PointerAdd(p, BTSize(levelBits));
}
board->sig = NailboardSig;
@@ -154,7 +163,7 @@ void NailboardDestroy(Nailboard board, Arena arena)
AVERT(Nailboard, board);
AVERT(Arena, arena);
- nails = nailboardLevelBits(board, 0);
+ nails = nailboardNails(board);
size = nailboardSize(nails, board->levels);
board->sig = SigInvalid;
@@ -191,8 +200,10 @@ Bool (NailboardNewNails)(Nailboard board)
static Index nailboardIndex(Nailboard board, Index level, Addr addr)
{
- return AddrOffset(RangeBase(&board->range), addr)
+ Index i = AddrOffset(RangeBase(&board->range), addr)
>> (board->alignShift + level * LEVEL_SHIFT);
+ AVER_CRITICAL(i < nailboardLevelBits(nailboardNails(board), level));
+ return i;
}
@@ -414,7 +425,7 @@ Res NailboardDescribe(Nailboard board, mps_lib_FILE *stream)
return res;
for(i = 0; i < board->levels; ++i) {
- Count levelNails = nailboardLevelBits(board, i);
+ Count levelNails = nailboardLevelBits(nailboardNails(board), i);
Count resetNails = BTCountResRange(board->level[i], 0, levelNails);
res = WriteF(stream, " Level $U ($U bits, $U set): ",
i, levelNails, levelNails - resetNails, NULL);
diff --git a/mps/code/nailboardtest.c b/mps/code/nailboardtest.c
index a78ba4b3b9e..24bf3be36c2 100644
--- a/mps/code/nailboardtest.c
+++ b/mps/code/nailboardtest.c
@@ -12,6 +12,8 @@
#include "bt.h"
#include "nailboard.h"
+#include /* printf */
+
static void test(mps_arena_t arena)
{
diff --git a/mps/code/poolamc.c b/mps/code/poolamc.c
index bbc582676a3..aeb04454efe 100644
--- a/mps/code/poolamc.c
+++ b/mps/code/poolamc.c
@@ -32,7 +32,7 @@ static Nailboard amcSegNailboard(Seg seg);
static Bool AMCCheck(AMC amc);
static Res AMCFix(Pool pool, ScanState ss, Seg seg, Ref *refIO);
static Res AMCHeaderFix(Pool pool, ScanState ss, Seg seg, Ref *refIO);
-extern PoolClass AMCPoolClassGet(void);
+extern PoolClass AMCZPoolClassGet(void);
extern BufferClass amcBufClassGet(void);
extern SegClass amcSegClassGet(void);
@@ -2164,7 +2164,7 @@ static void amcWalkAll(Pool pool, FormattedObjectsStepMethod f,
Arena arena;
Ring ring, next, node;
- AVER(IsSubclassPoly(pool->class, AMCPoolClassGet()));
+ AVER(IsSubclassPoly(pool->class, AMCZPoolClassGet()));
arena = PoolArena(pool);
ring = PoolSegRing(pool);
@@ -2449,7 +2449,7 @@ static Bool AMCCheck(AMC amc)
{
CHECKS(AMC, amc);
CHECKD(Pool, &amc->poolStruct);
- CHECKL(IsSubclassPoly(amc->poolStruct.class, EnsureAMCPoolClass()));
+ CHECKL(IsSubclassPoly(amc->poolStruct.class, AMCZPoolClassGet()));
CHECKL(RankSetCheck(amc->rankSet));
CHECKD_NOSIG(Ring, &amc->genRing);
CHECKL(BoolCheck(amc->gensBooted));
diff --git a/mps/code/poolams.c b/mps/code/poolams.c
index c67a2efd684..d769630f009 100644
--- a/mps/code/poolams.c
+++ b/mps/code/poolams.c
@@ -74,6 +74,11 @@ Bool AMSSegCheck(AMSSeg amsseg)
CHECKD_NOSIG(BT, amsseg->nongreyTable);
CHECKD_NOSIG(BT, amsseg->nonwhiteTable);
+ /* If tables are shared, they mustn't both be in use. */
+ CHECKL(!(amsseg->ams->shareAllocTable
+ && amsseg->allocTableInUse
+ && amsseg->colourTablesInUse));
+
return TRUE;
}
@@ -167,6 +172,10 @@ static Res amsCreateTables(AMS ams, BT *allocReturn,
goto failWhite;
}
+ /* Invalidate the colour tables in checking varieties. */
+ AVER((BTResRange(nongreyTable, 0, length), TRUE));
+ AVER((BTSetRange(nonwhiteTable, 0, length), TRUE));
+
*allocReturn = allocTable;
*nongreyReturn = nongreyTable;
*nonwhiteReturn = nonwhiteTable;
@@ -1023,7 +1032,8 @@ static void AMSBufferEmpty(Pool pool, Buffer buffer, Addr init, Addr limit)
AVER(limitIndex <= amsseg->firstFree);
if (limitIndex == amsseg->firstFree) /* is it at the end? */ {
amsseg->firstFree = initIndex;
- } else { /* start using allocTable */
+ } else if (!ams->shareAllocTable || !amsseg->colourTablesInUse) {
+ /* start using allocTable */
amsseg->allocTableInUse = TRUE;
BTSetRange(amsseg->allocTable, 0, amsseg->firstFree);
if (amsseg->firstFree < amsseg->grains)
@@ -1415,16 +1425,20 @@ static Res AMSFix(Pool pool, ScanState ss, Seg seg, Ref *refIO)
/* doing that here (this can be called from RootScan, during flip). */
clientRef = *refIO;
+ AVER_CRITICAL(SegBase(seg) <= clientRef);
+ AVER_CRITICAL(clientRef < SegLimit(seg)); /* see .ref-limit */
base = AddrSub((Addr)clientRef, format->headerSize);
/* can get an ambiguous reference too close to the base of the
* segment, so when we subtract the header we are not in the
* segment any longer. This isn't a real reference,
* so we can just skip it. */
if (base < SegBase(seg)) {
- return ResOK;
+ AVER_CRITICAL(ss->rank == RankAMBIG);
+ return ResOK;
}
i = AMS_ADDR_INDEX(seg, base);
+ AVER_CRITICAL(i < amsseg->grains);
AVER_CRITICAL(!AMS_IS_INVALID_COLOUR(seg, i));
ss->wasMarked = TRUE;
@@ -1584,12 +1598,13 @@ static void AMSReclaim(Pool pool, Trace trace, Seg seg)
/* preservedInPlaceCount is updated on fix */
trace->preservedInPlaceSize += (grains - amsseg->free) << ams->grainShift;
+ /* Ensure consistency of segment even if are just about to free it */
+ amsseg->colourTablesInUse = FALSE;
+ SegSetWhite(seg, TraceSetDel(SegWhite(seg), trace));
+
if (amsseg->free == grains && SegBuffer(seg) == NULL) {
/* No survivors */
SegFree(seg);
- } else {
- amsseg->colourTablesInUse = FALSE;
- SegSetWhite(seg, TraceSetDel(SegWhite(seg), trace));
}
}
diff --git a/mps/code/poolawl.c b/mps/code/poolawl.c
index 6332a91b7cd..cbece0b41fe 100644
--- a/mps/code/poolawl.c
+++ b/mps/code/poolawl.c
@@ -305,10 +305,14 @@ DEFINE_SEG_CLASS(AWLSegClass, class)
* it's possible to tweak them in a debugger.
*/
+extern Count AWLSegSALimit;
Count AWLSegSALimit = AWL_SEG_SA_LIMIT;
+extern Bool AWLHaveSegSALimit;
Bool AWLHaveSegSALimit = AWL_HAVE_SEG_SA_LIMIT;
+extern Count AWLTotalSALimit;
Count AWLTotalSALimit = AWL_TOTAL_SA_LIMIT;
+extern Bool AWLHaveTotalSALimit;
Bool AWLHaveTotalSALimit = AWL_HAVE_TOTAL_SA_LIMIT;
@@ -558,6 +562,7 @@ static Res AWLInit(Pool pool, ArgList args)
AVERT(Format, format);
pool->format = format;
+ pool->alignment = format->alignment;
AVER(FUNCHECK(findDependent));
awl->findDependent = findDependent;
@@ -570,7 +575,7 @@ static Res AWLInit(Pool pool, ArgList args)
if (res != ResOK)
goto failGenInit;
- awl->alignShift = SizeLog2(pool->alignment);
+ awl->alignShift = SizeLog2(PoolAlignment(pool));
awl->size = (Size)0;
awl->succAccesses = 0;
@@ -937,7 +942,7 @@ static Res awlScanSinglePass(Bool *anyScannedReturn,
i = awlIndexOfAddr(base, awl, p);
if (!BTGet(awlseg->alloc, i)) {
- p = AddrAdd(p, pool->alignment);
+ p = AddrAdd(p, PoolAlignment(pool));
continue;
}
hp = AddrAdd(p, format->headerSize);
@@ -954,7 +959,8 @@ static Res awlScanSinglePass(Bool *anyScannedReturn,
}
objectLimit = AddrSub(objectLimit, format->headerSize);
AVER(p < objectLimit);
- p = AddrAlignUp(objectLimit, pool->alignment);
+ AVER(AddrIsAligned(objectLimit, PoolAlignment(pool)));
+ p = objectLimit;
}
AVER(p == limit);
@@ -1051,7 +1057,7 @@ static Res AWLFix(Pool pool, ScanState ss, Seg seg, Ref *refIO)
switch(ss->rank) {
case RankAMBIG:
/* not a real pointer if not aligned or not allocated */
- if (!AddrIsAligned(base, pool->alignment) || !BTGet(awlseg->alloc, i))
+ if (!AddrIsAligned(base, sizeof(void *)) || !BTGet(awlseg->alloc, i))
return ResOK;
/* falls through */
case RankEXACT:
@@ -1125,7 +1131,7 @@ static void AWLReclaim(Pool pool, Trace trace, Seg seg)
}
q = format->skip(AddrAdd(p, format->headerSize));
q = AddrSub(q, format->headerSize);
- q = AddrAlignUp(q, pool->alignment);
+ AVER(AddrIsAligned(q, PoolAlignment(pool)));
j = awlIndexOfAddr(base, awl, q);
AVER(j <= awlseg->grains);
if(BTGet(awlseg->mark, i)) {
@@ -1243,13 +1249,13 @@ static void AWLWalk(Pool pool, Seg seg, FormattedObjectsStepMethod f,
i = awlIndexOfAddr(base, awl, object);
if (!BTGet(awlseg->alloc, i)) {
/* This grain is free */
- object = AddrAdd(object, pool->alignment);
+ object = AddrAdd(object, PoolAlignment(pool));
continue;
}
object = AddrAdd(object, format->headerSize);
next = format->skip(object);
next = AddrSub(next, format->headerSize);
- next = AddrAlignUp(next, pool->alignment);
+ AVER(AddrIsAligned(next, PoolAlignment(pool)));
if (BTGet(awlseg->mark, i) && BTGet(awlseg->scanned, i))
(*f)(object, pool->format, pool, p, s);
object = next;
diff --git a/mps/code/poolmfs.c b/mps/code/poolmfs.c
index fbb125a71f2..214b2b232d3 100644
--- a/mps/code/poolmfs.c
+++ b/mps/code/poolmfs.c
@@ -136,7 +136,7 @@ static Res MFSInit(Pool pool, ArgList args)
mfs->sig = MFSSig;
AVERT(MFS, mfs);
- EVENT5(PoolInitMFS, pool, arena, extendBy, extendSelf, unitSize);
+ EVENT5(PoolInitMFS, pool, arena, extendBy, BOOL(extendSelf), unitSize);
return ResOK;
}
diff --git a/mps/code/poolmv.h b/mps/code/poolmv.h
index 098cd3eaa2e..8e6885254bc 100644
--- a/mps/code/poolmv.h
+++ b/mps/code/poolmv.h
@@ -1,41 +1,16 @@
/* poolmv.h: MANUAL VARIABLE POOL
*
* $Id$
- * Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
+ * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Portions copyright (C) 2002 Global Graphics Software.
*
* .purpose: This is the interface to the manual-variable pool class.
*
- * .mv: Manual-variable pools manage variably-sized blocks of memory in a
- * flexible manner. They have higher overheads than a fixed-size pool.
+ * .mv: Manual-variable pools manage variably-sized blocks of memory
+ * in a flexible manner. They have higher overheads than a fixed-size
+ * pool.
*
- * .init: This class adds the following arguments to PoolCreate:
- *
- * Size extendBy
- *
- * extendBy is the default number of bytes reserved by the pool at a time.
- * A large size will make allocation cheaper but have a higher resource
- * overhead. A typical value might be 65536. See note 2.
- *
- * Size avgSize
- *
- * avgSize is an estimate of the average size of an allocation, and is used
- * to choose the size of internal tables. An accurate estimate will
- * improve the efficiency of the pool. A low estimate will make the pool
- * less space efficient. A high estimate will make the pool less time
- * efficient. A typical value might be 32. avgSize must not be less than
- * extendBy.
- *
- * Size maxSize
- *
- * maxSize is an estimate of the maximum total size that the pool will
- * reach. Setting this parameter does not actually contrain the pool, but
- * an accurate estimate will improve the efficiency of the pool. maxSize
- * must not be less than extendBy.
- *
- * Notes
- * 2. The documentation could suggest a segment size according to the
- * distribution of allocation size requests. richard 1994-11-08
+ * .design: See
*/
#ifndef poolmv_h
@@ -59,7 +34,7 @@ extern Bool MVCheck(MV mv);
/* C. COPYRIGHT AND LICENSE
*
- * Copyright (C) 2001-2002 Ravenbrook Limited .
+ * Copyright (C) 2001-2014 Ravenbrook Limited .
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*
diff --git a/mps/code/poolmv2.c b/mps/code/poolmv2.c
index 9d73e358a42..5c0a8265d3b 100644
--- a/mps/code/poolmv2.c
+++ b/mps/code/poolmv2.c
@@ -81,7 +81,6 @@ typedef struct MVTStruct
Bool abqOverflow; /* ABQ dropped some candidates */
/* .* */
Bool splinter; /* Saved splinter */
- Seg splinterSeg; /* Saved splinter seg */
Addr splinterBase; /* Saved splinter base */
Addr splinterLimit; /* Saved splinter size */
@@ -136,7 +135,7 @@ typedef struct MVTStruct
DEFINE_POOL_CLASS(MVTPoolClass, this)
{
- INHERIT_CLASS(this, AbstractSegBufPoolClass);
+ INHERIT_CLASS(this, AbstractBufferPoolClass);
this->name = "MVT";
this->size = sizeof(MVTStruct);
this->offset = offsetof(MVTStruct, poolStruct);
@@ -311,7 +310,6 @@ static Res MVTInit(Pool pool, ArgList args)
mvt->maxSize = maxSize;
mvt->fragLimit = fragLimit;
mvt->splinter = FALSE;
- mvt->splinterSeg = NULL;
mvt->splinterBase = (Addr)0;
mvt->splinterLimit = (Addr)0;
@@ -400,9 +398,7 @@ static Bool MVTCheck(MVT mvt)
if (mvt->splinter) {
CHECKL(AddrOffset(mvt->splinterBase, mvt->splinterLimit) >=
mvt->minSize);
- CHECKD(Seg, mvt->splinterSeg);
- CHECKL(mvt->splinterBase >= SegBase(mvt->splinterSeg));
- CHECKL(mvt->splinterLimit <= SegLimit(mvt->splinterSeg));
+ CHECKL(mvt->splinterBase < mvt->splinterLimit);
}
CHECKL(mvt->size == mvt->allocated + mvt->available +
mvt->unavailable);
@@ -937,7 +933,6 @@ static void MVTBufferEmpty(Pool pool, Buffer buffer,
}
mvt->splinter = TRUE;
- mvt->splinterSeg = BufferSeg(buffer);
mvt->splinterBase = base;
mvt->splinterLimit = limit;
}
@@ -984,8 +979,6 @@ static void MVTFree(Pool pool, Addr base, Size size)
AVER(mvt->size == mvt->allocated + mvt->available +
mvt->unavailable);
METER_ACC(mvt->exceptionReturns, SegSize(seg));
- if (SegBuffer(seg) != NULL)
- BufferDetach(SegBuffer(seg), MVT2Pool(mvt));
MVTSegFree(mvt, seg);
return;
}
@@ -1017,7 +1010,6 @@ static Res MVTDescribe(Pool pool, mps_lib_FILE *stream)
" availLimit: $U \n", (WriteFU)mvt->availLimit,
" abqOverflow: $S \n", mvt->abqOverflow?"TRUE":"FALSE",
" splinter: $S \n", mvt->splinter?"TRUE":"FALSE",
- " splinterSeg: $P \n", (WriteFP)mvt->splinterSeg,
" splinterBase: $A \n", (WriteFA)mvt->splinterBase,
" splinterLimit: $A \n", (WriteFU)mvt->splinterLimit,
" size: $U \n", (WriteFU)mvt->size,
@@ -1036,68 +1028,37 @@ static Res MVTDescribe(Pool pool, mps_lib_FILE *stream)
res = ABQDescribe(MVTABQ(mvt), (ABQDescribeElement)RangeDescribe, stream);
if(res != ResOK) return res;
- res = METER_WRITE(mvt->segAllocs, stream);
- if (res != ResOK) return res;
- res = METER_WRITE(mvt->segFrees, stream);
- if (res != ResOK) return res;
- res = METER_WRITE(mvt->bufferFills, stream);
- if (res != ResOK) return res;
- res = METER_WRITE(mvt->bufferEmpties, stream);
- if (res != ResOK) return res;
- res = METER_WRITE(mvt->poolFrees, stream);
- if (res != ResOK) return res;
- res = METER_WRITE(mvt->poolSize, stream);
- if (res != ResOK) return res;
- res = METER_WRITE(mvt->poolAllocated, stream);
- if (res != ResOK) return res;
- res = METER_WRITE(mvt->poolAvailable, stream);
- if (res != ResOK) return res;
- res = METER_WRITE(mvt->poolUnavailable, stream);
- if (res != ResOK) return res;
- res = METER_WRITE(mvt->poolUtilization, stream);
- if (res != ResOK) return res;
- res = METER_WRITE(mvt->finds, stream);
- if (res != ResOK) return res;
- res = METER_WRITE(mvt->overflows, stream);
- if (res != ResOK) return res;
- res = METER_WRITE(mvt->underflows, stream);
- if (res != ResOK) return res;
- res = METER_WRITE(mvt->refills, stream);
- if (res != ResOK) return res;
- res = METER_WRITE(mvt->refillPushes, stream);
- if (res != ResOK) return res;
- res = METER_WRITE(mvt->returns, stream);
- if (res != ResOK) return res;
- res = METER_WRITE(mvt->perfectFits, stream);
- if (res != ResOK) return res;
- res = METER_WRITE(mvt->firstFits, stream);
- if (res != ResOK) return res;
- res = METER_WRITE(mvt->secondFits, stream);
- if (res != ResOK) return res;
- res = METER_WRITE(mvt->failures, stream);
- if (res != ResOK) return res;
- res = METER_WRITE(mvt->emergencyContingencies, stream);
- if (res != ResOK) return res;
- res = METER_WRITE(mvt->fragLimitContingencies, stream);
- if (res != ResOK) return res;
- res = METER_WRITE(mvt->contingencySearches, stream);
- if (res != ResOK) return res;
- res = METER_WRITE(mvt->contingencyHardSearches, stream);
- if (res != ResOK) return res;
- res = METER_WRITE(mvt->splinters, stream);
- if (res != ResOK) return res;
- res = METER_WRITE(mvt->splintersUsed, stream);
- if (res != ResOK) return res;
- res = METER_WRITE(mvt->splintersDropped, stream);
- if (res != ResOK) return res;
- res = METER_WRITE(mvt->sawdust, stream);
- if (res != ResOK) return res;
- res = METER_WRITE(mvt->exceptions, stream);
- if (res != ResOK) return res;
- res = METER_WRITE(mvt->exceptionSplinters, stream);
- if (res != ResOK) return res;
- res = METER_WRITE(mvt->exceptionReturns, stream);
- if (res != ResOK) return res;
+ METER_WRITE(mvt->segAllocs, stream);
+ METER_WRITE(mvt->segFrees, stream);
+ METER_WRITE(mvt->bufferFills, stream);
+ METER_WRITE(mvt->bufferEmpties, stream);
+ METER_WRITE(mvt->poolFrees, stream);
+ METER_WRITE(mvt->poolSize, stream);
+ METER_WRITE(mvt->poolAllocated, stream);
+ METER_WRITE(mvt->poolAvailable, stream);
+ METER_WRITE(mvt->poolUnavailable, stream);
+ METER_WRITE(mvt->poolUtilization, stream);
+ METER_WRITE(mvt->finds, stream);
+ METER_WRITE(mvt->overflows, stream);
+ METER_WRITE(mvt->underflows, stream);
+ METER_WRITE(mvt->refills, stream);
+ METER_WRITE(mvt->refillPushes, stream);
+ METER_WRITE(mvt->returns, stream);
+ METER_WRITE(mvt->perfectFits, stream);
+ METER_WRITE(mvt->firstFits, stream);
+ METER_WRITE(mvt->secondFits, stream);
+ METER_WRITE(mvt->failures, stream);
+ METER_WRITE(mvt->emergencyContingencies, stream);
+ METER_WRITE(mvt->fragLimitContingencies, stream);
+ METER_WRITE(mvt->contingencySearches, stream);
+ METER_WRITE(mvt->contingencyHardSearches, stream);
+ METER_WRITE(mvt->splinters, stream);
+ METER_WRITE(mvt->splintersUsed, stream);
+ METER_WRITE(mvt->splintersDropped, stream);
+ METER_WRITE(mvt->sawdust, stream);
+ METER_WRITE(mvt->exceptions, stream);
+ METER_WRITE(mvt->exceptionSplinters, stream);
+ METER_WRITE(mvt->exceptionReturns, stream);
res = WriteF(stream, "}\n", NULL);
return res;
@@ -1175,7 +1136,7 @@ static Res MVTSegAlloc(Seg *segReturn, MVT mvt, Size size,
{
/* Can't use plain old SegClass here because we need to call
* SegBuffer() in MVTFree(). */
- Res res = SegAlloc(segReturn, GCSegClassGet(),
+ Res res = SegAlloc(segReturn, SegClassGet(),
SegPrefDefault(), size, MVT2Pool(mvt), withReservoirPermit,
argsNone);
@@ -1199,7 +1160,6 @@ static Res MVTSegAlloc(Seg *segReturn, MVT mvt, Size size,
*/
static void MVTSegFree(MVT mvt, Seg seg)
{
- Buffer buffer;
Size size;
size = SegSize(seg);
@@ -1209,16 +1169,6 @@ static void MVTSegFree(MVT mvt, Seg seg)
mvt->size -= size;
mvt->availLimit = mvt->size * mvt->fragLimit / 100;
AVER(mvt->size == mvt->allocated + mvt->available + mvt->unavailable);
-
- /* If the client program allocates the exactly the entire buffer then
- frees the allocated memory then we'll try to free the segment with
- the buffer still attached. It's safe, but we must detach the buffer
- first. See job003520 and job003672. */
- buffer = SegBuffer(seg);
- if (buffer != NULL) {
- AVER(BufferAP(buffer)->init == SegLimit(seg));
- BufferDetach(buffer, MVT2Pool(mvt));
- }
SegFree(seg);
METER_ACC(mvt->segFrees, size);
diff --git a/mps/code/poolmvff.c b/mps/code/poolmvff.c
index 6a530fb94bd..e50cf077f80 100644
--- a/mps/code/poolmvff.c
+++ b/mps/code/poolmvff.c
@@ -539,7 +539,7 @@ static Res MVFFInit(Pool pool, ArgList args)
mvff->sig = MVFFSig;
AVERT(MVFF, mvff);
EVENT8(PoolInitMVFF, pool, arena, extendBy, avgSize, align,
- slotHigh, arenaHigh, firstFit);
+ BOOL(slotHigh), BOOL(arenaHigh), BOOL(firstFit));
return ResOK;
failFailoverInit:
diff --git a/mps/code/poolncv.c b/mps/code/poolncv.c
index 6d77542db58..8b8dab2a8a1 100644
--- a/mps/code/poolncv.c
+++ b/mps/code/poolncv.c
@@ -10,6 +10,8 @@
#include "testlib.h"
#include "mpslib.h"
+#include /* printf */
+
static void testit(ArenaClass class, ArgList args)
{
diff --git a/mps/code/prmci3li.c b/mps/code/prmci3li.c
index 6a36ae7db2b..5b5d150b8cc 100644
--- a/mps/code/prmci3li.c
+++ b/mps/code/prmci3li.c
@@ -36,27 +36,34 @@ SRCID(prmci3li, "$Id$");
MRef Prmci3AddressHoldingReg(MutatorFaultContext mfc, unsigned int regnum)
{
+ MRef gregs;
+
+ AVER(mfc != NULL);
AVER(NONNEGATIVE(regnum));
AVER(regnum <= 7);
+ AVER(mfc->ucontext != NULL);
+
+ /* TODO: The current arrangement of the fix operation (taking a Ref *)
+ forces us to pun these registers (actually `int` on LII3GC). We can
+ suppress the warning by casting through `void *` and this might make
+ it safe, but does it really? RB 2012-09-10 */
+ AVER(sizeof(void *) == sizeof(*mfc->ucontext->uc_mcontext.gregs));
+ gregs = (void *)mfc->ucontext->uc_mcontext.gregs;
/* .source.i486 */
/* .assume.regref */
/* The register numbers (REG_EAX etc.) are defined in
but only if _GNU_SOURCE is defined: see .feature.li in
config.h. */
- /* TODO: The current arrangement of the fix operation (taking a Ref *)
- forces us to pun these registers (actually `int` on LII3GC). We can
- suppress the warning my casting through `char *` and this might make
- it safe, but does it really? RB 2012-09-10 */
switch (regnum) {
- case 0: return (MRef)((char *)&mfc->ucontext->uc_mcontext.gregs[REG_EAX]);
- case 1: return (MRef)((char *)&mfc->ucontext->uc_mcontext.gregs[REG_ECX]);
- case 2: return (MRef)((char *)&mfc->ucontext->uc_mcontext.gregs[REG_EDX]);
- case 3: return (MRef)((char *)&mfc->ucontext->uc_mcontext.gregs[REG_EBX]);
- case 4: return (MRef)((char *)&mfc->ucontext->uc_mcontext.gregs[REG_ESP]);
- case 5: return (MRef)((char *)&mfc->ucontext->uc_mcontext.gregs[REG_EBP]);
- case 6: return (MRef)((char *)&mfc->ucontext->uc_mcontext.gregs[REG_ESI]);
- case 7: return (MRef)((char *)&mfc->ucontext->uc_mcontext.gregs[REG_EDI]);
+ case 0: return &gregs[REG_EAX];
+ case 1: return &gregs[REG_ECX];
+ case 2: return &gregs[REG_EDX];
+ case 3: return &gregs[REG_EBX];
+ case 4: return &gregs[REG_ESP];
+ case 5: return &gregs[REG_EBP];
+ case 6: return &gregs[REG_ESI];
+ case 7: return &gregs[REG_EDI];
default:
NOTREACHED;
return NULL; /* Avoids compiler warning. */
diff --git a/mps/code/prmci3xc.c b/mps/code/prmci3xc.c
index 786145fc084..eafeff61540 100644
--- a/mps/code/prmci3xc.c
+++ b/mps/code/prmci3xc.c
@@ -34,8 +34,13 @@ SRCID(prmci3li, "$Id$");
MRef Prmci3AddressHoldingReg(MutatorFaultContext mfc, unsigned int regnum)
{
+ THREAD_STATE_S *threadState;
+
+ AVER(mfc != NULL);
AVER(NONNEGATIVE(regnum));
AVER(regnum <= 7);
+ AVER(mfc->threadState != NULL);
+ threadState = mfc->threadState;
/* .source.i486 */
/* .assume.regref */
@@ -44,17 +49,17 @@ MRef Prmci3AddressHoldingReg(MutatorFaultContext mfc, unsigned int regnum)
config.h. */
/* TODO: The current arrangement of the fix operation (taking a Ref *)
forces us to pun these registers (actually `int` on LII3GC). We can
- suppress the warning my casting through `char *` and this might make
+ suppress the warning by casting through `void *` and this might make
it safe, but does it really? RB 2012-09-10 */
switch (regnum) {
- case 0: return (MRef)((char *)&mfc->threadState->__eax);
- case 1: return (MRef)((char *)&mfc->threadState->__ecx);
- case 2: return (MRef)((char *)&mfc->threadState->__edx);
- case 3: return (MRef)((char *)&mfc->threadState->__ebx);
- case 4: return (MRef)((char *)&mfc->threadState->__esp);
- case 5: return (MRef)((char *)&mfc->threadState->__ebp);
- case 6: return (MRef)((char *)&mfc->threadState->__esi);
- case 7: return (MRef)((char *)&mfc->threadState->__edi);
+ case 0: return (void *)&threadState->__eax;
+ case 1: return (void *)&threadState->__ecx;
+ case 2: return (void *)&threadState->__edx;
+ case 3: return (void *)&threadState->__ebx;
+ case 4: return (void *)&threadState->__esp;
+ case 5: return (void *)&threadState->__ebp;
+ case 6: return (void *)&threadState->__esi;
+ case 7: return (void *)&threadState->__edi;
default:
NOTREACHED;
return NULL; /* Avoids compiler warning. */
diff --git a/mps/code/prmci6li.c b/mps/code/prmci6li.c
index 2f8bf9afc62..c00c1359014 100644
--- a/mps/code/prmci6li.c
+++ b/mps/code/prmci6li.c
@@ -33,12 +33,19 @@ SRCID(prmci6li, "$Id$");
MRef Prmci6AddressHoldingReg(MutatorFaultContext mfc, unsigned int regnum)
{
- Word *gregs;
+ MRef gregs;
+ AVER(mfc != NULL);
AVER(NONNEGATIVE(regnum));
AVER(regnum <= 15);
+ AVER(mfc->ucontext != NULL);
- gregs = (Word *)&mfc->ucontext->uc_mcontext.gregs;
+ /* TODO: The current arrangement of the fix operation (taking a Ref *)
+ forces us to pun these registers (actually `int` on LII6GC). We can
+ suppress the warning by casting through `void *` and this might make
+ it safe, but does it really? RB 2012-09-10 */
+ AVER(sizeof(void *) == sizeof(*mfc->ucontext->uc_mcontext.gregs));
+ gregs = (void *)mfc->ucontext->uc_mcontext.gregs;
/* .assume.regref */
/* The register numbers (REG_RAX etc.) are defined in
diff --git a/mps/code/prmci6xc.c b/mps/code/prmci6xc.c
index 02ccb840b6c..131447cd0cc 100644
--- a/mps/code/prmci6xc.c
+++ b/mps/code/prmci6xc.c
@@ -31,33 +31,38 @@ SRCID(prmci6li, "$Id$");
MRef Prmci6AddressHoldingReg(MutatorFaultContext mfc, unsigned int regnum)
{
+ THREAD_STATE_S *threadState;
+
+ AVER(mfc != NULL);
AVER(NONNEGATIVE(regnum));
AVER(regnum <= 15);
+ AVER(mfc->threadState != NULL);
+ threadState = mfc->threadState;
/* .assume.regref */
/* The register numbers (REG_RAX etc.) are defined in
but only if _XOPEN_SOURCE is defined: see .feature.xc in
config.h. */
/* MRef (a Word *) is not compatible with pointers to the register
- types (actually a __uint64_t). To avoid aliasing optimization
- problems, The registers are cast through (char *) */
+ types (actually a __uint64_t). To avoid aliasing optimization
+ problems, the registers are cast through (void *). */
switch (regnum) {
- case 0: return (MRef)((char *)&mfc->threadState->__rax);
- case 1: return (MRef)((char *)&mfc->threadState->__rcx);
- case 2: return (MRef)((char *)&mfc->threadState->__rdx);
- case 3: return (MRef)((char *)&mfc->threadState->__rbx);
- case 4: return (MRef)((char *)&mfc->threadState->__rsp);
- case 5: return (MRef)((char *)&mfc->threadState->__rbp);
- case 6: return (MRef)((char *)&mfc->threadState->__rsi);
- case 7: return (MRef)((char *)&mfc->threadState->__rdi);
- case 8: return (MRef)((char *)&mfc->threadState->__r8);
- case 9: return (MRef)((char *)&mfc->threadState->__r9);
- case 10: return (MRef)((char *)&mfc->threadState->__r10);
- case 11: return (MRef)((char *)&mfc->threadState->__r11);
- case 12: return (MRef)((char *)&mfc->threadState->__r12);
- case 13: return (MRef)((char *)&mfc->threadState->__r13);
- case 14: return (MRef)((char *)&mfc->threadState->__r14);
- case 15: return (MRef)((char *)&mfc->threadState->__r15);
+ case 0: return (void *)&threadState->__rax;
+ case 1: return (void *)&threadState->__rcx;
+ case 2: return (void *)&threadState->__rdx;
+ case 3: return (void *)&threadState->__rbx;
+ case 4: return (void *)&threadState->__rsp;
+ case 5: return (void *)&threadState->__rbp;
+ case 6: return (void *)&threadState->__rsi;
+ case 7: return (void *)&threadState->__rdi;
+ case 8: return (void *)&threadState->__r8;
+ case 9: return (void *)&threadState->__r9;
+ case 10: return (void *)&threadState->__r10;
+ case 11: return (void *)&threadState->__r11;
+ case 12: return (void *)&threadState->__r12;
+ case 13: return (void *)&threadState->__r13;
+ case 14: return (void *)&threadState->__r14;
+ case 15: return (void *)&threadState->__r15;
default:
NOTREACHED;
return NULL; /* Avoids compiler warning. */
diff --git a/mps/code/protxc.c b/mps/code/protxc.c
index 8f62bb3a5df..1d2ae27917c 100644
--- a/mps/code/protxc.c
+++ b/mps/code/protxc.c
@@ -243,7 +243,7 @@ static void protCatchOne(void)
different size" warnings in GCC, for the XCI3GC build. */
mfcStruct.address = (Addr)(Word)request.code[1];
AVER(sizeof(*mfcStruct.threadState) == sizeof(THREAD_STATE_S));
- mfcStruct.threadState = (THREAD_STATE_S *)request.old_state;
+ mfcStruct.threadState = (void *)request.old_state;
if (ArenaAccess(mfcStruct.address,
AccessREAD | AccessWRITE,
@@ -282,6 +282,7 @@ static void protCatchOne(void)
* handler won't cause a deadlock.
*/
+ATTRIBUTE_NORETURN
static void *protCatchThread(void *p) {
UNUSED(p);
for (;;)
diff --git a/mps/code/qs.c b/mps/code/qs.c
index 31005b4fc9b..50fe8c48723 100644
--- a/mps/code/qs.c
+++ b/mps/code/qs.c
@@ -29,10 +29,9 @@
#include "mpscamc.h"
#include "mpscmv.h"
#include "mpstd.h"
-#ifdef MPS_OS_W3
-#include "mpsw3.h"
-#endif
-#include
+
+#include /* printf */
+#include /* qsort */
#define testArenaSIZE ((size_t)1000*1024)
@@ -51,7 +50,7 @@ static mps_addr_t isMoved(mps_addr_t object);
static void copy(mps_addr_t object, mps_addr_t to);
static void pad(mps_addr_t base, size_t size);
-struct mps_fmt_A_s fmt_A_s =
+static struct mps_fmt_A_s fmt_A_s =
{
(mps_align_t)4,
scan, skip, copy,
@@ -318,14 +317,14 @@ static void validate(void)
for(i = 0; i < listl; ++i) {
cdie(((QSCell)reg[1])->tag == QSInt, "validate int");
if((mps_word_t)((QSCell)reg[1])->value != list[i]) {
- (void)fprintf(stdout, "mps_res_t: Element %"PRIuLONGEST" of the "
- "two lists do not match.\n", (ulongest_t)i);
+ printf("mps_res_t: Element %"PRIuLONGEST" of the "
+ "two lists do not match.\n", (ulongest_t)i);
return;
}
reg[1] = (mps_addr_t)((QSCell)reg[1])->tail;
}
cdie(reg[1] == (mps_word_t)0, "validate end");
- (void)fprintf(stdout, "Note: Lists compare equal.\n");
+ printf("Note: Lists compare equal.\n");
}
diff --git a/mps/code/ring.c b/mps/code/ring.c
index ff60149ce40..54902ec3818 100644
--- a/mps/code/ring.c
+++ b/mps/code/ring.c
@@ -1,7 +1,7 @@
/* ring.c: RING IMPLEMENTATION
*
* $Id$
- * Copyright (c) 2001,2003 Ravenbrook Limited. See end of file for license.
+ * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
*
* .intro: This is a portable implementation of Rings.
*
@@ -52,6 +52,16 @@ Bool RingIsSingle(Ring ring)
return (ring->next == ring);
}
+Size RingLength(Ring ring)
+{
+ Size size = 0;
+ Ring node, next;
+ AVERT(Ring, ring);
+ RING_FOR(node, ring, next)
+ ++ size;
+ return size;
+}
+
/* RingInit -- initialize a ring node
*/
@@ -131,7 +141,7 @@ Ring (RingPrev)(Ring ring)
/* C. COPYRIGHT AND LICENSE
*
- * Copyright (C) 2001-2003 Ravenbrook Limited .
+ * Copyright (C) 2001-2014 Ravenbrook Limited .
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*
diff --git a/mps/code/ring.h b/mps/code/ring.h
index d5b64076f6c..cbde6afe814 100644
--- a/mps/code/ring.h
+++ b/mps/code/ring.h
@@ -1,7 +1,7 @@
/* ring.h: RING INTERFACE
*
* $Id$
- * Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
+ * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Portions copyright (C) 2001 Global Graphics Software.
*/
@@ -30,6 +30,7 @@ typedef struct RingStruct { /* double-ended queue structure */
extern Bool RingCheck(Ring ring);
extern Bool RingCheckSingle(Ring ring);
extern Bool RingIsSingle(Ring ring);
+extern Size RingLength(Ring ring);
/* .ring.init: */
extern void (RingInit)(Ring ring);
@@ -115,7 +116,7 @@ extern Ring (RingPrev)(Ring ring);
/* C. COPYRIGHT AND LICENSE
*
- * Copyright (C) 2001-2013 Ravenbrook Limited .
+ * Copyright (C) 2001-2014 Ravenbrook Limited .
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*
diff --git a/mps/code/sac.c b/mps/code/sac.c
index 435988cf867..3caf9ab893f 100644
--- a/mps/code/sac.c
+++ b/mps/code/sac.c
@@ -48,18 +48,20 @@ static Bool SACCheck(SAC sac)
CHECKL(esac->_middle > 0);
/* check classes above middle */
prevSize = esac->_middle;
- for (j = sac->middleIndex + 1, i = 0;
- j <= sac->classesCount; ++j, i += 2) {
+ for (j = sac->middleIndex + 1, i = 0; j < sac->classesCount; ++j, i += 2) {
CHECKL(prevSize < esac->_freelists[i]._size);
b = sacFreeListBlockCheck(&(esac->_freelists[i]));
if (!b) return b;
prevSize = esac->_freelists[i]._size;
}
/* check overlarge class */
- CHECKL(esac->_freelists[i-2]._size == SizeMAX);
- CHECKL(esac->_freelists[i-2]._count == 0);
- CHECKL(esac->_freelists[i-2]._count_max == 0);
- CHECKL(esac->_freelists[i-2]._blocks == NULL);
+ CHECKL(prevSize < esac->_freelists[i]._size);
+ b = sacFreeListBlockCheck(&(esac->_freelists[i]));
+ if (!b) return b;
+ CHECKL(esac->_freelists[i]._size == SizeMAX);
+ CHECKL(esac->_freelists[i]._count == 0);
+ CHECKL(esac->_freelists[i]._count_max == 0);
+ CHECKL(esac->_freelists[i]._blocks == NULL);
/* check classes below middle */
prevSize = esac->_middle;
for (j = sac->middleIndex, i = 1; j > 0; --j, i += 2) {
@@ -69,6 +71,7 @@ static Bool SACCheck(SAC sac)
prevSize = esac->_freelists[i]._size;
}
/* check smallest class */
+ CHECKL(prevSize > esac->_freelists[i]._size);
CHECKL(esac->_freelists[i]._size == 0);
b = sacFreeListBlockCheck(&(esac->_freelists[i]));
return b;
diff --git a/mps/code/seg.c b/mps/code/seg.c
index 069b2c50049..31dd0759ff9 100644
--- a/mps/code/seg.c
+++ b/mps/code/seg.c
@@ -593,7 +593,7 @@ Res SegMerge(Seg *mergedSegReturn, Seg segLo, Seg segHi,
if (ResOK != res)
goto failMerge;
- EVENT3(SegMerge, segLo, segHi, withReservoirPermit);
+ EVENT3(SegMerge, segLo, segHi, BOOL(withReservoirPermit));
/* Deallocate segHi object */
ControlFree(arena, segHi, class->size);
AVERT(Seg, segLo);
@@ -1200,7 +1200,7 @@ static void gcSegSetGreyInternal(Seg seg, TraceSet oldGrey, TraceSet grey)
/* Internal method. Parameters are checked by caller */
gcseg = SegGCSeg(seg);
arena = PoolArena(SegPool(seg));
- seg->grey = grey;
+ seg->grey = BS_BITFIELD(Trace, grey);
/* If the segment is now grey and wasn't before, add it to the */
/* appropriate grey list so that TraceFindGrey can locate it */
@@ -1313,11 +1313,11 @@ static void gcSegSetWhite(Seg seg, TraceSet white)
AVERT_CRITICAL(Tract, tract);
AVER_CRITICAL(TRACT_SEG(&trseg, tract) && (trseg == seg));
- TractSetWhite(tract, white);
+ TractSetWhite(tract, BS_BITFIELD(Trace, white));
}
AVER(addr == limit);
- seg->white = white;
+ seg->white = BS_BITFIELD(Trace, white);
}
@@ -1350,7 +1350,7 @@ static void gcSegSetRankSet(Seg seg, RankSet rankSet)
arena = PoolArena(SegPool(seg));
oldRankSet = seg->rankSet;
- seg->rankSet = rankSet;
+ seg->rankSet = BS_BITFIELD(Rank, rankSet);
if (oldRankSet == RankSetEMPTY) {
if (rankSet != RankSetEMPTY) {
@@ -1427,7 +1427,7 @@ static void gcSegSetRankSummary(Seg seg, RankSet rankSet, RefSet summary)
wasShielded = (seg->rankSet != RankSetEMPTY && gcseg->summary != RefSetUNIV);
willbeShielded = (rankSet != RankSetEMPTY && summary != RefSetUNIV);
- seg->rankSet = rankSet;
+ seg->rankSet = BS_BITFIELD(Rank, rankSet);
gcseg->summary = summary;
if (willbeShielded && !wasShielded) {
diff --git a/mps/code/segsmss.c b/mps/code/segsmss.c
index 21a8b8846ed..978c352e0dd 100644
--- a/mps/code/segsmss.c
+++ b/mps/code/segsmss.c
@@ -21,14 +21,9 @@
#include "mpscams.h"
#include "mpsavm.h"
#include "mpstd.h"
-#ifdef MPS_OS_W3
-#include "mpsw3.h"
-#endif
#include "mps.h"
-#include
-#include
-#include
-#include
+
+#include /* fflush, printf, puts, stdout */
/* Forward declarations */
@@ -791,7 +786,7 @@ static void *test(void *arg, size_t s)
&ambigRoots[0], ambigRootsCOUNT),
"root_create_table(ambig)");
- (void)fputs(indent, stdout);
+ puts(indent);
/* create an ap, and leave it busy */
die(mps_reserve(&busy_init, busy_ap, 64), "mps_reserve busy");
diff --git a/mps/code/steptest.c b/mps/code/steptest.c
index 4d6353e78df..deee85fef2e 100644
--- a/mps/code/steptest.c
+++ b/mps/code/steptest.c
@@ -14,12 +14,9 @@
#include "mpscamc.h"
#include "mpsavm.h"
#include "mpstd.h"
-#ifdef MPS_OS_W3
-#include "mpsw3.h"
-#endif
#include "mps.h"
-#include
-#include
+
+#include /* fflush, printf, putchar, stdout */
#define testArenaSIZE ((size_t)((size_t)64 << 20))
#define avLEN 3
@@ -74,19 +71,19 @@ static mps_addr_t ambigRoots[ambigRootsCOUNT];
/* Things we want to measure. Times are all in microseconds. */
-double alloc_time; /* Time spent allocating */
-double max_alloc_time; /* Max time taken to allocate one object */
-double step_time; /* Time spent in mps_arena_step returning 1 */
-double max_step_time; /* Max time of mps_arena_step returning 1 */
-double no_step_time; /* Time spent in mps_arena_step returning 0 */
-double max_no_step_time; /* Max time of mps_arena_step returning 0 */
+static double alloc_time; /* Time spent allocating */
+static double max_alloc_time; /* Max time taken to allocate one object */
+static double step_time; /* Time spent in mps_arena_step returning 1 */
+static double max_step_time; /* Max time of mps_arena_step returning 1 */
+static double no_step_time; /* Time spent in mps_arena_step returning 0 */
+static double max_no_step_time; /* Max time of mps_arena_step returning 0 */
-double total_clock_time; /* Time spent reading the clock */
-long clock_reads; /* Number of times clock is read */
-long steps; /* # of mps_arena_step calls returning 1 */
-long no_steps; /* # of mps_arena_step calls returning 0 */
-size_t alloc_bytes; /* # of bytes allocated */
-long commit_failures; /* # of times mps_commit fails */
+static double total_clock_time; /* Time spent reading the clock */
+static long clock_reads; /* Number of times clock is read */
+static long steps; /* # of mps_arena_step calls returning 1 */
+static long no_steps; /* # of mps_arena_step calls returning 0 */
+static size_t alloc_bytes; /* # of bytes allocated */
+static long commit_failures; /* # of times mps_commit fails */
/* Operating-system dependent timing. Defines two functions, void
@@ -98,6 +95,8 @@ long commit_failures; /* # of times mps_commit fails */
#ifdef MPS_OS_W3
+#include "mpswin.h"
+
static HANDLE currentProcess;
static void prepare_clock(void)
@@ -152,7 +151,7 @@ static double my_clock(void)
* on thrush.ravenbrook.com on 2002-06-28, clock_time goes from 5.43
* us near process start to 7.45 us later). */
-double clock_time; /* current estimate of time to read the clock */
+static double clock_time; /* current estimate of time to read the clock */
/* take at least this many microseconds to set the clock */
#define CLOCK_TIME_SET 10000
diff --git a/mps/code/teletest.c b/mps/code/teletest.c
index 844fbc51329..1a6b1614553 100644
--- a/mps/code/teletest.c
+++ b/mps/code/teletest.c
@@ -12,7 +12,8 @@
#include "testlib.h"
#include "mpslib.h"
-#include
+#include /* fflush, fgets, printf, stdin, stdout */
+#include /* exit, EXIT_SUCCESS, strtoul */
SRCID(teletest, "$Id$");
@@ -34,8 +35,8 @@ static void callControl(mps_word_t reset, mps_word_t flip)
old = mps_telemetry_control(reset, flip);
new = mps_telemetry_control((mps_word_t)0, (mps_word_t)0);
- (void)printf(WORD_FORMAT " -> " WORD_FORMAT "\n",
- (ulongest_t)old, (ulongest_t)new);
+ printf(WORD_FORMAT " -> " WORD_FORMAT "\n",
+ (ulongest_t)old, (ulongest_t)new);
}
diff --git a/mps/code/testlib.c b/mps/code/testlib.c
index 18fe005ae5b..6ecedad0bd6 100644
--- a/mps/code/testlib.c
+++ b/mps/code/testlib.c
@@ -11,13 +11,11 @@
#include "clock.h" /* for EVENT_CLOCK */
#include "mps.h"
#include "misc.h" /* for NOOP */
-#include
-#include
-#include
-#ifdef MPS_OS_IA
-struct itimerspec; /* stop complaints from time.h */
-#endif
-#include
+
+#include /* fmod */
+#include /* fflush, printf, stderr, sscanf, vfprintf */
+#include /* abort, exit, getenv */
+#include /* time */
/* fail -- like assert, but (notionally) returns a value, so usable in an expression */
diff --git a/mps/code/testlib.h b/mps/code/testlib.h
index 447834254f4..9c197cae839 100644
--- a/mps/code/testlib.h
+++ b/mps/code/testlib.h
@@ -12,14 +12,7 @@
#include "mps.h"
#include "misc.h" /* for STR */
-
-/* Include system header hackery. */
#include "mpstd.h"
-#ifdef MPS_OS_W3
-#include "mpswin.h"
-#endif
-
-#include
/* Suppress Visual C warnings at warning level 4, */
@@ -35,13 +28,10 @@
/* Suppress Pelles C warnings at warning level 2 */
-/* Some of these are also done in config.h. */
+/* This is also done in config.h. */
#ifdef MPS_BUILD_PC
-/* "Structured Exception Handling is not portable." (mps_tramp). */
-#pragma warn(disable: 2008)
-
/* "Unreachable code" (AVER, if condition is constantly true). */
#pragma warn(disable: 2154)
@@ -65,6 +55,19 @@
#endif
+/* alloca -- memory allocator
+ *
+ * Windows calls this function _alloca() instead of alloca().
+ *
+ */
+
+#if defined(MPS_OS_W3)
+
+#define alloca _alloca
+
+#endif
+
+
/* ulongest_t -- longest unsigned integer type
*
* Define a longest unsigned integer type for testing, scanning, and
diff --git a/mps/code/testthr.h b/mps/code/testthr.h
new file mode 100644
index 00000000000..341f4f407b5
--- /dev/null
+++ b/mps/code/testthr.h
@@ -0,0 +1,123 @@
+/* testthr.h: MULTI-THREADED TEST INTERFACE
+ *
+ * $Id: //info.ravenbrook.com/project/mps/master/code/testlib.h#30 $
+ * Copyright (c) 2014 Ravenbrook Limited. See end of file for license.
+ *
+ * .purpose: Simple interface to threads that makes it possible to
+ * write test cases that are portable between Windows (using the
+ * implementation in testthrw3.c) and Unix (using the implementation
+ * in testthrix.c).
+ */
+
+#ifndef testthr_h
+#define testthr_h
+
+#include "mpstd.h"
+
+
+/* testthr_routine_t -- type of thread routines
+ *
+ * Use the pthread type here and convert back and forth in the Windows
+ * implementation.
+ */
+typedef void *(*testthr_routine_t)(void *);
+
+
+/* testthr_t -- type of thread identifiers
+ *
+ * It is necessary to define it here (even though it requires some
+ * #ifdefs) so that clients can allocate storage for them.
+ */
+
+#if defined(MPS_OS_W3)
+
+#include "mpswin.h"
+
+/* On Windows, a thread is identified by a HANDLE.
+ *
+ * But use a structure so that the thread has somewhere to store its
+ * result for use by testthr_join.
+ */
+typedef struct testthr_t {
+ HANDLE handle;
+ testthr_routine_t start;
+ void *arg; /* argument to pass to start */
+ void *result; /* result returned from start */
+} testthr_t;
+
+#elif defined(MPS_OS_FR) || defined(MPS_OS_LI) || defined(MPS_OS_XC)
+
+#include
+
+/* In pthreads, a thread is identified by a pthread_t, which is
+ * allowed "to be defined as a structure" [IEEE Std 1003.1, sys/types.h]
+ *
+ */
+typedef pthread_t testthr_t;
+
+#else
+#error "Unknown platform: can't determine a type for testthr_t."
+#endif
+
+
+/* testthr_create -- create a thread
+ *
+ * Store the identifier of the newly created thread in *thread_o, and
+ * call start, passing arg as the single parameter.
+ */
+
+void testthr_create(testthr_t *thread_o, testthr_routine_t start, void *arg);
+
+
+/* testthr_join -- wait for a thread to complete
+ *
+ * Suspend execution of the calling thread until the target thread
+ * terminates (if necessary), and if result_o is non-NULL, update
+ * *result_o with the return value of the thread's start.
+ */
+
+void testthr_join(testthr_t *thread, void **result_o);
+
+#endif /* testthr_h */
+
+
+/* C. COPYRIGHT AND LICENSE
+ *
+ * Copyright (C) 2014 Ravenbrook Limited .
+ * 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.
+ */
diff --git a/mps/code/mpsw3.h b/mps/code/testthrix.c
similarity index 69%
rename from mps/code/mpsw3.h
rename to mps/code/testthrix.c
index f32b7a09831..f4c544e0b8a 100644
--- a/mps/code/mpsw3.h
+++ b/mps/code/testthrix.c
@@ -1,45 +1,32 @@
-/* mpsw3.h: RAVENBROOK MEMORY POOL SYSTEM C INTERFACE, WINDOWS PART
+/* testthrix.c: MULTI-THREADED TEST IMPLEMENTATION (POSIX THREADS)
*
- * $Id$
- * Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
- *
- * .readership: customers, MPS developers.
- * .sources: .
+ * $Id: //info.ravenbrook.com/project/mps/master/code/testlib.h#30 $
+ * Copyright (c) 2014 Ravenbrook Limited. See end of file for license.
*/
-#ifndef mpsw3_h
-#define mpsw3_h
+#include "testlib.h"
+#include "testthr.h"
-#include "mps.h" /* needed for mps_tramp_t */
-#include "mpswin.h" /* needed for SEH filter */
+#include /* strerror */
+void testthr_create(testthr_t *thread_o, testthr_routine_t start, void *arg)
+{
+ int res = pthread_create(thread_o, NULL, start, arg);
+ if (res != 0)
+ error("pthread_create failed with result %d (%s)", res, strerror(res));
+}
-extern LONG mps_SEH_filter(LPEXCEPTION_POINTERS, void **, size_t *);
-extern void mps_SEH_handler(void *, size_t);
-
-
-#define mps_tramp(r_o, f, p, s) \
- MPS_BEGIN \
- void **_r_o = (r_o); \
- mps_tramp_t _f = (f); \
- void *_p = (p); \
- size_t _s = (s); \
- void *_hp = NULL; size_t _hs = 0; \
- __try { \
- *_r_o = (*_f)(_p, _s); \
- } __except(mps_SEH_filter(GetExceptionInformation(), \
- &_hp, &_hs)) { \
- mps_SEH_handler(_hp, _hs); \
- } \
- MPS_END
-
-
-#endif /* mpsw3_h */
+void testthr_join(testthr_t *thread, void **result_o)
+{
+ int res = pthread_join(*thread, result_o);
+ if (res != 0)
+ error("pthread_join failed with result %d (%s)", res, strerror(res));
+}
/* C. COPYRIGHT AND LICENSE
*
- * Copyright (C) 2001-2002 Ravenbrook Limited .
+ * Copyright (C) 2014 Ravenbrook Limited .
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*
diff --git a/mps/code/testthrw3.c b/mps/code/testthrw3.c
new file mode 100644
index 00000000000..cd5cf54ae79
--- /dev/null
+++ b/mps/code/testthrw3.c
@@ -0,0 +1,80 @@
+/* testthrw3.c: MULTI-THREADED TEST IMPLEMENTATION (WINDOWS)
+ *
+ * $Id: //info.ravenbrook.com/project/mps/master/code/testlib.h#30 $
+ * Copyright (c) 2014 Ravenbrook Limited. See end of file for license.
+ */
+
+#include "testlib.h"
+#include "testthr.h"
+
+static DWORD WINAPI testthr_start(LPVOID arg)
+{
+ testthr_t *thread = arg;
+ thread->result = (*thread->start)(thread->arg);
+ return 0;
+}
+
+void testthr_create(testthr_t *thread_o, testthr_routine_t start, void *arg)
+{
+ HANDLE res;
+ thread_o->start = start;
+ thread_o->arg = arg;
+ res = CreateThread(NULL, 0, testthr_start, thread_o, 0, NULL);
+ if (res == NULL)
+ error("CreateThread failed with error %lu",
+ (unsigned long)GetLastError());
+ else
+ thread_o->handle = res;
+}
+
+void testthr_join(testthr_t *thread, void **result_o)
+{
+ DWORD res = WaitForSingleObject(thread->handle, INFINITE);
+ if (res != WAIT_OBJECT_0)
+ error("WaitForSingleObject failed with result %lu (error %lu)",
+ (unsigned long)res, (unsigned long)GetLastError());
+ if (result_o)
+ *result_o = thread->result;
+}
+
+
+/* C. COPYRIGHT AND LICENSE
+ *
+ * Copyright (C) 2014 Ravenbrook Limited .
+ * 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.
+ */
diff --git a/mps/code/trace.c b/mps/code/trace.c
index 924badcd541..61e9d396155 100644
--- a/mps/code/trace.c
+++ b/mps/code/trace.c
@@ -797,10 +797,11 @@ void TraceDestroy(Trace trace)
(TraceStatReclaim, trace,
trace->reclaimCount, trace->reclaimSize));
+ EVENT1(TraceDestroy, trace);
+
trace->sig = SigInvalid;
trace->arena->busyTraces = TraceSetDel(trace->arena->busyTraces, trace);
trace->arena->flippedTraces = TraceSetDel(trace->arena->flippedTraces, trace);
- EVENT1(TraceDestroy, trace);
}
@@ -1569,7 +1570,7 @@ static void TraceStartPoolGen(Chain chain, GenDesc desc, Bool top, Index i)
Ring n, nn;
RING_FOR(n, &desc->locusRing, nn) {
PoolGen gen = RING_ELT(PoolGen, genRing, n);
- EVENT11(TraceStartPoolGen, chain, top, i, desc,
+ EVENT11(TraceStartPoolGen, chain, BOOL(top), i, desc,
desc->capacity, desc->mortality, desc->zones,
gen->pool, gen->nr, gen->totalSize,
gen->newSizeAtCreate);
diff --git a/mps/code/version.c b/mps/code/version.c
index 9f8d644e47a..4771c8a7c69 100644
--- a/mps/code/version.c
+++ b/mps/code/version.c
@@ -47,6 +47,7 @@ SRCID(version, "$Id$");
* (assuming we've made any substantial changes to the library this year).
*/
+extern char MPSCopyrightNotice[];
char MPSCopyrightNotice[] =
"Portions copyright (c) 2010-2014 Ravenbrook Limited and Global Graphics Software.";
@@ -59,6 +60,7 @@ char MPSCopyrightNotice[] =
* see also guide.mps.version.
*/
+extern char MPSVersionString[];
char MPSVersionString[] =
"@(#)Ravenbrook MPS, "
"product." MPS_PROD_STRING ", " MPS_RELEASE ", platform." MPS_PF_STRING
diff --git a/mps/code/vman.c b/mps/code/vman.c
index db7795c9f2e..6ba3d0b9dff 100644
--- a/mps/code/vman.c
+++ b/mps/code/vman.c
@@ -1,7 +1,7 @@
/* vman.c: ANSI VM: MALLOC-BASED PSEUDO MEMORY MAPPING
*
* $Id$
- * Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
+ * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
*/
#include "mpm.h"
@@ -117,13 +117,13 @@ void VMDestroy(VM vm)
AVER(vm->mapped == (Size)0);
AVER(vm->reserved == AddrOffset(vm->base, vm->limit));
+ EVENT1(VMDestroy, vm);
+
memset((void *)vm->base, VMJunkBYTE, AddrOffset(vm->base, vm->limit));
free(vm->block);
vm->sig = SigInvalid;
- free(vm);
-
- EVENT1(VMDestroy, vm);
+ free(vm);
}
@@ -215,7 +215,7 @@ void VMUnmap(VM vm, Addr base, Addr limit)
/* C. COPYRIGHT AND LICENSE
*
- * Copyright (C) 2001-2002 Ravenbrook Limited .
+ * Copyright (C) 2001-2014 Ravenbrook Limited .
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*
diff --git a/mps/code/vmix.c b/mps/code/vmix.c
index 01a0919b820..0903a031a2c 100644
--- a/mps/code/vmix.c
+++ b/mps/code/vmix.c
@@ -1,7 +1,7 @@
/* vmix.c: VIRTUAL MEMORY MAPPING FOR UNIX (ISH)
*
* $Id$
- * Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license.
+ * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
*
* .purpose: This is the implementation of the virtual memory mapping
* interface (vm.h) for Unix-like operating systems. It was created
@@ -186,6 +186,8 @@ void VMDestroy(VM vm)
AVERT(VM, vm);
AVER(vm->mapped == (Size)0);
+ EVENT1(VMDestroy, vm);
+
/* This appears to be pretty pointless, since the descriptor */
/* page is about to vanish completely. However, munmap might fail */
/* for some reason, and this would ensure that it was still */
@@ -197,8 +199,6 @@ void VMDestroy(VM vm)
r = munmap((void *)vm,
(size_t)SizeAlignUp(sizeof(VMStruct), vm->align));
AVER(r == 0);
-
- EVENT1(VMDestroy, vm);
}
@@ -304,7 +304,7 @@ void VMUnmap(VM vm, Addr base, Addr limit)
/* C. COPYRIGHT AND LICENSE
*
- * Copyright (C) 2001-2013 Ravenbrook Limited .
+ * Copyright (C) 2001-2014 Ravenbrook Limited .
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*
diff --git a/mps/code/vmw3.c b/mps/code/vmw3.c
index e82f14ccd51..5be8153c73c 100644
--- a/mps/code/vmw3.c
+++ b/mps/code/vmw3.c
@@ -1,7 +1,7 @@
/* vmw3.c: VIRTUAL MEMORY MAPPING FOR WIN32
*
* $Id$
- * Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
+ * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
*
* .design: See .
*
@@ -191,6 +191,8 @@ void VMDestroy(VM vm)
AVERT(VM, vm);
AVER(vm->mapped == 0);
+ EVENT1(VMDestroy, vm);
+
/* This appears to be pretty pointless, since the vm descriptor page
* is about to vanish completely. However, the VirtualFree might
* fail and it would be nice to have a dead sig there. */
@@ -201,7 +203,6 @@ void VMDestroy(VM vm)
b = VirtualFree((LPVOID)vm, (SIZE_T)0, MEM_RELEASE);
AVER(b != 0);
- EVENT1(VMDestroy, vm);
}
@@ -303,7 +304,7 @@ void VMUnmap(VM vm, Addr base, Addr limit)
/* C. COPYRIGHT AND LICENSE
*
- * Copyright (C) 2001-2002 Ravenbrook Limited .
+ * Copyright (C) 2001-2014 Ravenbrook Limited .
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*
diff --git a/mps/code/walk.c b/mps/code/walk.c
index 3f7f67f99e1..4dd0d6b9e98 100644
--- a/mps/code/walk.c
+++ b/mps/code/walk.c
@@ -273,6 +273,20 @@ static Res rootWalk(Root root, void *p)
}
+/* rootWalkGrey -- make the root grey for the trace passed as p */
+
+static Res rootWalkGrey(Root root, void *p)
+{
+ Trace trace = p;
+
+ AVERT(Root, root);
+ AVERT(Trace, trace);
+
+ RootGrey(root, trace);
+ return ResOK;
+}
+
+
/* ArenaRootsWalk -- walks all the root in the arena */
static Res ArenaRootsWalk(Globals arenaGlobals, mps_roots_stepper_t f,
@@ -315,7 +329,7 @@ static Res ArenaRootsWalk(Globals arenaGlobals, mps_roots_stepper_t f,
}
/* Make the roots grey so that they are scanned */
- res = RootsIterate(arenaGlobals, (RootIterateFn)RootGrey, (void *)trace);
+ res = RootsIterate(arenaGlobals, rootWalkGrey, trace);
/* Make this trace look like any other trace. */
arena->flippedTraces = TraceSetAdd(arena->flippedTraces, trace);
@@ -330,6 +344,16 @@ static Res ArenaRootsWalk(Globals arenaGlobals, mps_roots_stepper_t f,
break;
}
+ /* Turn segments black again. */
+ if (SegFirst(&seg, arena)) {
+ do {
+ if (PoolHasAttr(SegPool(seg), AttrGC)) {
+ SegSetGrey(seg, TraceSetDel(SegGrey(seg), trace));
+ SegSetWhite(seg, TraceSetDel(SegWhite(seg), trace));
+ }
+ } while (SegNext(&seg, arena, seg));
+ }
+
rootsStepClosureFinish(rsc);
/* Make this trace look like any other finished trace. */
trace->state = TraceFINISHED;
diff --git a/mps/code/walkt0.c b/mps/code/walkt0.c
index 629a5276ead..929408fc4b4 100644
--- a/mps/code/walkt0.c
+++ b/mps/code/walkt0.c
@@ -13,15 +13,12 @@
#include "mpscamc.h"
#include "mpscams.h"
#include "mpscawl.h"
+#include "mpsclo.h"
#include "mpsavm.h"
#include "mpstd.h"
-#ifdef MPS_OS_W3
-#include "mpsw3.h"
-#endif
#include "mps.h"
-#include
-#include
+#include /* printf */
#define testArenaSIZE ((size_t)((size_t)64 << 20))
#define avLEN 3
@@ -216,8 +213,10 @@ int main(int argc, char *argv[])
die(mps_thread_reg(&thread, arena), "thread_reg");
test(arena, mps_class_amc());
- test(arena, mps_class_awl());
+ test(arena, mps_class_amcz());
/* TODO: test(arena, mps_class_ams()); -- see job003738 */
+ test(arena, mps_class_awl());
+ test(arena, mps_class_lo());
mps_thread_dereg(thread);
mps_arena_destroy(arena);
diff --git a/mps/code/zcoll.c b/mps/code/zcoll.c
index 20cb8f06dc1..06ef499f5b7 100644
--- a/mps/code/zcoll.c
+++ b/mps/code/zcoll.c
@@ -62,11 +62,8 @@
#include "fmtdy.h"
#include "fmtdytst.h"
#include "mpstd.h"
-#ifdef MPS_OS_W3
-#include "mpsw3.h"
-#endif
-#include
-#include /* clock */
+
+#include /* fflush, printf, putchar, puts, stdout */
/* testChain -- generation parameters for the test */
diff --git a/mps/code/zmess.c b/mps/code/zmess.c
index a97c10ea8f1..555e7377d2c 100644
--- a/mps/code/zmess.c
+++ b/mps/code/zmess.c
@@ -107,10 +107,8 @@
#include "fmtdy.h"
#include "fmtdytst.h"
#include "mpstd.h"
-#ifdef MPS_OS_W3
-#include "mpsw3.h"
-#endif
-#include
+
+#include /* printf */
#define testArenaSIZE ((size_t)16<<20)
diff --git a/mps/design/nailboard.txt b/mps/design/nailboard.txt
index d54a58cf03c..dd3608d8990 100644
--- a/mps/design/nailboard.txt
+++ b/mps/design/nailboard.txt
@@ -187,8 +187,8 @@ Performance might be improved by special-casing the small levels.
_`.future.limit`: In C and C++, a pointer to "one past the last
element of an array object" (the limit of the object in our
terminology) is a valid pointer and can be used in pointer arithmetic.
-See §6.5.6.8–9 of [C1999]. So in theory a programmer could have such
-as pointer as the only reference keeping an object alive, and still
+See §6.5.6.8–9 of [C1999]_. So in theory a programmer could have such
+a pointer as the only reference keeping an object alive, and still
expect to be able to subtract from it to get back to the object. The
current nailboard implementation does not support this use case.
diff --git a/mps/manual/source/design/.p4ignore b/mps/manual/source/design/.p4ignore
index 0e9be69cee0..2457ad19192 100644
--- a/mps/manual/source/design/.p4ignore
+++ b/mps/manual/source/design/.p4ignore
@@ -1,5 +1,6 @@
# The files in this directory are generated by the "mps" extension to Sphinx,
# except the index and the "old designs" index.
*.rst
+*.svg
!index.rst
!old.rst
diff --git a/mps/manual/source/extensions/mps/designs.py b/mps/manual/source/extensions/mps/designs.py
index e73dbe4b934..57959f1ea0c 100644
--- a/mps/manual/source/extensions/mps/designs.py
+++ b/mps/manual/source/extensions/mps/designs.py
@@ -18,11 +18,14 @@ from sphinx.util.console import bold
TYPES = '''
- AccessSet Accumulation Addr Align AP Arg Arena Attr Bool BT Buffer
- Byte Clock Compare Count Epoch Format Fun Index LD Lock Message
- Pointer Pool PThreadext Rank RankSet Ref Res Reservoir Ring Root
- RootVar ScanState Seg Serial Shift Sig Size Space SplayNode
- SplayTree Thread Trace TraceId TraceSet ULongest VM Word
+ AccessSet Accumulation Addr Align AllocFrame AllocPattern AP Arg
+ Arena Attr Bool BootBlock BT Buffer BufferMode Byte Chain Chunk
+ Clock Compare Count Epoch FindDelete Format FrameState Fun Globals
+ Index Land LD Lock Message MessageType MutatorFaultContext Page
+ Pointer Pool PThreadext Range Rank RankSet Ref Res Reservoir Ring
+ Root RootMode RootVar ScanState Seg SegBuf SegPref SegPrefKind
+ Serial Shift Sig Size Space SplayNode SplayTree StackContext
+ Thread Trace TraceId TraceSet ULongest VM Word ZoneSet
'''
diff --git a/mps/manual/source/glossary/k.rst b/mps/manual/source/glossary/k.rst
index 4033cce5fd5..d84d07711e1 100644
--- a/mps/manual/source/glossary/k.rst
+++ b/mps/manual/source/glossary/k.rst
@@ -14,7 +14,7 @@ Memory Management Glossary: K
keyword argument
- A argument to a function call that's identified by an
+ An argument to a function call that's identified by an
associated keyword rather than by its position in the argument
list.
@@ -35,5 +35,3 @@ Memory Management Glossary: K
The standard abbreviation is "kB", but "KB" is often used by
people unfamiliar with the metric system.
-
-
diff --git a/mps/manual/source/pool/awl.rst b/mps/manual/source/pool/awl.rst
index 4128339227a..79df0258804 100644
--- a/mps/manual/source/pool/awl.rst
+++ b/mps/manual/source/pool/awl.rst
@@ -282,11 +282,10 @@ the format of objects allocated in it:
that it does not look like an aligned pointer.
"Aligned pointer" means a word whose numeric value (that is, its
- value when treated as an unsigned integer) is a multiple of the
- architecture's :term:`natural alignment` (see
- :c:macro:`MPS_PF_ALIGN`). If you're using a 32-bit architecture,
- that means that an aligned pointer is a multiple of 4 and its bottom
- two bits are both zero.
+ value when treated as an unsigned integer) is a multiple of the size
+ of a pointer. For you're using a 32-bit architecture, that means
+ that an aligned pointer is a multiple of 4 and its bottom two bits
+ are both zero.
The bottom line is that references from an object in an AWL pool
must be untagged and aligned, and integers must be tagged with a
diff --git a/mps/manual/source/pool/mv.rst b/mps/manual/source/pool/mv.rst
index 433525f7362..361cd41c0b5 100644
--- a/mps/manual/source/pool/mv.rst
+++ b/mps/manual/source/pool/mv.rst
@@ -75,17 +75,19 @@ MV interface
When creating an MV pool, :c:func:`mps_pool_create_k` may take
three :term:`keyword arguments`:
- * :c:macro:`MPS_KEY_EXTEND_BY` (type :c:type:`size_t`, default 65536) is the
- :term:`size` of segment that the pool will request from the
- :term:`arena`.
+ * :c:macro:`MPS_KEY_EXTEND_BY` (type :c:type:`size_t`,
+ default 65536) is the :term:`size` of segment that the pool will
+ request from the :term:`arena`.
- * :c:macro:`MPS_KEY_MEAN_SIZE` (type :c:type:`size_t`, default 32) is the
- predicted mean size of blocks that will be allocated from the
- pool.
+ * :c:macro:`MPS_KEY_MEAN_SIZE` (type :c:type:`size_t`, default 32)
+ is the predicted mean size of blocks that will be allocated from
+ the pool. This value must be smaller than, or equal to, the
+ value for :c:macro:`MPS_KEY_EXTEND_BY`.
- * :c:macro:`MPS_KEY_MAX_SIZE` (type :c:type:`size_t`, default 65536) is the
- predicted maximum size of blocks that will be allocated from the
- pool.
+ * :c:macro:`MPS_KEY_MAX_SIZE` (type :c:type:`size_t`,
+ default 65536) is the predicted maximum size of blocks that will
+ be allocated from the pool. This value must be larger than, or
+ equal to, the value for :c:macro:`MPS_KEY_EXTEND_BY`.
The mean and maximum sizes are *hints* to the MPS: the pool will be
less efficient if these are wrong, but nothing will break.
diff --git a/mps/manual/source/release.rst b/mps/manual/source/release.rst
index 294b6545b91..18cc8ed72e9 100644
--- a/mps/manual/source/release.rst
+++ b/mps/manual/source/release.rst
@@ -27,6 +27,45 @@ New features
calling :c:func:`mps_pool_create_k`.
+Interface changes
+.................
+
+#. There is now a default value (currently 1 \ :term:`megabyte`) for
+ the :c:macro:`MPS_KEY_ARENA_SIZE` keyword argument to
+ :c:func:`mps_arena_create_k` when creating a virtual memory arena.
+ See :c:func:`mps_arena_class_vm`.
+
+
+Other changes
+.............
+
+#. The :ref:`pool-ams` pool class no longer triggers the assertion
+ ``!AMS_IS_INVALID_COLOUR(seg, i)`` under rare circumstances
+ (namely, detaching an :term:`allocation point` from a :term:`grey`
+ segment when :c:macro:`MPS_KEY_AMS_SUPPORT_AMBIGUOUS` is
+ ``FALSE``). See job001549_.
+
+ .. _job001549: https://www.ravenbrook.com/project/mps/issue/job001549/
+
+#. :c:func:`mps_arena_roots_walk` no longer triggers an assertion
+ failure when run twice in succession. See job003496_.
+
+ .. _job003496: https://www.ravenbrook.com/project/mps/issue/job003496/
+
+#. The alignment of :ref:`pool-awl` pools is now configurable via the
+ object format, as documented, and is no longer always
+ :c:macro:`MPS_PF_ALIGN`. See job003745_.
+
+ .. _job003745: https://www.ravenbrook.com/project/mps/issue/job003745/
+
+#. :program:`mpseventtxt` now successfully processes a telemetry log
+ containing multiple labels associated with the same address. See
+ job003756_.
+
+ .. _job003756: https://www.ravenbrook.com/project/mps/issue/job003756/
+
+
+
.. _release-notes-1.113:
Release 1.113.0
diff --git a/mps/manual/source/topic/arena.rst b/mps/manual/source/topic/arena.rst
index 5220ece4007..1925117cc84 100644
--- a/mps/manual/source/topic/arena.rst
+++ b/mps/manual/source/topic/arena.rst
@@ -233,18 +233,18 @@ Virtual memory arenas
more efficient.
When creating a virtual memory arena, :c:func:`mps_arena_create_k`
- requires one :term:`keyword argument`:
+ accepts one :term:`keyword argument` on all platforms:
- * :c:macro:`MPS_KEY_ARENA_SIZE` (type :c:type:`size_t`). is the
- initial amount of virtual address space, in :term:`bytes (1)`,
- that the arena will reserve (this space is initially reserved so
- that the arena can subsequently use it without interference from
- other parts of the program, but most of it is not committed, so
- it doesn't require any RAM or backing store). The arena may
- allocate more virtual address space beyond this initial
- reservation as and when it deems it necessary. The MPS is most
- efficient if you reserve an address space that is several times
- larger than your peak memory usage.
+ * :c:macro:`MPS_KEY_ARENA_SIZE` (type :c:type:`size_t`, default
+ 2\ :superscript:`20`) is the initial amount of virtual address
+ space, in :term:`bytes (1)`, that the arena will reserve (this
+ space is initially reserved so that the arena can subsequently
+ use it without interference from other parts of the program, but
+ most of it is not committed, so it doesn't require any RAM or
+ backing store). The arena may allocate more virtual address
+ space beyond this initial reservation as and when it deems it
+ necessary. The MPS is most efficient if you reserve an address
+ space that is several times larger than your peak memory usage.
.. note::
@@ -252,8 +252,8 @@ Virtual memory arenas
more times it has to extend its address space, the less
efficient garbage collection will become.
- An optional :term:`keyword argument` may be passed, but is
- only used on the Windows operating system:
+ A second optional :term:`keyword argument` may be passed, but it
+ only has any effect on the Windows operating system:
* :c:macro:`MPS_KEY_VMW3_TOP_DOWN` (type :c:type:`mps_bool_t`). If
true, the arena will allocate address space starting at the
@@ -273,8 +273,9 @@ Virtual memory arenas
If the MPS fails to allocate memory for the internal arena
structures, :c:func:`mps_arena_create_k` returns
- :c:macro:`MPS_RES_MEMORY`. Either ``size`` was far too small or
- the operating system refused to provide enough memory.
+ :c:macro:`MPS_RES_MEMORY`. Either :c:macro:`MPS_KEY_ARENA_SIZE`
+ was far too small or the operating system refused to provide
+ enough memory.
For example::
diff --git a/mps/manual/source/topic/error.rst b/mps/manual/source/topic/error.rst
index 97ec2f73216..6b2e9452fc2 100644
--- a/mps/manual/source/topic/error.rst
+++ b/mps/manual/source/topic/error.rst
@@ -232,7 +232,7 @@ assertion that is listed here but for which you discovered a different
cause), please :ref:`let us know ` so that we can improve
this documentation.
-``arenavm.c: BTIsResRange(vmChunk->pageTableMapped, 0, chunk->pageTablePages)``
+``sa.c: BTIsResRange(sa->mapped, 0, sa->length)``
The client program called :c:func:`mps_arena_destroy` without
having destroyed all pools in that arena first. (The assertion is
@@ -283,14 +283,6 @@ this documentation.
point` instead.
-``poolams.c: !AMS_IS_INVALID_COLOUR(seg, i)``
-
- The client program failed to :term:`fix` a reference to an object
- in an :ref:`pool-ams` pool, violating the :term:`tri-colour
- invariant` that the MPS depends on for the correctness of its
- :term:`incremental garbage collection`.
-
-
``poolams.c: AMS_ALLOCED(seg, i)``
The client program tried to :term:`fix` a :term:`reference` to a
diff --git a/mps/manual/source/topic/format.rst b/mps/manual/source/topic/format.rst
index 91ac7ae6462..b9bbdae61bb 100644
--- a/mps/manual/source/topic/format.rst
+++ b/mps/manual/source/topic/format.rst
@@ -468,22 +468,27 @@ Object format introspection
Each :term:`pool class` determines for which objects the stepper
function is called. Typically, all validly formatted objects are
- visited. During a :term:`trace` this will in general be only the
- :term:`black` objects, though the :ref:`pool-lo` pool, for
- example, will walk all objects since they are validly formatted
- whether they are black or :term:`white`. :term:`Padding objects`
- may be visited at the pool class's discretion: the :term:`client
- program` should handle this case.
-
- .. seealso::
-
- :ref:`topic-arena`.
+ visited. :term:`Padding objects` may be visited at the pool
+ class's discretion: the stepper function must handle this
+ case.
.. note::
This function is intended for heap analysis, tuning, and
debugging, not for frequent use in production.
+ .. warning::
+
+ If a garbage collection is currently in progress (that is, if
+ the arena is in the :term:`clamped ` or
+ :term:`unclamped state`), then only objects that are known to
+ be currently valid are visited.
+
+ For the most reliable results, ensure the arena is in the
+ :term:`parked state` by calling :c:func:`mps_arena_park`
+ before calling this function (and release it by calling
+ :c:func:`mps_arena_release` afterwards, if desired).
+
.. c:type:: void (*mps_formatted_objects_stepper_t)(mps_addr_t addr, mps_fmt_t fmt, mps_pool_t pool, void *p, size_t s)
@@ -515,10 +520,6 @@ Object format introspection
It must not access other memory managed by the MPS.
- .. seealso::
-
- :ref:`topic-arena`.
-
Obsolete interface
------------------
diff --git a/mps/manual/source/topic/keyword.rst b/mps/manual/source/topic/keyword.rst
index 665daa91e64..3b3fbcb01ad 100644
--- a/mps/manual/source/topic/keyword.rst
+++ b/mps/manual/source/topic/keyword.rst
@@ -36,9 +36,8 @@ help with forming keyword argument lists::
} MPS_ARGS_END(args);
The argument array must not be ``NULL``, and must end with
-:c:macro:`MPS_KEY_ARGS_END`. If you don't want to pass any arguments, you can
-either call the equivalent function that does not take keyword arguments
-(named without the ``_k``) or pass :c:macro:`mps_args_none`.
+:c:macro:`MPS_KEY_ARGS_END`. If you don't want to pass any arguments,
+you can pass :c:macro:`mps_args_none`.
When a function that takes keyword arguments returns, the keyword
argument array has been *modified* to remove any arguments that have
diff --git a/mps/manual/source/topic/telemetry.rst b/mps/manual/source/topic/telemetry.rst
index f33de3516ce..a665aaf4b07 100644
--- a/mps/manual/source/topic/telemetry.rst
+++ b/mps/manual/source/topic/telemetry.rst
@@ -110,7 +110,7 @@ The MPS writes the telemetry to the log in an encoded form for speed.
It can be decoded using the :ref:`mpseventcnv `
and :ref:`mpseventtxt ` programs::
- (gdb) shell mpseventcnv | mpseventtxt | sort > mpsio.txt
+ (gdb) shell mpseventcnv | sort | mpseventtxt > mpsio.txt
The ``sort`` is useful because the events are not necessarily written
to the telemetry file in time order, but each event starts with a
diff --git a/mps/test/function/122.c b/mps/test/function/122.c
index 6f1465289cb..4ba0c0c6090 100644
--- a/mps/test/function/122.c
+++ b/mps/test/function/122.c
@@ -133,7 +133,7 @@ static void test(void)
die(allocrdumb(&a[0], aplo, 64, mps_rank_exact()), "alloc");
die(allocrdumb(&a[1], apamc, 64, mps_rank_exact()), "alloc");
die(allocrdumb(&a[3], apawl, 64, mps_rank_exact()), "alloc");
- a[2] = (mycell *)((int)a[3] | 4);
+ a[2] = (mycell *)((mps_word_t)a[3] | 4);
die(allocrdumb(&b[0], aplo, 64, mps_rank_exact()), "alloc");
die(allocrdumb(&b[1], apamc, 64, mps_rank_exact()), "alloc");
diff --git a/mps/test/function/40.c b/mps/test/function/40.c
index c57f8c62ba5..5257e1fcfc1 100644
--- a/mps/test/function/40.c
+++ b/mps/test/function/40.c
@@ -66,7 +66,7 @@ static void test(void)
comment("%i of 10.", i);
UC;
z[i] = allocone(ap, 1, 1);
- if (i % 8 == 0) { z[i] = (mycell *) ((int)z[i] + 4); } /* error to scan this! */
+ if (i % 8 == 0) { z[i] = (mycell *) ((mps_word_t)z[i] + 4); } /* error to scan this! */
}
for (i=0; i<1000; i++) {
diff --git a/mps/test/function/51.c b/mps/test/function/51.c
index 7be804d666a..779445218ae 100644
--- a/mps/test/function/51.c
+++ b/mps/test/function/51.c
@@ -14,6 +14,7 @@ END_HEADER
#include "testlib.h"
#include "mpscawl.h"
#include "mpscamc.h"
+#include "mpscams.h"
#include "mpsclo.h"
#include "mpsavm.h"
#include "rankfmt.h"
@@ -94,15 +95,15 @@ static void finalpoll(mycell **ref, int faction)
static void test(void)
{
- mps_pool_t poolamc, poolawl, poollo;
+ mps_pool_t poolamc, poolamcz, poolams, poolawl, poollo;
mps_thr_t thread;
mps_root_t root0, root1;
mps_fmt_t format;
mps_chain_t chain;
- mps_ap_t apamc, apawl, aplo;
+ mps_ap_t apamc, apamcz, apams, apawl, aplo;
- mycell *a, *b, *c, *d, *z;
+ mycell *a, *b, *c, *d, *e, *z;
long int i,j;
@@ -126,20 +127,39 @@ static void test(void)
die(mmqa_pool_create_chain(&poolamc, arena, mps_class_amc(), format, chain),
"create pool");
- cdie(mps_pool_create(&poolawl, arena, mps_class_awl(), format, getassociated),
- "create pool");
+ die(mmqa_pool_create_chain(&poolamcz, arena, mps_class_amcz(), format, chain),
+ "create pool");
- cdie(mps_pool_create(&poollo, arena, mps_class_lo(), format),
- "create pool");
+ MPS_ARGS_BEGIN(args) {
+ MPS_ARGS_ADD(args, MPS_KEY_FORMAT, format);
+ MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain);
+ MPS_ARGS_ADD(args, MPS_KEY_GEN, 0);
+ cdie(mps_pool_create_k(&poolams, arena, mps_class_ams(), args),
+ "create pool");
+ } MPS_ARGS_END(args);
- cdie(mps_ap_create(&apawl, poolawl, mps_rank_weak()),
- "create ap");
+ MPS_ARGS_BEGIN(args) {
+ MPS_ARGS_ADD(args, MPS_KEY_FORMAT, format);
+ MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain);
+ MPS_ARGS_ADD(args, MPS_KEY_GEN, 0);
+ MPS_ARGS_ADD(args, MPS_KEY_AWL_FIND_DEPENDENT, getassociated);
+ cdie(mps_pool_create_k(&poolawl, arena, mps_class_awl(), args),
+ "create pool");
+ } MPS_ARGS_END(args);
- cdie(mps_ap_create(&apamc, poolamc, mps_rank_exact()),
- "create ap");
-
- cdie(mps_ap_create(&aplo, poollo, mps_rank_exact()),
- "create ap");
+ MPS_ARGS_BEGIN(args) {
+ MPS_ARGS_ADD(args, MPS_KEY_FORMAT, format);
+ MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain);
+ MPS_ARGS_ADD(args, MPS_KEY_GEN, 0);
+ cdie(mps_pool_create_k(&poollo, arena, mps_class_lo(), args),
+ "create pool");
+ } MPS_ARGS_END(args);
+
+ cdie(mps_ap_create(&apawl, poolawl, mps_rank_weak()), "create ap");
+ cdie(mps_ap_create(&apamc, poolamc, mps_rank_exact()), "create ap");
+ cdie(mps_ap_create(&apamcz, poolamcz, mps_rank_exact()), "create ap");
+ cdie(mps_ap_create(&apams, poolams, mps_rank_exact()), "create ap");
+ cdie(mps_ap_create(&aplo, poollo, mps_rank_exact()), "create ap");
mps_message_type_enable(arena, mps_message_type_finalization());
@@ -150,13 +170,17 @@ static void test(void)
for (j=0; j<1000; j++) {
a = allocone(apamc, 2, mps_rank_exact());
- c = allocone(apawl, 2, mps_rank_weak());
- d = allocone(aplo, 2, mps_rank_exact()); /* rank irrelevant here! */
+ b = allocone(apamcz, 2, mps_rank_exact()); /* rank irrelevant here! */
+ c = allocone(apams, 2, mps_rank_exact());
+ d = allocone(apawl, 2, mps_rank_weak());
+ e = allocone(aplo, 2, mps_rank_exact()); /* rank irrelevant here! */
mps_finalize(arena, (mps_addr_t*)&a);
+ mps_finalize(arena, (mps_addr_t*)&b);
mps_finalize(arena, (mps_addr_t*)&c);
mps_finalize(arena, (mps_addr_t*)&d);
- mps_finalize(arena, (mps_addr_t*)&d);
- final_count += 4;
+ mps_finalize(arena, (mps_addr_t*)&e);
+ mps_finalize(arena, (mps_addr_t*)&e);
+ final_count += 6;
}
/* throw them all away and collect everything */
@@ -176,10 +200,12 @@ static void test(void)
while (final_count != 0 && i < 10) {
finalpoll(&z, FINAL_DISCARD);
- if (mps_message_poll(arena) == 0) {
+ if (final_count != 0 && mps_message_poll(arena) == 0) {
i++;
- a = allocdumb(apawl, 1024, mps_rank_weak());
a = allocdumb(apamc, 1024, mps_rank_exact());
+ a = allocdumb(apamcz, 1024, mps_rank_exact());
+ a = allocdumb(apams, 1024, mps_rank_exact());
+ a = allocdumb(apawl, 1024, mps_rank_weak());
a = allocdumb(aplo, 1024, mps_rank_exact());
mps_arena_collect(arena);
comment(" %i", final_count);
@@ -193,12 +219,16 @@ static void test(void)
/* now to test leaving messages open for a long time! */
- mps_ap_destroy(apawl);
mps_ap_destroy(apamc);
+ mps_ap_destroy(apamcz);
+ mps_ap_destroy(apams);
+ mps_ap_destroy(apawl);
mps_ap_destroy(aplo);
comment("Destroyed aps.");
mps_pool_destroy(poolamc);
+ mps_pool_destroy(poolamcz);
+ mps_pool_destroy(poolams);
mps_pool_destroy(poolawl);
mps_pool_destroy(poollo);
comment("Destroyed pools.");
diff --git a/mps/test/testsets/passing b/mps/test/testsets/passing
index 64c72fe2982..fc00f37feb0 100644
--- a/mps/test/testsets/passing
+++ b/mps/test/testsets/passing
@@ -110,7 +110,7 @@ function/118.c
function/119.c
function/120.c
% function/121.c -- job003495
-% function/122.c -- job003496
+function/122.c
function/123.c
function/124.c
function/125.c
diff --git a/mps/tool/branch b/mps/tool/branch
index f60eccae235..686cdefa244 100755
--- a/mps/tool/branch
+++ b/mps/tool/branch
@@ -46,9 +46,9 @@ CHILD_RE = r'(?:{}|{})$'.format(TASK_BRANCH_RE, VERSION_BRANCH_RE)
TASK_BRANCH_ENTRY = '''
- {child}
+ {date}/{task}
Changes
- {description}
+ {desc_html}
In development (diffs).
@@ -60,7 +60,7 @@ VERSION_BRANCH_ENTRY = '''
None.
{parent}/...@{changelevel}
- {description}
+ {desc_html}
base
@@ -161,6 +161,9 @@ def main(argv):
if not args.description:
args.description = fmt("Branching {parent} to {child}.")
print(fmt("description={description}"))
+ args.desc_html = re.sub(r'\b(job\d{6})\b',
+ fmt(r'\1'),
+ args.description)
# Create the branch specification
args.branch = fmt('{project}/{child}')
diff --git a/mps/tool/p4-bisect b/mps/tool/p4-bisect
new file mode 100755
index 00000000000..97ff39dad74
--- /dev/null
+++ b/mps/tool/p4-bisect
@@ -0,0 +1,174 @@
+#!/usr/bin/env python
+#
+#
+# Ravenbrook
+#
+#
+# P4-BISECT -- FIND CHANGE THAT INTRODUCED A BUG
+#
+# Gareth Rees, Ravenbrook Limited, 2014-04-14
+#
+#
+# 1. INTRODUCTION
+#
+# This script automates (or partly automates) the process of finding,
+# by binary search, the change that introduced a bug.
+#
+# The interface is modelled closely on git-bisect(1).
+
+import argparse
+from functools import partial
+import json
+from os import unlink
+import p4
+import subprocess
+import sys
+
+BISECT_FILE = '.p4-bisect'
+
+def error(msg):
+ sys.stderr.write(msg)
+ sys.stderr.write('\n')
+ exit(1)
+
+def sync(*filespecs):
+ try:
+ p4.do('sync', *filespecs)
+ except p4.Error as e:
+ if 'file(s) up-to-date' not in e.args[0]:
+ raise
+
+class State(object):
+ def __init__(self, **d):
+ self.filespec = d['filespec']
+ self.changes = d['changes']
+ if 'current' in d:
+ self.current = d['current']
+
+ @classmethod
+ def load(cls):
+ try:
+ with open(BISECT_FILE, 'r') as f:
+ return cls(**json.load(f))
+ except FileNotFoundError:
+ error("p4-bisect not in progress here.")
+
+ def save(self):
+ with open(BISECT_FILE, 'w') as f:
+ json.dump(vars(self), f)
+
+ def update(self):
+ n = len(self.changes)
+ if n == 0:
+ print("no changes remaining.".format(**vars(self)))
+ elif n == 1:
+ print("{} change remaining: {}.".format(n, self.changes[0]))
+ elif n == 2:
+ print("{} changes remaining: [{}, {}]."
+ .format(n, self.changes[0], self.changes[-1]))
+ else:
+ print("{} changes remaining: [{}, ..., {}]."
+ .format(n, self.changes[0], self.changes[-1]))
+ if n > 0:
+ self.current = self.changes[n // 2]
+ print("Syncing to changelevel {current}.".format(**vars(self)))
+ sync(*['{}@{}'.format(f, self.current) for f in self.filespec])
+ self.save()
+
+def help(parser, args):
+ parser.print_help()
+
+def start(args):
+ args.filespec = args.filespec or ['...']
+ changes = sorted(int(c['change']) for c in p4.run('changes', *args.filespec))
+ if not changes:
+ error("No changes for {}".format(' '.join(args.filespec)))
+ if args.first is None:
+ args.first = changes[0]
+ if args.last is None:
+ args.last = changes[-1]
+ state = State(filespec=args.filespec,
+ changes=[c for c in changes if args.first <= c <= args.last])
+ state.update()
+
+def good(args):
+ state = State.load()
+ print("Change {current} good.".format(**vars(state)))
+ state.changes = [c for c in state.changes if c > state.current]
+ state.update()
+
+def bad(args):
+ state = State.load()
+ print("Change {current} bad.".format(**vars(state)))
+ state.changes = [c for c in state.changes if c < state.current]
+ state.update()
+
+def skip(args):
+ state = State.load()
+ print("Skipping change {current}.".format(**vars(state)))
+ state.changes.remove(state.current)
+ state.update()
+
+def reset(args):
+ state = State.load()
+ sync(*state.filespec)
+ unlink(BISECT_FILE)
+
+def run(args):
+ while True:
+ state = State.load()
+ if not state.changes:
+ break
+ result = subprocess.call([args.cmd] + args.args)
+ if result == 0:
+ good(None)
+ elif result == 125:
+ skip(None)
+ elif 0 < result < 128:
+ bad(None)
+ else:
+ exit(result)
+
+def main(argv):
+ parser = argparse.ArgumentParser(prog='p4-bisect')
+ subparsers = parser.add_subparsers()
+ a = subparsers.add_parser
+
+ help_parser = a('help', help='show this help message')
+ help_parser.set_defaults(func=partial(help, parser))
+
+ start_parser = a('start', help='start a p4-bisect session')
+ aa = start_parser.add_argument
+ start_parser.add_argument('-f', '--filespec', action='append',
+ help='filespec to search')
+ start_parser.add_argument('first', nargs='?', type=int,
+ help='earliest changelevel to examine')
+ start_parser.add_argument('last', nargs='?', type=int,
+ help='latest changelevel to examine')
+ start_parser.set_defaults(func=start)
+
+ good_parser = a('good', help='declare current revision good')
+ good_parser.set_defaults(func=good)
+
+ bad_parser = a('bad', help='declare current revision bad')
+ bad_parser.set_defaults(func=bad)
+
+ skip_parser = a('skip', help='skip current revision')
+ skip_parser.set_defaults(func=skip)
+
+ reset_parser = a('reset', help='finish p4-bisect session')
+ reset_parser.set_defaults(func=reset)
+
+ run_parser = a('run', help='run p4-bisect session automatically')
+ run_parser.add_argument('cmd',
+ help='command that determines if current '
+ 'changelevel is good or bad')
+ run_parser.add_argument('args', nargs=argparse.REMAINDER,
+ help='arguments to pass to cmd')
+ run_parser.set_defaults(func=run)
+
+ args = parser.parse_args(argv[1:])
+ args.func(args)
+
+if __name__ == '__main__':
+ main(sys.argv)
diff --git a/mps/tool/testopendylan b/mps/tool/testopendylan
index 9c18938ef1e..a8aee4a0025 100755
--- a/mps/tool/testopendylan
+++ b/mps/tool/testopendylan
@@ -104,7 +104,7 @@ if [ -f "$REPO/Makefile" ]; then
else (
cd -- "$REPO" &&
./autogen.sh &&
- ./configure --with-mps="$MPS" --prefix="$PREFIX"
+ ./configure --with-gc=mps --with-gc-path="$MPS" --prefix="$PREFIX"
) fi
(
cd -- "$REPO" &&
@@ -128,6 +128,9 @@ else (
#
# 2014-03-20 GDR Created based on [WELCOME].
#
+# 2014-04-14 GDR Updated configure args based on revised build
+# instructions [WELCOME].
+#
#
# C. COPYRIGHT AND LICENCE
#
diff --git a/mps/tool/testrun.bat b/mps/tool/testrun.bat
index 7be1b135379..f4e06e56d09 100755
--- a/mps/tool/testrun.bat
+++ b/mps/tool/testrun.bat
@@ -24,12 +24,14 @@ set ALL_TEST_CASES=^
airtest.exe ^
amcss.exe ^
amcsshe.exe ^
+ amcssth.exe ^
amsss.exe ^
amssshe.exe ^
apss.exe ^
arenacv.exe ^
awlut.exe ^
awluthe.exe ^
+ awlutth.exe ^
btcv.exe ^
exposet0.exe ^
expt825.exe ^
@@ -39,7 +41,7 @@ set ALL_TEST_CASES=^
landtest.exe ^
locbwcss.exe ^
lockcov.exe ^
- lockutw3.exe ^
+ lockut.exe ^
locusss.exe ^
locv.exe ^
messtest.exe ^
diff --git a/mps/tool/testrun.sh b/mps/tool/testrun.sh
index 290c124c0d8..a9d6cd87c33 100755
--- a/mps/tool/testrun.sh
+++ b/mps/tool/testrun.sh
@@ -36,6 +36,7 @@ ALL_TEST_CASES="
landtest
locbwcss
lockcov
+ lockut
locusss
locv
messtest