*
* ---------------------------------------------------------------------------*/
+#include <unistd.h>
+
#include "Rts.h"
#include "RtsFlags.h"
#include "Storage.h"
while (1) {
- ACQUIRE_SPIN_LOCK(&static_objects_sync);
-
/* get the next static object from the list. Remember, there might
* be more stuff on this list after each evacuation...
* (static_objects is a global)
*/
- p = static_objects;
+ p = gct->static_objects;
if (p == END_OF_STATIC_LIST) {
- RELEASE_SPIN_LOCK(&static_objects_sync);
break;
}
/* Take this object *off* the static_objects list,
* and put it on the scavenged_static_objects list.
*/
- static_objects = *STATIC_LINK(info,p);
- *STATIC_LINK(info,p) = scavenged_static_objects;
- scavenged_static_objects = p;
-
- RELEASE_SPIN_LOCK(&static_objects_sync);
+ gct->static_objects = *STATIC_LINK(info,p);
+ *STATIC_LINK(info,p) = gct->scavenged_static_objects;
+ gct->scavenged_static_objects = p;
switch (info -> type) {
scavenge_find_global_work (void)
{
bdescr *bd;
- int g, s;
+ int s;
rtsBool flag;
step_workspace *ws;
+ gct->scav_global_work++;
+
flag = rtsFalse;
- for (g = RtsFlags.GcFlags.generations-1; g >= 0; g--) {
- for (s = generations[g].n_steps-1; s >= 0; s--) {
- if (g == 0 && s == 0 && RtsFlags.GcFlags.generations > 1) {
- continue;
- }
- ws = &gct->steps[g][s];
+ for (s = total_steps-1; s>=0; s--)
+ {
+ if (s == 0 && RtsFlags.GcFlags.generations > 1) {
+ continue;
+ }
+ ws = &gct->steps[s];
- // If we have any large objects to scavenge, do them now.
- if (ws->todo_large_objects) {
- scavenge_large(ws);
- flag = rtsTrue;
- }
+ // If we have any large objects to scavenge, do them now.
+ if (ws->todo_large_objects) {
+ scavenge_large(ws);
+ flag = rtsTrue;
+ }
- if ((bd = grab_todo_block(ws)) != NULL) {
- // no need to assign this to ws->scan_bd, we're going
- // to scavenge the whole thing and then push it on
- // our scavd list. This saves pushing out the
- // scan_bd block, which might be partial.
- if (N == 0) {
- scavenge_block0(bd, bd->start);
- } else {
- scavenge_block(bd, bd->start);
- }
- push_scan_block(bd, ws);
- return rtsTrue;
- }
+ if ((bd = grab_todo_block(ws)) != NULL) {
+ // no need to assign this to ws->scan_bd, we're going
+ // to scavenge the whole thing and then push it on
+ // our scavd list. This saves pushing out the
+ // scan_bd block, which might be partial.
+ if (N == 0) {
+ scavenge_block0(bd, bd->start);
+ } else {
+ scavenge_block(bd, bd->start);
+ }
+ push_scan_block(bd, ws);
+ return rtsTrue;
+ }
- if (flag) return rtsTrue;
- }
+ if (flag) return rtsTrue;
}
return rtsFalse;
}
static rtsBool
scavenge_find_local_work (void)
{
- int g, s;
+ int s;
step_workspace *ws;
rtsBool flag;
+ gct->scav_local_work++;
+
flag = rtsFalse;
- for (g = RtsFlags.GcFlags.generations; --g >= 0; ) {
- for (s = generations[g].n_steps; --s >= 0; ) {
- if (g == 0 && s == 0 && RtsFlags.GcFlags.generations > 1) {
- continue;
- }
- ws = &gct->steps[g][s];
+ for (s = total_steps-1; s >= 0; s--) {
+ if (s == 0 && RtsFlags.GcFlags.generations > 1) {
+ continue;
+ }
+ ws = &gct->steps[s];
- if (ws->todo_bd != NULL)
- {
- ws->todo_bd->free = ws->todo_free;
+ if (ws->todo_bd != NULL)
+ {
+ ws->todo_bd->free = ws->todo_free;
+ }
+
+ // If we have a todo block and no scan block, start
+ // scanning the todo block.
+ if (ws->scan_bd == NULL && ws->todo_bd != NULL)
+ {
+ ws->scan_bd = ws->todo_bd;
+ ws->scan = ws->scan_bd->start;
+ }
+
+ // If we have a scan block with some work to do,
+ // scavenge everything up to the free pointer.
+ if (ws->scan != NULL && ws->scan < ws->scan_bd->free)
+ {
+ if (N == 0) {
+ scavenge_block0(ws->scan_bd, ws->scan);
+ } else {
+ scavenge_block(ws->scan_bd, ws->scan);
}
-
- // If we have a todo block and no scan block, start
- // scanning the todo block.
- if (ws->scan_bd == NULL && ws->todo_bd != NULL)
- {
- ws->scan_bd = ws->todo_bd;
- ws->scan = ws->scan_bd->start;
- }
-
- // If we have a scan block with some work to do,
- // scavenge everything up to the free pointer.
- if (ws->scan != NULL && ws->scan < ws->scan_bd->free)
- {
- if (N == 0) {
- scavenge_block0(ws->scan_bd, ws->scan);
- } else {
- scavenge_block(ws->scan_bd, ws->scan);
- }
- ws->scan = ws->scan_bd->free;
- flag = rtsTrue;
- }
-
- if (ws->scan_bd != NULL && ws->scan == ws->scan_bd->free
- && ws->scan_bd != ws->todo_bd)
- {
- // we're not going to evac any more objects into
- // this block, so push it now.
- push_scan_block(ws->scan_bd, ws);
- ws->scan_bd = NULL;
- ws->scan = NULL;
- // we might be able to scan the todo block now. But
- // don't do it right away: there might be full blocks
- // waiting to be scanned as a result of scavenge_block above.
- flag = rtsTrue;
- }
-
- if (flag) return rtsTrue;
- }
+ ws->scan = ws->scan_bd->free;
+ flag = rtsTrue;
+ }
+
+ if (ws->scan_bd != NULL && ws->scan == ws->scan_bd->free
+ && ws->scan_bd != ws->todo_bd)
+ {
+ // we're not going to evac any more objects into
+ // this block, so push it now.
+ push_scan_block(ws->scan_bd, ws);
+ ws->scan_bd = NULL;
+ ws->scan = NULL;
+ // we might be able to scan the todo block now. But
+ // don't do it right away: there might be full blocks
+ // waiting to be scanned as a result of scavenge_block above.
+ flag = rtsTrue;
+ }
+
+ if (flag) return rtsTrue;
}
return rtsFalse;
}
work_to_do = rtsFalse;
// scavenge static objects
- if (major_gc && static_objects != END_OF_STATIC_LIST) {
- IF_DEBUG(sanity, checkStaticObjects(static_objects));
+ if (major_gc && gct->static_objects != END_OF_STATIC_LIST) {
+ IF_DEBUG(sanity, checkStaticObjects(gct->static_objects));
scavenge_static();
}
rtsBool
any_work (void)
{
- int g, s;
+ int s;
step_workspace *ws;
+ gct->any_work++;
+
write_barrier();
- // scavenge static objects
- if (major_gc && static_objects != END_OF_STATIC_LIST) {
- return rtsTrue;
- }
-
// scavenge objects in compacted generation
if (mark_stack_overflowed || oldgen_scan_bd != NULL ||
(mark_stack_bdescr != NULL && !mark_stack_empty())) {
// Check for global work in any step. We don't need to check for
// local work, because we have already exited scavenge_loop(),
// which means there is no local work for this thread.
- for (g = RtsFlags.GcFlags.generations-1; g >= 0; g--) {
- for (s = generations[g].n_steps-1; s >= 0; s--) {
- if (g == 0 && s == 0 && RtsFlags.GcFlags.generations > 1) {
- continue;
- }
- ws = &gct->steps[g][s];
- if (ws->todo_large_objects) return rtsTrue;
- if (ws->stp->todos) return rtsTrue;
- }
+ for (s = total_steps-1; s >= 0; s--) {
+ if (s == 0 && RtsFlags.GcFlags.generations > 1) {
+ continue;
+ }
+ ws = &gct->steps[s];
+ if (ws->todo_large_objects) return rtsTrue;
+ if (ws->stp->todos) return rtsTrue;
}
+ gct->no_work++;
+ usleep(1);
+
return rtsFalse;
}