1 /* ----------------------------------------------------------------------------
2 Time-stamp: <Fri Jan 14 2000 09:41:07 Stardate: [-30]4202.01 hwloidl>
3 $Id: FetchMe.hc,v 1.4 2000/01/14 16:15:08 simonmar 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;
74 rga_GLOBAL = ((StgFetchMe *)R1.p)->ga;
75 ASSERT(rga->payload.gc.gtid != mytid);
77 /* Turn the FETCH_ME into a FETCH_ME_BQ, and place the current thread
78 * on the blocking queue.
80 // R1.cl->header.info = FETCH_ME_BQ_info;
81 SET_INFO((StgClosure *)R1.cl, &FETCH_ME_BQ_info);
83 CurrentTSO->link = END_BQ_QUEUE;
84 ((StgFetchMeBlockingQueue *)R1.cl)->blocking_queue = (StgBlockingQueueElement *)CurrentTSO;
86 /* record onto which closure the current thread is blcoking */
87 CurrentTSO->block_info.closure = R1.cl;
88 //recordMutable((StgMutClosure *)R1.cl);
91 /* Save the Thread State here, before calling RTS routines below! */
92 //BLOCK_NP_NO_JUMP(1);
95 /* unknown junk... needed? --SDM yes, want to see what's happening -- HWL */
96 if (RtsFlags.ParFlags.ParStats.Full) {
97 /* Note that CURRENT_TIME may perform an unsafe call */
98 //rtsTime now = CURRENT_TIME; /* Now */
99 CurrentTSO->par.exectime += CURRENT_TIME - CurrentTSO->par.blockedat;
100 CurrentTSO->par.fetchcount++;
101 /* TSO_QUEUE(CurrentTSO) = Q_FETCHING; */
102 CurrentTSO->par.blockedat = CURRENT_TIME;
103 /* we are about to send off a FETCH message, so dump a FETCH event */
104 /* following should be an STGCALL --SDM */
105 DumpRawGranEvent(CURRENT_PROC, taskIDtoPE(rga_GLOBAL->payload.gc.gtid),
106 GR_FETCH, CurrentTSO, (StgClosure *)R1.p, 0);
109 /* Phil T. claims that this was a workaround for a hard-to-find
110 * bug, hence I'm leaving it out for now --SDM
112 /* Assign a brand-new global address to the newly created FMBQ */
113 lga_GLOBAL = makeGlobal(p_GLOBAL, rtsFalse);
114 splitWeight(&fmbqga_GLOBAL, lga_GLOBAL);
115 ASSERT(fmbqga_GLOBAL.weight == 1L << (BITS_IN(unsigned) - 1));
117 STGCALL3(sendFetch, rga_GLOBAL, &fmbqga_GLOBAL, 0/*load*/);
119 // sendFetch now called from processTheRealFetch, to make SDM happy
120 //theGlobalFromGA.payload.gc.gtid = rga->payload.gc.gtid;
121 //theGlobalFromGA.payload.gc.slot = rga->payload.gc.slot;
122 //theGlobalFromGA.weight = rga->weight;
123 //theGlobalToGA.payload.gc.gtid = fmbqga.payload.gc.gtid;
124 //theGlobalToGA.payload.gc.slot = fmbqga.payload.gc.slot;
125 //theGlobalToGA.weight = fmbqga.weight;
127 // STGCALL6(fprintf,stderr,"%% Fetching %p from remote PE ((%x,%d,%x))\n",R1.p,rga->payload.gc.gtid, rga->payload.gc.slot, rga->weight);
129 THREAD_RETURN(1); /* back to the scheduler */
134 /* ---------------------------------------------------------------------------
137 On the first entry of a FETCH_ME closure, we turn the closure into
138 a FETCH_ME_BQ, which behaves just like a BLACKHOLE_BQ. Any thread
139 entering the FETCH_ME_BQ will be placed in the blocking queue.
140 When the data arrives from the remote PE, all waiting threads are
141 woken up and the FETCH_ME_BQ is overwritten with the fetched data.
143 FETCH_ME_BQ_entry is a copy of BLACKHOLE_BQ_entry -- HWL
144 ------------------------------------------------------------------------ */
146 INFO_TABLE(FETCH_ME_BQ_info, FETCH_ME_BQ_entry,0,2,FETCH_ME_BQ,const,EF_,0,0);
147 //@cindex FETCH_ME_BQ_info
148 STGFUN(FETCH_ME_BQ_entry)
153 /* Put ourselves on the blocking queue for this black hole */
154 CurrentTSO->block_info.closure = R1.cl;
155 CurrentTSO->link = ((StgBlockingQueue *)R1.p)->blocking_queue;
156 ((StgBlockingQueue *)R1.p)->blocking_queue = CurrentTSO;
159 /* Save the Thread State here, before calling RTS routines below! */
160 SAVE_THREAD_STATE(1);
162 if (RtsFlags.ParFlags.ParStats.Full) {
163 /* Note that CURRENT_TIME may perform an unsafe call */
164 //rtsTime now = CURRENT_TIME; /* Now */
165 CurrentTSO->par.exectime += CURRENT_TIME - CurrentTSO->par.blockedat;
166 CurrentTSO->par.blockcount++;
167 CurrentTSO->par.blockedat = CURRENT_TIME;
168 DumpRawGranEvent(CURRENT_PROC, thisPE,
169 GR_BLOCK, CurrentTSO, (StgClosure *)R1.p, 0);
172 THREAD_RETURN(1); /* back to the scheduler */
174 /* stg_gen_block is too heavyweight, use a specialised one */
180 /* ---------------------------------------------------------------------------
183 A BLOCKED_FETCH closure only ever exists in the blocking queue of a
184 globally visible closure i.e. one with a GA. A BLOCKED_FETCH closure
185 indicates that a TSO on another PE is waiting for the result of this
186 computation. Thus, when updating the closure, the result has to be sent
187 to that PE. The relevant routines handling that are awaken_blocked_queue
188 and blockFetch (for putting BLOCKED_FETCH closure into a BQ).
191 //@cindex BLOCKED_FETCH_info
192 INFO_TABLE(BLOCKED_FETCH_info, BLOCKED_FETCH_entry,0,2,BLOCKED_FETCH,const,EF_,0,0);
193 //@cindex BLOCKED_FETCH_entry
194 STGFUN(BLOCKED_FETCH_entry)
197 /* see NON_ENTERABLE_ENTRY_CODE in StgMiscClosures.hc */
198 DUMP_ERRMSG("BLOCKED_FETCH object entered!\n");
199 STGCALL1(shutdownHaskellAndExit, EXIT_FAILURE);
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