1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-03-26 08:41:47 -07:00

Catch-up merge from master sources at change 193831 to branch/2017-03-04/seg-methods.

Copied from Perforce
 Change: 193836
This commit is contained in:
Gareth Rees 2018-06-15 13:46:23 +01:00
commit de94fe2aa3
84 changed files with 1135 additions and 365 deletions

View file

@ -193,7 +193,7 @@ static void test_pool(const char *name, mps_pool_t pool, size_t roots_count)
size_t condemned = mps_message_gc_condemned_size(arena, msg);
size_t not_condemned = mps_message_gc_not_condemned_size(arena, msg);
printf("\nCollection %lu finished:\n", collections++);
printf("\nCollection %lu finished:\n", (unsigned long)collections++);
printf("live %"PRIuLONGEST"\n", (ulongest_t)live);
printf("condemned %"PRIuLONGEST"\n", (ulongest_t)condemned);
printf("not_condemned %"PRIuLONGEST"\n", (ulongest_t)not_condemned);

View file

@ -266,6 +266,7 @@ TEST_TARGETS=\
expt825 \
finalcv \
finaltest \
forktest \
fotest \
gcbench \
landtest \
@ -499,6 +500,9 @@ $(PFM)/$(VARIETY)/finalcv: $(PFM)/$(VARIETY)/finalcv.o \
$(PFM)/$(VARIETY)/finaltest: $(PFM)/$(VARIETY)/finaltest.o \
$(FMTDYTSTOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a
$(PFM)/$(VARIETY)/forktest: $(PFM)/$(VARIETY)/forktest.o \
$(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a
$(PFM)/$(VARIETY)/fotest: $(PFM)/$(VARIETY)/fotest.o \
$(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a

View file

@ -1,7 +1,7 @@
/* config.h: MPS CONFIGURATION
*
* $Id$
* Copyright (c) 2001-2017 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2018 Ravenbrook Limited. See end of file for license.
* Portions copyright (c) 2002 Global Graphics Software.
*
* PURPOSE
@ -546,7 +546,7 @@
#endif
/* .feature.xc: OS X feature specification
/* .feature.xc: macOS feature specification
*
* The MPS needs the following symbols which are not defined by default
*
@ -589,7 +589,7 @@
#else
#error "Unknown OS X architecture"
#error "Unknown macOS architecture"
#endif
#endif
@ -694,7 +694,7 @@
*
* TODO: These settings were determined by trial and error, but should
* be based on measurement of the protection overhead on each
* platform. We know it's extremely different between OS X and
* platform. We know it's extremely different between macOS and
* Windows, for example. See design.mps.write-barrier.improv.by-os.
*
* TODO: Consider basing the count on the amount of time that has
@ -712,7 +712,7 @@
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2017 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2001-2018 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -1,7 +1,7 @@
/* eventpy.c: GENERATE PYTHON INTERFACE TO EVENTS
*
* $Id$
* Copyright (c) 2016 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2016-2018 Ravenbrook Limited. See end of file for license.
*
* This command-line program emits Python data structures that can be
* used to parse an event stream in text format (as output by the
@ -22,37 +22,37 @@ int main(int argc, char *argv[])
printf("__version__ = %d, %d, %d\n", EVENT_VERSION_MAJOR,
EVENT_VERSION_MEDIAN, EVENT_VERSION_MINOR);
puts("EventKind = namedtuple('EventKind', 'name code doc')");
puts("class kind:");
puts("KindDesc = namedtuple('KindDesc', 'name code doc')");
puts("class Kind:");
#define ENUM(_, NAME, DOC) \
printf(" " #NAME " = EventKind('" #NAME "', %d, \"%s\")\n", \
printf(" " #NAME " = KindDesc('" #NAME "', %d, \"%s\")\n", \
EventKind ## NAME, DOC);
EventKindENUM(ENUM, _);
#undef ENUM
puts("kinds = {");
puts("KIND = {");
#define ENUM(_, NAME, _1) \
printf(" %d: kind." #NAME ",\n", EventKind ## NAME);
printf(" %d: Kind." #NAME ",\n", EventKind ## NAME);
EventKindENUM(ENUM, _);
#undef ENUM
puts("}");
puts("EventParam = namedtuple('EventParam', 'sort, name')");
puts("Event = namedtuple('Event', 'name code always kind params')");
puts("class event:");
puts("EventParam = namedtuple('EventParam', 'sort name')");
puts("EventDesc = namedtuple('EventDesc', 'name code always kind params')");
puts("class Event:");
#define EVENT_PARAM(X, INDEX, SORT, NAME) \
puts(" EventParam('" #SORT "', '" #NAME "'),");
#define EVENT_DEFINE(X, NAME, CODE, ALWAYS, KIND) \
printf(" " #NAME " = Event('" #NAME "', %d, %s, kind." #KIND ", [\n", \
printf(" " #NAME " = EventDesc('" #NAME "', %d, %s, Kind." #KIND ", [\n", \
CODE, ALWAYS ? "True" : "False"); \
EVENT_ ## NAME ## _PARAMS(EVENT_PARAM, X); \
puts(" ]);");
puts(" ])");
EVENT_LIST(EVENT_DEFINE, 0);
#undef EVENT
puts("events = {");
puts("EVENT = {");
#define EVENT_ITEM(X, NAME, CODE, ALWAYS, KIND) \
printf(" %d: event." #NAME ",\n", CODE);
printf(" %d: Event." #NAME ",\n", CODE);
EVENT_LIST(EVENT_ITEM, 0);
#undef EVENT
puts("}");
@ -63,7 +63,7 @@ int main(int argc, char *argv[])
/* C. COPYRIGHT AND LICENSE
*
* Copyright (c) 2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (c) 2016-2018 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -1,7 +1,7 @@
/* fmtdy.c: DYLAN OBJECT FORMAT IMPLEMENTATION
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2018 Ravenbrook Limited. See end of file for license.
* Portions copyright (c) 2002 Global Graphics Software.
*
* .readership: MPS developers, Dylan developers
@ -407,8 +407,11 @@ extern mps_res_t dylan_scan1(mps_ss_t mps_ss, mps_addr_t *object_io)
return MPS_RES_OK;
}
res = mps_fix(mps_ss, p); /* fix the wrapper */
if ( res != MPS_RES_OK ) return res;
MPS_SCAN_BEGIN(mps_ss) {
res = MPS_FIX12(mps_ss, p); /* fix the wrapper */
} MPS_SCAN_END(mps_ss);
if (res != MPS_RES_OK)
return res;
w = (mps_word_t *)p[0]; /* wrapper is header word */
assert(dylan_wrapper_check(w));
@ -567,8 +570,11 @@ extern mps_res_t dylan_scan1_weak(mps_ss_t mps_ss, mps_addr_t *object_io)
assert((h & 3) == 0);
unused(h);
res = mps_fix(mps_ss, p);
if ( res != MPS_RES_OK ) return res;
MPS_SCAN_BEGIN(mps_ss) {
res = MPS_FIX12(mps_ss, p);
} MPS_SCAN_END(mps_ss);
if (res != MPS_RES_OK)
return res;
/* w points to wrapper */
w = (mps_word_t *)p[0];
@ -852,7 +858,7 @@ mps_res_t dylan_fmt_weak(mps_fmt_t *mps_fmt_o, mps_arena_t arena)
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2001-2018 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

231
mps/code/forktest.c Normal file
View file

@ -0,0 +1,231 @@
/* forktest.c: FORK SAFETY TEST
*
* $Id: //info.ravenbrook.com/project/mps/branch/2018-06-13/fork/code/tagtest.c#1 $
* Copyright (c) 2018 Ravenbrook Limited. See end of file for license.
*
* .overview: This test case is a regression test for job004062. It
* checks that the MPS correctly runs in the child process after a
* fork() on FreeBSD, Linux or macOS.
*
* .format: This test case uses a trivial object format in which each
* object contains a single reference.
*/
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
#include "mps.h"
#include "mpsavm.h"
#include "mpscamc.h"
#include "testlib.h"
enum {
TYPE_REF,
TYPE_FWD,
TYPE_PAD
};
typedef struct obj_s {
unsigned type; /* One of the TYPE_ enums */
union {
struct obj_s *ref; /* TYPE_REF */
mps_addr_t fwd; /* TYPE_FWD */
size_t pad; /* TYPE_PAD */
} u;
} obj_s, *obj_t;
static void obj_fwd(mps_addr_t old, mps_addr_t new)
{
obj_t obj = old;
obj->type = TYPE_FWD;
obj->u.fwd = new;
}
static mps_addr_t obj_isfwd(mps_addr_t addr)
{
obj_t obj = addr;
if (obj->type == TYPE_FWD) {
return obj->u.fwd;
} else {
return NULL;
}
}
static void obj_pad(mps_addr_t addr, size_t size)
{
obj_t obj = addr;
obj->type = TYPE_PAD;
obj->u.pad = size;
}
static mps_addr_t obj_skip(mps_addr_t addr)
{
obj_t obj = addr;
size_t size;
if (obj->type == TYPE_PAD) {
size = obj->u.pad;
} else {
size = sizeof(obj_s);
}
return (char *)addr + size;
}
static mps_res_t obj_scan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit)
{
MPS_SCAN_BEGIN(ss) {
while (base < limit) {
obj_t obj = base;
if (obj->type == TYPE_REF) {
mps_addr_t p = obj->u.ref;
mps_res_t res = MPS_FIX12(ss, &p);
if (res != MPS_RES_OK) {
return res;
}
obj->u.ref = p;
}
base = obj_skip(base);
}
} MPS_SCAN_END(ss);
return MPS_RES_OK;
}
int main(int argc, char *argv[])
{
void *marker = &marker;
int pid;
mps_arena_t arena;
mps_fmt_t obj_fmt;
mps_pool_t pool;
mps_thr_t thread;
mps_root_t stack_root;
mps_ap_t obj_ap;
size_t i;
obj_t obj, first;
testlib_init(argc, argv);
/* Set the pause time to be very small so that the incremental
collector (when it runs) will have to leave a read barrier in
place for us to hit. */
MPS_ARGS_BEGIN(args) {
MPS_ARGS_ADD(args, MPS_KEY_PAUSE_TIME, 0.0);
die(mps_arena_create_k(&arena, mps_arena_class_vm(), args),
"mps_arena_create");
} MPS_ARGS_END(args);
mps_arena_park(arena);
die(mps_thread_reg(&thread, arena), "Couldn't register thread");
die(mps_root_create_thread(&stack_root, arena, thread, marker),
"Couldn't create thread root");
MPS_ARGS_BEGIN(args) {
MPS_ARGS_ADD(args, MPS_KEY_FMT_ALIGN, sizeof(obj_s));
MPS_ARGS_ADD(args, MPS_KEY_FMT_SCAN, obj_scan);
MPS_ARGS_ADD(args, MPS_KEY_FMT_SKIP, obj_skip);
MPS_ARGS_ADD(args, MPS_KEY_FMT_FWD, obj_fwd);
MPS_ARGS_ADD(args, MPS_KEY_FMT_ISFWD, obj_isfwd);
MPS_ARGS_ADD(args, MPS_KEY_FMT_PAD, obj_pad);
die(mps_fmt_create_k(&obj_fmt, arena, args), "Couldn't create obj format");
} MPS_ARGS_END(args);
MPS_ARGS_BEGIN(args) {
MPS_ARGS_ADD(args, MPS_KEY_FORMAT, obj_fmt);
die(mps_pool_create_k(&pool, arena, mps_class_amc(), args),
"Couldn't create pool");
} MPS_ARGS_END(args);
die(mps_ap_create_k(&obj_ap, pool, mps_args_none),
"Couldn't create obj allocation point");
/* Create a linked list of objects. */
first = NULL;
for (i = 0; i < 100000; ++i) {
size_t size = sizeof(obj_s);
mps_addr_t addr;
do {
die(mps_reserve(&addr, obj_ap, size), "Couldn't allocate.");
obj = addr;
obj->type = TYPE_REF;
obj->u.ref = NULL;
} while (!mps_commit(obj_ap, addr, size));
obj->u.ref = first;
first = obj;
}
pid = fork();
cdie(pid >= 0, "fork failed");
/* Allow a collection to start, which will cause a read barrier to
be applied to any segment containing live objects that was
scanned. */
mps_arena_release(arena);
/* Read all the objects, so that if there is read barrier in place
we will hit it. */
for (obj = first; obj != NULL; obj = obj->u.ref) {
Insist(obj->type == TYPE_REF);
}
mps_arena_park(arena);
if (pid != 0) {
/* Parent: wait for child and check that its exit status is zero. */
int stat;
cdie(pid == waitpid(pid, &stat, 0), "waitpid failed");
cdie(WIFEXITED(stat), "child did not exit normally");
cdie(WEXITSTATUS(stat) == 0, "child exited with nonzero status");
printf("%s: Conclusion: Failed to find any defects.\n", argv[0]);
}
mps_ap_destroy(obj_ap);
mps_pool_destroy(pool);
mps_fmt_destroy(obj_fmt);
mps_root_destroy(stack_root);
mps_thread_dereg(thread);
mps_arena_destroy(arena);
return 0;
}
/* C. COPYRIGHT AND LICENSE
*
* Copyright (c) 2018 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Redistributions in any form must be accompanied by information on how
* to obtain complete source code for this software and any accompanying
* software that uses this software. The source code must either be
* included in the distribution or be available for no more than the cost
* of distribution plus a nominal fee, and must be freely redistributable
* under reasonable conditions. For an executable file, complete source
* code means the source code for all modules it contains. It does not
* include source code for modules or files that typically accompany the
* major components of the operating system on which the executable file
* runs.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

View file

@ -53,6 +53,45 @@ static void arenaReleaseRingLock(void)
}
/* GlobalsClaimAll -- claim all MPS locks <design/thread-safety/#fork.lock> */
void GlobalsClaimAll(void)
{
LockClaimGlobalRecursive();
arenaClaimRingLock();
GlobalsArenaMap(ArenaEnter);
}
/* GlobalsReleaseAll -- release all MPS locks. GlobalsClaimAll must
* previously have been called. <design/thread-safety/#sol.fork.lock> */
void GlobalsReleaseAll(void)
{
GlobalsArenaMap(ArenaLeave);
arenaReleaseRingLock();
LockReleaseGlobalRecursive();
}
/* arenaReinitLock -- reinitialize the lock for an arena */
static void arenaReinitLock(Arena arena)
{
AVERT(Arena, arena);
ShieldLeave(arena);
LockInit(ArenaGlobals(arena)->lock);
}
/* GlobalsReinitializeAll -- reinitialize all MPS locks, and leave the
* shield for all arenas. GlobalsClaimAll must previously have been
* called. <design/thread-safety/#sol.fork.lock> */
void GlobalsReinitializeAll(void)
{
GlobalsArenaMap(arenaReinitLock);
LockInitGlobal();
}
/* arenaAnnounce -- add a new arena into the global ring of arenas
*
* On entry, the arena must not be locked (there should be no need,
@ -100,6 +139,21 @@ static void arenaDenounce(Arena arena)
}
/* GlobalsArenaMap -- map a function over the arenas. The caller must
* have acquired the ring lock. */
void GlobalsArenaMap(void (*func)(Arena arena))
{
Ring node, nextNode;
AVERT(Ring, &arenaRing);
RING_FOR(node, &arenaRing, nextNode) {
Globals arenaGlobals = RING_ELT(Globals, globalRing, node);
Arena arena = GlobalsArena(arenaGlobals);
func(arena);
}
}
/* GlobalsCheck -- check the arena globals */
Bool GlobalsCheck(Globals arenaGlobals)
@ -221,7 +275,13 @@ Res GlobalsInit(Globals arenaGlobals)
arenaRingInit = TRUE;
RingInit(&arenaRing);
arenaSerial = (Serial)0;
/* The setup functions call pthread_atfork (on the appropriate
platforms) and so must be called in the correct order. Here we
require the locks to be taken first in the "prepare" case and
released last in the "parent" and "child" cases. */
ThreadSetup();
ProtSetup();
LockSetup();
}
arena = GlobalsArena(arenaGlobals);
/* Ensure updates to arenaSerial do not race by doing the update

View file

@ -21,6 +21,11 @@
extern size_t LockSize(void);
/* LockInitGlobal -- initialize global locks */
extern void LockInitGlobal(void);
/* LockInit/Finish
*
* lock points to the allocated lock structure. A lock has no
@ -128,6 +133,11 @@ extern void LockClaimGlobal(void);
extern void LockReleaseGlobal(void);
/* LockSetup -- one-time lock initialization */
extern void LockSetup(void);
#endif /* lock_h */

View file

@ -106,6 +106,13 @@ static Lock globalLock = &globalLockStruct;
static Lock globalRecLock = &globalRecursiveLockStruct;
void LockInitGlobal(void)
{
globalLock->claims = 0;
LockInit(globalLock);
globalRecLock->claims = 0;
LockInit(globalRecLock);
}
void (LockClaimGlobalRecursive)(void)
{
@ -127,6 +134,11 @@ void (LockReleaseGlobal)(void)
LockRelease(globalLock);
}
void LockSetup(void)
{
/* Nothing to do as ANSI platform does not have fork(). */
}
/* C. COPYRIGHT AND LICENSE
*

View file

@ -1,7 +1,7 @@
/* lockix.c: RECURSIVE LOCKS FOR POSIX SYSTEMS
*
* $Id$
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2018 Ravenbrook Limited. See end of file for license.
*
* .posix: The implementation uses a POSIX interface, and should be reusable
* for many Unix-like operating systems.
@ -9,7 +9,7 @@
* .freebsd: This implementation supports FreeBSD (platform
* MPS_OS_FR).
*
* .darwin: This implementation supports Darwin (OS X) (platform
* .darwin: This implementation supports Darwin (macOS) (platform
* MPS_OS_XC).
*
* .design: These locks are implemented using mutexes.
@ -212,7 +212,7 @@ static Lock globalLock = &globalLockStruct;
static Lock globalRecLock = &globalRecLockStruct;
static pthread_once_t isGlobalLockInit = PTHREAD_ONCE_INIT;
static void globalLockInit(void)
void LockInitGlobal(void)
{
LockInit(globalLock);
LockInit(globalRecLock);
@ -226,7 +226,7 @@ void (LockClaimGlobalRecursive)(void)
int res;
/* Ensure the global lock has been initialized */
res = pthread_once(&isGlobalLockInit, globalLockInit);
res = pthread_once(&isGlobalLockInit, LockInitGlobal);
AVER(res == 0);
LockClaimRecursive(globalRecLock);
}
@ -247,7 +247,7 @@ void (LockClaimGlobal)(void)
int res;
/* Ensure the global lock has been initialized */
res = pthread_once(&isGlobalLockInit, globalLockInit);
res = pthread_once(&isGlobalLockInit, LockInitGlobal);
AVER(res == 0);
LockClaim(globalLock);
}
@ -261,6 +261,16 @@ void (LockReleaseGlobal)(void)
}
/* LockSetup -- one-time lock initialization */
void LockSetup(void)
{
/* Claim all locks before a fork; release in the parent;
reinitialize in the child <design/thread-safety/#sol.fork.lock> */
pthread_atfork(GlobalsClaimAll, GlobalsReleaseAll, GlobalsReinitializeAll);
}
#elif defined(LOCK_NONE)
#include "lockan.c"
#else
@ -270,7 +280,7 @@ void (LockReleaseGlobal)(void)
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2001-2018 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -127,15 +127,21 @@ static Lock globalLock = &globalLockStruct;
static Lock globalRecLock = &globalRecLockStruct;
static Bool globalLockInit = FALSE; /* TRUE iff initialized */
void LockInitGlobal(void)
{
globalLock->claims = 0;
LockInit(globalLock);
globalRecLock->claims = 0;
LockInit(globalRecLock);
globalLockInit = TRUE;
}
static void lockEnsureGlobalLock(void)
{
/* Ensure both global locks have been initialized. */
/* There is a race condition initializing them. */
/* There is a race condition initializing them (job004056). */
if (!globalLockInit) {
LockInit(globalLock);
LockInit(globalRecLock);
globalLockInit = TRUE;
LockInitGlobal();
}
}
@ -165,6 +171,10 @@ void (LockReleaseGlobal)(void)
LockRelease(globalLock);
}
void LockSetup(void)
{
/* Nothing to do as MPS does not support fork() on Windows. */
}
#elif defined(LOCK_NONE)
#include "lockan.c"

