97b61d163eec8167c547556a60191a3567a7cbf9
[ghc-hetmet.git] / ghc / rts / parallel / FetchMe.hc
1 /* ----------------------------------------------------------------------------
2  Time-stamp: <Thu Feb 24 2000 21:31:41 Stardate: [-30]4409.48 hwloidl>
3  $Id: FetchMe.hc,v 1.5 2000/03/31 03:09:37 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    A word on the ptr/nonptr fields in the macros: they are unused at the
44    moment; all closures defined here have constant size (ie. no payload
45    that varies from closure to closure). Therefore, all routines that 
46    need to know the size of these closures have to do a sizeofW(StgFetchMe) 
47    etc to get the closure size. See get_closure_info(), evacuate() and
48    checkClosure() (using the same fcts for determining the size of the 
49    closures would be a good idea; at least it would be a nice step towards
50    making this code bug free).
51
52    About the difference between std and PAR in returning to the RTS:
53    in PAR we call RTS functions from within the entry code (see also
54    BLACKHOLE_entry and friends in StgMiscClosures.hc); therefore, we
55    have to save the thread state before calling these functions --- 
56    this is done via SAVE_THREAD_STATE; we then just load the return
57    code into R1 before jumping into the RTS --- this is done via
58    THREAD_RETURN; so, in short we have something like
59      SAVE_THREAD_STATE + THREAD_RETURN = BLOCK_NP
60    
61    ------------------------------------------------------------------------ */
62
63 //@node Info tables, Index, Includes
64 //@subsection Info tables
65
66 //@cindex FETCH_ME_info
67 INFO_TABLE(FETCH_ME_info, FETCH_ME_entry, 0,2, FETCH_ME, const, EF_,0,0);
68 //@cindex FETCH_ME_entry
69 STGFUN(FETCH_ME_entry)
70 {
71   /* 
72      Not needed any more since we call blockThread in the scheduler
73      (via BLOCK_NP(1) which returns with BlockedOnGA
74
75   extern globalAddr *rga_GLOBAL;
76   extern globalAddr *lga_GLOBAL;
77   extern globalAddr fmbqga_GLOBAL;
78   extern StgClosure *p_GLOBAL;
79   globalAddr *rga;
80   globalAddr *lga;
81   globalAddr fmbqga;
82   StgClosure *p;
83   */
84
85   FB_
86     /*
87       rga_GLOBAL = ((StgFetchMe *)R1.p)->ga;
88       ASSERT(rga->payload.gc.gtid != mytid);
89     */
90     ASSERT(((StgFetchMe *)R1.p)->ga->payload.gc.gtid != mytid);
91   
92     /* Turn the FETCH_ME into a FETCH_ME_BQ, and place the current thread
93      * on the blocking queue.
94      */
95     // R1.cl->header.info = FETCH_ME_BQ_info;
96     SET_INFO((StgClosure *)R1.cl, &FETCH_ME_BQ_info);
97   
98     /* Put ourselves on the blocking queue for this black hole */
99     // This is really, really BAD; tmp HACK to remember ga (checked in blockThread)
100     ASSERT(looks_like_ga(((StgFetchMe *)R1.p)->ga));
101     CurrentTSO->link = (StgBlockingQueueElement *)((StgFetchMe *)R1.p)->ga; // END_BQ_QUEUE;
102     ((StgFetchMeBlockingQueue *)R1.cl)->blocking_queue = (StgBlockingQueueElement *)CurrentTSO;
103   
104     /* jot down why and on what closure we are blocked */
105     CurrentTSO->why_blocked = BlockedOnGA;
106     CurrentTSO->block_info.closure = R1.cl;
107     //recordMutable((StgMutClosure *)R1.cl);
108     //p_GLOBAL = R1.cl;
109
110     /* sendFetch etc is now done in blockThread, which is called from the
111        scheduler -- HWL */
112
113     BLOCK_NP(1); 
114   FE_
115 }
116
117 /* ---------------------------------------------------------------------------
118    FETCH_ME_BQ
119    
120    On the first entry of a FETCH_ME closure, we turn the closure into
121    a FETCH_ME_BQ, which behaves just like a BLACKHOLE_BQ.  Any thread
122    entering the FETCH_ME_BQ will be placed in the blocking queue.
123    When the data arrives from the remote PE, all waiting threads are
124    woken up and the FETCH_ME_BQ is overwritten with the fetched data.
125
126    FETCH_ME_BQ_entry is a copy of BLACKHOLE_BQ_entry -- HWL
127    ------------------------------------------------------------------------ */
128
129 INFO_TABLE(FETCH_ME_BQ_info, FETCH_ME_BQ_entry,0,2,FETCH_ME_BQ,const,EF_,0,0);
130 //@cindex FETCH_ME_BQ_info
131 STGFUN(FETCH_ME_BQ_entry)
132 {
133   FB_
134     TICK_ENT_BH();
135
136     /* Put ourselves on the blocking queue for this node */
137     CurrentTSO->link = ((StgBlockingQueue *)R1.p)->blocking_queue;
138     ((StgBlockingQueue *)R1.p)->blocking_queue = CurrentTSO;
139
140     /* jot down why and on what closure we are blocked */
141     CurrentTSO->why_blocked = BlockedOnGA_NoSend;
142     CurrentTSO->block_info.closure = R1.cl;
143
144     /* stg_gen_block is too heavyweight, use a specialised one */
145     BLOCK_NP(1);
146   FE_
147 }
148
149 /* ---------------------------------------------------------------------------
150    BLOCKED_FETCH_BQ
151    
152    A BLOCKED_FETCH closure only ever exists in the blocking queue of a
153    globally visible closure i.e. one with a GA. A BLOCKED_FETCH closure
154    indicates that a TSO on another PE is waiting for the result of this
155    computation. Thus, when updating the closure, the result has to be sent
156    to that PE. The relevant routines handling that are awakenBlockedQueue
157    and blockFetch (for putting BLOCKED_FETCH closure into a BQ).
158 */
159
160 //@cindex BLOCKED_FETCH_info
161 INFO_TABLE(BLOCKED_FETCH_info, BLOCKED_FETCH_entry,0,2,BLOCKED_FETCH,const,EF_,0,0);
162 //@cindex BLOCKED_FETCH_entry
163 STGFUN(BLOCKED_FETCH_entry)
164 {
165   FB_
166     /* see NON_ENTERABLE_ENTRY_CODE in StgMiscClosures.hc */
167     STGCALL2(fprintf,stderr,"BLOCKED_FETCH object entered!\n");
168     STGCALL1(shutdownHaskellAndExit, EXIT_FAILURE);
169   FE_
170 }
171
172 #endif /* PAR */
173
174 //@node Index,  , Info tables
175 //@subsection Index
176
177 //@index
178 //* BLOCKED_FETCH_entry::  @cindex\s-+BLOCKED_FETCH_entry
179 //* BLOCKED_FETCH_info::  @cindex\s-+BLOCKED_FETCH_info
180 //* FETCH_ME_BQ_info::  @cindex\s-+FETCH_ME_BQ_info
181 //* FETCH_ME_entry::  @cindex\s-+FETCH_ME_entry
182 //* FETCH_ME_info::  @cindex\s-+FETCH_ME_info
183 //@end index