------------------------------------------------------------------------- */
typedef struct step_workspace_ {
- step * stp; // the step for this workspace
+ step * step; // the step for this workspace
struct gc_thread_ * gct; // the gc_thread that contains this workspace
- // block that is currently being scanned
- bdescr * scan_bd;
- StgPtr scan; // the scan pointer
-
// where objects to be scavenged go
bdescr * todo_bd;
+ StgPtr todo_free; // free ptr for todo_bd
+ StgPtr todo_lim; // lim for todo_bd
+
bdescr * buffer_todo_bd; // buffer to reduce contention
// on the step's todos list
// where large objects to be scavenged go
bdescr * todo_large_objects;
- // Objects that need not be, or have already been, scavenged. The
- // block at the front of the list is special: objects that don't
- // need to be scavenged are copied directly to this block.
- // Completed scan blocks also go on this list; but we put them
- // after the head block.
+ // Objects that have already been, scavenged.
bdescr * scavd_list;
- lnat n_scavd_blocks; // count of blocks in this list
+ nat n_scavd_blocks; // count of blocks in this list
+
+ // Partially-full, scavenged, blocks
+ bdescr * part_list;
+ unsigned int n_part_blocks; // count of above
} step_workspace;
typedef struct gc_thread_ {
#ifdef THREADED_RTS
OSThreadId id; // The OS thread that this struct belongs to
+ Mutex wake_mutex;
+ Condition wake_cond; // So we can go to sleep between GCs
+ rtsBool wakeup;
+ rtsBool exit;
#endif
nat thread_index; // a zero based index identifying the thread
- step_workspace ** steps; // 2-d array (gen,step) of workspaces
-
bdescr * free_blocks; // a buffer of free blocks for this thread
// during GC without accessing the block
// allocators spin lock.
- lnat gc_count; // number of gc's this thread has done
+ StgClosure* static_objects; // live static objects
+ StgClosure* scavenged_static_objects; // static objects scavenged so far
+
+ lnat gc_count; // number of GCs this thread has done
+
+ // block that is currently being scanned
+ bdescr * scan_bd;
// --------------------
// evacuate flags
- nat evac_gen; // Youngest generation that objects
+ step *evac_step; // Youngest generation that objects
// should be evacuated to in
// evacuate(). (Logically an
// argument to evacuate, but it's
// optimise it into a per-thread
// variable).
- rtsBool failed_to_evac; // failue to evacuate an object typically
- // causes it to be recorded in the mutable
- // object list
+ rtsBool failed_to_evac; // failure to evacuate an object typically
+ // Causes it to be recorded in the mutable
+ // object list
rtsBool eager_promotion; // forces promotion to the evac gen
// instead of the to-space
lnat thunk_selector_depth; // ummm.... not used as of now
+#ifdef USE_PAPI
+ int papi_events;
+#endif
+
+ // -------------------
+ // stats
+
+ lnat copied;
+ lnat scanned;
+ lnat any_work;
+ lnat no_work;
+ lnat scav_find_work;
+
+ // -------------------
+ // workspaces
+
+ // array of workspaces, indexed by stp->abs_no. This is placed
+ // directly at the end of the gc_thread structure so that we can get from
+ // the gc_thread pointer to a workspace using only pointer
+ // arithmetic, no memory access. This happens in the inner loop
+ // of the GC, see Evac.c:alloc_for_copy().
+ step_workspace steps[];
} gc_thread;
extern nat N;
extern rtsBool major_gc;
+extern nat n_gc_threads;
-extern gc_thread *gc_threads;
-extern gc_thread *gct; // this thread's gct TODO: make thread-local
-
-extern StgClosure* static_objects;
-extern StgClosure* scavenged_static_objects;
+extern gc_thread **gc_threads;
+register gc_thread *gct __asm__("%rbx");
+// extern gc_thread *gct; // this thread's gct TODO: make thread-local
extern bdescr *mark_stack_bdescr;
extern StgPtr *mark_stack;
extern StgPtr oldgen_scan;
extern long copied;
-extern long scavd_copied;
#ifdef DEBUG
extern nat mutlist_MUTVARS, mutlist_MUTARRS, mutlist_MVARS, mutlist_OTHERS;
StgClosure * isAlive(StgClosure *p);
+#define WORK_UNIT_WORDS 128
+
#endif /* GC_H */