[project @ 2001-03-23 16:36:20 by simonmar]
[ghc-hetmet.git] / ghc / rts / parallel / FetchMe.hc
1 /* ----------------------------------------------------------------------------
2  Time-stamp: <Tue Mar 06 2001 17:01:46 Stardate: [-30]6288.54 hwloidl>
3  $Id: FetchMe.hc,v 1.7 2001/03/23 16:36:21 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 "Stg.h"
25 #include "Rts.h"
26 #include "RtsFlags.h"
27 #include "RtsUtils.h"
28 #include "Storage.h"
29 #include "GranSim.h"
30 #include "GranSimRts.h"
31 #include "Parallel.h"
32 #include "ParallelRts.h"
33 #include "FetchMe.h"
34 #include "HLC.h"
35 #include "StgRun.h"     /* for StgReturn and register saving */
36
37 /* --------------------------------------------------------------------------
38    FETCH_ME closures.
39
40    A FETCH_ME closure represents data that currently resides on
41    another PE.  We issue a fetch message, and wait for the data to be
42    retrieved.
43
44    A word on the ptr/nonptr fields in the macros: they are unused at the
45    moment; all closures defined here have constant size (ie. no payload
46    that varies from closure to closure). Therefore, all routines that 
47    need to know the size of these closures have to do a sizeofW(StgFetchMe) 
48    etc to get the closure size. See get_closure_info(), evacuate() and
49    checkClosure() (using the same fcts for determining the size of the 
50    closures would be a good idea; at least it would be a nice step towards
51    making this code bug free).
52    ------------------------------------------------------------------------ */
53
54 //@node Info tables, Index, Includes
55 //@subsection Info tables
56
57 //@cindex FETCH_ME_info
58 INFO_TABLE(stg_FETCH_ME_info, stg_FETCH_ME_entry, 0,2, FETCH_ME,, EF_,"FETCH_ME","FETCH_ME");
59 //@cindex FETCH_ME_entry
60 STGFUN(stg_FETCH_ME_entry)
61 {
62   FB_
63     TICK_ENT_BH();
64
65     ASSERT(((StgFetchMe *)R1.p)->ga->payload.gc.gtid != mytid);
66   
67     /* Turn the FETCH_ME into a FETCH_ME_BQ, and place the current thread
68      * on the blocking queue.
69      */
70     // ((StgFetchMeBlockingQueue *)R1.cl)->header.info = &FETCH_ME_BQ_info; // does the same as SET_INFO
71     SET_INFO((StgClosure *)R1.cl, &stg_FETCH_ME_BQ_info);
72   
73     /* Remember GA as a global var (used in blockThread); NB: not thread safe! */
74     ASSERT(theGlobalFromGA.payload.gc.gtid == (GlobalTaskId)0);
75     theGlobalFromGA = *((StgFetchMe *)R1.p)->ga; 
76
77     /* Put ourselves on the blocking queue for this black hole */
78     ASSERT(looks_like_ga(((StgFetchMe *)R1.p)->ga));
79     CurrentTSO->link = END_BQ_QUEUE;
80     ((StgFetchMeBlockingQueue *)R1.cl)->blocking_queue = (StgBlockingQueueElement *)CurrentTSO;
81   
82     /* jot down why and on what closure we are blocked */
83     CurrentTSO->why_blocked = BlockedOnGA;
84     CurrentTSO->block_info.closure = R1.cl;
85     /* closure is mutable since something has just been added to its BQ */
86     //recordMutable((StgMutClosure *)R1.cl);
87
88     /* sendFetch etc is now done in blockThread, which is called from the
89        scheduler -- HWL */
90
91     BLOCK_NP(1); 
92   FE_
93 }
94
95 /* ---------------------------------------------------------------------------
96    FETCH_ME_BQ
97    
98    On the first entry of a FETCH_ME closure, we turn the closure into
99    a FETCH_ME_BQ, which behaves just like a BLACKHOLE_BQ.  Any thread
100    entering the FETCH_ME_BQ will be placed in the blocking queue.
101    When the data arrives from the remote PE, all waiting threads are
102    woken up and the FETCH_ME_BQ is overwritten with the fetched data.
103
104    FETCH_ME_BQ_entry is almost identical to BLACKHOLE_BQ_entry -- HWL
105    ------------------------------------------------------------------------ */
106
107 INFO_TABLE(stg_FETCH_ME_BQ_info, stg_FETCH_ME_BQ_entry,0,2,FETCH_ME_BQ,,EF_,"FETCH_ME_BQ","FETCH_ME_BQ");
108 //@cindex FETCH_ME_BQ_info
109 STGFUN(stg_FETCH_ME_BQ_entry)
110 {
111   FB_
112     TICK_ENT_BH();
113
114     /* Put ourselves on the blocking queue for this node */
115     CurrentTSO->link = (StgTSO*)((StgBlockingQueue *)R1.p)->blocking_queue;
116     ((StgBlockingQueue *)R1.p)->blocking_queue = (StgBlockingQueueElement *)CurrentTSO;
117
118     /* jot down why and on what closure we are blocked */
119     CurrentTSO->why_blocked = BlockedOnGA_NoSend;
120     CurrentTSO->block_info.closure = R1.cl;
121
122     /* stg_gen_block is too heavyweight, use a specialised one */
123     BLOCK_NP(1);
124   FE_
125 }
126
127 /* ---------------------------------------------------------------------------
128    BLOCKED_FETCH_BQ
129    
130    A BLOCKED_FETCH closure only ever exists in the blocking queue of a
131    globally visible closure i.e. one with a GA. A BLOCKED_FETCH closure
132    indicates that a TSO on another PE is waiting for the result of this
133    computation. Thus, when updating the closure, the result has to be sent
134    to that PE. The relevant routines handling that are awakenBlockedQueue
135    and blockFetch (for putting BLOCKED_FETCH closure into a BQ).
136    ------------------------------------------------------------------------ */
137
138 //@cindex BLOCKED_FETCH_info
139 INFO_TABLE(stg_BLOCKED_FETCH_info, stg_BLOCKED_FETCH_entry,0,2,BLOCKED_FETCH,,EF_,"BLOCKED_FETCH","BLOCKED_FETCH");
140 //@cindex BLOCKED_FETCH_entry
141 STGFUN(stg_BLOCKED_FETCH_entry)
142 {
143   FB_
144     /* see NON_ENTERABLE_ENTRY_CODE in StgMiscClosures.hc */
145     STGCALL2(fprintf,stderr,"BLOCKED_FETCH object entered!\n");
146     STGCALL1(shutdownHaskellAndExit, EXIT_FAILURE);
147   FE_
148 }
149
150
151 /* ---------------------------------------------------------------------------
152    REMOTE_REF
153    
154    A REMOTE_REF closure is generated whenever we wish to refer to a sticky
155    object on another PE.
156    ------------------------------------------------------------------------ */
157
158 //@cindex REMOTE_REF_info
159 INFO_TABLE(stg_REMOTE_REF_info, stg_REMOTE_REF_entry,0,2,REMOTE_REF,,EF_,"REMOTE_REF","REMOTE_REF");
160 //@cindex REMOTE_REF_entry
161 STGFUN(stg_REMOTE_REF_entry)
162 {
163   FB_
164     /* see NON_ENTERABLE_ENTRY_CODE in StgMiscClosures.hc */
165     STGCALL2(fprintf,stderr,"REMOTE REF object entered!\n");
166     STGCALL1(shutdownHaskellAndExit, EXIT_FAILURE);
167   FE_
168 }
169
170 #endif /* PAR */
171
172 //@node Index,  , Info tables
173 //@subsection Index
174
175 //@index
176 //* BLOCKED_FETCH_entry::  @cindex\s-+BLOCKED_FETCH_entry
177 //* BLOCKED_FETCH_info::  @cindex\s-+BLOCKED_FETCH_info
178 //* FETCH_ME_BQ_info::  @cindex\s-+FETCH_ME_BQ_info
179 //* FETCH_ME_entry::  @cindex\s-+FETCH_ME_entry
180 //* FETCH_ME_info::  @cindex\s-+FETCH_ME_info
181 //@end index