X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=includes%2FSMP.h;h=0e6322d40b29a779e7552219cf168a0caade0d5b;hb=ffa600f6702f215dd132b8b1b8a1f07d3a9e3ea6;hp=f574ec8100a97f9da7790b3d9425168b8fb6f8b4;hpb=16ed3e3cd3ba05ae7222f8da2c80f8294540817d;p=ghc-hetmet.git diff --git a/includes/SMP.h b/includes/SMP.h index f574ec8..0e6322d 100644 --- a/includes/SMP.h +++ b/includes/SMP.h @@ -1,8 +1,8 @@ /* ---------------------------------------------------------------------------- * - * (c) The GHC Team, 2005 + * (c) The GHC Team, 2005-2008 * - * Macros for THREADED_RTS support + * Macros for multi-CPU support * * -------------------------------------------------------------------------- */ @@ -175,132 +175,6 @@ write_barrier(void) { #endif } -/* ----------------------------------------------------------------------------- - * Locking/unlocking closures - * - * This is used primarily in the implementation of MVars. - * -------------------------------------------------------------------------- */ - -#define SPIN_COUNT 4000 - -#ifdef KEEP_LOCKCLOSURE -// We want a callable copy of lockClosure() so that we can refer to it -// from .cmm files compiled using the native codegen. -extern StgInfoTable *lockClosure(StgClosure *p); -INLINE_ME -#else -INLINE_HEADER -#endif -StgInfoTable * -lockClosure(StgClosure *p) -{ - StgWord info; - do { - nat i = 0; - do { - info = xchg((P_)(void *)&p->header.info, (W_)&stg_WHITEHOLE_info); - if (info != (W_)&stg_WHITEHOLE_info) return (StgInfoTable *)info; - } while (++i < SPIN_COUNT); - yieldThread(); - } while (1); -} - -INLINE_HEADER void -unlockClosure(StgClosure *p, StgInfoTable *info) -{ - // This is a strictly ordered write, so we need a write_barrier(): - write_barrier(); - p->header.info = info; -} - -/* ----------------------------------------------------------------------------- - * Spin locks - * - * These are simple spin-only locks as opposed to Mutexes which - * probably spin for a while before blocking in the kernel. We use - * these when we are sure that all our threads are actively running on - * a CPU, eg. in the GC. - * - * TODO: measure whether we really need these, or whether Mutexes - * would do (and be a bit safer if a CPU becomes loaded). - * -------------------------------------------------------------------------- */ - -#if defined(DEBUG) -typedef struct StgSync_ -{ - StgWord32 lock; - StgWord64 spin; // DEBUG version counts how much it spins -} StgSync; -#else -typedef StgWord StgSync; -#endif - -typedef lnat StgSyncCount; - - -#if defined(DEBUG) - -// Debug versions of spin locks maintain a spin count - -// How to use: -// To use the debug veriosn of the spin locks, a debug version of the program -// can be run under a deugger with a break point on stat_exit. At exit time -// of the program one can examine the state the spin count counts of various -// spin locks to check for contention. - -// acquire spin lock -INLINE_HEADER void ACQUIRE_SPIN_LOCK(StgSync * p) -{ - StgWord32 r = 0; - do { - p->spin++; - r = cas((StgVolatilePtr)&(p->lock), 1, 0); - } while(r == 0); - p->spin--; -} - -// release spin lock -INLINE_HEADER void RELEASE_SPIN_LOCK(StgSync * p) -{ - write_barrier(); - p->lock = 1; -} - -// initialise spin lock -INLINE_HEADER void initSpinLock(StgSync * p) -{ - write_barrier(); - p->lock = 1; - p->spin = 0; -} - -#else - -// acquire spin lock -INLINE_HEADER void ACQUIRE_SPIN_LOCK(StgSync * p) -{ - StgWord32 r = 0; - do { - r = cas((StgVolatilePtr)p, 1, 0); - } while(r == 0); -} - -// release spin lock -INLINE_HEADER void RELEASE_SPIN_LOCK(StgSync * p) -{ - write_barrier(); - (*p) = 1; -} - -// init spin lock -INLINE_HEADER void initSpinLock(StgSync * p) -{ - write_barrier(); - (*p) = 1; -} - -#endif /* DEBUG */ - /* ---------------------------------------------------------------------- */ #else /* !THREADED_RTS */ @@ -314,30 +188,8 @@ xchg(StgPtr p, StgWord w) return old; } -INLINE_HEADER StgInfoTable * -lockClosure(StgClosure *p) -{ return (StgInfoTable *)p->header.info; } - -INLINE_HEADER void -unlockClosure(StgClosure *p STG_UNUSED, StgInfoTable *info STG_UNUSED) -{ /* nothing */ } - -// Using macros here means we don't have to ensure the argument is in scope -#define ACQUIRE_SPIN_LOCK(p) /* nothing */ -#define RELEASE_SPIN_LOCK(p) /* nothing */ - -INLINE_HEADER void initSpinLock(void * p STG_UNUSED) -{ /* nothing */ } - #endif /* !THREADED_RTS */ -// Handy specialised versions of lockClosure()/unlockClosure() -INLINE_HEADER void lockTSO(StgTSO *tso) -{ lockClosure((StgClosure *)tso); } - -INLINE_HEADER void unlockTSO(StgTSO *tso) -{ unlockClosure((StgClosure*)tso, (StgInfoTable*)&stg_TSO_info); } +#endif /* CMINUSMINUS */ #endif /* SMP_H */ - -#endif /* CMINUSMINUS */