1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
|
#include "Rts.h"
#include "StablePtr.h"
#include "TopHandler.h"
#if defined(THREADED_RTS)
static Mutex m; // Protects the operations on topHandlerPtr,
// which aren't atomic
#endif
static StgStablePtr topHandlerPtr;
void rts_setMainThread(StgWeak *weak) {
ACQUIRE_LOCK(&m);
if (topHandlerPtr != NULL) {
freeStablePtr(topHandlerPtr); // OK to do under the lock
}
topHandlerPtr = getStablePtr((StgPtr)weak);
// referent is a Weak#
ASSERT(weak->header.info == &stg_WEAK_info);
// See Note [rts_setMainThread has an unsound type] in
// libraries/base/GHC/TopHandler.hs.
ASSERT(weak->key->header.info == &stg_TSO_info);
RELEASE_LOCK(&m);
}
StgTSO *getTopHandlerThread(void) {
ACQUIRE_LOCK(&m);
StgWeak *weak = (StgWeak*)deRefStablePtr(topHandlerPtr);
RELEASE_LOCK(&m);
if (weak == NULL) {
// topHandlerPtr was never initialised
return NULL;
}
const StgInfoTable *info = ACQUIRE_LOAD(&weak->header.info);
if (info == &stg_WEAK_info) {
StgClosure *key = ((StgWeak*)weak)->key;
// See Note [rts_setMainThread has an unsound type] in
// libraries/base/GHC/TopHandler.hs.
ASSERT(key->header.info == &stg_TSO_info);
return (StgTSO *)key;
} else if (info == &stg_DEAD_WEAK_info) {
return NULL;
} else {
barf("getTopHandlerThread: neither a WEAK nor a DEAD_WEAK: %p %p %d",
weak, info, info->type);
return NULL;
}
}
void initTopHandler(void) {
#if defined(THREADED_RTS)
initMutex(&m);
#endif
topHandlerPtr = NULL;
}
void exitTopHandler(void) {
freeStablePtr(topHandlerPtr);
topHandlerPtr = NULL;
#if defined(THREADED_RTS)
closeMutex(&m);
#endif
}
|