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
------------------------------------------------------------------------- */
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