? m3-libs/m3core/src/Csupport/Common/a.out Index: m3-libs/m3core/src/m3core.h =================================================================== RCS file: /usr/cvs/cm3/m3-libs/m3core/src/m3core.h,v retrieving revision 1.8 diff -u -r1.8 m3core.h --- m3-libs/m3core/src/m3core.h 19 Mar 2010 17:07:58 -0000 1.8 +++ m3-libs/m3core/src/m3core.h 20 Mar 2010 20:42:51 -0000 @@ -404,6 +404,13 @@ UINT32 __cdecl Uin__htonl(UINT32 x); UINT16 __cdecl Uin__htons(UINT16 x); +typedef void (*PThreadForkHandler)(void); + +INTEGER +RTOS__PThreadAtFork(PThreadForkHandler prep, + PThreadForkHandler parent, + PThreadForkHandler child); + #ifdef __cplusplus } /* extern "C" */ #endif Index: m3-libs/m3core/src/runtime/common/RTCollector.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-libs/m3core/src/runtime/common/RTCollector.m3,v retrieving revision 1.88 diff -u -r1.88 RTCollector.m3 --- m3-libs/m3core/src/runtime/common/RTCollector.m3 15 Dec 2009 19:52:08 -0000 1.88 +++ m3-libs/m3core/src/runtime/common/RTCollector.m3 20 Mar 2010 20:42:52 -0000 @@ -2033,19 +2033,31 @@ VAR startedWeakCleaner := FALSE; -PROCEDURE WeakRefFromRef (r: REFANY; p: WeakRefCleanUpProc := NIL): WeakRef = +PROCEDURE StartWeakCleaner () = VAR start := FALSE; - result: WeakRef; BEGIN - <* ASSERT r # NIL *> TRY RTOS.LockHeap(); - (* create a WeakCleaner thread the first time through *) - IF p # NIL AND NOT startedWeakCleaner THEN + IF NOT startedWeakCleaner THEN start := TRUE; startedWeakCleaner := TRUE; END; + FINALLY + RTOS.UnlockHeap(); + END; + IF start THEN + EVAL Thread.Fork(NEW(Thread.Closure, apply := WeakCleaner)); + END; + END StartWeakCleaner; + +PROCEDURE WeakRefFromRef (r: REFANY; p: WeakRefCleanUpProc := NIL): WeakRef = + VAR + result: WeakRef; + BEGIN + <* ASSERT r # NIL *> + TRY + RTOS.LockHeap(); (* if necessary, expand weakTable *) IF weakFree0 = -1 THEN ExpandWeakTable(); END; IF p # NIL THEN @@ -2075,9 +2087,8 @@ FINALLY RTOS.UnlockHeap(); END; - IF start THEN - EVAL Thread.Fork(NEW(Thread.Closure, apply := WeakCleaner)); - END; + (* create a WeakCleaner thread the first time through *) + StartWeakCleaner(); RETURN result; END WeakRefFromRef; @@ -2771,8 +2782,24 @@ (*** INITIALIZATION ***) +PROCEDURE AtForkChild() = + BEGIN + IF startedForeground THEN + StartBackgroundCollection(); + END; + IF startedBackground THEN + StartBackgroundCollection(); + END; + IF startedWeakCleaner THEN + StartWeakCleaner(); + END; + END AtForkChild; + PROCEDURE Init () = + VAR r: INTEGER; BEGIN + r := RTProcess.RegisterForkHandlers((*prepare*)NIL, (*parent*)NIL, AtForkChild); + <* ASSERT r = 0 *> IF RTParams.IsPresent("paranoidgc") THEN InstallSanityCheck(); END; IF RTParams.IsPresent("nogc") THEN disableCount := 1; END; IF RTParams.IsPresent("noincremental") THEN incremental := FALSE; END; Index: m3-libs/m3core/src/runtime/common/RTProcess.i3 =================================================================== RCS file: /usr/cvs/cm3/m3-libs/m3core/src/runtime/common/RTProcess.i3,v retrieving revision 1.3 diff -u -r1.3 RTProcess.i3 --- m3-libs/m3core/src/runtime/common/RTProcess.i3 18 Feb 2009 02:32:36 -0000 1.3 +++ m3-libs/m3core/src/runtime/common/RTProcess.i3 20 Mar 2010 20:42:52 -0000 @@ -37,5 +37,13 @@ (* Registers "enable" and "disable" as the machine-specific setup procedures to enable and disable respectively control-C handling. *) -END RTProcess. +TYPE ForkHandler = PROCEDURE(); + +(* RegisterForkHandlers = pthread_atfork or just 0 on Win32. *) +<* EXTERNAL RTProcess__RegisterForkHandlers *> +PROCEDURE RegisterForkHandlers(prep, parent, child: ForkHandler): INTEGER; +<* EXTERNAL RTProcess__Fork *> +PROCEDURE Fork(): INTEGER; + +END RTProcess. Index: m3-libs/m3core/src/runtime/common/RTProcessC.c =================================================================== RCS file: /usr/cvs/cm3/m3-libs/m3core/src/runtime/common/RTProcessC.c,v retrieving revision 1.1 diff -u -r1.1 RTProcessC.c --- m3-libs/m3core/src/runtime/common/RTProcessC.c 20 Mar 2010 20:40:39 -0000 1.1 +++ m3-libs/m3core/src/runtime/common/RTProcessC.c 20 Mar 2010 20:42:52 -0000 @@ -1 +1,66 @@ +typedef void (*ForkHandler)(void); +#include +#ifndef _WIN32 +#include +#include +#include +#endif + +#if !defined(_MSC_VER) && !defined(__cdecl) +#define __cdecl /* nothing */ +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* NOTE: Even userthreads now depends + * on availability of pthreads. + * This can be fixed if need be. + */ + +ptrdiff_t +__cdecl +RTProcess__RegisterForkHandlers( + ForkHandler prepare, + ForkHandler parent, + ForkHandler child) +{ +#ifdef _WIN32 + return 0; +#else + while (1) + { + int i = pthread_atfork(prepare, parent, child); + if (i != EAGAIN) + return i; + sleep(0); + } +#endif +} + +#ifndef _WIN32 + +ptrdiff_t +RTProcess__Fork(void) +{ + while (1) + { + int i = +#ifdef __sun + fork1() +#else + fork() +#endif + ;if (i != EAGAIN) + return i; + sleep(0); + } +} + +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif Index: m3-libs/m3core/src/runtime/common/m3makefile =================================================================== RCS file: /usr/cvs/cm3/m3-libs/m3core/src/runtime/common/m3makefile,v retrieving revision 1.27 diff -u -r1.27 m3makefile --- m3-libs/m3core/src/runtime/common/m3makefile 14 Dec 2009 08:09:48 -0000 1.27 +++ m3-libs/m3core/src/runtime/common/m3makefile 20 Mar 2010 20:42:52 -0000 @@ -45,6 +45,7 @@ Module ("RTParams") Module ("RTProcedure") Module ("RTProcess") +c_source ("RTProcessC") interface ("RTThread") Module ("RTTipe") Module ("RTType") Index: m3-libs/m3core/src/thread/POSIX/ThreadPosix.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-libs/m3core/src/thread/POSIX/ThreadPosix.m3,v retrieving revision 1.63 diff -u -r1.63 ThreadPosix.m3 --- m3-libs/m3core/src/thread/POSIX/ThreadPosix.m3 27 Nov 2009 21:13:15 -0000 1.63 +++ m3-libs/m3core/src/thread/POSIX/ThreadPosix.m3 20 Mar 2010 20:42:52 -0000 @@ -1311,6 +1311,10 @@ VAR xx: INTEGER; BEGIN inCritical := 1; + + xx := RTProcess.RegisterForkHandlers(AtForkPrepare, AtForkParent, AtForkChild); + <* ASSERT xx = 0 *> + self := NEW (T, state := State.alive, id := nextId, stackbase := ADR(xx), context := MakeContext(NIL, 0)); @@ -1352,6 +1356,35 @@ RETURN ADR (xx); END QQ; +PROCEDURE AtForkAssert() = + BEGIN + <* ASSERT self.state = State.alive *> + <* ASSERT self.nextWaiting = NIL *> + <* ASSERT self.waitingForCondition = NIL *> + <* ASSERT self.waitingForMutex = NIL *> + END AtForkAssert; + +PROCEDURE AtForkPrepare() = + BEGIN + AtForkAssert(); + INC(inCritical); + END AtForkPrepare; + +PROCEDURE AtForkParent() = + BEGIN + AtForkAssert(); + DEC(inCritical); + END AtForkParent; + +PROCEDURE AtForkChild() = + BEGIN + AtForkAssert(); + pausedThreads := NIL; + self.next := self; + self.previous := self; + AtForkParent(); + END AtForkChild; + (*------------------------------------------------------------- collector ---*) (* These procedures provide synchronization primitives for the allocator and collector. *) Index: m3-libs/m3core/src/thread/PTHREAD/ThreadPThread.m3 =================================================================== RCS file: /usr/cvs/cm3/m3-libs/m3core/src/thread/PTHREAD/ThreadPThread.m3,v retrieving revision 1.233 diff -u -r1.233 ThreadPThread.m3 --- m3-libs/m3core/src/thread/PTHREAD/ThreadPThread.m3 18 Mar 2010 11:12:10 -0000 1.233 +++ m3-libs/m3core/src/thread/PTHREAD/ThreadPThread.m3 20 Mar 2010 20:42:52 -0000 @@ -7,7 +7,7 @@ IMPORT Cerrno, FloatMode, MutexRep, RTCollectorSRC, RTError, RTHeapRep, RTIO, RTParams, - RTPerfTool, RTProcess, ThreadEvent, Time, + RTPerfTool, RTProcess, Thread, ThreadEvent, Time, Unix, Utime, Word, Usched, Uerror, Uexec; FROM Compiler IMPORT ThisFile, ThisLine; @@ -1294,18 +1294,18 @@ (*-------------------------------------------------------- Initialization ---*) -PROCEDURE Init ()= +PROCEDURE InitWithStackBase (stackbase: ADDRESS) = VAR self: T; me: Activation; BEGIN - InitC(ADR(self)); + InitC(stackbase); me := NEW(Activation, mutex := pthread_mutex_new(), cond := pthread_cond_new()); InitActivations(me); - me.stackbase := ADR(self); (* not quite accurate but hopefully ok *) + me.stackbase := stackbase; IF me.mutex = NIL OR me.cond = NIL THEN Die(ThisLine(), "Thread initialization failed."); END; @@ -1322,8 +1322,94 @@ IF RTParams.IsPresent("foregroundgc") THEN RTCollectorSRC.StartForegroundCollection(); END; + END InitWithStackBase; + +PROCEDURE Init ()= + VAR r: INTEGER; + BEGIN + r := RTProcess.RegisterForkHandlers(AtForkPrepare, AtForkParent, AtForkChild); + IF r # 0 THEN DieI(ThisLine(), r) END; + InitWithStackBase(ADR(r)); (* not quite accurate but hopefully ok *) END Init; +VAR locks := ARRAY [0..3] OF pthread_mutex_t{ + activeMu, slotsMu, initMu, perfMu}; + +PROCEDURE PThreadLockMutex(mutex: pthread_mutex_t; line: INTEGER) = + VAR r: INTEGER; + BEGIN + IF mutex # NIL THEN + r := pthread_mutex_lock(mutex); + IF r # 0 THEN DieI(line, r) END; + END; + END PThreadLockMutex; + +PROCEDURE PThreadUnlockMutex(mutex: pthread_mutex_t; line: INTEGER) = + VAR r: INTEGER; + BEGIN + IF mutex # NIL THEN + r := pthread_mutex_unlock(mutex); + IF r # 0 THEN DieI(line, r) END; + END; + END PThreadUnlockMutex; + +PROCEDURE AtForkPrepare() = + VAR me := GetActivation(); + act: Activation; + cond: Condition; + BEGIN + Thread.Acquire(joinMu); + LockHeap(); + FOR i := FIRST(locks) TO LAST(locks) DO + PThreadLockMutex(locks[i], ThisLine()); + END; + (* Walk activations and lock all threads, conditions. + * NOTE: We have initMu, activeMu, so slots + * won't change, conditions and mutexes + * won't be initialized on-demand. + *) + act := me; + REPEAT + PThreadLockMutex(act.mutex, ThisLine()); + PThreadLockMutex(act.waitingOn, ThisLine()); + cond := slots[act.slot].join; + IF cond # NIL THEN + PThreadLockMutex(cond.mutex, ThisLine()); + END; + act := act.next; + UNTIL act = me; + END AtForkPrepare; + +PROCEDURE AtForkParent() = + VAR me := GetActivation(); + act: Activation; + cond: Condition; + BEGIN + (* Walk activations and unlock all threads, conditions. *) + act := me; + REPEAT + PThreadUnlockMutex(act.mutex, ThisLine()); + PThreadUnlockMutex(act.waitingOn, ThisLine()); + cond := slots[act.slot].join; + IF cond # NIL THEN + PThreadUnlockMutex(cond.mutex, ThisLine()); + END; + act := act.next; + UNTIL act = me; + + FOR i := LAST(locks) TO FIRST(locks) BY -1 DO + PThreadUnlockMutex(locks[i], ThisLine()); + END; + UnlockHeap(); + Thread.Release(joinMu); + END AtForkParent; + +PROCEDURE AtForkChild() = + BEGIN + AtForkParent(); + InitWithStackBase(GetActivation().stackbase); + END AtForkChild; + (*------------------------------------------------------------- collector ---*) (* These procedures provide synchronization primitives for the allocator and collector. *) Index: m3-libs/m3core/src/thread/WIN32/ThreadWin32C.c =================================================================== RCS file: /usr/cvs/cm3/m3-libs/m3core/src/thread/WIN32/ThreadWin32C.c,v retrieving revision 1.64 diff -u -r1.64 ThreadWin32C.c --- m3-libs/m3core/src/thread/WIN32/ThreadWin32C.c 16 Jan 2010 12:44:56 -0000 1.64 +++ m3-libs/m3core/src/thread/WIN32/ThreadWin32C.c 20 Mar 2010 20:42:52 -0000 @@ -146,6 +146,15 @@ p(bottom, __getReg(?)); /* bsp? bspstore? try numbers until we find it? */ #endif } + +/*-------------------------------------------------------------------------*/ + +INTEGER +RTOS__PThreadAtFork(PThreadForkHandler prep, + PThreadForkHandler parent, + PThreadForkHandler child) +{ + return 0; } /*-------------------------------------------------------------------------*/