1 /* ----------------------------------------------------------------------------
2 Time-stamp: <Wed Jan 12 2000 13:39:33 Stardate: [-30]4193.88 hwloidl>
3 $Id: FetchMe.hc,v 1.2 2000/01/13 14:34:06 hwloidl Exp $
5 Entry code for a FETCH_ME closure
7 This module defines routines for handling remote pointers (@FetchMe@s)
8 in GUM. It is threaded (@.hc@) because @FetchMe_entry@ will be
9 called during evaluation.
11 * --------------------------------------------------------------------------*/
13 #ifdef PAR /* all of it */
21 //@node Includes, Info tables
22 //@subsection Includes
29 #include "GranSimRts.h"
31 #include "ParallelRts.h"
34 #include "StgRun.h" /* for StgReturn and register saving */
36 /* --------------------------------------------------------------------------
39 A FETCH_ME closure represents data that currently resides on
40 another PE. We issue a fetch message, and wait for the data to be
43 About the difference between std and PAR in returning to the RTS:
44 in PAR we call RTS functions from within the entry code (see also
45 BLACKHOLE_entry and friends in StgMiscClosures.hc); therefore, we
46 have to save the thread state before calling these functions ---
47 this is done via SAVE_THREAD_STATE; we then just load the return
48 code into R1 before jumping into the RTS --- this is done via
49 THREAD_RETURN; so, in short we have something like
50 SAVE_THREAD_STATE + THREAD_RETURN = BLOCK_NP
52 ------------------------------------------------------------------------ */
54 //@node Info tables, Index, Includes
55 //@subsection Info tables
57 //@cindex FETCH_ME_info
58 INFO_TABLE(FETCH_ME_info, FETCH_ME_entry, 0,2, FETCH_ME, const, EF_,0,0);
59 //@cindex FETCH_ME_entry
60 STGFUN(FETCH_ME_entry)
62 extern globalAddr *rga_GLOBAL;
63 extern globalAddr *lga_GLOBAL;
64 extern globalAddr fmbqga_GLOBAL;
65 extern StgClosure *p_GLOBAL;
73 rga_GLOBAL = ((StgFetchMe *)R1.p)->ga;
74 ASSERT(rga->payload.gc.gtid != mytid);
76 /* Turn the FETCH_ME into a FETCH_ME_BQ, and place the current thread
77 * on the blocking queue.
79 // R1.cl->header.info = FETCH_ME_BQ_info;
80 SET_INFO((StgClosure *)R1.cl, &FETCH_ME_BQ_info);
82 CurrentTSO->link = END_BQ_QUEUE;
83 ((StgFetchMeBlockingQueue *)R1.cl)->blocking_queue = (StgBlockingQueueElement *)CurrentTSO;
85 /* record onto which closure the current thread is blcoking */
86 CurrentTSO->block_info.closure = R1.cl;
87 //recordMutable((StgMutClosure *)R1.cl);
90 /* Save the Thread State here, before calling RTS routines below! */
91 //BLOCK_NP_NO_JUMP(1);
94 /* unknown junk... needed? --SDM yes, want to see what's happening -- HWL */
95 if (RtsFlags.ParFlags.ParStats.Full) {
96 /* Note that CURRENT_TIME may perform an unsafe call */
97 //rtsTime now = CURRENT_TIME; /* Now */
98 CurrentTSO->par.exectime += CURRENT_TIME - CurrentTSO->par.blockedat;
99 CurrentTSO->par.fetchcount++;
100 /* TSO_QUEUE(CurrentTSO) = Q_FETCHING; */
101 CurrentTSO->par.blockedat = CURRENT_TIME;
102 /* we are about to send off a FETCH message, so dump a FETCH event */
103 DumpRawGranEvent(CURRENT_PROC, taskIDtoPE(rga_GLOBAL->payload.gc.gtid),
104 GR_FETCH, CurrentTSO, (StgClosure *)R1.p, 0);
107 /* Phil T. claims that this was a workaround for a hard-to-find
108 * bug, hence I'm leaving it out for now --SDM
110 /* Assign a brand-new global address to the newly created FMBQ */
111 lga_GLOBAL = makeGlobal(p_GLOBAL, rtsFalse);
112 splitWeight(&fmbqga_GLOBAL, lga_GLOBAL);
113 ASSERT(fmbqga_GLOBAL.weight == 1L << (BITS_IN(unsigned) - 1));
115 /* I *hope* it's ok to call this from STG land. --SDM */
116 STGCALL3(sendFetch, rga_GLOBAL, &fmbqga_GLOBAL, 0/*load*/);
118 // sendFetch now called from processTheRealFetch, to make SDM happy
119 //theGlobalFromGA.payload.gc.gtid = rga->payload.gc.gtid;
120 //theGlobalFromGA.payload.gc.slot = rga->payload.gc.slot;
121 //theGlobalFromGA.weight = rga->weight;
122 //theGlobalToGA.payload.gc.gtid = fmbqga.payload.gc.gtid;
123 //theGlobalToGA.payload.gc.slot = fmbqga.payload.gc.slot;
124 //theGlobalToGA.weight = fmbqga.weight;
126 // STGCALL6(fprintf,stderr,"%% Fetching %p from remote PE ((%x,%d,%x))\n",R1.p,rga->payload.gc.gtid, rga->payload.gc.slot, rga->weight);
128 THREAD_RETURN(1); /* back to the scheduler */
133 /* ---------------------------------------------------------------------------
136 On the first entry of a FETCH_ME closure, we turn the closure into
137 a FETCH_ME_BQ, which behaves just like a BLACKHOLE_BQ. Any thread
138 entering the FETCH_ME_BQ will be placed in the blocking queue.
139 When the data arrives from the remote PE, all waiting threads are
140 woken up and the FETCH_ME_BQ is overwritten with the fetched data.
142 FETCH_ME_BQ_entry is a copy of BLACKHOLE_BQ_entry -- HWL
143 ------------------------------------------------------------------------ */
145 INFO_TABLE(FETCH_ME_BQ_info, FETCH_ME_BQ_entry,0,2,FETCH_ME_BQ,const,EF_,0,0);
146 //@cindex FETCH_ME_BQ_info
147 STGFUN(FETCH_ME_BQ_entry)
152 /* Put ourselves on the blocking queue for this black hole */
153 CurrentTSO->block_info.closure = R1.cl;
154 CurrentTSO->link = ((StgBlockingQueue *)R1.p)->blocking_queue;
155 ((StgBlockingQueue *)R1.p)->blocking_queue = CurrentTSO;
158 /* Save the Thread State here, before calling RTS routines below! */
159 SAVE_THREAD_STATE(1);
161 if (RtsFlags.ParFlags.ParStats.Full) {
162 /* Note that CURRENT_TIME may perform an unsafe call */
163 //rtsTime now = CURRENT_TIME; /* Now */
164 CurrentTSO->par.exectime += CURRENT_TIME - CurrentTSO->par.blockedat;
165 CurrentTSO->par.blockcount++;
166 CurrentTSO->par.blockedat = CURRENT_TIME;
167 DumpRawGranEvent(CURRENT_PROC, thisPE,
168 GR_BLOCK, CurrentTSO, (StgClosure *)R1.p, 0);
171 THREAD_RETURN(1); /* back to the scheduler */
173 /* stg_gen_block is too heavyweight, use a specialised one */
179 /* ---------------------------------------------------------------------------
182 A BLOCKED_FETCH closure only ever exists in the blocking queue of a
183 globally visible closure i.e. one with a GA. A BLOCKED_FETCH closure
184 indicates that a TSO on another PE is waiting for the result of this
185 computation. Thus, when updating the closure, the result has to be sent
186 to that PE. The relevant routines handling that are awaken_blocked_queue
187 and blockFetch (for putting BLOCKED_FETCH closure into a BQ).
190 //@cindex BLOCKED_FETCH_info
191 INFO_TABLE(BLOCKED_FETCH_info, BLOCKED_FETCH_entry,0,2,BLOCKED_FETCH,const,EF_,0,0);
192 //@cindex BLOCKED_FETCH_entry
193 STGFUN(BLOCKED_FETCH_entry)
196 /* see NON_ENTERABLE_ENTRY_CODE in StgMiscClosures.hc */
197 fprintf(stderr,"Qagh: BLOCKED_FETCH entered!\n");
198 STGCALL1(raiseError, errorHandler);
199 stg_exit(EXIT_FAILURE); /* not executed */
205 //@node Index, , Info tables
209 //* BLOCKED_FETCH_entry:: @cindex\s-+BLOCKED_FETCH_entry
210 //* BLOCKED_FETCH_info:: @cindex\s-+BLOCKED_FETCH_info
211 //* FETCH_ME_BQ_info:: @cindex\s-+FETCH_ME_BQ_info
212 //* FETCH_ME_entry:: @cindex\s-+FETCH_ME_entry
213 //* FETCH_ME_info:: @cindex\s-+FETCH_ME_info