Commit 2d5e052d authored by Simon Marlow's avatar Simon Marlow

Second attempt to fix #1185 (forkProcess and -threaded)

Patch 1/2: second part of the patch is to libraries/base

This time without dynamic linker hacks, instead I've expanded the
existing rts/Globals.c to cache more CAFs, specifically those in
GHC.Conc.  We were already using this trick for signal handlers, I
should have realised before.

It's still quite unsavoury, but we can do away with rts/Globals.c in
the future when we switch to a dynamically-linked GHCi.
parent cd0e2c0c
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
#define RTS_GLOBALS_H #define RTS_GLOBALS_H
StgStablePtr getOrSetTypeableStore(StgStablePtr value); StgStablePtr getOrSetTypeableStore(StgStablePtr value);
StgStablePtr getOrSetSignalHandlerStore(StgStablePtr value); StgStablePtr getOrSetGHCConcSignalHandlerStore(StgStablePtr value);
StgStablePtr getOrSetGHCConcPendingEventsStore(StgStablePtr ptr);
StgStablePtr getOrSetGHCConcPendingDelaysStore(StgStablePtr ptr);
StgStablePtr getOrSetGHCConcIOManagerThreadStore(StgStablePtr ptr);
StgStablePtr getOrSetGHCConcProddingStore(StgStablePtr ptr);
#endif /* RTS_GLOBALS_H */ #endif /* RTS_GLOBALS_H */
...@@ -27,6 +27,7 @@ void sendIOManagerEvent (HsWord32 event); ...@@ -27,6 +27,7 @@ void sendIOManagerEvent (HsWord32 event);
#else #else
void setIOManagerPipe (int fd); void setIOManagerPipe (int fd);
void ioManagerSync (void);
#endif #endif
...@@ -35,8 +36,8 @@ void setIOManagerPipe (int fd); ...@@ -35,8 +36,8 @@ void setIOManagerPipe (int fd);
// Posix implementation in posix/Signals.c // Posix implementation in posix/Signals.c
// Win32 implementation in win32/ThrIOManager.c // Win32 implementation in win32/ThrIOManager.c
// //
#if defined(THREADED_RTS)
void ioManagerWakeup (void); void ioManagerWakeup (void);
#if defined(THREADED_RTS)
void ioManagerDie (void); void ioManagerDie (void);
void ioManagerStart (void); void ioManagerStart (void);
#endif #endif
......
...@@ -7,6 +7,9 @@ ...@@ -7,6 +7,9 @@
* even when multiple versions of the library are loaded. e.g. see * even when multiple versions of the library are loaded. e.g. see
* Data.Typeable and GHC.Conc. * Data.Typeable and GHC.Conc.
* *
* If/when we switch to a dynamically-linked GHCi, this can all go
* away, because there would be just one copy of each library.
*
* ---------------------------------------------------------------------------*/ * ---------------------------------------------------------------------------*/
#include "PosixSource.h" #include "PosixSource.h"
...@@ -15,18 +18,29 @@ ...@@ -15,18 +18,29 @@
#include "Globals.h" #include "Globals.h"
#include "Stable.h" #include "Stable.h"
static StgStablePtr typeableStore = 0; typedef enum {
static StgStablePtr signalHandlerStore = 0; TypeableStore,
GHCConcSignalHandlerStore,
GHCConcPendingEventsStore,
GHCConcPendingDelaysStore,
GHCConcIOManagerThreadStore,
GHCConcProddingStore,
MaxStoreKey
} StoreKey;
#ifdef THREADED_RTS #ifdef THREADED_RTS
Mutex globalStoreLock; Mutex globalStoreLock;
#endif #endif
StgStablePtr store[MaxStoreKey];
void void
initGlobalStore(void) initGlobalStore(void)
{ {
typeableStore = 0; nat i;
signalHandlerStore = 0; for (i=0; i < MaxStoreKey; i++) {
store[i] = 0;
}
#ifdef THREADED_RTS #ifdef THREADED_RTS
initMutex(&globalStoreLock); initMutex(&globalStoreLock);
#endif #endif
...@@ -35,30 +49,28 @@ initGlobalStore(void) ...@@ -35,30 +49,28 @@ initGlobalStore(void)
void void
exitGlobalStore(void) exitGlobalStore(void)
{ {
nat i;
#ifdef THREADED_RTS #ifdef THREADED_RTS
closeMutex(&globalStoreLock); closeMutex(&globalStoreLock);
#endif #endif
if(typeableStore!=0) { for (i=0; i < MaxStoreKey; i++) {
freeStablePtr((StgStablePtr)typeableStore); if (store[i] != 0) {
typeableStore=0; freeStablePtr(store[i]);
store[i] = 0;
} }
if(signalHandlerStore!=0) {
freeStablePtr((StgStablePtr)signalHandlerStore);
signalHandlerStore=0;
} }
} }
StgStablePtr static StgStablePtr getOrSetKey(StoreKey key, StgStablePtr ptr)
getOrSetTypeableStore(StgStablePtr ptr)
{ {
StgStablePtr ret = typeableStore; StgStablePtr ret = store[key];
if(ret==0) { if(ret==0) {
#ifdef THREADED_RTS #ifdef THREADED_RTS
ACQUIRE_LOCK(&globalStoreLock); ACQUIRE_LOCK(&globalStoreLock);
ret=typeableStore; ret = store[key];
if(ret==0) { if(ret==0) {
#endif #endif
typeableStore = ret = ptr; store[key] = ret = ptr;
#ifdef THREADED_RTS #ifdef THREADED_RTS
} }
RELEASE_LOCK(&globalStoreLock); RELEASE_LOCK(&globalStoreLock);
...@@ -67,21 +79,39 @@ getOrSetTypeableStore(StgStablePtr ptr) ...@@ -67,21 +79,39 @@ getOrSetTypeableStore(StgStablePtr ptr)
return ret; return ret;
} }
StgStablePtr StgStablePtr
getOrSetSignalHandlerStore(StgStablePtr ptr) getOrSetTypeableStore(StgStablePtr ptr)
{ {
StgStablePtr ret = signalHandlerStore; return getOrSetKey(TypeableStore,ptr);
if(ret==0) { }
#ifdef THREADED_RTS
ACQUIRE_LOCK(&globalStoreLock); StgStablePtr
ret=signalHandlerStore; getOrSetGHCConcSignalHandlerStore(StgStablePtr ptr)
if(ret==0) { {
#endif return getOrSetKey(GHCConcSignalHandlerStore,ptr);
signalHandlerStore = ret = ptr; }
#ifdef THREADED_RTS
} StgStablePtr
RELEASE_LOCK(&globalStoreLock); getOrSetGHCConcPendingEventsStore(StgStablePtr ptr)
#endif {
} return getOrSetKey(GHCConcPendingEventsStore,ptr);
return ret; }
StgStablePtr
getOrSetGHCConcPendingDelaysStore(StgStablePtr ptr)
{
return getOrSetKey(GHCConcPendingDelaysStore,ptr);
}
StgStablePtr
getOrSetGHCConcIOManagerThreadStore(StgStablePtr ptr)
{
return getOrSetKey(GHCConcIOManagerThreadStore,ptr);
}
StgStablePtr
getOrSetGHCConcProddingStore(StgStablePtr ptr)
{
return getOrSetKey(GHCConcProddingStore,ptr);
} }
...@@ -505,10 +505,13 @@ typedef struct _RtsSymbolVal { ...@@ -505,10 +505,13 @@ typedef struct _RtsSymbolVal {
#if !defined(mingw32_HOST_OS) #if !defined(mingw32_HOST_OS)
#define RTS_USER_SIGNALS_SYMBOLS \ #define RTS_USER_SIGNALS_SYMBOLS \
SymI_HasProto(setIOManagerPipe) \ SymI_HasProto(setIOManagerPipe) \
SymI_HasProto(ioManagerWakeup) \
SymI_HasProto(ioManagerSync) \
SymI_HasProto(blockUserSignals) \ SymI_HasProto(blockUserSignals) \
SymI_HasProto(unblockUserSignals) SymI_HasProto(unblockUserSignals)
#else #else
#define RTS_USER_SIGNALS_SYMBOLS \ #define RTS_USER_SIGNALS_SYMBOLS \
SymI_HasProto(ioManagerWakeup) \
SymI_HasProto(sendIOManagerEvent) \ SymI_HasProto(sendIOManagerEvent) \
SymI_HasProto(readIOManagerEvent) \ SymI_HasProto(readIOManagerEvent) \
SymI_HasProto(getIOManagerEvent) \ SymI_HasProto(getIOManagerEvent) \
...@@ -736,7 +739,11 @@ typedef struct _RtsSymbolVal { ...@@ -736,7 +739,11 @@ typedef struct _RtsSymbolVal {
SymI_HasProto(forkOS_createThread) \ SymI_HasProto(forkOS_createThread) \
SymI_HasProto(freeHaskellFunctionPtr) \ SymI_HasProto(freeHaskellFunctionPtr) \
SymI_HasProto(getOrSetTypeableStore) \ SymI_HasProto(getOrSetTypeableStore) \
SymI_HasProto(getOrSetSignalHandlerStore) \ SymI_HasProto(getOrSetGHCConcSignalHandlerStore) \
SymI_HasProto(getOrSetGHCConcPendingEventsStore) \
SymI_HasProto(getOrSetGHCConcPendingDelaysStore) \
SymI_HasProto(getOrSetGHCConcIOManagerThreadStore) \
SymI_HasProto(getOrSetGHCConcProddingStore) \
SymI_HasProto(genSymZh) \ SymI_HasProto(genSymZh) \
SymI_HasProto(genericRaise) \ SymI_HasProto(genericRaise) \
SymI_HasProto(getProgArgv) \ SymI_HasProto(getProgArgv) \
......
...@@ -86,18 +86,16 @@ static int io_manager_pipe = -1; ...@@ -86,18 +86,16 @@ static int io_manager_pipe = -1;
#define IO_MANAGER_WAKEUP 0xff #define IO_MANAGER_WAKEUP 0xff
#define IO_MANAGER_DIE 0xfe #define IO_MANAGER_DIE 0xfe
#define IO_MANAGER_SYNC 0xfd
void void
setIOManagerPipe (int fd) setIOManagerPipe (int fd)
{ {
// only called when THREADED_RTS, but unconditionally // only called when THREADED_RTS, but unconditionally
// compiled here because GHC.Conc depends on it. // compiled here because GHC.Conc depends on it.
if (io_manager_pipe < 0) {
io_manager_pipe = fd; io_manager_pipe = fd;
}
} }
#if defined(THREADED_RTS)
void void
ioManagerWakeup (void) ioManagerWakeup (void)
{ {
...@@ -110,6 +108,19 @@ ioManagerWakeup (void) ...@@ -110,6 +108,19 @@ ioManagerWakeup (void)
} }
} }
void
ioManagerSync (void)
{
int r;
// Wake up the IO Manager thread by sending a byte down its pipe
if (io_manager_pipe >= 0) {
StgWord8 byte = (StgWord8)IO_MANAGER_SYNC;
r = write(io_manager_pipe, &byte, 1);
if (r == -1) { sysErrorBelch("ioManagerSync: write"); }
}
}
#if defined(THREADED_RTS)
void void
ioManagerDie (void) ioManagerDie (void)
{ {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment