diff options
Diffstat (limited to 'ghc/includes/SMP.h')
-rw-r--r-- | ghc/includes/SMP.h | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/ghc/includes/SMP.h b/ghc/includes/SMP.h new file mode 100644 index 0000000000..fa247988cf --- /dev/null +++ b/ghc/includes/SMP.h @@ -0,0 +1,91 @@ +/* ---------------------------------------------------------------------------- + * $Id: SMP.h,v 1.1 1999/11/02 15:05:52 simonmar Exp $ + * + * (c) The GHC Team, 1999 + * + * Macros for SMP support + * + * -------------------------------------------------------------------------- */ + +#ifndef SMP_H +#define SMP_H + +/* SMP is currently not compatible with the following options: + * + * INTERPRETER + * PROFILING + * TICKY_TICKY + * and unregisterised builds. + */ + +#if defined(SMP) + +#if defined(INTERPRETER) \ + || defined(PROFILING) \ + || defined(TICKY_TICKY) +#error Build options incompatible with SMP. +#endif + +/* + * CMPXCHG - this instruction is the standard "test & set". We use it + * for locking closures in the thunk and blackhole entry code. If the + * closure is already locked, or has an unexpected info pointer + * (because another thread is altering it in parallel), we just jump + * to the new entry point. + */ +#if defined(i386_TARGET_ARCH) && defined(TABLES_NEXT_TO_CODE) +#define CMPXCHG(p, cmp, new) \ + __asm__ __volatile__ ( \ + "lock ; cmpxchg %1, %0\n" \ + "\tje 1f\n" \ + "\tjmp *%%eax\n" \ + "\t1:\n" \ + : /* no outputs */ \ + : "m" (p), "r" (new), "r" (cmp) \ + ) + +/* + * XCHG - the atomic exchange instruction. Used for locking closures + * during updates (see LOCK_CLOSURE below) and the MVar primops. + */ +#define XCHG(reg, obj) \ + __asm__ __volatile__ ( \ + "xchgl %1,%0" \ + :"+r" (reg), "+m" (obj) \ + : /* no input-only operands */ \ + ) + +#else +#error SMP macros not defined for this architecture +#endif + +/* + * LOCK_CLOSURE locks the specified closure, busy waiting for any + * existing locks to be cleared. + */ +#define LOCK_CLOSURE(c) \ + ({ \ + const StgInfoTable *__info; \ + __info = &WHITEHOLE_info; \ + do { \ + XCHG(__info,((StgClosure *)(c))->header.info); \ + } while (__info == &WHITEHOLE_info); \ + __info; \ + }) + +#define LOCK_THUNK(__info) \ + CMPXCHG(R1.cl->header.info, __info, &WHITEHOLE_info); + +#define ACQUIRE_LOCK(mutex) pthread_mutex_lock(mutex); +#define RELEASE_LOCK(mutex) pthread_mutex_unlock(mutex); + +#else /* !SMP */ + +#define LOCK_CLOSURE(c) /* nothing */ +#define LOCK_THUNK(__info) /* nothing */ +#define ACQUIRE_LOCK(mutex) /* nothing */ +#define RELEASE_LOCK(mutex) /* nothing */ + +#endif /* SMP */ + +#endif /* SMP_H */ |