#include "RetainerProfile.h"
#include "RaiseAsync.h"
#include "Sparks.h"
+#include "Papi.h"
#include "GC.h"
#include "Compact.h"
gc_thread *gc_threads = NULL;
// gc_thread *gct = NULL; // this thread's gct TODO: make thread-local
+// Number of threads running in *this* GC. Affects how many
+// step->todos[] lists we have to look in to find work.
+nat n_gc_threads;
+
// For stats:
long copied; // *words* copied & scavenged during this GC
step *stp;
lnat live, allocated;
lnat oldgen_saved_blocks = 0;
- nat n_threads; // number of threads participating in GC
gc_thread *saved_gct;
nat g, s, t;
*/
#if defined(THREADED_RTS)
if (N == 0) {
- n_threads = 1;
+ n_gc_threads = 1;
} else {
- n_threads = RtsFlags.ParFlags.gcThreads;
+ n_gc_threads = RtsFlags.ParFlags.gcThreads;
}
#else
- n_threads = 1;
+ n_gc_threads = 1;
#endif
#ifdef RTS_GTK_FRONTPANEL
// Initialise all the generations/steps that we're collecting.
for (g = 0; g <= N; g++) {
- init_collected_gen(g,n_threads);
+ init_collected_gen(g,n_gc_threads);
}
// Initialise all the generations/steps that we're *not* collecting.
for (g = N+1; g < RtsFlags.GcFlags.generations; g++) {
- init_uncollected_gen(g,n_threads);
+ init_uncollected_gen(g,n_gc_threads);
}
/* Allocate a mark stack if we're doing a major collection.
}
// Initialise all our gc_thread structures
- for (t = 0; t < n_threads; t++) {
+ for (t = 0; t < n_gc_threads; t++) {
init_gc_thread(&gc_threads[t]);
}
// the main thread is running: this prevents any other threads from
// exiting prematurely, so we can start them now.
inc_running();
- wakeup_gc_threads(n_threads);
+ wakeup_gc_threads(n_gc_threads);
// Initialise stats
copied = 0;
step_workspace *ws;
bdescr *prev;
- for (t = 0; t < n_threads; t++) {
+ for (t = 0; t < n_gc_threads; t++) {
thr = &gc_threads[t];
for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
init_gc_thread(t);
+#ifdef USE_PAPI
+ t->papi_events = -1;
+#endif
+
t->steps = stgMallocBytes(RtsFlags.GcFlags.generations *
sizeof(step_workspace *),
"initialise_gc_thread");
gct->wakeup = rtsFalse;
if (gct->exit) break;
+#ifdef USE_PAPI
+ // start performance counters in this thread...
+ if (gct->papi_events == -1) {
+ papi_init_eventset(&gct->papi_events);
+ }
+ papi_thread_start_gc_count(gct->papi_events);
+#endif
+
gc_thread_work();
+
+#ifdef USE_PAPI
+ // count events in this thread towards the GC totals
+ papi_thread_stop_gc_count(gct->papi_events);
+#endif
}
}
#endif