typedef struct step_workspace_ {
step * step; // the step for this workspace
- struct gc_thread_ * gct; // the gc_thread that contains this workspace
+ struct gc_thread_ * my_gct; // the gc_thread that contains this workspace
// where objects to be scavenged go
bdescr * todo_bd;
extern nat n_gc_threads;
-extern gc_thread **gc_threads;
-
/* -----------------------------------------------------------------------------
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
__thread version.
-------------------------------------------------------------------------- */
+extern gc_thread **gc_threads;
+
+#if defined(THREADED_RTS)
+
#define GLOBAL_REG_DECL(type,name,reg) register type name REG(reg);
-#if defined(sparc_HOST_ARCH)
+#define SET_GCT(to) gct = (to)
+
+#if defined(sparc_HOST_ARCH) || (defined(i386_HOST_ARCH) && defined(linux_HOST_OS))
// Don't use REG_base or R1 for gct on SPARC because they're getting clobbered
// by something else. Not sure what yet. -- BL 2009/01/03
+// Using __thread is better than stealing a register on x86/Linux, because
+// we have too few registers available. In my tests it was worth
+// about 5% in GC performance, but of course that might change as gcc
+// improves. -- SDM 2009/04/03
+
extern __thread gc_thread* gct;
#define DECLARE_GCT __thread gc_thread* gct;
#endif
+#else // not the threaded RTS
+
+extern StgWord8 the_gc_thread[];
+
+#define gct ((gc_thread*)&the_gc_thread)
+#define SET_GCT(to) /*nothing*/
+#define DECLARE_GCT /*nothing*/
+
+#endif
+
#endif // GCTHREAD_H