2
Time-stamp: <Wed Jan 12 2000 13:29:08 Stardate: [-30]4193.85 hwloidl>
4
Unpacking closures which have been exported to remote processors
6
This module defines routines for unpacking closures in the parallel
9
In the case of GrAnSim, this module defines routines for *simulating* the
10
unpacking of closures as it is done in the parallel runtime system.
14
Code in this file has been merged with Pack.c
19
//@node Unpacking closures, , ,
20
//@section Unpacking closures
31
//@node Includes, Prototypes, Unpacking closures, Unpacking closures
32
//@subsection Includes
36
#include "GranSimRts.h"
37
#include "ParallelRts.h"
38
#include "ParallelDebug.h"
42
//@node Prototypes, GUM code, Includes, Unpacking closures
43
//@subsection Prototypes
45
void InitPacking(void);
47
void InitPackBuffer(void);
49
/* Interface for ADT of closure queues */
50
void AllocClosureQueue(nat size);
51
void InitClosureQueue(void);
52
rtsBool QueueEmpty(void);
53
void QueueClosure(StgClosure *closure);
54
StgClosure *DeQueueClosure(void);
56
StgPtr AllocateHeap(nat size);
58
//@node GUM code, GranSim Code, Prototypes, Unpacking closures
59
//@subsection GUM code
63
//@node Local Definitions, , GUM code, GUM code
64
//@subsubsection Local Definitions
66
//@cindex PendingGABuffer
67
static globalAddr *PendingGABuffer;
68
/* is initialised in main; */
70
//@cindex InitPendingGABuffer
72
InitPendingGABuffer(size)
75
PendingGABuffer = (globalAddr *)
76
stgMallocBytes((size-PACK_HDR_SIZE)*2*sizeof(globalAddr),
77
"InitPendingGABuffer");
81
@CommonUp@ commons up two closures which we have discovered to be
82
variants of the same object. One is made an indirection to the other. */
86
CommonUp(StgClosure *src, StgClosure *dst)
88
StgBlockingQueueElement *bqe;
91
switch (get_itbl(src)->type) {
93
bqe = ((StgBlockingQueue *)src)->blocking_queue;
97
bqe = ((StgFetchMeBlockingQueue *)src)->blocking_queue;
101
bqe = ((StgRBH *)src)->blocking_queue;
110
/* Don't common up anything else */
113
/* We do not use UPD_IND because that would awaken the bq, too */
114
// UPD_IND(src, dst);
115
updateWithIndirection(get_itbl(src), src, dst);
116
//ASSERT(!IS_BIG_MOTHER(INFO_PTR(dst)));
117
if (bqe != END_BQ_QUEUE)
118
awaken_blocked_queue(bqe, src);
122
@UnpackGraph@ unpacks the graph contained in a message buffer. It
123
returns a pointer to the new graph. The @gamap@ parameter is set to
124
point to an array of (oldGA,newGA) pairs which were created as a result
125
of unpacking the buffer; @nGAs@ is set to the number of GA pairs which
128
The format of graph in the pack buffer is as defined in @Pack.lc@. */
130
//@cindex UnpackGraph
132
UnpackGraph(packBuffer, gamap, nGAs)
133
rtsPackBuffer *packBuffer;
137
nat size, ptrs, nonptrs, vhs;
138
StgWord **buffer, **bufptr, **slotptr;
139
globalAddr ga, *gaga;
140
StgClosure *closure, *existing,
141
*graphroot, *graph, *parent;
142
StgInfoTable *ip, *oldip;
144
pptr = 0, pptrs = 0, pvhs;
147
InitPackBuffer(); /* in case it isn't already init'd */
148
graphroot = (StgClosure *)NULL;
150
gaga = PendingGABuffer;
154
/* Unpack the header */
155
bufsize = packBuffer->size;
156
buffer = packBuffer->buffer;
161
graph = allocate(bufsize);
162
ASSERT(graph != NULL);
165
parent = (StgClosure *)NULL;
168
/* This is where we will ultimately save the closure's address */
171
/* First, unpack the next GA or PLC */
172
ga.weight = (rtsWeight) *bufptr++;
175
ga.payload.gc.gtid = (GlobalTaskId) *bufptr++;
176
ga.payload.gc.slot = (int) *bufptr++;
178
ga.payload.plc = (StgPtr) *bufptr++;
180
/* Now unpack the closure body, if there is one */
182
/* No more to unpack; just set closure to local address */
184
belch("Unpacked PLC at %x", ga.payload.plc));
185
closure = ga.payload.plc;
186
} else if (isOffset(&ga)) {
187
/* No more to unpack; just set closure to cached address */
188
ASSERT(parent != (StgClosure *)NULL);
189
closure = (StgClosure *) buffer[ga.payload.gc.slot];
191
/* Now we have to build something. */
196
* Close your eyes. You don't want to see where we're looking. You
197
* can't get closure info until you've unpacked the variable header,
198
* but you don't know how big it is until you've got closure info.
199
* So...we trust that the closure in the buffer is organized the
200
* same way as they will be in the heap...at least up through the
201
* end of the variable header.
203
ip = get_closure_info(bufptr, &size, &ptrs, &nonptrs, &vhs, str);
206
Remember, the generic closure layout is as follows:
207
+-------------------------------------------------+
208
| FIXED HEADER | VARIABLE HEADER | PTRS | NON-PRS |
209
+-------------------------------------------------+
211
/* Fill in the fixed header */
212
for (i = 0; i < FIXED_HS; i++)
213
((StgPtr)graph)[i] = *bufptr++;
215
if (ip->type == FETCH_ME)
216
size = ptrs = nonptrs = vhs = 0;
218
/* Fill in the packed variable header */
219
for (i = 0; i < vhs; i++)
220
((StgPtr)graph)[FIXED_HS + i] = *bufptr++;
222
/* Pointers will be filled in later */
224
/* Fill in the packed non-pointers */
225
for (i = 0; i < nonptrs; i++)
226
((StgPtr)graph)[FIXED_HS + i + vhs + ptrs] = *bufptr++;
228
/* Indirections are never packed */
229
// ASSERT(INFO_PTR(graph) != (W_) Ind_info_TO_USE);
231
/* Add to queue for processing */
235
* Common up the new closure with any existing closure having the same
239
if ((existing = GALAlookup(&ga)) == NULL) {
241
/* Just keep the new object */
243
belch("Unpacking new (%x, %d, %x)\n",
244
ga.payload.gc.gtid, ga.payload.gc.slot, ga.weight));
247
newGA = setRemoteGA(graph, &ga, rtsTrue);
248
if (ip->type == FETCH_ME)
249
// FETCHME_GA(closure) = newGA;
250
((StgFetchMe *)closure)->ga = newGA;
252
/* Two closures, one global name. Someone loses */
253
oldip = get_itbl(existing);
255
if ((oldip->type == FETCH_ME || IS_BLACK_HOLE(existing)) &&
256
ip->type != FETCH_ME) {
258
/* What we had wasn't worth keeping */
260
CommonUp(existing, graph);
264
* Either we already had something worthwhile by this name or
265
* the new thing is just another FetchMe. However, the thing we
266
* just unpacked has to be left as-is, or the child unpacking
267
* code will fail. Remember that the way pointer words are
268
* filled in depends on the info pointers of the parents being
269
* the same as when they were packed.
272
belch("Unpacking old (%x, %d, %x), keeping %#lx",
273
ga.payload.gc.gtid, ga.payload.gc.slot, ga.weight,
278
/* Pool the total weight in the stored ga */
279
(void) addWeight(&ga);
282
/* Sort out the global address mapping */
283
if ((ip_THUNK(ip) && !ip_UNPOINTED(ip)) ||
284
(ip_MUTABLE(ip) && ip->type != FETCH_ME)) {
285
/* Make up new GAs for single-copy closures */
286
globalAddr *newGA = makeGlobal(closure, rtsTrue);
288
ASSERT(closure == graph);
290
/* Create an old GA to new GA mapping */
292
splitWeight(gaga, newGA);
293
ASSERT(gaga->weight == 1L << (BITS_IN(unsigned) - 1));
296
graph += FIXED_HS + (size < MIN_UPD_SIZE ? MIN_UPD_SIZE : size);
300
* Set parent pointer to point to chosen closure. If we're at the top of
301
* the graph (our parent is NULL), then we want to arrange to return the
302
* chosen closure to our caller (possibly in place of the allocated graph
308
((StgPtr)parent)[FIXED_HS + pvhs + pptr] = (StgWord) closure;
310
/* Save closure pointer for resolving offsets */
311
*slotptr = (StgWord) closure;
313
/* Locate next parent pointer */
315
while (pptr + 1 > pptrs) {
316
parent = DeQueueClosure();
321
(void) get_closure_info(parent, &size, &pptrs, &nonptrs,
326
} while (parent != NULL);
328
ASSERT(bufsize == 0 || graph - 1 <= SAVE_Hp);
330
*gamap = PendingGABuffer;
331
*nGAs = (gaga - PendingGABuffer) / 2;
333
/* ToDo: are we *certain* graphroot has been set??? WDP 95/07 */
334
ASSERT(graphroot!=NULL);
339
//@node GranSim Code, Index, GUM code, Unpacking closures
340
//@subsection GranSim Code
343
For GrAnSim: In general no actual unpacking should be necessary. We just
344
have to walk over the graph and set the bitmasks appropriately. -- HWL */
346
//@node Unpacking, , GranSim Code, GranSim Code
347
//@subsubsection Unpacking
351
CommonUp(StgClosure *src, StgClosure *dst)
353
barf("CommonUp: should never be entered in a GranSim setup");
356
/* This code fakes the unpacking of a somewhat virtual buffer */
359
rtsPackBuffer* buffer;
361
nat size, ptrs, nonptrs, vhs,
363
StgClosure *closure, *graphroot, *graph;
365
StgWord bufsize, unpackedsize,
366
pptr = 0, pptrs = 0, pvhs;
368
char str[240], str1[80];
372
graphroot = buffer->buffer[0];
376
/* Unpack the header */
377
unpackedsize = buffer->unpacked_size;
378
bufsize = buffer->size;
381
belch("<<< Unpacking <<%d>> (buffer @ %p):\n (root @ %p, PE %d,size=%d), demanded by TSO %d (%p)[PE %d]",
382
buffer->id, buffer, graphroot, where_is(graphroot),
383
bufsize, tso->id, tso,
384
where_is((StgClosure *)tso)));
387
closure = buffer->buffer[bufptr++]; /* that's all we need for GrAnSim -- HWL */
389
/* Actually only ip is needed; rest is useful for TESTING -- HWL */
390
ip = get_closure_info(closure,
391
&size, &ptrs, &nonptrs, &vhs, str);
394
sprintf(str, "** (%p): Changing bitmask[%s]: 0x%x ",
395
closure, (closure_HNF(closure) ? "NF" : "__"),
398
if (ip->type == RBH) {
399
closure->header.gran.procs = PE_NUMBER(CurrentProc); /* Move node */
402
strcat(str, " (converting RBH) "));
404
convertFromRBH(closure); /* In GUM that's done by convertToFetchMe */
405
} else if (IS_BLACK_HOLE(closure)) {
406
closure->header.gran.procs |= PE_NUMBER(CurrentProc); /* Copy node */
407
} else if ( closure->header.gran.procs & PE_NUMBER(CurrentProc) == 0 ) {
408
if (closure_HNF(closure))
409
closure->header.gran.procs |= PE_NUMBER(CurrentProc); /* Copy node */
411
closure->header.gran.procs = PE_NUMBER(CurrentProc); /* Move node */
415
sprintf(str1, "0x%x", PROCS(closure)); strcat(str, str1));
416
IF_GRAN_DEBUG(pack, belch(str));
418
} while (bufptr<buffer->size) ; /* (parent != NULL); */
420
/* In GrAnSim we allocate pack buffers dynamically! -- HWL */
421
free(buffer->buffer);
425
belch("PrintGraph of %p is:", graphroot); PrintGraph(graphroot,0));
432
//@node Index, , GranSim Code, Unpacking closures
436
//* CommonUp:: @cindex\s-+CommonUp
437
//* InitPendingGABuffer:: @cindex\s-+InitPendingGABuffer
438
//* PendingGABuffer:: @cindex\s-+PendingGABuffer
439
//* UnpackGraph:: @cindex\s-+UnpackGraph