FIX #1779 and qq005: export hs_hpc_module
[ghc-hetmet.git] / rts / parallel / FetchMe.hc
1 /* ----------------------------------------------------------------------------
2  Time-stamp: <Tue Mar 06 2001 17:01:46 Stardate: [-30]6288.54 hwloidl>
3
4  Entry code for a FETCH_ME closure
5
6  This module defines routines for handling remote pointers (@FetchMe@s)
7  in GUM.  It is threaded (@.hc@) because @FetchMe_entry@ will be
8  called during evaluation.
9
10  * --------------------------------------------------------------------------*/
11  
12 #ifdef PAR /* all of it */
13
14 //@menu
15 //* Includes::                  
16 //* Info tables::               
17 //* Index::                     
18 //@end menu
19
20 //@node Includes, Info tables
21 //@subsection Includes
22
23 #include "Stg.h"
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
53 //@node Info tables, Index, Includes
54 //@subsection Info tables
55
56 //@cindex FETCH_ME_info
57 INFO_TABLE(stg_FETCH_ME_info, stg_FETCH_ME_entry, 0,2, FETCH_ME,, EF_,"FETCH_ME","FETCH_ME");
58 //@cindex FETCH_ME_entry
59 STGFUN(stg_FETCH_ME_entry)
60 {
61   FB_
62     TICK_ENT_BH();
63
64     ASSERT(((StgFetchMe *)R1.p)->ga->payload.gc.gtid != mytid);
65   
66     /* Turn the FETCH_ME into a FETCH_ME_BQ, and place the current thread
67      * on the blocking queue.
68      */
69     // ((StgFetchMeBlockingQueue *)R1.cl)->header.info = &FETCH_ME_BQ_info; // does the same as SET_INFO
70     SET_INFO((StgClosure *)R1.cl, &stg_FETCH_ME_BQ_info);
71   
72     /* Remember GA as a global var (used in blockThread); NB: not thread safe! */
73     ASSERT(theGlobalFromGA.payload.gc.gtid == (GlobalTaskId)0);
74     theGlobalFromGA = *((StgFetchMe *)R1.p)->ga; 
75
76     /* Put ourselves on the blocking queue for this black hole */
77     ASSERT(looks_like_ga(((StgFetchMe *)R1.p)->ga));
78     CurrentTSO->link = END_BQ_QUEUE;
79     ((StgFetchMeBlockingQueue *)R1.cl)->blocking_queue = (StgBlockingQueueElement *)CurrentTSO;
80   
81     /* jot down why and on what closure we are blocked */
82     CurrentTSO->why_blocked = BlockedOnGA;
83     CurrentTSO->block_info.closure = R1.cl;
84     /* closure is mutable since something has just been added to its BQ */
85     //recordMutable((StgMutClosure *)R1.cl);
86
87     /* sendFetch etc is now done in blockThread, which is called from the
88        scheduler -- HWL */
89
90     BLOCK_NP(1); 
91   FE_
92 }
93
94 /* ---------------------------------------------------------------------------
95    FETCH_ME_BQ
96    
97    On the first entry of a FETCH_ME closure, we turn the closure into
98    a FETCH_ME_BQ, which behaves just like a BLACKHOLE_BQ.  Any thread
99    entering the FETCH_ME_BQ will be placed in the blocking queue.
100    When the data arrives from the remote PE, all waiting threads are
101    woken up and the FETCH_ME_BQ is overwritten with the fetched data.
102
103    FETCH_ME_BQ_entry is almost identical to BLACKHOLE_BQ_entry -- HWL
104    ------------------------------------------------------------------------ */
105
106 INFO_TABLE(stg_FETCH_ME_BQ_info, stg_FETCH_ME_BQ_entry,0,2,FETCH_ME_BQ,,EF_,"FETCH_ME_BQ","FETCH_ME_BQ");
107 //@cindex FETCH_ME_BQ_info
108 STGFUN(stg_FETCH_ME_BQ_entry)
109 {
110   FB_
111     TICK_ENT_BH();
112
113     /* Put ourselves on the blocking queue for this node */
114     CurrentTSO->link = (StgTSO*)((StgBlockingQueue *)R1.p)->blocking_queue;
115     ((StgBlockingQueue *)R1.p)->blocking_queue = (StgBlockingQueueElement *)CurrentTSO;
116
117     /* jot down why and on what closure we are blocked */
118     CurrentTSO->why_blocked = BlockedOnGA_NoSend;
119     CurrentTSO->block_info.closure = R1.cl;
120
121     /* stg_gen_block is too heavyweight, use a specialised one */
122     BLOCK_NP(1);
123   FE_
124 }
125
126 /* ---------------------------------------------------------------------------
127    BLOCKED_FETCH_BQ
128    
129    A BLOCKED_FETCH closure only ever exists in the blocking queue of a
130    globally visible closure i.e. one with a GA. A BLOCKED_FETCH closure
131    indicates that a TSO on another PE is waiting for the result of this
132    computation. Thus, when updating the closure, the result has to be sent
133    to that PE. The relevant routines handling that are awakenBlockedQueue
134    and blockFetch (for putting BLOCKED_FETCH closure into a BQ).
135    ------------------------------------------------------------------------ */
136
137 //@cindex BLOCKED_FETCH_info
138 INFO_TABLE(stg_BLOCKED_FETCH_info, stg_BLOCKED_FETCH_entry,0,2,BLOCKED_FETCH,,EF_,"BLOCKED_FETCH","BLOCKED_FETCH");
139 //@cindex BLOCKED_FETCH_entry
140 STGFUN(stg_BLOCKED_FETCH_entry)
141 {
142   FB_
143     /* see NON_ENTERABLE_ENTRY_CODE in StgMiscClosures.hc */
144     STGCALL2(fprintf,stderr,"BLOCKED_FETCH object entered!\n");
145     STGCALL1(shutdownHaskellAndExit, EXIT_FAILURE);
146   FE_
147 }
148
149
150 /* ---------------------------------------------------------------------------
151    REMOTE_REF
152    
153    A REMOTE_REF closure is generated whenever we wish to refer to a sticky
154    object on another PE.
155    ------------------------------------------------------------------------ */
156
157 //@cindex REMOTE_REF_info
158 INFO_TABLE(stg_REMOTE_REF_info, stg_REMOTE_REF_entry,0,2,REMOTE_REF,,EF_,"REMOTE_REF","REMOTE_REF");
159 //@cindex REMOTE_REF_entry
160 STGFUN(stg_REMOTE_REF_entry)
161 {
162   FB_
163     /* see NON_ENTERABLE_ENTRY_CODE in StgMiscClosures.hc */
164     STGCALL2(fprintf,stderr,"REMOTE REF object entered!\n");
165     STGCALL1(shutdownHaskellAndExit, EXIT_FAILURE);
166   FE_
167 }
168
169 #endif /* PAR */
170
171 //@node Index,  , Info tables
172 //@subsection Index
173
174 //@index
175 //* BLOCKED_FETCH_entry::  @cindex\s-+BLOCKED_FETCH_entry
176 //* BLOCKED_FETCH_info::  @cindex\s-+BLOCKED_FETCH_info
177 //* FETCH_ME_BQ_info::  @cindex\s-+FETCH_ME_BQ_info
178 //* FETCH_ME_entry::  @cindex\s-+FETCH_ME_entry
179 //* FETCH_ME_info::  @cindex\s-+FETCH_ME_info
180 //@end index