[project @ 2000-01-14 11:45:21 by hwloidl]
[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.3 2000/01/14 11:45:22 hwloidl 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   rga_GLOBAL = ((StgFetchMe *)R1.p)->ga;
74   ASSERT(rga->payload.gc.gtid != mytid);
75
76   /* Turn the FETCH_ME into a FETCH_ME_BQ, and place the current thread
77    * on the blocking queue.
78    */
79   // R1.cl->header.info = FETCH_ME_BQ_info;
80   SET_INFO((StgClosure *)R1.cl, &FETCH_ME_BQ_info);
81
82   CurrentTSO->link = END_BQ_QUEUE;
83   ((StgFetchMeBlockingQueue *)R1.cl)->blocking_queue = (StgBlockingQueueElement *)CurrentTSO;
84
85   /* record onto which closure the current thread is blcoking */
86   CurrentTSO->block_info.closure = R1.cl;
87   //recordMutable((StgMutClosure *)R1.cl);
88   p_GLOBAL = R1.cl;
89
90   /* Save the Thread State here, before calling RTS routines below! */
91   //BLOCK_NP_NO_JUMP(1);
92   SAVE_THREAD_STATE(1);
93
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);
105   }
106
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 
109    */
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));
114
115   /* I *hope* it's ok to call this from STG land. --SDM */
116   STGCALL3(sendFetch, rga_GLOBAL, &fmbqga_GLOBAL, 0/*load*/);
117
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;
125
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);
127
128   THREAD_RETURN(1); /* back to the scheduler */  
129   // was: BLOCK_NP(1); 
130   FE_
131 }
132
133 /* ---------------------------------------------------------------------------
134    FETCH_ME_BQ
135    
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.
141
142    FETCH_ME_BQ_entry is a copy of BLACKHOLE_BQ_entry -- HWL
143    ------------------------------------------------------------------------ */
144
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)
148 {
149   FB_
150     TICK_ENT_BH();
151
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;
156
157 #if defined(PAR)
158     /* Save the Thread State here, before calling RTS routines below! */
159     SAVE_THREAD_STATE(1);
160
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);
169     }
170
171     THREAD_RETURN(1);  /* back to the scheduler */  
172 #else
173     /* stg_gen_block is too heavyweight, use a specialised one */
174     BLOCK_NP(1);
175 #endif
176   FE_
177 }
178
179 /* ---------------------------------------------------------------------------
180    BLOCKED_FETCH_BQ
181    
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).
188 */
189
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)
194 {
195   FB_
196     /* see NON_ENTERABLE_ENTRY_CODE in StgMiscClosures.hc */
197     DUMP_ERRMSG("BLOCKED_FETCH object entered!\n");
198     STGCALL1(shutdownHaskellAndExit, EXIT_FAILURE);
199   FE_
200 }
201
202 #endif /* PAR */
203
204 //@node Index,  , Info tables
205 //@subsection Index
206
207 //@index
208 //* BLOCKED_FETCH_entry::  @cindex\s-+BLOCKED_FETCH_entry
209 //* BLOCKED_FETCH_info::  @cindex\s-+BLOCKED_FETCH_info
210 //* FETCH_ME_BQ_info::  @cindex\s-+FETCH_ME_BQ_info
211 //* FETCH_ME_entry::  @cindex\s-+FETCH_ME_entry
212 //* FETCH_ME_info::  @cindex\s-+FETCH_ME_info
213 //@end index