X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=rts%2Fsm%2FGCThread.h;h=1b5c5d429182f897d3db4249c4f5a68468b109e5;hb=66579ff945831c5fc9a17c58c722ff01f2268d76;hp=ba12615a3df023807ac6a69aff33126ea1eb973e;hpb=f86e7206ea94b48b94fb61007a1c5d55b8c60f45;p=ghc-hetmet.git diff --git a/rts/sm/GCThread.h b/rts/sm/GCThread.h index ba12615..1b5c5d4 100644 --- a/rts/sm/GCThread.h +++ b/rts/sm/GCThread.h @@ -1,6 +1,6 @@ /* ----------------------------------------------------------------------------- * - * (c) The GHC Team 1998-2006 + * (c) The GHC Team 1998-2008 * * Generational garbage collector * @@ -95,13 +95,17 @@ typedef struct step_workspace_ { bdescr * part_list; unsigned int n_part_blocks; // count of above -} step_workspace; + StgWord pad[5]; + +} step_workspace ATTRIBUTE_ALIGNED(64); +// align so that computing gct->steps[n] is a shift, not a multiply +// fails if the size is <64, which is why we need the pad above /* ---------------------------------------------------------------------------- GC thread object Every GC thread has one of these. It contains all the step specific - workspaces and other GC thread loacl information. At some later + workspaces and other GC thread local information. At some later point it maybe useful to move this other into the TLS store of the GC threads ------------------------------------------------------------------------- */ @@ -177,8 +181,43 @@ typedef struct gc_thread_ { extern nat n_gc_threads; extern gc_thread **gc_threads; -register gc_thread *gct __asm__("%rbx"); -// extern gc_thread *gct; // this thread's gct TODO: make thread-local + +/* ----------------------------------------------------------------------------- + The gct variable is thread-local and points to the current thread's + gc_thread structure. It is heavily accessed, so we try to put gct + into a global register variable if possible; if we don't have a + register then use gcc's __thread extension to create a thread-local + variable. + + Even on x86 where registers are scarce, it is worthwhile using a + register variable here: I measured about a 2-5% slowdown with the + __thread version. + -------------------------------------------------------------------------- */ + +#define GLOBAL_REG_DECL(type,name,reg) register type name REG(reg); + +#if defined(REG_Base) && !defined(i386_HOST_ARCH) +// on i386, REG_Base is %ebx which is also used for PIC, so we don't +// want to steal it + +GLOBAL_REG_DECL(gc_thread*, gct, REG_Base) +#define DECLARE_GCT /* nothing */ + +#elif defined(REG_R1) + +GLOBAL_REG_DECL(gc_thread*, gct, REG_R1) +#define DECLARE_GCT /* nothing */ + +#elif defined(__GNUC__) + +extern __thread gc_thread* gct; +#define DECLARE_GCT __thread gc_thread* gct; + +#else + +#error Cannot find a way to declare the thread-local gct + +#endif #endif // GCTHREAD_H