View file

@ -469,6 +469,10 @@ extern Res GlobalsCompleteCreate(Globals arenaGlobals);
extern void GlobalsPrepareToDestroy(Globals arenaGlobals);
extern Res GlobalsDescribe(Globals arena, mps_lib_FILE *stream, Count depth);
extern Ring GlobalsRememberedSummaryRing(Globals);
extern void GlobalsArenaMap(void (*func)(Arena arena));
extern void GlobalsClaimAll(void);
extern void GlobalsReleaseAll(void);
extern void GlobalsReinitializeAll(void);
#define ArenaGlobals(arena) (&(arena)->globals)
#define GlobalsArena(glob) PARENT(ArenaStruct, globals, glob)

View file

@ -1,14 +1,14 @@
/* mps.c: MEMORY POOL SYSTEM ALL-IN-ONE TRANSLATION UNIT
*
* $Id$
* Copyright (C) 2012-2016 Ravenbrook Limited. See end of file for license.
* Copyright (C) 2012-2018 Ravenbrook Limited. See end of file for license.
*
* .purpose: This file can be compiled to create the complete MPS library in
* a single compilation, allowing the compiler to apply global optimizations
* and inlining effectively. On most modern compilers this is also faster
* than compiling each file separately.
*
* .purpose.universal: This file also allows simple building of a Mac OS X
* .purpose.universal: This file also allows simple building of a macOS
* "universal" (multiple architecture) binary when the set of source files
* differs by architecture. It may work for other platforms in a similar
* manner.
@ -111,33 +111,33 @@
#include "span.c" /* generic stack probe */
#include "ssan.c" /* generic stack scanner */
/* Mac OS X on 32-bit Intel built with Clang or GCC */
/* macOS on 32-bit Intel built with Clang or GCC */
#elif defined(MPS_PF_XCI3LL) || defined(MPS_PF_XCI3GC)
#include "lockix.c" /* Posix locks */
#include "thxc.c" /* OS X Mach threading */
#include "thxc.c" /* macOS Mach threading */
#include "vmix.c" /* Posix virtual memory */
#include "protix.c" /* Posix protection */
#include "protxc.c" /* OS X Mach exception handling */
#include "protxc.c" /* macOS Mach exception handling */
#include "prmci3.c" /* 32-bit Intel mutator context decoding */
#include "prmcxc.c" /* Mac OS X mutator context */
#include "prmcxci3.c" /* 32-bit Intel for Mac OS X mutator context */
#include "prmcxc.c" /* macOS mutator context */
#include "prmcxci3.c" /* 32-bit Intel for macOS mutator context */
#include "span.c" /* generic stack probe */
#include "ssixi3.c" /* Posix on 32-bit Intel stack scan */
/* Mac OS X on 64-bit Intel build with Clang or GCC */
/* macOS on 64-bit Intel build with Clang or GCC */
#elif defined(MPS_PF_XCI6LL) || defined(MPS_PF_XCI6GC)
#include "lockix.c" /* Posix locks */
#include "thxc.c" /* OS X Mach threading */
#include "thxc.c" /* macOS Mach threading */
#include "vmix.c" /* Posix virtual memory */
#include "protix.c" /* Posix protection */
#include "protxc.c" /* OS X Mach exception handling */
#include "protxc.c" /* macOS Mach exception handling */
#include "prmci6.c" /* 64-bit Intel mutator context decoding */
#include "prmcxc.c" /* Mac OS X mutator context */
#include "prmcxci6.c" /* 64-bit Intel for Mac OS X mutator context */
#include "prmcxc.c" /* macOS mutator context */
#include "prmcxci6.c" /* 64-bit Intel for macOS mutator context */
#include "span.c" /* generic stack probe */
#include "ssixi6.c" /* Posix on 64-bit Intel stack scan */
@ -275,7 +275,7 @@
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2012-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2012-2018 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -93,6 +93,7 @@
2291A5E8175CB20E001D4920 /* PBXTargetDependency */,
3114A5CC156E932C001E0AA3 /* PBXTargetDependency */,
3114A5EA156E93C4001E0AA3 /* PBXTargetDependency */,
22EA3F4820D2B23F0065F5B6 /* PBXTargetDependency */,
224CC79D175E187C002FF81B /* PBXTargetDependency */,
22B2BC3F18B643B700C33E63 /* PBXTargetDependency */,
3114A65B156E95B4001E0AA3 /* PBXTargetDependency */,
@ -172,6 +173,9 @@
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 */; };
22EA3F3D20D2B0D90065F5B6 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; };
22EA3F3F20D2B0D90065F5B6 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; };
22EA3F4620D2B0FD0065F5B6 /* forktest.c in Sources */ = {isa = PBXBuildFile; fileRef = 22EA3F3720D2B0730065F5B6 /* forktest.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 */; };
@ -531,6 +535,20 @@
remoteGlobalIDString = 3104AFF1156D37A0000A585A;
remoteInfo = all;
};
22EA3F3A20D2B0D90065F5B6 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 31EEABFA156AAF9D00714D05;
remoteInfo = mps;
};
22EA3F4720D2B23F0065F5B6 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 22EA3F3820D2B0D90065F5B6;
remoteInfo = forktest;
};
22F846B218F437B900982BA7 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 31EEABDA156AAE9E00714D05 /* Project object */;
@ -1098,6 +1116,15 @@
);
runOnlyForDeploymentPostprocessing = 1;
};
22EA3F4020D2B0D90065F5B6 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
22F846B818F437B900982BA7 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
@ -1491,6 +1518,8 @@
22DD93E218ED815F00240DD2 /* land.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = land.txt; path = ../design/land.txt; sourceTree = "<group>"; };
22E30E821886FF1400D98EA9 /* nailboard.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nailboard.c; sourceTree = "<group>"; };
22E30E831886FF1400D98EA9 /* nailboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nailboard.h; sourceTree = "<group>"; };
22EA3F3720D2B0730065F5B6 /* forktest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = forktest.c; sourceTree = "<group>"; };
22EA3F4520D2B0D90065F5B6 /* forktest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = forktest; sourceTree = BUILT_PRODUCTS_DIR; };
22F846AF18F4379C00982BA7 /* lockut.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lockut.c; sourceTree = "<group>"; };
22F846BD18F437B900982BA7 /* lockut */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = lockut; sourceTree = BUILT_PRODUCTS_DIR; };
22FA177516E8D6FC0098B23F /* amcssth */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = amcssth; sourceTree = BUILT_PRODUCTS_DIR; };
@ -1569,6 +1598,7 @@
31160D971899540D0071EB17 /* buffer.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = buffer.txt; path = ../design/buffer.txt; sourceTree = "<group>"; };
31160D981899540D0071EB17 /* cbs.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = cbs.txt; path = ../design/cbs.txt; sourceTree = "<group>"; };
31160D991899540D0071EB17 /* check.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = check.txt; path = ../design/check.txt; sourceTree = "<group>"; };
31160D9A1899540D0071EB17 /* pool.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = pool.txt; path = ../design/pool.txt; sourceTree = "<group>"; };
31160D9B1899540D0071EB17 /* collection.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = collection.txt; path = ../design/collection.txt; sourceTree = "<group>"; };
31160D9C1899540D0071EB17 /* config.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = config.txt; path = ../design/config.txt; sourceTree = "<group>"; };
31160D9D1899540D0071EB17 /* critical-path.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = "critical-path.txt"; path = "../design/critical-path.txt"; sourceTree = "<group>"; };
@ -1588,7 +1618,6 @@
31160DAB1899540D0071EB17 /* message-gc.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = "message-gc.txt"; path = "../design/message-gc.txt"; sourceTree = "<group>"; };
31160DAC1899540D0071EB17 /* message.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = message.txt; path = ../design/message.txt; sourceTree = "<group>"; };
31160DAD1899540D0071EB17 /* object-debug.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = "object-debug.txt"; path = "../design/object-debug.txt"; sourceTree = "<group>"; };
31160D9A1899540D0071EB17 /* pool.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = "pool.txt"; path = "../design/pool.txt"; sourceTree = "<group>"; };
31160DAF1899540D0071EB17 /* poolamc.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = poolamc.txt; path = ../design/poolamc.txt; sourceTree = "<group>"; };
31160DB01899540D0071EB17 /* poolams.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = poolams.txt; path = ../design/poolams.txt; sourceTree = "<group>"; };
31160DB11899540D0071EB17 /* poolawl.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = poolawl.txt; path = ../design/poolawl.txt; sourceTree = "<group>"; };
@ -1852,6 +1881,14 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
22EA3F3E20D2B0D90065F5B6 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
22EA3F3F20D2B0D90065F5B6 /* libmps.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
22F846B618F437B900982BA7 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@ -2324,6 +2361,7 @@
22FACED5188807FF000FDBC1 /* fmtno.h */,
22FACED6188807FF000FDBC1 /* fmtscheme.c */,
22FACED7188807FF000FDBC1 /* fmtscheme.h */,
22EA3F3720D2B0730065F5B6 /* forktest.c */,
224CC79E175E3202002FF81B /* fotest.c */,
2291A5E9175CB4EC001D4920 /* landtest.c */,
2231BB6818CA9834002D6322 /* locbwcss.c */,
@ -2442,6 +2480,7 @@
22F846BD18F437B900982BA7 /* lockut */,
31108A471C6B90E900E728EA /* tagtest */,
223E796519EAB00B00DC26A6 /* sncss */,
22EA3F4520D2B0D90065F5B6 /* forktest */,
);
name = Products;
sourceTree = "<group>";
@ -2789,6 +2828,24 @@
productReference = 22C2ACAF18BE400A006B3677 /* nailboardtest */;
productType = "com.apple.product-type.tool";
};
22EA3F3820D2B0D90065F5B6 /* forktest */ = {
isa = PBXNativeTarget;
buildConfigurationList = 22EA3F4120D2B0D90065F5B6 /* Build configuration list for PBXNativeTarget "forktest" */;
buildPhases = (
22EA3F3B20D2B0D90065F5B6 /* Sources */,
22EA3F3E20D2B0D90065F5B6 /* Frameworks */,
22EA3F4020D2B0D90065F5B6 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
22EA3F3920D2B0D90065F5B6 /* PBXTargetDependency */,
);
name = forktest;
productName = mv2test;
productReference = 22EA3F4520D2B0D90065F5B6 /* forktest */;
productType = "com.apple.product-type.tool";
};
22F846B018F437B900982BA7 /* lockut */ = {
isa = PBXNativeTarget;
buildConfigurationList = 22F846B918F437B900982BA7 /* Build configuration list for PBXNativeTarget "lockut" */;
@ -3549,6 +3606,7 @@
2291A5C1175CAFCA001D4920 /* expt825 */,
3114A5BC156E9315001E0AA3 /* finalcv */,
3114A5D5156E93A0001E0AA3 /* finaltest */,
22EA3F3820D2B0D90065F5B6 /* forktest */,
224CC78C175E1821002FF81B /* fotest */,
6313D46718A400B200EB03EF /* gcbench */,
3114A64B156E9596001E0AA3 /* landtest */,
@ -3748,6 +3806,15 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
22EA3F3B20D2B0D90065F5B6 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
22EA3F4620D2B0FD0065F5B6 /* forktest.c in Sources */,
22EA3F3D20D2B0D90065F5B6 /* testlib.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
22F846B318F437B900982BA7 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@ -4303,6 +4370,16 @@
target = 3104AFF1156D37A0000A585A /* all */;
targetProxy = 22CDE92D16E9EB9300366D0A /* PBXContainerItemProxy */;
};
22EA3F3920D2B0D90065F5B6 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 31EEABFA156AAF9D00714D05 /* mps */;
targetProxy = 22EA3F3A20D2B0D90065F5B6 /* PBXContainerItemProxy */;
};
22EA3F4820D2B23F0065F5B6 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 22EA3F3820D2B0D90065F5B6 /* forktest */;
targetProxy = 22EA3F4720D2B23F0065F5B6 /* PBXContainerItemProxy */;
};
22F846B118F437B900982BA7 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 31EEABFA156AAF9D00714D05 /* mps */;
@ -4917,6 +4994,27 @@
};
name = Release;
};
22EA3F4220D2B0D90065F5B6 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
22EA3F4320D2B0D90065F5B6 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
22EA3F4420D2B0D90065F5B6 /* RASH */ = {
isa = XCBuildConfiguration;
buildSettings = {
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = RASH;
};
22F846BA18F437B900982BA7 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@ -6133,6 +6231,16 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
22EA3F4120D2B0D90065F5B6 /* Build configuration list for PBXNativeTarget "forktest" */ = {
isa = XCConfigurationList;
buildConfigurations = (
22EA3F4220D2B0D90065F5B6 /* Debug */,
22EA3F4320D2B0D90065F5B6 /* Release */,
22EA3F4420D2B0D90065F5B6 /* RASH */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
22F846B918F437B900982BA7 /* Build configuration list for PBXNativeTarget "lockut" */ = {
isa = XCConfigurationList;
buildConfigurations = (

View file

@ -1,7 +1,7 @@
/* mpsi.c: MEMORY POOL SYSTEM C INTERFACE LAYER
*
* $Id$
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2018 Ravenbrook Limited. See end of file for license.
* Portions copyright (c) 2002 Global Graphics Software.
*
* .purpose: This code bridges between the MPS interface to C,
@ -1697,7 +1697,7 @@ mps_res_t mps_fix(mps_ss_t mps_ss, mps_addr_t *ref_io)
mps_res_t res;
MPS_SCAN_BEGIN(mps_ss) {
res = MPS_FIX(mps_ss, ref_io);
res = MPS_FIX12(mps_ss, ref_io);
} MPS_SCAN_END(mps_ss);
return res;
@ -2159,7 +2159,7 @@ void _mps_args_set_key(mps_arg_s args[MPS_ARGS_MAX], unsigned i,
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2001-2018 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -1,7 +1,7 @@
/* prmcxc.c: MUTATOR CONTEXT INTEL 386 (MAC OS X)
/* prmcxc.c: MUTATOR CONTEXT (macOS)
*
* $Id$
* Copyright (c) 2016 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2016-2018 Ravenbrook Limited. See end of file for license.
*
* .purpose: Implement the mutator context module. See <design/prmc/>.
*
@ -88,7 +88,7 @@ Res MutatorContextScan(ScanState ss, MutatorContext context,
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2016-2018 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -1,7 +1,7 @@
/* prmcxc.h: MUTATOR CONTEXT FOR OS X MACH
/* prmcxc.h: MUTATOR CONTEXT (macOS)
*
* $Id$
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2018 Ravenbrook Limited. See end of file for license.
*
* .readership: MPS developers.
*/
@ -32,7 +32,7 @@ extern void MutatorContextInitThread(MutatorContext context, THREAD_STATE_S *thr
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2001-2018 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -1,7 +1,7 @@
/* prmcxci3.c: MUTATOR CONTEXT INTEL 386 (MAC OS X)
/* prmcxci3.c: MUTATOR CONTEXT (macOS, IA-32)
*
* $Id$
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2018 Ravenbrook Limited. See end of file for license.
*
* .purpose: Implement the mutator context module. See <design/prmc/>.
*
@ -102,7 +102,7 @@ Addr MutatorContextSP(MutatorContext context)
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2001-2018 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -1,7 +1,7 @@
/* prmcxci6.c: MUTATOR CONTEXT x64 (OS X)
/* prmcxci6.c: MUTATOR CONTEXT (macOS, x86-64)
*
* $Id$
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2018 Ravenbrook Limited. See end of file for license.
*
* .purpose: Implement the mutator context module. See <design/prmc/>.
*
@ -107,7 +107,7 @@ Addr MutatorContextSP(MutatorContext context)
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2001-2018 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -1,10 +1,10 @@
/* protix.c: PROTECTION FOR UNIX
*
* $Id$
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2018 Ravenbrook Limited. See end of file for license.
*
* Somewhat generic across different Unix systems. Shared between
* OS X, FreeBSD, and Linux.
* macOS, FreeBSD, and Linux.
*
*
* SOURCES
@ -19,7 +19,7 @@
* be safely passed as a void *. Single UNIX Specification Version 2 (aka
* X/OPEN XSH5) says that the parameter is a void *. Some Unix-likes may
* declare this parameter as a caddr_t. FreeBSD used to do this (on the now
* very obsolete FreeBSD 2.2.x series), as did OS X, but both now implement
* very obsolete FreeBSD 2.2.x series), as did macOS, but both now implement
* it correctly as void *. caddr_t is usually char *.
*
* .assume.write-only: More of an anti-assumption really. We
@ -119,7 +119,7 @@ Size ProtGranularity(void)
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2001-2018 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -1,9 +1,9 @@
/* protxc.c: PROTECTION EXCEPTION HANDLER FOR OS X MACH
/* protxc.c: PROTECTION EXCEPTION HANDLER (macOS)
*
* $Id$
* Copyright (c) 2013-2016 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2013-2018 Ravenbrook Limited. See end of file for license.
*
* This is the protection exception handling code for OS X using the
* This is the protection exception handling code for macOS using the
* Mach interface (not pthreads).
*
* In Mach, a thread that hits protected memory is suspended, and a message
@ -15,7 +15,7 @@
* at the next level out (the levels are thread, task, host) by sending a
* "fail" reply.
*
* In OS X, pthreads are implemented by Mach threads. (The implementation is
* In macOS, pthreads are implemented by Mach threads. (The implementation is
* part of the XNU source code at opensource.apple.com. [copy to import?]) So
* we can use some pthread interfaces (pthread_create, pthread_once) for
* convenience in setting up threads.
@ -47,7 +47,7 @@
* TRANSGRESSIONS
*
* .trans.stdlib: It's OK to use the C library from here because we know
* we're on OS X and not freestanding. In particular, we use memcpy.
* we're on macOS and not freestanding. In particular, we use memcpy.
*
* .trans.must: Various OS calls are asserted to succeed, since there isn't
* really a dynamic reason they should fail, so it must be a static error.
@ -74,7 +74,7 @@
#include <mach/exc.h>
#if !defined(MPS_OS_XC)
#error "protxc.c is OS X specific"
#error "protxc.c is macOS specific"
#endif
SRCID(protxc, "$Id$");
@ -178,7 +178,7 @@ static void protMustSend(mach_msg_header_t *head)
/* protCatchOne -- catch one EXC_BAD_ACCESS exception message.
*
* OS X provides a function exc_server (in
* macOS provides a function exc_server (in
* /usr/lib/system/libsystem_kernel.dylib) that's documented in the XNU
* sources <http://www.opensource.apple.com/source/xnu/xnu-2050.22.13/osfmk/man/exc_server.html>
* and generated by the Mach Interface Generator (mig). It unpacks
@ -288,7 +288,7 @@ static void *protCatchThread(void *p) {
/* ProtThreadRegister -- register a thread for protection exception handling */
extern void ProtThreadRegister(Bool setup)
extern void ProtThreadRegister(void)
{
kern_return_t kr;
mach_msg_type_number_t old_exception_count = 1;
@ -298,24 +298,10 @@ extern void ProtThreadRegister(Bool setup)
exception_behavior_t old_behaviors;
thread_state_flavor_t old_flavors;
mach_port_t self;
static mach_port_t setupThread = MACH_PORT_NULL;
self = mach_thread_self();
AVER(MACH_PORT_VALID(self));
/* Avoid setting up the exception handler for the thread that calls
ProtSetup twice, in the case where the mutator registers that thread
explicitly. We need a special case because we don't require thread
registration of the sole thread of a single-threaded mutator. */
if (setup) {
AVER(setupThread == MACH_PORT_NULL);
setupThread = self;
} else {
AVER(setupThread != MACH_PORT_NULL);
if (self == setupThread)
return;
}
/* Ask to receive EXC_BAD_ACCESS exceptions on our port, complete
with thread state and identity information in the message.
The MACH_EXCEPTION_CODES flag causes the code fields to be
@ -342,14 +328,17 @@ extern void ProtThreadRegister(Bool setup)
}
/* ProtSetup -- set up protection exception handling */
/* protExcThreadStart -- create exception port, register the current
* thread with that port, and create a thread to handle exception
* messages.
*/
static void protSetupInner(void)
static void protExcThreadStart(void)
{
kern_return_t kr;
int pr;
pthread_t excThread;
mach_port_t self;
pthread_t excThread;
int pr;
/* Create a port to send and receive exceptions. */
self = mach_task_self();
@ -373,18 +362,49 @@ static void protSetupInner(void)
if (kr != KERN_SUCCESS)
mach_error("ERROR: MPS mach_port_insert_right", kr); /* .trans.must */
ProtThreadRegister(TRUE);
/* We don't require the mutator to register the sole thread in a
* single-threaded program, so register it automatically now. */
ProtThreadRegister();
/* Launch the exception handling thread. We use pthread_create because
it's much simpler than setting up a thread from scratch using Mach,
and that's basically what it does. See [Libc]
<http://www.opensource.apple.com/source/Libc/Libc-825.26/pthreads/pthread.c> */
/* Launch the exception handling thread. We use pthread_create
* because it's much simpler than setting up a thread from scratch
* using Mach, and that's basically what it does. See [Libc]
* <http://www.opensource.apple.com/source/Libc/Libc-825.26/pthreads/pthread.c> */
pr = pthread_create(&excThread, NULL, protCatchThread, NULL);
AVER(pr == 0);
if (pr != 0)
fprintf(stderr, "ERROR: MPS pthread_create: %d\n", pr); /* .trans.must */
}
/* atfork handlers -- support for fork(). See <design/thread-safety/> */
static void protAtForkPrepare(void)
{
}
static void protAtForkParent(void)
{
}
static void protAtForkChild(void)
{
/* Restart the exception handling thread
<design/thread-safety/#sol.fork.exc-thread>. */
protExcThreadStart();
}
/* ProtSetup -- set up protection exception handling */
static void protSetupInner(void)
{
protExcThreadStart();
/* Install fork handlers <design/thread-safety/#sol.fork.atfork>. */
pthread_atfork(protAtForkPrepare, protAtForkParent, protAtForkChild);
}
void ProtSetup(void)
{
int pr;
@ -401,7 +421,7 @@ void ProtSetup(void)
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2013-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2013-2018 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -1,19 +1,19 @@
/* protxc.h: PROTECTION EXCPETION HANDLER FOR OS X MACH
/* protxc.h: PROTECTION EXCEPTION HANDLER (macOS)
*
* $Id$
* Copyright (c) 2013 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2013-2018 Ravenbrook Limited. See end of file for license.
*/
#ifndef protxc_h
#define protxc_h
extern void ProtThreadRegister(Bool setup);
extern void ProtThreadRegister(void);
#endif /* protxc_h */
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2013 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2013-2018 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -1,7 +1,7 @@
/* sc.h: STACK CONTEXT
*
* $Id$
* Copyright (c) 2012 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2012-2018 Ravenbrook Limited. See end of file for license.
*
* Provides a context to hold the registers and stack pointer
*
@ -45,7 +45,7 @@
*/
/* Mac OS X on 32-bit Intel built with Clang or GCC */
/* macOS on IA-32 built with Clang or GCC */
#if defined(MPS_PF_XCI3LL) || defined(MPS_PF_XCI3GC)
@ -64,7 +64,7 @@ typedef struct StackContextStruct {
#define StackContextSP(sc) ((Addr *)(sc)->jumpBuffer[JB_ESP/sizeof(int)])
/* On MacOS X the stackPointer can end up pointing above the StackContext
/* On macOS the stackPointer can end up pointing above the StackContext
* which we assume to be stored on the stack because it is no longer
* needed once we have _longjmp()ed back. So take the minimum of the
* SP and the base of the StackContext structure. */
@ -72,7 +72,7 @@ typedef struct StackContextStruct {
(StackContextSP(sc) < (Addr*)(sc) ? StackContextSP(sc) : (Addr*)(sc))
/* Mac OS X on 64-bit Intel build with Clang or GCC */
/* macOS on x86-64 built with Clang or GCC */
#elif defined(MPS_PF_XCI6LL) || defined(MPS_PF_XCI6GC)
@ -99,7 +99,7 @@ typedef struct StackContextStruct {
#define StackContextSP(sc) \
(*(Addr **)((char *)(sc)->jumpBuffer+JB_RSP))
/* On MacOS X the stackPointer can end up pointing above the StackContext
/* On macOS the stackPointer can end up pointing above the StackContext
* which we assume to be stored on the stack because it is no longer
* needed once we have _longjmp()ed back. So take the minimum of the
* SP and the base of the StackContext structure. */
@ -165,7 +165,7 @@ typedef struct StackContextStruct {
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2012 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2001-2018 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -1,7 +1,7 @@
/* shield.c: SHIELD IMPLEMENTATION
*
* $Id$
* Copyright (c) 2001-2017 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2018 Ravenbrook Limited. See end of file for license.
*
* See: idea.shield, design.mps.shield.
*
@ -381,7 +381,7 @@ static Compare shieldQueueEntryCompare(void *left, void *right, void *closure)
*
* Sort the shield queue into address order, then iterate over it
* coalescing protection work, in order to reduce the number of system
* calls to a minimum. This is very important on OS X, where
* calls to a minimum. This is very important on macOS, where
* protection calls are extremely inefficient, but has no net gain on
* Windows.
*
@ -762,7 +762,7 @@ void (ShieldCover)(Arena arena, Seg seg)
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2017 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2001-2018 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -1,14 +1,14 @@
/* ssixi3.c: UNIX/INTEL STACK SCANNING
/* ssixi3.c: STACK SCANNING (POSIX, IA-32)
*
* $Id$
* Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2018 Ravenbrook Limited. See end of file for license.
*
* This scans the stack and fixes the registers which may contain
* roots. See <design/thread-manager/>
*
* This code was originally developed and tested on Linux, and then
* copied to the FreeBSD and Darwin (OS X) operating systems where it
* also seems to work. Note that on FreeBSD and Darwin it has not
* copied to the FreeBSD and Darwin (macOS) operating systems where
* it also seems to work. Note that on FreeBSD and Darwin it has not
* been indepently verified with respect to any ABI documentation.
*
* This code is common to more than one Unix implementation on
@ -71,7 +71,7 @@ Res StackScan(ScanState ss, Word *stackCold,
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2001-2018 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -1,17 +1,17 @@
/* ssixi6.c: UNIX/x64 STACK SCANNING
/* ssixi6.c: STACK SCANNING (POSIX, x86-64)
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2018 Ravenbrook Limited. See end of file for license.
*
* This scans the stack and fixes the registers which may contain
* roots. See <design/thread-manager/>
*
* This code was branched from ssixi3.c (32-bit Intel) initially for the
* port to XCI6LL (Mac OS X on x86_64 with Clang).
* This code was branched from ssixi3.c (POSIX, IA-32) initially for
* the port to XCI6LL (macOS, x86-64, Clang/LLVM).
*
* This code is common to more than one Unix implementation on
* Intel hardware (but is not portable Unix code). According to Wikipedia,
* all the non-Windows platforms use the System V AMD64 ABI. See
* This code is common to more than one Unix implementation on Intel
* hardware (but is not portable Unix code). According to Wikipedia,
* all the non-Windows platforms use the System V AMD64 ABI. See
* .sources.callees.saves.
*
* SOURCES
@ -71,7 +71,7 @@ Res StackScan(ScanState ss, Word *stackCold,
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2001-2018 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -388,7 +388,7 @@ void error(const char *format, ...)
va_start(args, format);
verror(format, args);
va_end(args);
/* va_end(args); */ /* provokes "unreachable code" error from MSVC */
}

View file

@ -72,6 +72,8 @@ extern Res ThreadScan(ScanState ss, Thread thread, Word *stackCold,
mps_area_scan_t scan_area,
void *closure);
extern void ThreadSetup(void);
#endif /* th_h */

View file

@ -142,6 +142,12 @@ Res ThreadDescribe(Thread thread, mps_lib_FILE *stream, Count depth)
}
void ThreadSetup(void)
{
/* Nothing to do as ANSI platform does not have fork(). */
}
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.

View file

@ -133,30 +133,26 @@ void ThreadDeregister(Thread thread, Arena arena)
/* mapThreadRing -- map over threads on ring calling a function on
* each one except the current thread.
* each one.
*
* Threads that are found to be dead (that is, if func returns FALSE)
* are moved to deadRing, in order to implement
* are marked as dead and moved to deadRing, in order to implement
* design.thread-manager.sol.thread.term.attempt.
*/
static void mapThreadRing(Ring threadRing, Ring deadRing, Bool (*func)(Thread))
{
Ring node, next;
pthread_t self;
AVERT(Ring, threadRing);
AVERT(Ring, deadRing);
AVER(FUNCHECK(func));
self = pthread_self();
RING_FOR(node, threadRing, next) {
Thread thread = RING_ELT(Thread, arenaRing, node);
AVERT(Thread, thread);
AVER(thread->alive);
if (!pthread_equal(self, thread->id) /* .thread.id */
&& !(*func)(thread))
{
if (!(*func)(thread)) {
thread->alive = FALSE;
RingRemove(&thread->arenaRing);
RingAppend(deadRing, &thread->arenaRing);
@ -171,9 +167,14 @@ static void mapThreadRing(Ring threadRing, Ring deadRing, Bool (*func)(Thread))
static Bool threadSuspend(Thread thread)
{
Res res;
pthread_t self;
self = pthread_self();
if (pthread_equal(self, thread->id)) /* .thread.id */
return TRUE;
/* .error.suspend: if PThreadextSuspend fails, we assume the thread
* has been terminated. */
Res res;
AVER(thread->context == NULL);
res = PThreadextSuspend(&thread->thrextStruct, &thread->context);
AVER(res == ResOK);
@ -196,6 +197,11 @@ void ThreadRingSuspend(Ring threadRing, Ring deadRing)
static Bool threadResume(Thread thread)
{
Res res;
pthread_t self;
self = pthread_self();
if (pthread_equal(self, thread->id)) /* .thread.id */
return TRUE;
/* .error.resume: If PThreadextResume fails, we assume the thread
* has been terminated. */
AVER(thread->context != NULL);
@ -307,6 +313,33 @@ Res ThreadDescribe(Thread thread, mps_lib_FILE *stream, Count depth)
}
/* threadAtForkChild -- for each arena, move threads except for the
* current thread to the dead ring <design/thread-safety/#sol.fork.thread>.
*/
static Bool threadForkChild(Thread thread)
{
AVERT(Thread, thread);
return pthread_equal(pthread_self(), thread->id); /* .thread.id */
}
static void threadRingForkChild(Arena arena)
{
AVERT(Arena, arena);
mapThreadRing(ArenaThreadRing(arena), ArenaDeadRing(arena), threadForkChild);
}
static void threadAtForkChild(void)
{
GlobalsArenaMap(threadRingForkChild);
}
void ThreadSetup(void)
{
pthread_atfork(NULL, NULL, threadAtForkChild);
}
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.

View file

@ -312,6 +312,12 @@ Res ThreadScan(ScanState ss, Thread thread, Word *stackCold,
}
void ThreadSetup(void)
{
/* Nothing to do as MPS does not support fork() on Windows. */
}
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.

View file

@ -1,7 +1,7 @@
/* thxc.c: OS X MACH THREADS MANAGER
/* thxc.c: THREAD MANAGER (macOS)
*
* $Id$
* Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2018 Ravenbrook Limited. See end of file for license.
*
* .design: See <design/thread-manager/>.
*
@ -26,17 +26,19 @@
#include <mach/task.h>
#include <mach/thread_act.h>
#include <mach/thread_status.h>
#include <pthread.h>
SRCID(thxc, "$Id$");
typedef struct mps_thr_s { /* OS X / Mach thread structure */
typedef struct mps_thr_s { /* macOS thread structure */
Sig sig; /* <design/sig/> */
Serial serial; /* from arena->threadSerial */
Arena arena; /* owning arena */
RingStruct arenaRing; /* attaches to arena */
Bool alive; /* thread believed to be alive? */
Bool forking; /* thread currently calling fork? */
thread_port_t port; /* thread kernel port */
} ThreadStruct;
@ -48,6 +50,7 @@ Bool ThreadCheck(Thread thread)
CHECKL(thread->serial < thread->arena->threadSerial);
CHECKD_NOSIG(Ring, &thread->arenaRing);
CHECKL(BoolCheck(thread->alive));
CHECKL(BoolCheck(thread->forking));
CHECKL(MACH_PORT_VALID(thread->port));
return TRUE;
}
@ -80,11 +83,13 @@ Res ThreadRegister(Thread *threadReturn, Arena arena)
thread->serial = arena->threadSerial;
++arena->threadSerial;
thread->alive = TRUE;
thread->forking = FALSE;
thread->port = mach_thread_self();
AVER(MACH_PORT_VALID(thread->port));
thread->sig = ThreadSig;
AVERT(Thread, thread);
ProtThreadRegister(FALSE);
ProtThreadRegister();
ring = ArenaThreadRing(arena);
@ -99,6 +104,7 @@ void ThreadDeregister(Thread thread, Arena arena)
{
AVERT(Thread, thread);
AVERT(Arena, arena);
AVER(!thread->forking);
RingRemove(&thread->arenaRing);
@ -111,7 +117,7 @@ void ThreadDeregister(Thread thread, Arena arena)
/* mapThreadRing -- map over threads on ring calling a function on
* each one except the current thread.
* each one.
*
* Threads that are found to be dead (that is, if func returns FALSE)
* are marked as dead and moved to deadRing, in order to implement
@ -121,21 +127,16 @@ void ThreadDeregister(Thread thread, Arena arena)
static void mapThreadRing(Ring threadRing, Ring deadRing, Bool (*func)(Thread))
{
Ring node, next;
mach_port_t self;
AVERT(Ring, threadRing);
AVERT(Ring, deadRing);
AVER(FUNCHECK(func));
self = mach_thread_self();
AVER(MACH_PORT_VALID(self));
RING_FOR(node, threadRing, next) {
Thread thread = RING_ELT(Thread, arenaRing, node);
AVERT(Thread, thread);
AVER(thread->alive);
if (thread->port != self
&& !(*func)(thread))
{
if (!(*func)(thread)) {
thread->alive = FALSE;
RingRemove(&thread->arenaRing);
RingAppend(deadRing, &thread->arenaRing);
@ -147,6 +148,11 @@ static void mapThreadRing(Ring threadRing, Ring deadRing, Bool (*func)(Thread))
static Bool threadSuspend(Thread thread)
{
kern_return_t kern_return;
mach_port_t self = mach_thread_self();
AVER(MACH_PORT_VALID(self));
if (thread->port == self)
return TRUE;
kern_return = thread_suspend(thread->port);
/* No rendezvous is necessary: thread_suspend "prevents the thread
* from executing any more user-level instructions" */
@ -157,18 +163,6 @@ static Bool threadSuspend(Thread thread)
return kern_return == KERN_SUCCESS;
}
static Bool threadResume(Thread thread)
{
kern_return_t kern_return;
kern_return = thread_resume(thread->port);
/* Mach has no equivalent of EAGAIN. */
AVER(kern_return == KERN_SUCCESS);
/* Experimentally, values other then KERN_SUCCESS indicate the thread has
terminated <https://info.ravenbrook.com/mail/2014/10/25/18-12-36/0/>. */
/* design.thread-manager.sol.thread.term.attempt */
return kern_return == KERN_SUCCESS;
}
/* ThreadRingSuspend -- suspend all threads on a ring, except the
* current one.
@ -178,6 +172,24 @@ void ThreadRingSuspend(Ring threadRing, Ring deadRing)
mapThreadRing(threadRing, deadRing, threadSuspend);
}
static Bool threadResume(Thread thread)
{
kern_return_t kern_return;
mach_port_t self = mach_thread_self();
AVER(MACH_PORT_VALID(self));
if (thread->port == self)
return TRUE;
kern_return = thread_resume(thread->port);
/* Mach has no equivalent of EAGAIN. */
AVER(kern_return == KERN_SUCCESS);
/* Experimentally, values other then KERN_SUCCESS indicate the thread has
terminated <https://info.ravenbrook.com/mail/2014/10/25/18-12-36/0/>. */
/* design.thread-manager.sol.thread.term.attempt */
return kern_return == KERN_SUCCESS;
}
/* ThreadRingResume -- resume all threads on a ring, except the
* current one.
*/
@ -186,6 +198,7 @@ void ThreadRingResume(Ring threadRing, Ring deadRing)
mapThreadRing(threadRing, deadRing, threadResume);
}
Thread ThreadRingThread(Ring threadRing)
{
Thread thread;
@ -291,9 +304,95 @@ Res ThreadDescribe(Thread thread, mps_lib_FILE *stream, Count depth)
}
/* threadAtForkPrepare -- for each arena, mark the current thread as
* forking <design/thread-safety/#sol.fork.thread>.
*/
static Bool threadForkPrepare(Thread thread)
{
mach_port_t self;
AVERT(Thread, thread);
AVER(!thread->forking);
self = mach_thread_self();
AVER(MACH_PORT_VALID(self));
thread->forking = (thread->port == self);
return TRUE;
}
static void threadRingForkPrepare(Arena arena)
{
AVERT(Arena, arena);
mapThreadRing(ArenaThreadRing(arena), ArenaDeadRing(arena), threadForkPrepare);
}
static void threadAtForkPrepare(void)
{
GlobalsArenaMap(threadRingForkPrepare);
}
/* threadAtForkParent -- for each arena, clear the forking flag for
* all threads <design/thread-safety/#sol.fork.thread>.
*/
static Bool threadForkParent(Thread thread)
{
AVERT(Thread, thread);
thread->forking = FALSE;
return TRUE;
}
static void threadRingForkParent(Arena arena)
{
AVERT(Arena, arena);
mapThreadRing(ArenaThreadRing(arena), ArenaDeadRing(arena), threadForkParent);
}
static void threadAtForkParent(void)
{
GlobalsArenaMap(threadRingForkParent);
}
/* threadAtForkChild -- For each arena, move all threads to the dead
* ring, except for the thread that was marked as forking by the
* prepare handler <design/thread-safety/#sol.fork.thread>, for which
* update its mach port <design/thread-safety/#sol.fork.mach-port>.
*/
static Bool threadForkChild(Thread thread)
{
AVERT(Thread, thread);
if (thread->forking) {
thread->port = mach_thread_self();
AVER(MACH_PORT_VALID(thread->port));
thread->forking = FALSE;
return TRUE;
} else {
return FALSE;
}
}
static void threadRingForkChild(Arena arena)
{
AVERT(Arena, arena);
mapThreadRing(ArenaThreadRing(arena), ArenaDeadRing(arena), threadForkChild);
}
static void threadAtForkChild(void)
{
GlobalsArenaMap(threadRingForkChild);
}
void ThreadSetup(void)
{
pthread_atfork(threadAtForkPrepare, threadAtForkParent, threadAtForkChild);
}
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2001-2018 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -1,7 +1,7 @@
/* vmix.c: VIRTUAL MEMORY MAPPING FOR UNIX (ISH)
/* vmix.c: VIRTUAL MEMORY MAPPING (POSIX)
*
* $Id$
* Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
* Copyright (c) 2001-2018 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
@ -10,7 +10,7 @@
* copied from vli.c (Linux) which was itself copied from vmo1.c (OSF/1
* / DIGITAL UNIX / Tru64).
*
* .deployed: Currently used on Darwin (OS X) and FreeBSD.
* .deployed: Currently used on Darwin (macOS) and FreeBSD.
*
* .design: See <design/vm/>. .design.mmap: mmap(2) is used to
* reserve address space by creating a mapping with page access none.
@ -225,7 +225,7 @@ void VMUnmap(VM vm, Addr base, Addr limit)
/* C. COPYRIGHT AND LICENSE
*
* Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
* Copyright (C) 2001-2018 Ravenbrook Limited <http://www.ravenbrook.com/>.
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*

View file

@ -1,9 +1,9 @@
# -*- makefile -*-
#
# xci3gc.gmk: BUILD FOR MACOS X (CARBON)/INTEL IA32/GCC PLATFORM
# xci3gc.gmk: BUILD FOR macOS/IA-32/GCC PLATFORM
#
# $Id$
# Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
# Copyright (c) 2001-2018 Ravenbrook Limited. See end of file for license.
#
# Naively copied from xcppgc.gmk, could do with going over properly.
@ -34,7 +34,7 @@ include comm.gmk
# C. COPYRIGHT AND LICENSE
#
# Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
# Copyright (C) 2001-2018 Ravenbrook Limited <http://www.ravenbrook.com/>.
# All rights reserved. This is an open source license. Contact
# Ravenbrook for commercial licensing options.
#

View file

@ -1,9 +1,9 @@
# -*- makefile -*-
#
# xci3ll.gmk: BUILD FOR MAC OS X/i386/Clang PLATFORM
# xci3ll.gmk: BUILD FOR macOS/IA-32/Clang/LLVM PLATFORM
#
# $Id$
# Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
# Copyright (c) 2001-2018 Ravenbrook Limited. See end of file for license.
#
# .prefer.xcode: The documented and preferred way to develop the MPS
# for this platform is to use the Xcode project (mps.xcodeproj). This
@ -34,7 +34,7 @@ include comm.gmk
# C. COPYRIGHT AND LICENSE
#
# Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
# Copyright (C) 2001-2018 Ravenbrook Limited <http://www.ravenbrook.com/>.
# All rights reserved. This is an open source license. Contact
# Ravenbrook for commercial licensing options.
#

View file

@ -1,9 +1,9 @@
# -*- makefile -*-
#
# xci6gc.gmk: BUILD FOR MAC OS X/x86_64/GCC PLATFORM
# xci6gc.gmk: BUILD FOR macOS/x86-64/GCC PLATFORM
#
# $Id$
# Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
# Copyright (c) 2001-2018 Ravenbrook Limited. See end of file for license.
#
# .prefer.xcode: The documented and preferred way to develop the MPS
# for this platform is to use the Xcode project (mps.xcodeproj). This
@ -31,7 +31,7 @@ include comm.gmk
# C. COPYRIGHT AND LICENSE
#
# Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
# Copyright (C) 2001-2018 Ravenbrook Limited <http://www.ravenbrook.com/>.
# All rights reserved. This is an open source license. Contact
# Ravenbrook for commercial licensing options.
#

View file

@ -1,9 +1,9 @@
# -*- makefile -*-
#
# xci6ll.gmk: BUILD FOR MAC OS X/x86_64/Clang PLATFORM
# xci6ll.gmk: BUILD FOR macOS/x86-64/Clang/LLVM PLATFORM
#
# $Id$
# Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license.
# Copyright (c) 2001-2018 Ravenbrook Limited. See end of file for license.
#
# .prefer.xcode: The documented and preferred way to develop the MPS
# for this platform is to use the Xcode project (mps.xcodeproj). This
@ -31,7 +31,7 @@ include comm.gmk
# C. COPYRIGHT AND LICENSE
#
# Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
# Copyright (C) 2001-2018 Ravenbrook Limited <http://www.ravenbrook.com/>.
# All rights reserved. This is an open source license. Contact
# Ravenbrook for commercial licensing options.
#

View file

@ -68,24 +68,18 @@ is typically embedded in another structure.
External classes
................
``CLASS(CBS)``
_`.class.cbs`: ``CLASS(CBS)`` is the CBS class, a subclass of
``CLASS(Land)`` suitable for passing to ``LandInit()``.
_`.class.cbs`: The CBS class, a subclass of ``CLASS(Land)`` suitable
for passing to ``LandInit()``.
``CLASS(CBSFast)``
_`.class.fast`: A subclass of ``CLASS(CBS)`` that maintains, for each
subtree, the size of the largest block in that subtree. This enables
the ``LandFindFirst()``, ``LandFindLast()``, and ``LandFindLargest()``
generic functions.
``CLASS(CBSZoned)``
_`.class.zoned`: A subclass of ``CLASS(CBSFast)`` that maintains, for
each subtree, the union of the zone sets of all ranges in that
subtree. This enables the ``LandFindInZones()`` generic function.
_`.class.fast`: ``CLASS(CBSFast)`` is subclass of ``CLASS(CBS)`` that
maintains, for each subtree, the size of the largest block in that
subtree. This enables the ``LandFindFirst()``, ``LandFindLast()``, and
``LandFindLargest()`` generic functions.
_`.class.zoned`: ``CLASS(CBSZoned)`` is a subclass of
``CLASS(CBSFast)`` that maintains, for each subtree, the union of the
zone sets of all ranges in that subtree. This enables the
``LandFindInZones()`` generic function.
Keyword arguments
@ -279,7 +273,7 @@ Document History
Copyright and License
---------------------
Copyright © 1998-2016 Ravenbrook Limited. All rights reserved.
Copyright © 1998-2018 Ravenbrook Limited. All rights reserved.
<http://www.ravenbrook.com/>. This is an open source license. Contact
Ravenbrook for commercial licensing options.

View file

@ -116,7 +116,7 @@ Very briefly, the critical path consists of five stages:
write a good scanner. Then that could be linked from here.
#. The first-stage fix, which filters out pointers inline in the
scanner. This is implemented in ``MPS_FIX()`` macros in
scanner. This is implemented in the ``MPS_FIX1()`` macro in
mps.h_.
.. _mps.h: ../code/mps.h
@ -371,7 +371,7 @@ Document History
Copyright and License
---------------------
Copyright © 2012-2014 Ravenbrook Limited. All rights reserved.
Copyright © 2012-2018 Ravenbrook Limited. All rights reserved.
<http://www.ravenbrook.com/>. This is an open source license. Contact
Ravenbrook for commercial licensing options.

View file

@ -136,6 +136,15 @@ corresponding ``LockClaimRecursive()`` call.
Return true if the lock is held by any thread, false otherwise. Note
that this function need not be thread-safe (see `.req.held`_).
``void LockInitGlobal(void)``
Initialize (or re-initialize) the global locks. This should only be
called in the following circumstances: the first time either of the
global locks is claimed; and in the child process after a ``fork()``.
See design.mps.thread-safety.sol.fork.lock_.
.. _design.mps.thread-safety.sol.fork.lock: thread-safety#sol-fork-lock
``void LockClaimGlobal(void)``
Claims ownership of the binary global lock which was previously not
@ -155,6 +164,11 @@ to the current thread and claims the lock (if not already held).
Restores the previous state of the recursive global lock remembered by
the corresponding ``LockClaimGlobalRecursive()`` call.
``void LockSetup(void)``
One-time initialization function, intended for calling
``pthread_atfork()`` on the appropriate platforms: see design.mps.thread-safety.sol.fork.lock_.
Implementation
--------------
@ -278,6 +292,8 @@ Document History
- 2014-10-21 GDR_ Brought up to date.
- 2018-06-14 GDR_ Added ``LockInitGlobal()``.
.. _RB: http://www.ravenbrook.com/consultants/rb/
.. _GDR: http://www.ravenbrook.com/consultants/gdr/

View file

@ -263,8 +263,8 @@ _`.impl.w3.context.sp`: The stack pointer is obtained from
``CONTEXT.Esp`` (on IA-32) or ``CONTEXT.Rsp`` (on x86-64).
OS X implementation
...................
macOS implementation
....................
_`.impl.xc`: In ``prmcix.c`` and ``prmcxc.c``, with processor-specific
parts in ``prmci3.c`` and ``prmci6.c``, and other platform-specific
@ -311,7 +311,7 @@ Document History
Copyright and License
---------------------
Copyright © 2014-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
Copyright © 2014-2018 Ravenbrook Limited <http://www.ravenbrook.com/>.
All rights reserved. This is an open source license. Contact
Ravenbrook for commercial licensing options.

View file

@ -139,7 +139,7 @@ _`.impl.ix`: POSIX implementation. See design.mps.protix_.
_`.impl.w3`: Windows implementation.
_`.impl.xc`: OS X implementation.
_`.impl.xc`: macOS implementation.
Document History
@ -163,7 +163,7 @@ Document History
Copyright and License
---------------------
Copyright © 2013-2016 Ravenbrook Limited <http://www.ravenbrook.com/>.
Copyright © 2013-2018 Ravenbrook Limited <http://www.ravenbrook.com/>.
All rights reserved. This is an open source license. Contact
Ravenbrook for commercial licensing options.

View file

@ -156,7 +156,7 @@ This hysteresis allows the MPS to proceed with garbage collection
during a pause without actually setting hardware protection until it
returns to the mutator. This is particularly important on operating
systems where the protection is expensive and poorly implemented, such
as OS X.
as macOS.
The queue also ensures that no memory protection system calls will be
needed for incremental garbage collection if a complete collection
@ -362,7 +362,7 @@ Theoretically we can do this, but:
non-moving collection.
2. The main cost of protection is changing it at all, not whether we
change just read or write. On OS X, the main cost seems to be the
change just read or write. On macOS, the main cost seems to be the
TLB flush, which affects wall-clock time of everything on the
processor!
@ -406,7 +406,7 @@ Document History
Copyright and License
---------------------
Copyright © 2013-2017 Ravenbrook Limited <http://www.ravenbrook.com/>.
Copyright © 2013-2018 Ravenbrook Limited <http://www.ravenbrook.com/>.
All rights reserved. This is an open source license. Contact
Ravenbrook for commercial licensing options.

View file

@ -279,8 +279,8 @@ _`.impl.w3.scan.suspended`: Otherwise, ``ThreadScan()`` calls
pointer.
OS X implementation
...................
macOS implementation
....................
_`.impl.xc`: In ``thxc.c``.
@ -335,7 +335,7 @@ Document History
Copyright and License
---------------------
Copyright © 2013-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
Copyright © 2013-2018 Ravenbrook Limited <http://www.ravenbrook.com/>.
All rights reserved. This is an open source license. Contact
Ravenbrook for commercial licensing options.

View file

@ -45,6 +45,11 @@ updated at most once (that is, the protocol classes).
_`.req.deadlock`: The MPS must not deadlock.
_`.req.fork`: On Unix platforms, the MPS should be able to continue in
the child process after a ``fork()``. (Source: job004062_.)
.. _job004062: https://www.ravenbrook.com/project/mps/issue/job004062/
_`.req.perf`: Performance should not be unreasonably hindered.
@ -131,6 +136,38 @@ easiest to implement first, but could be evolved into a `.binary`_
strategy. (That evolution has now happened. tony 1999-08-31).
Fork safety
...........
In order to support ``fork()``, we need to solve the following problems:
_`.anal.fork.lock`: Any MPS lock might be held by another thread at
the point where ``fork()`` is called. The lock would be protecting the
integrity of some data structure. But in the child the thread holding
the lock no longer exists, and so there is no way to restore the
integrity.
_`.anal.fork.threads`: In the child process after a ``fork()``, there
is only one thread, which is a copy of the thread that called
``fork()`` in the parent process. All other threads no longer exist.
But the MPS maintains references to these threads, via the
``ThreadStruct`` object` created by calls to ``mps_thread_reg()``. If
we try to communicate with these threads it will fail or crash.
_`.anal.fork.exc-thread`: On macOS, the MPS handles protection faults
using a dedicated thread. But in the child process after a ``fork()``,
this dedicated thread no longer exists. Also, the Mach port on which
the dedicated thread receives its messages does not exist in the child
either.
_`.anal.fork.mach-port`: On macOS, the MPS identifies threads via
their Mach port numbers, which are stashed in the ``ThreadStruct`` and
used to identify the current thread, for example in
``ThreadSuspend()``. But in the child process after ``fork()`` the
running thread has a different Mach port number than it did in the
parent.
Design
------
@ -209,6 +246,44 @@ design.mps.sig.check.arg.unlocked_).
.. _design.mps.sig.check.arg.unlocked: sig#check-arg-unlocked
Fork safety
-----------
_`.sol.fork.atfork`: The MPS solves the fork-safety problems by
calling |pthread_atfork|_ to install handler functions that are
called in the parent process just before fork (the "prepare" handler),
and in the parent and child processes just after fork (the "parent"
and "child" handlers respectively).
.. |pthread_atfork| replace:: ``pthread_atfork()``
.. _pthread_atfork: http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_atfork.html
_`.sol.fork.lock`: In the prepare handler, the MPS takes all the
locks: that is, the global locks, and then the arena lock for every
arena. Note that a side-effect of this is that the shield is entered
for each arena. In the parent handler, the MPS releases all the locks.
In the child handler, the MPS would like to release the locks but this
does not work on any supported platform, so instead it reinitializes
them, by calling ``LockInitGlobal()``.
_`.sol.fork.thread`: On macOS, in the prepare handler, the MPS
identifies for each arena the current thread, that is, the one calling
``fork()`` which will survive into the child process, and marks this
thread by setting a flag in the appropriate ``ThreadStruct``. In the
parent handler, this flag is cleared. On all Unix platforms, in the
child handler, all threads (except for the current thread) are marked
as dead and transferred to the ring of dead threads. (The MPS can't
destroy the thread structures at this point because they are owned by
the client program.)
_`.sol.fork.exc-thread`: On macOS, in the child handler, the exception
port and dedicated thread are re-created, and the current thread
re-registered with the exception port.
_`.sol.fork.mach-port`: On macOS, in the child handler, the thread
flagged as forking gets its port number updated.
Document History
----------------
@ -218,6 +293,8 @@ Document History
- 2013-05-22 GDR_ Converted to reStructuredText.
- 2018-06-14 GDR_ Added fork safety design.
.. _RB: http://www.ravenbrook.com/consultants/rb/
.. _GDR: http://www.ravenbrook.com/consultants/gdr/

View file

@ -270,7 +270,7 @@ passing ``PROT_NONE`` and ``MAP_PRIVATE | MAP_ANON``.
_`.impl.ix.anon.trans`: Note that ``MAP_ANON`` ("map anonymous
memory not associated with any specific file") is an extension to
POSIX, but it is supported by FreeBSD, Linux, and OS X. A work-around
POSIX, but it is supported by FreeBSD, Linux, and macOS. A work-around
that was formerly used on systems lacking ``MAP_ANON`` was to map
the file ``/dev/zero``.
@ -369,7 +369,7 @@ Document History
Copyright and License
---------------------
Copyright © 2013-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
Copyright © 2013-2018 Ravenbrook Limited <http://www.ravenbrook.com/>.
All rights reserved. This is an open source license. Contact
Ravenbrook for commercial licensing options.

View file

@ -105,7 +105,7 @@ Improvements
.improv.by-os: The overheads hardware barriers varies widely between
operating systems. On Windows it is very cheap to change memory
protection and to handle protecion faults. On OS X it is very
protection and to handle protecion faults. On macOS it is very
expensive. The balance between barriers and scanning work is
different. We should measure the relative costs and tune the deferral
for each separately.
@ -138,7 +138,7 @@ Document History
Copyright and License
---------------------
Copyright © 2016 Ravenbrook Limited <http://www.ravenbrook.com/>. All
Copyright © 2016-2018 Ravenbrook Limited <http://www.ravenbrook.com/>. All
rights reserved. This is an open source license. Contact Ravenbrook
for commercial licensing options.

View file

@ -34,14 +34,14 @@ Compiling for production
In the simplest case, you can compile the MPS to an object file with just::
cc -c mps.c (Unix/Mac OS X)
cc -c mps.c (Unix/macOS)
cl /c mps.c (Windows)
This will build a "hot" variety (for production) object file for use
with ``mps.h``. You can greatly improve performance by allowing global
optimization, for example::
cc -O2 -c mps.c (Unix/Mac OS X)
cc -O2 -c mps.c (Unix/macOS)
cl /O2 /c mps.c (Windows)
@ -51,7 +51,7 @@ Compiling for debugging
You can get a "cool" variety MPS (with more internal checking, for
debugging and development) with::
cc -g -DCONFIG_VAR_COOL -c mps.c (Unix/Mac OS X)
cc -g -DCONFIG_VAR_COOL -c mps.c (Unix/macOS)
cl /Zi /DCONFIG_VAR_COOL /c mps.c (Windows)
@ -68,7 +68,7 @@ between it and the MPS. So if your format implementation is in, say,
then::
cc -O2 -c mymps.c (Unix/Mac OS X)
cc -O2 -c mymps.c (Unix/macOS)
cl /O2 /c mymps.c (Windows)
This will get your format code inlined with the MPS garbage collector.
@ -111,7 +111,7 @@ with ``pkg_add -r gmake``.
On Windows platforms the NMAKE tool is used. This comes with Microsoft
Visual Studio C++ or the Microsoft Windows SDK.
On Mac OS X the MPS is built using Xcode, either by opening
On macOS the MPS is built using Xcode, either by opening
``mps.xcodeproj`` with the Xcode app, or using the command-line
"xcodebuild" tool, installed from Xcode → Preferences → Downloads →
Components → Command Line Tools.
@ -137,15 +137,15 @@ Platform OS Architecture Compiler Makefile
========== ========= ============= ============ =================
``fri3gc`` FreeBSD IA-32 GCC ``fri3gc.gmk``
``fri3ll`` FreeBSD IA-32 Clang ``fri3ll.gmk``
``fri6gc`` FreeBSD x86_64 GCC ``fri6gc.gmk``
``fri6ll`` FreeBSD x86_64 Clang ``fri6ll.gmk``
``fri6gc`` FreeBSD x86-64 GCC ``fri6gc.gmk``
``fri6ll`` FreeBSD x86-64 Clang ``fri6ll.gmk``
``lii3gc`` Linux IA-32 GCC ``lii3gc.gmk``
``lii6gc`` Linux x86_64 GCC ``lii6gc.gmk``
``lii6ll`` Linux x86_64 Clang ``lii6ll.gmk``
``lii6gc`` Linux x86-64 GCC ``lii6gc.gmk``
``lii6ll`` Linux x86-64 Clang ``lii6ll.gmk``
``w3i3mv`` Windows IA-32 Microsoft C ``w3i3mv.nmk``
``w3i6mv`` Windows x86_64 Microsoft C ``w3i6mv.nmk``
``xci3ll`` Mac OS X IA-32 Clang ``mps.xcodeproj``
``xci6ll`` Mac OS X x86_64 Clang ``mps.xcodeproj``
``w3i6mv`` Windows x86-64 Microsoft C ``w3i6mv.nmk``
``xci3ll`` macOS IA-32 Clang ``mps.xcodeproj``
``xci6ll`` macOS x86-64 Clang ``mps.xcodeproj``
========== ========= ============= ============ =================
Historically, the MPS worked on a much wider variety of platforms, and
@ -195,13 +195,13 @@ To build just one target, run one of these commands::
nmake /f w3i3mv.nmk <target> (32-bit)
nmake /f w3i6mv.nmk <target> (64-bit)
On Mac OS X, you can build from the command line with::
On macOS, you can build from the command line with::
xcodebuild
On most platforms, the output of the build goes to a directory named
after the platform (e.g. ``lii6ll``) so that you can share the source
tree across platforms. On Mac OS X the output goes in a directory
tree across platforms. On macOS the output goes in a directory
called ``xc``. Building generates ``mps.a`` or ``mps.lib`` or
equivalent, a library of object code which you can link with your
application, subject to the :ref:`MPS licensing conditions <license>`.
@ -241,7 +241,7 @@ loads a diagnostic stream of events into a `SQLite3
<http://www.sqlite.org/>`_ database for processing. In order to build
this program, you need to install the SQLite3 development resources.
* On Mac OS X, SQLite3 is pre-installed, so this tool builds by
* On macOS, SQLite3 is pre-installed, so this tool builds by
default.
* On Linux, you need to install the ``libsqlite3-dev`` package::

View file

@ -180,17 +180,17 @@ prmcw3.c Mutator context implementation for Windows.
prmcw3.h Mutator context interface for Windows.
prmcw3i3.c Mutator context implementation for Windows, IA-32.
prmcw3i6.c Mutator context implementation for Windows, x86-64.
prmcxc.c Mutator context implementation for OS X.
prmcxc.h Mutator context interface for OS X.
prmcxci3.c Mutator context implementation for OS X, IA-32.
prmcxci6.c Mutator context implementation for OS X, x86-64.
prmcxc.c Mutator context implementation for macOS.
prmcxc.h Mutator context interface for macOS.
prmcxci3.c Mutator context implementation for macOS, IA-32.
prmcxci6.c Mutator context implementation for macOS, x86-64.
prot.h Protection interface. See design.mps.prot_.
protan.c Protection implementation for standard C.
protix.c Protection implementation for POSIX.
protsgix.c Protection implementation for POSIX (signals part).
protw3.c Protection implementation for Windows.
protxc.c Protection implementation for OS X.
protxc.h Protection interface for OS X.
protxc.c Protection implementation for macOS.
protxc.h Protection interface for macOS.
pthrdext.c Protection implementation for POSIX (threads part).
pthrdext.h Protection interface for POSIX (threads part).
sp.h Stack probe interface. See design.mps.sp_.
@ -210,7 +210,7 @@ th.h Threads interface. See design.mps.thread-manager_.
than.c Threads implementation for standard C.
thix.c Threads implementation for POSIX.
thw3.c Threads implementation for Windows.
thxc.c Threads implementation for OS X.
thxc.c Threads implementation for macOS.
vm.c Virtual memory implementation (common part).
vm.h Virtual memory interface. See design.mps.vm_.
vman.c Virtual memory implementation for standard C.
@ -349,6 +349,7 @@ expt825.c Regression test for job000825_.
fbmtest.c Free block manager (CBS and Freelist) test.
finalcv.c :ref:`topic-finalization` coverage test.
finaltest.c :ref:`topic-finalization` test.
forktest.c :ref:`topic-thread-fork` test.
fotest.c Failover allocator test.
landtest.c Land test.
locbwcss.c Locus backwards compatibility stress test.

View file

@ -144,10 +144,6 @@ html_static_path = ['images']
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
html_use_smartypants = True
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}

View file

@ -6,17 +6,40 @@ See <http://sphinx-doc.org/extensions.html>
from collections import defaultdict
from inspect import isabstract, isclass
import re
from . import designs
import warnings
from docutils import nodes, transforms
from docutils.parsers.rst import Directive
from docutils.parsers.rst.directives.admonitions import BaseAdmonition
from sphinx import addnodes
from sphinx.directives.other import VersionChange
from sphinx.domains import Domain
from sphinx.roles import XRefRole
from sphinx.util.compat import Directive, make_admonition
from sphinx.util.nodes import set_source_info, process_index_entry
from sphinx.locale import versionlabels
versionlabels['deprecatedstarting'] = 'Deprecated starting with version %s'
from sphinx.locale import admonitionlabels, versionlabels
from . import designs
versionlabels['deprecatedstarting'] = "Deprecated starting with version %s"
admonitionlabels.update(
aka="Also known as",
bibref="Related publication",
bibrefs="Related publications",
deprecated="Deprecated",
historical="Historical note",
link="Related link",
links="Related links",
note="Note",
notes="Notes",
opposite="Opposite term",
opposites="Opposite terms",
relevance="Relevance to memory management",
see="See",
similar="Similar term",
similars="Similar terms",
specific="In the MPS",
topics="Topic",
topicss="Topics"),
class MpsDomain(Domain):
label = 'MPS'
@ -25,12 +48,15 @@ class MpsDomain(Domain):
class MpsDirective(Directive):
@classmethod
def add_to_app(cls, app):
if hasattr(cls, 'name'): name = cls.name
elif hasattr(cls, 'nodecls'): name = cls.nodecls.__name__
else: return
if hasattr(cls, 'nodecls') and hasattr(cls, 'visit'):
app.add_node(cls.nodecls, html = cls.visit, latex = cls.visit,
text = cls.visit, man = cls.visit)
if hasattr(cls, 'name'):
name = cls.name
elif hasattr(cls, 'node_class') and cls.node_class is not None:
name = cls.node_class.__name__
else:
return
if hasattr(cls, 'node_class') and hasattr(cls, 'visit'):
app.add_node(cls.node_class, html=cls.visit, latex=cls.visit,
text=cls.visit, man=cls.visit)
if hasattr(cls, 'domain'):
app.add_directive_to_domain(cls.domain, name, cls)
else:
@ -82,143 +108,110 @@ def mps_ref_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
return [refnode], []
class Admonition(nodes.Admonition, nodes.Element):
pass
plural = False
def visit_admonition_node(self, node):
self.visit_admonition(node)
name = type(node).__name__ + ('s' if node.plural else '')
self.visit_admonition(node, name=name)
def depart_admonition_node(self, node):
self.depart_admonition(node)
class AdmonitionDirective(MpsDirective):
label = 'Admonition'
class AdmonitionDirective(MpsDirective, BaseAdmonition):
has_content = True
visit = visit_admonition_node, depart_admonition_node
@classmethod
def add_to_app(cls, app):
if not hasattr(cls, 'nodecls'): return
super(AdmonitionDirective, cls).add_to_app(app)
def run(self):
ad = make_admonition(self.nodecls, self.name, [self.label],
self.options, self.content, self.lineno,
self.content_offset, self.block_text,
self.state, self.state_machine)
return ad
class PluralDirective(AdmonitionDirective):
def run(self):
ad = super(PluralDirective, self).run()
refs = sum(1 for node in ad[0][1]
if isinstance(node, addnodes.pending_xref)
or isinstance(node, nodes.Referential))
refs = sum(1 for node in ad[0][0]
if isinstance(node, (addnodes.pending_xref,
nodes.Referential)))
if refs > 1:
assert(isinstance(ad[0][0], nodes.title))
ad[0][0][0] = nodes.Text(self.plural)
ad[0].plural = True
return ad
class aka(Admonition):
pass
class AkaDirective(AdmonitionDirective):
nodecls = aka
label = 'Also known as'
node_class = aka
class bibref(Admonition):
pass
class BibrefDirective(PluralDirective):
nodecls = bibref
label = 'Related publication'
plural = 'Related publications'
node_class = bibref
class deprecated(Admonition):
pass
class DeprecatedDirective(AdmonitionDirective):
nodecls = deprecated
label = 'Deprecated'
node_class = deprecated
class historical(Admonition):
pass
class HistoricalDirective(AdmonitionDirective):
nodecls = historical
label = 'Historical note'
node_class = historical
class link(Admonition):
pass
class LinkDirective(PluralDirective):
nodecls = link
label = 'Related link'
plural = 'Related links'
node_class = link
class note(Admonition):
pass
class NoteDirective(AdmonitionDirective):
nodecls = note
label = 'Note'
plural = 'Notes'
node_class = note
def run(self):
ad = super(NoteDirective, self).run()
assert(isinstance(ad[0][0], nodes.title))
if len(ad[0]) == 1: return ad
if (isinstance(ad[0][1], nodes.enumerated_list)
and sum(1 for _ in ad[0][1].traverse(nodes.list_item)) > 1
or isinstance(ad[0][1], nodes.footnote)
if (isinstance(ad[0][0], nodes.enumerated_list)
and sum(1 for _ in ad[0][0].traverse(nodes.list_item)) > 1
or isinstance(ad[0][0], nodes.footnote)
and sum(1 for _ in ad[0].traverse(nodes.footnote)) > 1):
ad[0][0][0] = nodes.Text(self.plural)
ad[0].plural = True
return ad
class opposite(Admonition):
pass
class OppositeDirective(PluralDirective):
nodecls = opposite
label = 'Opposite term'
plural = 'Opposite terms'
node_class = opposite
class relevance(Admonition):
pass
class RelevanceDirective(AdmonitionDirective):
nodecls = relevance
label = 'Relevance to memory management'
node_class = relevance
class see(Admonition):
pass
class SeeDirective(AdmonitionDirective):
nodecls = see
label = 'See'
node_class = see
class similar(Admonition):
pass
class SimilarDirective(PluralDirective):
nodecls = similar
label = 'Similar term'
plural = 'Similar terms'
node_class = similar
class specific(Admonition):
pass
class SpecificDirective(AdmonitionDirective):
domain = 'mps'
nodecls = specific
label = 'In the MPS'
node_class = specific
class topics(Admonition):
pass
class TopicsDirective(PluralDirective):
nodecls = topics
label = 'Topic'
plural = 'Topics'
node_class = topics
class GlossaryTransform(transforms.Transform):
"""
@ -329,8 +322,6 @@ class GlossaryTransform(transforms.Transform):
print('{}:{}: WARNING: cross-reference to {}.'
.format(doc, line, i))
def setup(app):
designs.convert_updated(app)
app.add_domain(MpsDomain)

View file

@ -30,8 +30,8 @@ Memory Management Glossary: M
but faster and more expensive than :term:`backing store`.
It is common to refer only to the main memory of a computer;
for example, "This server has 128 GB of memory" and "OS X 10.8
requires at least 2 GB of memory".
for example, "This server has 128 GB of memory" and "macOS
High Sierra requires at least 2 GB of memory".
.. historical::

View file

@ -91,7 +91,7 @@ General debugging advice
On these operating systems, you can add this command to your
``.gdbinit`` if you always want it to be run.
On OS X, barrier hits do not use signals and so do not enter the
On macOS, barrier hits do not use signals and so do not enter the
debugger.
#. .. index::
@ -155,7 +155,7 @@ program (data segment, text segment, stack and heap):
}
When ASLR is turned on, running this program outputs different
addresses on each run. For example, here are four runs on OS X
addresses on each run. For example, here are four runs on macOS
10.9.3::
data: 0x10a532020 text: 0x10a531ed0 stack: 0x7fff556ceb1c heap: 0x7f9f80c03980
@ -196,7 +196,7 @@ Here's the situation on each of the operating systems supported by the MPS:
$ setarch $(uname -m) -R ./myprogram
* On **OS X** (10.7 or later), ASLR can be disabled for a single
* On **macOS** (10.7 or later), ASLR can be disabled for a single
process by starting the process using :c:func:`posix_spawn`, passing
the undocumented attribute ``0x100``, like this:
@ -213,7 +213,7 @@ Here's the situation on each of the operating systems supported by the MPS:
The MPS provides the source code for a command-line tool
implementing this (``tool/noaslr.c``). We've confirmed that this
works on OS X 10.9.3, but since the technique is undocumented, it
works on macOS 10.9.3, but since the technique is undocumented, it
may well break in future releases. (If you know of a documented way
to achieve this, please :ref:`contact us <contact>`.)

View file

@ -976,8 +976,8 @@ as a root by calling :c:func:`mps_root_create_thread`::
void *marker = &marker;
mps_root_t stack_root;
res = mps_root_create_thread(&reg_root, arena, thread, marker);
if (res != MPS_RES_OK) error("Couldn't create root");
res = mps_root_create_thread(&stack_root, arena, thread, marker);
if (res != MPS_RES_OK) error("Couldn't create stack root");
In order to scan the control stack, the MPS needs to know where the
:term:`cold end` of the stack is, and that's the role of the
@ -1175,13 +1175,13 @@ before destroying the arena, and so on.
For example::
mps_arena_park(arena); /* ensure no collection is running */
mps_ap_destroy(obj_ap); /* destroy ap before pool */
mps_pool_destroy(obj_pool); /* destroy pool before fmt */
mps_root_destroy(reg_root); /* destroy root before thread */
mps_thread_dereg(thread); /* deregister thread before arena */
mps_fmt_destroy(obj_fmt); /* destroy fmt before arena */
mps_arena_destroy(arena); /* last of all */
mps_arena_park(arena); /* ensure no collection is running */
mps_ap_destroy(obj_ap); /* destroy ap before pool */
mps_pool_destroy(obj_pool); /* destroy pool before fmt */
mps_root_destroy(stack_root); /* destroy root before thread */
mps_thread_dereg(thread); /* deregister thread before arena */
mps_fmt_destroy(obj_fmt); /* destroy fmt before arena */
mps_arena_destroy(arena); /* last of all */
What next?

View file

@ -43,6 +43,8 @@ for details.
single: Memory Pool System; supported target platforms
single: platforms; supported
.. _guide-overview-platforms:
Supported target platforms
--------------------------
@ -53,9 +55,9 @@ The MPS is currently supported for deployment on:
- Linux 2.6 or later, on IA-32 using GCC and on x86-64 using GCC or
Clang/LLVM;
- FreeBSD 7 or later, on IA-32 and x86-64, using GCC;
- FreeBSD 7 or later, on IA-32 and x86-64, using GCC or Clang/LLVM;
- OS X 10.4 or later, on IA-32 and x86-64, using Clang/LLVM.
- macOS 10.4 or later, on IA-32 and x86-64, using Clang/LLVM.
The MPS is highly portable and has run on many other processors and
operating systems in the past (see :ref:`guide-build`). Most of the

View file

@ -539,7 +539,7 @@ Memory management in various languages
.. link::
`Borland Delphi Home Page <http://www.borland.com/delphi/>`_,
`Embarcadero (formely Borland) Delphi <https://www.embarcadero.com/products/delphi>`_,
`Pascal standardization <http://www.open-std.org/JTC1/sc22/docs/oldwgs/wg2.html>`_.
Perl

View file

@ -252,7 +252,7 @@ following are true:
#. The MPS is running on Linux/IA-32 or Windows/IA-32. Extending this
list to new (reasonable) operating systems should be tolerable (for
example, OS X/IA-32). Extending this to new processor architectures
example, macOS/IA-32). Extending this to new processor architectures
requires more work.
#. The processor instruction that is accessing the object is of a

View file

@ -4,6 +4,18 @@ Release notes
=============
.. _release-notes-1.117:
Release 1.117.0
---------------
New features
............
#. On FreeBSD, Linux and macOS, the MPS is now able to run in the
child process after ``fork()``. See :ref:`topic-thread-fork`.
.. _release-notes-1.116:
Release 1.116.0
@ -21,7 +33,8 @@ New features
#. The MPS no longer supports Linux 2.4 and 2.5. (These versions used
LinuxThreads_ instead of POSIX threads; all major distributions
have long since ceased to support these versions and so it is no
longer convenient to test against them.)
longer convenient to test against them.) See
:ref:`guide-overview-platforms`.
.. _LinuxThreads: http://pauillac.inria.fr/~xleroy/linuxthreads/

View file

@ -1024,3 +1024,10 @@ Arena introspection and debugging
return storage to the operating system). For reliable results
call this function and interpret the result while the arena is
in the :term:`parked state`.
.. seealso::
To find out which :term:`pool` the address belongs to, use
:c:func:`mps_addr_pool`, and to find out which :term:`object
format` describes the object at the address, use
:c:func:`mps_addr_fmt`.

View file

@ -228,7 +228,8 @@ Cautions
Therefore, the format methods must be able to be run at any time,
including asynchronously or in parallel with the rest of the
program.
program. On POSIX systems, this means that format methods must be
async-signal-safe.
#. Format methods must be re-entrant.

View file

@ -20,7 +20,7 @@ six-character code breaks down into three pairs of characters:
``fr`` FreeBSD :c:macro:`MPS_OS_FR`
``li`` Linux :c:macro:`MPS_OS_LI`
``w3`` Windows :c:macro:`MPS_OS_W3`
``xc`` OS X :c:macro:`MPS_OS_XC`
``xc`` macOS :c:macro:`MPS_OS_XC`
====== ================ ====================
The second pair of characters names the processor architecture:
@ -126,7 +126,7 @@ Platform interface
.. c:macro:: MPS_OS_XC
A :term:`C` preprocessor macro that indicates, if defined, that
the MPS was compiled on an OS X operating system.
the MPS was compiled on an macOS operating system.
.. c:macro:: MPS_PF_ALIGN
@ -209,28 +209,28 @@ Platform interface
.. c:macro:: MPS_PF_XCI3GC
A :term:`C` preprocessor macro that indicates, if defined, that
the :term:`platform` consists of the OS X operating system, the
the :term:`platform` consists of the macOS operating system, the
IA-32 processor architecture, and the GCC compiler.
.. c:macro:: MPS_PF_XCI3LL
A :term:`C` preprocessor macro that indicates, if defined, that
the :term:`platform` consists of the OS X operating system, the
the :term:`platform` consists of the macOS operating system, the
IA-32 processor architecture, and the Clang/LLVM compiler.
.. c:macro:: MPS_PF_XCI6GC
A :term:`C` preprocessor macro that indicates, if defined, that
the :term:`platform` consists of the OS X operating system, the
the :term:`platform` consists of the macOS operating system, the
x86-64 processor architecture, and the GCC compiler.
.. c:macro:: MPS_PF_XCI6LL
A :term:`C` preprocessor macro that indicates, if defined, that
the :term:`platform` consists of the OS X operating system, the
the :term:`platform` consists of the macOS operating system, the
x86-64 processor architecture, and the Clang/LLVM compiler.

View file

@ -72,7 +72,7 @@ for useful advice.)
If this preprocessor constant is defined, exclude the ANSI plinth
(``mpsioan.c`` and ``mpsliban.c``) from the MPS. For example::
cc -DCONFIG_PLINTH_NONE -c mps.c (Unix/OS X)
cc -DCONFIG_PLINTH_NONE -c mps.c (Unix/macOS)
cl /Gs /DCONFIG_PLINTH_NONE /c mps.c (Windows)
Having excluded the ANSI plinth, you must of course supply your

View file

@ -163,3 +163,10 @@ Pool introspection
may immediately become invalidated. For reliable results call
this function and interpret the result while the arena is in
the :term:`parked state`.
.. seealso::
To find out which :term:`object format` describes the object
at the address, use :c:func:`mps_addr_fmt`. If you only care
whether the address belongs to a particular :term:`arena`, use
:c:func:`mps_arena_has_addr`.

View file

@ -61,7 +61,7 @@ usable.
See :ref:`design-prot` for the design, and ``prot.h`` for the
interface. There are implementations for POSIX in ``protix.c`` plus
``protsgix.c``, Windows in ``protw3.c``, and OS X using Mach in
``protsgix.c``, Windows in ``protw3.c``, and macOS using Mach in
``protix.c`` plus ``protxc.c``.
There is a generic implementation in ``protan.c``, which can't
@ -76,7 +76,7 @@ usable.
stack` can be scanned.
See :ref:`design-prmc` for the design, and ``prmc.h`` for the
interface. There are implementations on Unix, Windows, and OS X for
interface. There are implementations on Unix, Windows, and macOS for
IA-32 and x86-64.
There is a generic implementation in ``prmcan.c``, which can't
@ -117,7 +117,7 @@ usable.
See :ref:`design-thread-manager` for the design, and ``th.h`` for
the interface. There are implementations for POSIX in ``thix.c``
plus ``pthrdext.c``, OS X using Mach in ``thxc.c``, Windows in
plus ``pthrdext.c``, macOS using Mach in ``thxc.c``, Windows in
``thw3.c``.
There is a generic implementation in ``than.c``, which necessarily

View file

@ -34,7 +34,7 @@ determine the address of allocated structures.
There is currently no workaround for this issue. If this affects you,
please :ref:`contact us <contact>`.
Other supported platforms are unaffected by this issue: Linux and OS X
Other supported platforms are unaffected by this issue: Linux and macOS
randomize the addresses allocated by :c:func:`mmap`, and Windows
randomizes the addresses allocated by :c:func:`VirtualAlloc`.

View file

@ -104,7 +104,7 @@ Signal and exception handling issues
* On Windows, you must not install a first-chance exception handler.
* On OS X, you must not install a thread-local Mach exception handler
* On macOS, you must not install a thread-local Mach exception handler
for ``EXC_BAD_ACCESS`` exceptions.
All of these things are, in fact, possible, but your program must
@ -113,6 +113,43 @@ Signal and exception handling issues
us <contact>`.
.. index::
single: fork safety
.. _topic-thread-fork:
Fork safety
-----------
On Linux, FreeBSD and macOS, the MPS makes a best-effort attempt to
continue running in the child process after a call to :c:func:`fork`,
even if the :term:`client program` was running multiple
:term:`threads` at the point where the call is made to :c:func:`fork`.
.. warning::
POSIX offers little or nothing in the way of guarantees about the
situation of a child process running after a multi-threaded parent
forked. The specification_ says:
.. _specification: http://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html
A process shall be created with a single thread. If a
multi-threaded process calls :c:func:`fork`, the new process shall
contain a replica of the calling thread and its entire address
space, possibly including the states of mutexes and other
resources. Consequently, to avoid errors, the child process may
only execute async-signal-safe operations until such time as one
of the :c:func:`exec` functions is called.
.. note::
Although only one thread is created in the child process, any
threads in the parent process that were registered with the MPS by
calling :c:func:`mps_thread_reg` must still be deregistered, by
calling :c:func:`mps_thread_dereg`, before the arena is destroyed.
.. index::
single: thread; interface

View file

@ -146,7 +146,7 @@ the branch. A typical invocation looks like this::
release name according to the variant, for example,
``mps-cet-1.110.0.zip``
On a Unix (including OS X) machine:
On a Unix (including macOS) machine:
#. Create a fresh Perforce client workspace::

View file

@ -53,7 +53,7 @@ using it. The basic case is straightforward on supported platforms
(see below)::
cd code
cc -O2 -c mps.c Unix / Mac OS X (with Xcode command line)
cc -O2 -c mps.c Unix / macOS (with Xcode command line)
cl /O2 /c mps.c Windows (with Microsoft SDK or Visual Studio 2010)
This will produce an object file you can link with your project. For
@ -79,7 +79,7 @@ The MPS is currently supported for deployment on:
- FreeBSD 7 or later, on IA-32 and x86-64, using GCC or Clang/LLVM;
- OS X 10.4 or later, on IA-32 and x86-64, using Clang/LLVM.
- macOS 10.4 or later, on IA-32 and x86-64, using Clang/LLVM.
The MPS is highly portable and has run on many other processors and
operating systems in the past (see `Building the MPS
@ -144,7 +144,7 @@ Document History
Copyright and Licence
---------------------
Copyright (C) 2001-2016 Ravenbrook Limited. All rights reserved.
Copyright (C) 2001-2018 Ravenbrook Limited. All rights reserved.
<http://www.ravenbrook.com/>. This is an open source license. Contact
Ravenbrook for commercial licensing options.

View file

@ -221,7 +221,9 @@ static mps_res_t myscan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit)
the pun would probably work fine almost everywhere)
*/
comment("About to fix with null scan state...");
res = mps_fix(NULL, (mps_addr_t *) &p);
MPS_SCAN_BEGIN(ss) {
res = MPS_FIX12(NULL, (mps_addr_t *) &p);
} MPS_SCAN_END(ss);
error("fix with NULL scan state");
if (res != MPS_RES_OK) return res;
obj->data.ref[i].addr = p;

View file

@ -222,7 +222,9 @@ static mps_res_t myscan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit)
the pun would probably work fine almost everywhere)
*/
comment("About to fix with unaligned scan state...");
res = mps_fix(UNALIGNED, (mps_addr_t *) &p);
MPS_SCAN_BEGIN(ss) {
res = MPS_FIX12(UNALIGNED, (mps_addr_t *) &p);
} MPS_SCAN_END(ss);
error("fix with unaligned scan state");
if (res != MPS_RES_OK) return res;
obj->data.ref[i].addr = p;

View file

@ -221,7 +221,9 @@ static mps_res_t myscan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit)
the pun would probably work fine almost everywhere)
*/
comment("About to fix with null pointer...");
res = mps_fix(ss, NULL);
MPS_SCAN_BEGIN(ss) {
res = MPS_FIX2(ss, NULL);
} MPS_SCAN_END(ss);
error("fix with null pointer");
if (res != MPS_RES_OK) return res;
obj->data.ref[i].addr = p;

View file

@ -255,7 +255,7 @@ static mps_res_t myscan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit)
*/
comment("About to fix with null pointer...");
p = NULL;
res = mps_fix(ss, (mps_addr_t *) &p);
res = MPS_FIX12(ss, (mps_addr_t *) &p);
error("fix with null pointer");
if (res != MPS_RES_OK) return res;
obj->data.ref[i].addr = p;

View file

@ -254,7 +254,7 @@ static mps_res_t myscan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit)
the pun would probably work fine almost everywhere)
*/
comment("About to fix on unaligned addr...");
res = mps_fix(ss, UNALIGNED);
res = MPS_FIX12(ss, (mps_addr_t *) UNALIGNED);
error("unaligned fix");
if (res != MPS_RES_OK) return res;
obj->data.ref[i].addr = p;

View file

@ -255,7 +255,7 @@ static mps_res_t myscan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit)
*/
comment("About to fix with unaligned pointer...");
p = UNALIGNED;
res = mps_fix(ss, &p);
res = MPS_FIX2(ss, &p);
error("fix with unaligned pointer");
if (res != MPS_RES_OK) return res;
obj->data.ref[i].addr = p;

View file

@ -13,7 +13,7 @@
# Set lots of variables correctly, depending on the platform
# (which was determined in 'options')
#
# Currently, it should work correctly on Windows, Linux, MacOS X,
# Currently, it should work correctly on Windows, Linux, macOS,
# FreeBSD.
#

View file

@ -33,4 +33,4 @@ $HARNESS_VERSION="3.5";
# 3.3.1: fix bug in reporting compiler errors when compilation
# _succeeds_
# 3.4 -- Added P= (pathname equality) operator
# 3.5 -- Platform detection based on uname; Linux and Mac OS X stuff
# 3.5 -- Platform detection based on uname; Linux and macOS stuff

View file

@ -231,7 +231,7 @@ static mps_res_t myscan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit)
p = obj->data.assoc;
if (p != NULL) {
commentif(fixcomments, "fix %li[assoc]", obj->data.id);
res = MPS_FIX(ss, (mps_addr_t *) &p);
res = MPS_FIX12(ss, (mps_addr_t *) &p);
if (res != MPS_RES_OK) return res;
if (p == NULL) {
commentif(deathcomments, "fixed %li[assoc] to NULL", obj->data.id);
@ -250,7 +250,7 @@ static mps_res_t myscan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit)
*/
commentif(fixcomments, "fix %li[%i] -> %li",
obj->data.id, i, obj->data.ref[i].id);
res = MPS_FIX(ss, (mps_addr_t *) &p);
res = MPS_FIX12(ss, (mps_addr_t *) &p);
if (p == NULL) {
commentif(deathcomments, "fixed %li[%i] to NULL", obj->data.id, i);
INCCOUNTIF(obj->data.countflag, DYING_REFERENCE_COUNT);

View file

@ -217,7 +217,7 @@ static mps_res_t myscan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit)
p = obj->data.assoc;
if (p != NULL) {
commentif(fixcomments, "fix %li[assoc]", obj->data.id);
res = MPS_FIX(ss, (mps_addr_t *) &p);
res = MPS_FIX12(ss, (mps_addr_t *) &p);
if (res != MPS_RES_OK) return res;
if (p == NULL) {
commentif(deathcomments, "fixed %li[assoc] to NULL", obj->data.id);
@ -236,7 +236,7 @@ static mps_res_t myscan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit)
*/
commentif(fixcomments, "fix %li[%i] -> %li",
obj->data.id, i, obj->data.ref[i].id);
res = MPS_FIX(ss, (mps_addr_t *) &p);
res = MPS_FIX12(ss, (mps_addr_t *) &p);
if (p == NULL) {
commentif(deathcomments, "fixed %li[%i] to NULL", obj->data.id, i);
INCCOUNTIF(obj->data.countflag, DYING_REFERENCE_COUNT);

View file

@ -151,7 +151,7 @@ static mps_res_t myscan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit)
/* make sure to fix the assoc pointer first */
p = obj->data.assoc;
if (p != NULL) {
res = MPS_FIX(ss, (mps_addr_t *) &p);
res = MPS_FIX12(ss, (mps_addr_t *) &p);
if (res != MPS_RES_OK) return res;
obj->data.assoc = p;
}
@ -161,7 +161,7 @@ static mps_res_t myscan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit)
p = obj->data.ref[i].addr;
if (p != NULL)
{
res = MPS_FIX(ss, (mps_addr_t *) &p);
res = MPS_FIX12(ss, (mps_addr_t *) &p);
if (res != MPS_RES_OK) return res;
obj->data.ref[i].addr = p;
}

View file

@ -103,7 +103,7 @@ mps_res_t myscan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit)
if (obj->ref[0] != NULL)
{
if (formatcomments) printf("Fix: %p.\n", (void*)&(obj->ref[0]));
res = MPS_FIX(ss, (mps_addr_t *) &(obj->ref[0])); /* pun! */
res = MPS_FIX12(ss, (mps_addr_t *) &(obj->ref[0])); /* pun! */
if (res != MPS_RES_OK)
{
return res;
@ -112,7 +112,7 @@ mps_res_t myscan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit)
if (obj->ref[1] != NULL)
{
if (formatcomments) printf("Fix: %p.\n", (void*)&(obj->ref[1]));
res = MPS_FIX(ss, (mps_addr_t *) &(obj->ref[1])); /* pun! */
res = MPS_FIX12(ss, (mps_addr_t *) &(obj->ref[1])); /* pun! */
if (res != MPS_RES_OK)
{
return res;

View file

@ -210,7 +210,7 @@ static mps_res_t myscan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit)
*/
commentif(fixcomments, "fix %li[%i] -> %li",
obj->data.id, i, obj->data.ref[i].id);
res = MPS_FIX(ss, (mps_addr_t *) &p);
res = MPS_FIX12(ss, (mps_addr_t *) &p);
if (res != MPS_RES_OK) return res;
obj->data.ref[i].addr = p;
}

View file

@ -362,7 +362,7 @@ static mps_res_t myscan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit)
if (p != NULL) {
commentif(fixcomments, "fix %li[assoc]", obj->data.id);
q = p;
res = MPS_FIX(ss, (mps_addr_t *) &p);
res = MPS_FIX12(ss, (mps_addr_t *) &p);
if (res != MPS_RES_OK) return res;
if (p == NULL) {
asserts(rank == mps_rank_weak(),
@ -387,7 +387,7 @@ static mps_res_t myscan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit)
commentif(fixcomments, "fix %li[%i] -> %li",
obj->data.id, i, obj->data.ref[i].id);
q = p;
res = MPS_FIX(ss, (mps_addr_t *) &p);
res = MPS_FIX12(ss, (mps_addr_t *) &p);
if (p == NULL) {
asserts(rank == mps_rank_weak(),
"non-weak reference fixed to NULL at %p[i]", obj);

View file

@ -37,8 +37,8 @@ This document is not confidential.
`testrun.bat`_ Implements the ``testrun`` make target on Windows, where
it is invoked from ``commpost.nmk``.
`testrun.sh`_ Implements the ``testrun`` make target on FreeBSD and
Linux, it is invoked from ``comm.gmk``, and on OS X, where
it is invoked from the Xcode project.
Linux, it is invoked from ``comm.gmk``, and on macOS,
where it is invoked from the Xcode project.
================= ==========================================================
.. _branch: branch
@ -75,7 +75,7 @@ B. Document History
C. Copyright and License
------------------------
Copyright © 2002-2014 Ravenbrook Limited. All rights reserved.
Copyright © 2002-2018 Ravenbrook Limited. All rights reserved.
<http://www.ravenbrook.com/> This is an open source license. Contact
Ravenbrook for commercial licensing options.

View file

@ -20,6 +20,7 @@ exposet0 =P
expt825
finalcv =P
finaltest =P
forktest =X
fotest
gcbench =N benchmark
landtest