[project @ 2000-01-14 16:15:08 by simonmar]
[ghc-hetmet.git] / ghc / rts / parallel / FetchMe.hc
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 $
4
5  Entry code for a FETCH_ME closure
6
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.
10
11  * --------------------------------------------------------------------------*/
12  
13 #ifdef PAR /* all of it */
14
15 //@menu
16 //* Includes::                  
17 //* Info tables::               
18 //* Index::                     
19 //@end menu
20
21 //@node Includes, Info tables
22 //@subsection Includes
23
24 #include "Rts.h"
25 #include "RtsFlags.h"
26 #include "RtsUtils.h"
27 #include "Storage.h"
28 #include "GranSim.h"
29 #include "GranSimRts.h"
30 #include "Parallel.h"
31 #include "ParallelRts.h"
32 #include "FetchMe.h"
33 #include "HLC.h"
34 #include "StgRun.h"     /* for StgReturn and register saving */
35
36 /* --------------------------------------------------------------------------
37    FETCH_ME closures.
38
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
41    retrieved.
42
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
51    
52    ------------------------------------------------------------------------ */
53
54 //@node Info tables, Index, Includes
55 //@subsection Info tables
56
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)
61 {
62   extern globalAddr *rga_GLOBAL;
63   extern globalAddr *lga_GLOBAL;
64   extern globalAddr fmbqga_GLOBAL;
65   extern StgClosure *p_GLOBAL;
66   /* 
67   globalAddr *rga;
68   globalAddr *lga;
69   globalAddr fmbqga;
70   StgClosure *p;
71   */
72
73   FB_
74   rga_GLOBAL = ((StgFetchMe *)R1.p)->ga;
75   ASSERT(rga->payload.gc.gtid != mytid);
76
77   /* Turn the FETCH_ME into a FETCH_ME_BQ, and place the current thread
78    * on the blocking queue.
79    */
80   // R1.cl->header.info = FETCH_ME_BQ_info;
81   SET_INFO((StgClosure *)R1.cl, &FETCH_ME_BQ_info);
82
83   CurrentTSO->link = END_BQ_QUEUE;
84   ((StgFetchMeBlockingQueue *)R1.cl)->blocking_queue = (StgBlockingQueueElement *)CurrentTSO;
85
86   /* record onto which closure the current thread is blcoking */
87   CurrentTSO->block_info.closure = R1.cl;
88   //recordMutable((StgMutClosure *)R1.cl);
89   p_GLOBAL = R1.cl;
90
91   /* Save the Thread State here, before calling RTS routines below! */
92   //BLOCK_NP_NO_JUMP(1);
93   SAVE_THREAD_STATE(1);
94
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);
107   }
108
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 
111    */
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));
116
117   STGCALL3(sendFetch, rga_GLOBAL, &fmbqga_GLOBAL, 0/*load*/);
118
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;
126
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);
128
129   THREAD_RETURN(1); /* back to the scheduler */  
130   // was: BLOCK_NP(1); 
131   FE_
132 }
133
134 /* ---------------------------------------------------------------------------
135    FETCH_ME_BQ
136    
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.
142
143    FETCH_ME_BQ_entry is a copy of BLACKHOLE_BQ_entry -- HWL
144    ------------------------------------------------------------------------ */
145
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)
149 {
150   FB_
151     TICK_ENT_BH();
152
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;
157
158 #if defined(PAR)
159     /* Save the Thread State here, before calling RTS routines below! */
160     SAVE_THREAD_STATE(1);
161
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);
170     }
171
172     THREAD_RETURN(1);  /* back to the scheduler */  
173 #else
174     /* stg_gen_block is too heavyweight, use a specialised one */
175     BLOCK_NP(1);
176 #endif
177   FE_
178 }
179
180 /* ---------------------------------------------------------------------------
181    BLOCKED_FETCH_BQ
182    
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).
189 */
190
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)
195 {
196   FB_
197     /* see NON_ENTERABLE_ENTRY_CODE in StgMiscClosures.hc */
198     DUMP_ERRMSG("BLOCKED_FETCH object entered!\n");
199     STGCALL1(shutdownHaskellAndExit, EXIT_FAILURE);
200   FE_
201 }
202
203 #endif /* PAR */
204
205 //@node Index,  , Info tables
206 //@subsection Index
207
208 //@index
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
214 //@end index