/* ---------------------------------------------------------------------------
- Time-stamp: <Mon Mar 27 2000 17:10:57 Stardate: [-30]4568.37 hwloidl>
- $Id: Global.c,v 1.3 2000/03/31 03:09:37 hwloidl Exp $
+ Time-stamp: <Wed Mar 21 2001 16:32:23 Stardate: [-30]6363.44 hwloidl>
(c) The AQUA/Parade Projects, Glasgow University, 1995
The GdH/APART 624 Projects, Heriot-Watt University, Edinburgh, 1999
//* GC functions for GALA tables::
//* Index::
//@end menu
+//*/
//@node Includes, Global tables and lists, Global Address Manipulation, Global Address Manipulation
//@subsection Includes
#include "RtsUtils.h"
#include "Storage.h"
#include "Hash.h"
+#include "HLC.h"
#include "ParallelRts.h"
+#if defined(DEBUG)
+# include "Sanity.h"
+#include "ParallelDebug.h"
+#endif
#if defined(DIST)
-#include "Dist.h"
+# include "Dist.h"
#endif
/*
if ((gl = freeGALAList) != NULL) {
IF_DEBUG(sanity,
ASSERT(gl->ga.weight==0xdead0add);
- ASSERT(gl->la==0xdead00aa));
+ ASSERT(gl->la==(StgPtr)0xdead00aa));
freeGALAList = gl->next;
} else {
gl = (GALA *) stgMallocBytes(GCHUNK * sizeof(GALA), "allocGALA");
p->next = p + 1;
IF_DEBUG(sanity,
p->ga.weight=0xdead0add;
- p->la=0xdead00aa);
+ p->la=(StgPtr)0xdead00aa);
}
/* last elem in the new block has NULL pointer in link field */
p->next = NULL;
IF_DEBUG(sanity,
p->ga.weight=0xdead0add;
- p->la=0xdead00aa);
+ p->la=(StgPtr)0xdead00aa);
}
IF_DEBUG(sanity,
gl->ga.weight=0xdead0add;
- gl->la=0xdead00aa);
+ gl->la=(StgPtr)0xdead00aa);
return gl;
}
PEs
taskIDtoPE(GlobalTaskId gtid)
{
- return (PEs) lookupHashTable(taskIDtoPEtable, gtid);
+ return ((PEs) lookupHashTable(taskIDtoPEtable, gtid));
}
//@cindex registerTask
void
-registerTask(gtid)
-GlobalTaskId gtid;
-{
+registerTask(GlobalTaskId gtid) {
+ nextPE++; //start counting from 1
if (gtid == mytid)
thisPE = nextPE;
- insertHashTable(taskIDtoPEtable, gtid, (void *) (StgWord) nextPE++);
+ insertHashTable(taskIDtoPEtable, gtid, (void *) (StgWord) nextPE);
}
//@node Interface to LAGA table, Interface to GALA table, Interface to taskId-PE table, Global Address Manipulation
gala = (GALA *) lookupHashTable(pGAtoGALAtable, pga);
ASSERT(gala!=NULL);
ASSERT(gala->preferred==rtsTrue);
- gala->preferred==rtsFalse;
+ gala->preferred = rtsFalse;
}
/*
if ((gala = freeIndirections) != NULL) {
IF_DEBUG(sanity,
ASSERT(gala->ga.weight==0xdead0add);
- ASSERT(gala->la==0xdead00aa));
+ ASSERT(gala->la==(StgPtr)0xdead00aa));
freeIndirections = gala->next;
} else {
gala = allocGALA();
IF_DEBUG(sanity,
ASSERT(gala->ga.weight==0xdead0add);
- ASSERT(gala->la==0xdead00aa));
+ ASSERT(gala->la==(StgPtr)0xdead00aa));
gala->ga.payload.gc.gtid = mytid;
gala->ga.payload.gc.slot = nextIndirection++;
+ IF_DEBUG(sanity,
+ if (nextIndirection>=MAX_SLOTS)
+ barf("Cannot handle more than %d slots for GA in a sanity-checking setup (this is no error)"));
}
gala->ga.weight = MAX_GA_WEIGHT;
- gala->la = closure;
+ gala->la = (StgPtr)closure;
IF_DEBUG(sanity,
- gala->next=0xcccccccc);
+ gala->next=(struct gala *)0xcccccccc);
return gala;
}
/* check whether we already have a GA for this local closure */
GALA *oldGALA = lookupHashTable(LAtoGALAtable, (StgWord) closure);
/* create an entry in the LAGA table */
- GALA *newGALA = allocIndirection((StgPtr)closure);
+ GALA *newGALA = allocIndirection(closure);
StgWord pga = PackGA(thisPE, newGALA->ga.payload.gc.slot);
IF_DEBUG(sanity,
- ASSERT(newGALA->next==0xcccccccc););
+ ASSERT(newGALA->next==(struct gala *)0xcccccccc););
// ASSERT(HEAP_ALLOCED(closure)); // check that closure might point into the heap; might be static, though
ASSERT(GALAlookup(&(newGALA->ga)) == NULL);
- newGALA->la = closure;
+ /* global statistics gathering */
+ if (RtsFlags.ParFlags.ParStats.Global &&
+ RtsFlags.GcFlags.giveStats > NO_GC_STATS) {
+ globalParStats.local_alloc_GA++;
+ }
+
+ newGALA->la = (StgPtr)closure;
newGALA->preferred = preferred;
if (preferred) {
ASSERT(GALAlookup(remote_ga) == NULL);
newGALA->ga = *remote_ga;
- newGALA->la = local_closure;
+ newGALA->la = (StgPtr)local_closure;
newGALA->preferred = preferred;
if (preferred) {
addWeight(ga)
globalAddr *ga;
{
- StgWord pga = PackGA(taskIDtoPE(ga->payload.gc.gtid), ga->payload.gc.slot);
- GALA *gala = (GALA *) lookupHashTable(pGAtoGALAtable, pga);
+ StgWord pga;
+ GALA *gala;
+
+ ASSERT(LOOKS_LIKE_GA(ga));
+
+ pga = PackGA(taskIDtoPE(ga->payload.gc.gtid), ga->payload.gc.slot);
+ gala = (GALA *) lookupHashTable(pGAtoGALAtable, pga);
IF_PAR_DEBUG(weight,
fprintf(stderr, "@* Adding weight %x to ", ga->weight);
taskIDtoPEtable = allocHashTable();
LAtoGALAtable = allocHashTable();
pGAtoGALAtable = allocHashTable();
-#ifdef DIST
- stickyClosureTable = allocHashTable();
-#endif
}
//@cindex PackGA
void
markLocalGAs(rtsBool full)
{
- GALA *gala;
- GALA *next;
- GALA *prev = NULL;
+ GALA *gala, *next, *prev = NULL;
StgPtr old_la, new_la;
nat n=0, m=0; // debugging only
-
+ double start_time_GA; // stats only
+
IF_PAR_DEBUG(tables,
- belch("@@%%%% markLocalGAs: Marking LIVE INDIRECTIONS in GALA table starting with GALA at %p\n",
- liveIndirections);
+ belch("@@%%%% markLocalGAs (full=%d): Marking LIVE INDIRECTIONS in GALA table starting with GALA at %p\n",
+ full, liveIndirections);
printLAGAtable());
+ PAR_TICKY_MARK_LOCAL_GAS_START();
+
for (gala = liveIndirections, m=0; gala != NULL; gala = next, m++) {
IF_PAR_DEBUG(tables,
fputs("@@ ",stderr);
printGA(&(gala->ga));
fprintf(stderr, ";@ %d: LA: %p (%s) ",
- m, gala->la, info_type(gala->la)));
+ m, (void*)gala->la, info_type((StgClosure*)gala->la)));
next = gala->next;
old_la = gala->la;
ASSERT(gala->ga.payload.gc.gtid == mytid); /* it's supposed to be local */
/* Remote references exist, so we must evacuate the local closure */
if (get_itbl((StgClosure *)old_la)->type == EVACUATED) {
/* somebody else already evacuated this closure */
- new_la = ((StgEvacuated *)old_la)->evacuee;
+ new_la = (StgPtr)((StgEvacuated *)old_la)->evacuee;
IF_PAR_DEBUG(tables,
belch(" already evacuated to %p", new_la));
} else {
//ASSERT(HEAP_ALLOCED(foo));
n++;
- new_la = MarkRoot(foo); // or just evacuate(old_ga)
+ new_la = (StgPtr) MarkRoot(foo);
IF_PAR_DEBUG(tables,
belch(" evacuated %p to %p", foo, new_la));
- //ASSERT(Bdescr(new_la)->evacuated);
+ /* ToDo: is this the right assertion to check that new_la is in to-space?
+ ASSERT(!HEAP_ALLOCED(new_la) || Bdescr(new_la)->evacuated);
+ */
#else
new_la = MarkRoot(old_la); // or just evacuate(old_ga)
IF_PAR_DEBUG(tables,
gala->la = new_la;
/* remove old LA and replace with new LA */
- if (!full && gala->preferred && new_la != old_la) {
+ if (/* !full && */ gala->preferred && new_la != old_la) {
GALA *q;
ASSERT(lookupHashTable(LAtoGALAtable, (StgWord)old_la));
(void) removeHashTable(LAtoGALAtable, (StgWord) old_la, (void *) gala);
q->preferred = rtsFalse;
IF_PAR_DEBUG(tables,
fprintf(stderr, "@@## found hash entry for closure %p (%s): deprecated GA ",
- new_la, info_type(new_la));
+ new_la, info_type((StgClosure*)new_la));
printGA(&(q->ga));
fputc('\n', stderr));
}
gala->next = prev;
prev = gala;
+ } else if(LOOKS_LIKE_STATIC_CLOSURE(gala->la)) {
+ /* to handle the CAFs, is this all?*/
+ MarkRoot(gala->la);
+ IF_PAR_DEBUG(tables,
+ belch(" processed static closure"));
+ n++;
+ gala->next = prev;
+ prev = gala;
} else {
/* Since we have all of the weight, this GA is no longer needed */
StgWord pga = PackGA(thisPE, gala->ga.payload.gc.slot);
gala->next = freeIndirections;
freeIndirections = gala;
(void) removeHashTable(pGAtoGALAtable, pga, (void *) gala);
- if (!full && gala->preferred)
+ if (/* !full && */ gala->preferred)
(void) removeHashTable(LAtoGALAtable, (W_) gala->la, (void *) gala);
IF_DEBUG(sanity,
gala->ga.weight = 0xdead0add;
- gala->la = (StgClosure *) 0xdead00aa);
+ gala->la = (StgPtr) 0xdead00aa);
}
} /* for gala ... */
liveIndirections = prev; /* list has been reversed during the marking */
+
+ PAR_TICKY_MARK_LOCAL_GAS_END(n);
+
IF_PAR_DEBUG(tables,
belch("@@%%%% markLocalGAs: %d of %d GALAs marked on PE %x",
n, m, mytid));
void
rebuildGAtables(rtsBool full)
{
- GALA *gala;
- GALA *next;
- GALA *prev;
- StgClosure *closure, *last, *new_closure;
-
- prepareFreeMsgBuffers();
+ GALA *gala, *next, *prev;
+ StgClosure *closure;
+ nat n = 0, size_GA = 0; // stats only (no. of GAs, and their heap size in bytes)
IF_PAR_DEBUG(tables,
- belch("@@%%%% rebuildGAtables: rebuilding LIVE REMOTE GAs in GALA table starting with GALA at %p\n",
- liveRemoteGAs));
+ belch("@@%%%% rebuildGAtables (full=%d): rebuilding LIVE REMOTE GAs in GALA table starting with GALA at %p\n",
+ full, liveRemoteGAs));
+
+ PAR_TICKY_REBUILD_GA_TABLES_START();
+
+ prepareFreeMsgBuffers();
for (gala = liveRemoteGAs, prev = NULL; gala != NULL; gala = next) {
IF_PAR_DEBUG(tables,
closure = (StgClosure *) (gala->la);
IF_PAR_DEBUG(tables,
- fprintf(stderr, " %p (%s) ",
- (StgClosure *)closure, info_type(closure)));
+ fprintf(stderr, " %p (%s) ",
+ (StgClosure *)closure, info_type(closure)));
- if (!full && gala->preferred)
+ if (/* !full && */ gala->preferred)
(void) removeHashTable(LAtoGALAtable, (StgWord) gala->la, (void *) gala);
/* Follow indirection chains to the end, just in case */
This approach also drops global aliases for PLCs.
*/
+ //ASSERT(!HEAP_ALLOCED(closure) || !(Bdescr((StgPtr)closure)->evacuated));
if (get_itbl(closure)->type == EVACUATED) {
closure = ((StgEvacuated *)closure)->evacuee;
IF_PAR_DEBUG(tables,
StgWord pga = PackGA(pe, gala->ga.payload.gc.slot);
/* check that the block containing this closure is not in to-space */
- //ASSERT(Bdescr(closure)->evacuated==0);
IF_PAR_DEBUG(tables,
fprintf(stderr, " !EVAC %p (%s); sending free to PE %d\n",
closure, info_type(closure), pe));
(void) removeHashTable(pGAtoGALAtable, pga, (void *) gala);
- freeRemoteGA(pe, &(gala->ga));
+ freeRemoteGA(pe-1, &(gala->ga)); //-1 cause ids start at 1... not 0
gala->next = freeGALAList;
freeGALAList = gala;
IF_DEBUG(sanity,
gala->ga.weight = 0xdead0add;
- gala->la = 0xdead00aa);
+ gala->la = (StgPtr)0xdead00aa);
continue;
}
- gala->la = closure;
- if (!full && gala->preferred) {
+ gala->la = (StgPtr)closure;
+ if (/* !full && */ gala->preferred) {
GALA *q;
if ((q = lookupHashTable(LAtoGALAtable, (StgWord) gala->la))!=NULL) {
if (q->preferred && gala->preferred) {
q->preferred = rtsFalse;
IF_PAR_DEBUG(tables,
fprintf(stderr, "@@## found hash entry for closure %p (%s): deprecated GA ",
- gala->la, info_type(gala->la));
+ gala->la, info_type((StgClosure*)gala->la));
printGA(&(q->ga));
fputc('\n', stderr));
}
}
gala->next = prev;
prev = gala;
+ /* Global statistics: count GAs and total size
+ if (RtsFlags.ParFlags.ParStats.Global &&
+ RtsFlags.GcFlags.giveStats > NO_GC_STATS) {
+ StgInfoTable *info;
+ nat size, ptrs, nonptrs, vhs, i;
+ char str[80];
+
+ info = get_closure_info(closure, &size, &ptrs, &nonptrs, &vhs, str);
+
+ size_GA += size ;
+ n++; // stats: count number of GAs we add to the new table
+ }
+ */
}
- //}
liveRemoteGAs = prev; /* list is reversed during marking */
/* If we have any remaining FREE messages to send off, do so now */
sendFreeMessages();
+ PAR_TICKY_CNT_FREE_GA();
+
IF_DEBUG(sanity,
checkFreeGALAList();
checkFreeIndirectionsList());
- if (full)
- rebuildLAGAtable();
+ rebuildLAGAtable();
+
+#if defined(PAR_TICKY)
+ getLAGAtableSize(&n, &size_GA); // determine no of GAs and global heap
+ PAR_TICKY_REBUILD_GA_TABLES_END(n, size_GA); // record these values
+#endif
IF_PAR_DEBUG(tables,
belch("@#%%%% rebuildGAtables: After ReBuilding GALA table starting with GALA at %p",
n++;
if (gala->preferred) {
GALA *q;
- if (q = lookupHashTable(LAtoGALAtable, (StgWord) gala->la)) {
+ if ((q = lookupHashTable(LAtoGALAtable, (StgWord) gala->la))!=NULL) {
if (q->preferred && gala->preferred) {
/* this deprecates q (see also GALAdeprecate) */
q->preferred = rtsFalse;
(void) removeHashTable(LAtoGALAtable, (StgWord) gala->la, (void *)q);
IF_PAR_DEBUG(tables,
fprintf(stderr, "@@## found hash entry for closure %p (%s): deprecated GA ",
- gala->la, info_type(gala->la));
+ gala->la, info_type((StgClosure*)gala->la));
printGA(&(q->ga));
fputc('\n', stderr));
}
m++;
if (gala->preferred) {
GALA *q;
- if (q = lookupHashTable(LAtoGALAtable, (StgWord) gala->la)) {
+ if ((q = lookupHashTable(LAtoGALAtable, (StgWord) gala->la))!=NULL) {
if (q->preferred && gala->preferred) {
/* this deprecates q (see also GALAdeprecate) */
q->preferred = rtsFalse;
(void) removeHashTable(LAtoGALAtable, (StgWord) gala->la, (void *)q);
IF_PAR_DEBUG(tables,
fprintf(stderr, "@@## found hash entry for closure %p (%s): deprecated GA ",
- gala->la, info_type(gala->la));
+ (StgClosure*)gala->la, info_type((StgClosure*)gala->la));
printGA(&(q->ga));
fputc('\n', stderr));
}
n,m));
}
+/*
+ Determine the size of the LAGA and GALA tables.
+ Has to be done after rebuilding the tables.
+ Only used for global statistics gathering.
+*/
+
+//@cindex getLAGAtableSize
+void
+getLAGAtableSize(nat *nP, nat *sizeP)
+{
+ GALA *gala;
+ // nat n=0, tot_size=0;
+ StgClosure *closure;
+ StgInfoTable *info;
+ nat size, ptrs, nonptrs, vhs, i;
+ char str[80];
+ /* IN order to avoid counting closures twice we maintain a hash table
+ of all closures seen so far.
+ ToDo: collect this data while rebuilding the GALA table and make use
+ of the existing hash tables;
+ */
+ HashTable *closureTable; // hash table for closures encountered already
+
+ closureTable = allocHashTable();
+
+ (*nP) = (*sizeP) = 0;
+ for (gala = liveIndirections; gala != NULL; gala = gala->next) {
+ closure = (StgClosure*) gala->la;
+ if (lookupHashTable(closureTable, (StgWord)closure)==NULL) { // not seen yet
+ insertHashTable(closureTable, (StgWord)closure, (void *)1);
+ info = get_closure_info(closure, &size, &ptrs, &nonptrs, &vhs, str);
+ (*sizeP) += size ; // stats: measure total heap size of global closures
+ (*nP)++; // stats: count number of GAs
+ }
+ }
+
+ for (gala = liveRemoteGAs; gala != NULL; gala = gala->next) {
+ closure = (StgClosure*) gala->la;
+ if (lookupHashTable(closureTable, (StgWord)closure)==NULL) { // not seen yet
+ insertHashTable(closureTable, (StgWord)closure, (void *)1);
+ info = get_closure_info(closure, &size, &ptrs, &nonptrs, &vhs, str);
+ (*sizeP) += size ; // stats: measure total heap size of global closures
+ (*nP)++; // stats: count number of GAs
+ }
+ }
+
+ freeHashTable(closureTable, NULL);
+}
+
//@node Debugging routines, Index, GC functions for GALA tables, Global Address Manipulation
//@subsection Debugging routines
printGALA (GALA *gala)
{
printGA(&(gala->ga));
- fprintf(stderr, " -> %p (%s)", (StgPtr)gala->la, info_type(gala->la));
- fprintf(stderr, " %s", (gala->preferred) ? "PREF" : "____");
+ fprintf(stderr, " -> %p (%s)",
+ (StgClosure*)gala->la, info_type((StgClosure*)gala->la));
+ fprintf(stderr, " %s",
+ (gala->preferred) ? "PREF" : "____");
}
/*
for (gl=freeGALAList; gl != NULL; gl=gl->next) {
ASSERT(gl->ga.weight==0xdead0add);
- ASSERT(gl->la==0xdead00aa);
+ ASSERT(gl->la==(StgPtr)0xdead00aa);
}
}
for (gl=freeIndirections; gl != NULL; gl=gl->next) {
ASSERT(gl->ga.weight==0xdead0add);
- ASSERT(gl->la==0xdead00aa);
+ ASSERT(gl->la==(StgPtr)0xdead00aa);
}
}
#endif /* PAR -- whole file */