- Moved 4 files (ComlibStrategy.*, ComlibArrayListener.*) from ck-core to the
[charm.git] / src / ck-com / ComlibStrategy.C
1
2 #include "charm++.h"
3 #include "envelope.h"
4
5 //Class that defines the entry methods that a Charm level strategy
6 //must define.  To write a new strategy inherit from this class and
7 //define the virtual methods.  Every strategy can also define its own
8 //constructor and have any number of arguments. Also call the parent
9 //class methods in those methods.
10
11 void CharmStrategy::insertMessage(MessageHolder *mh){
12     insertMessage((CharmMessageHolder *)mh);
13 }
14
15 void CharmStrategy::pup(PUP::er &p) {
16     Strategy::pup(p);
17     p | nginfo;
18     p | ginfo;
19     p | ainfo;
20     p | forwardOnMigration;
21 }
22
23 CharmMessageHolder::CharmMessageHolder(char * msg, int proc) 
24     : MessageHolder((char *)UsrToEnv(msg), proc, 
25                     UsrToEnv(msg)->getTotalsize()){
26     
27     sec_id = NULL;    
28 }
29
30 CharmMessageHolder::~CharmMessageHolder() { 
31 }
32
33 char * CharmMessageHolder::getCharmMessage(){
34     return (char *)EnvToUsr((envelope *) data);
35 }
36
37 void CharmMessageHolder::pup(PUP::er &p) {
38
39     //    CkPrintf("In CharmMessageHolder::pup \n"); 
40
41     MessageHolder::pup(p);
42
43     //Sec ID depends on the message
44     //Currently this pup is only being used for remote messages
45     sec_id = NULL;
46 }
47
48 PUPable_def(CharmStrategy);
49 PUPable_def(CharmMessageHolder);
50
51 ComlibNodeGroupInfo::ComlibNodeGroupInfo() {
52     isNodeGroup = 0;
53     ngid.setZero();
54 };
55
56 void ComlibNodeGroupInfo::pup(PUP::er &p) {
57     p | isNodeGroup;
58     p | ngid;
59 }
60
61 ComlibGroupInfo::ComlibGroupInfo() {
62     
63     isGroup = 0;
64     nsrcpes = 0;
65     srcpelist = NULL;
66     gid.setZero();
67 };
68
69 void ComlibGroupInfo::pup(PUP::er &p){
70
71     p | gid;
72     p | nsrcpes;
73
74     if(p.isUnpacking()) {
75         if(nsrcpes >0) 
76             srcpelist = new int[nsrcpes];
77     }
78
79     if(nsrcpes > 0) 
80         p(srcpelist, nsrcpes);
81 }
82
83 void ComlibGroupInfo::setSourceGroup(CkGroupID gid, int *pelist, 
84                                          int npes) {
85     this->gid = gid;
86     srcpelist = pelist;
87     nsrcpes = npes;
88     isGroup = 1;
89 }
90
91 void ComlibGroupInfo::getSourceGroup(CkGroupID &gid, int *&pelist, 
92                                          int &npes){
93     gid = this->gid;
94
95     pelist = srcpelist;
96     npes = nsrcpes;
97 }
98
99 void ComlibGroupInfo::getSourceGroup(CkGroupID &gid){
100     gid = this->gid;
101 }
102
103 ComlibArrayInfo::ComlibArrayInfo() {
104
105     src_aid.setZero();
106     nSrcIndices = -1;
107     src_elements = NULL;
108     isSrcArray = 0;
109
110     dest_aid.setZero();
111     nDestIndices = -1;
112     dest_elements = NULL;
113     isDestArray = 0;
114 };
115
116 void ComlibArrayInfo::setSourceArray(CkArrayID aid, 
117                                          CkArrayIndexMax *e, int nind){
118     src_aid = aid;
119     isSrcArray = 1;    
120     nSrcIndices = nind;
121     if(nind > 0) {
122         src_elements = new CkArrayIndexMax[nind];
123         memcpy(src_elements, e, sizeof(CkArrayIndexMax) * nind);
124     }
125 }
126
127
128 void ComlibArrayInfo::getSourceArray(CkArrayID &aid, 
129                                          CkArrayIndexMax *&e, int &nind){
130     aid = src_aid;
131     nind = nSrcIndices;
132     e = src_elements;
133 }
134
135
136 void ComlibArrayInfo::setDestinationArray(CkArrayID aid, 
137                                           CkArrayIndexMax *e, int nind){
138     dest_aid = aid;
139     isDestArray = 1;    
140     nDestIndices = nind;
141     if(nind > 0) {
142         dest_elements = new CkArrayIndexMax[nind];
143         memcpy(dest_elements, e, sizeof(CkArrayIndexMax) * nind);
144     }
145 }
146
147
148 void ComlibArrayInfo::getDestinationArray(CkArrayID &aid, 
149                                           CkArrayIndexMax *&e, int &nind){
150     aid = dest_aid;
151     nind = nDestIndices;
152     e = dest_elements;
153 }
154
155
156 //Each strategy must define his own Pup interface.
157 void ComlibArrayInfo::pup(PUP::er &p){ 
158     p | src_aid;
159     p | nSrcIndices;
160     p | isSrcArray;
161     
162     p | dest_aid;
163     p | nDestIndices;
164     p | isDestArray;
165     
166     if(p.isUnpacking() && nSrcIndices > 0) 
167         src_elements = new CkArrayIndexMax[nSrcIndices];
168     
169     if(p.isUnpacking() && nDestIndices > 0) 
170         dest_elements = new CkArrayIndexMax[nDestIndices];        
171     
172     if(nSrcIndices > 0)
173         p((char *)src_elements, nSrcIndices * sizeof(CkArrayIndexMax));    
174     else
175         src_elements = NULL;
176
177     if(nDestIndices > 0)
178         p((char *)dest_elements, nDestIndices * sizeof(CkArrayIndexMax));    
179     else
180         dest_elements = NULL;
181
182     //Insert all local elements into a vector
183     if(p.isUnpacking() && !dest_aid.isZero()) {
184         CkArray *dest_array = CkArrayID::CkLocalBranch(dest_aid);
185         
186         if(nDestIndices == 0){            
187             dest_array->getComlibArrayListener()->getLocalIndices
188                 (localDestIndexVec);
189         }
190         else {
191             for(int count = 0; count < nDestIndices; count++) 
192                 if(dest_array->lastKnown(dest_elements[count]) == CkMyPe())
193                     localDestIndexVec.insertAtEnd(dest_elements[count]);
194         }
195     }
196 }
197
198 //Get the list of destination processors
199 void ComlibArrayInfo::getDestinationPeList(int *&destpelist, int &ndestpes) {
200     
201     int count = 0, acount =0;
202     
203     //Destination has not been set
204     if(nDestIndices < 0) {
205         destpelist = 0;
206         ndestpes = 0;
207         return;
208     }
209
210     //Create an array of size CkNumPes()
211     //Inefficient in space
212     ndestpes = CkNumPes();
213     destpelist = new int[ndestpes];
214
215     memset(destpelist, 0, ndestpes * sizeof(int));    
216
217     if(nDestIndices == 0){
218         for(count =0; count < CkNumPes(); count ++) 
219             destpelist[count] = count;             
220         return;
221     }
222
223     ndestpes = 0;
224
225     //Find the last known processors of the array elements
226     for(acount = 0; acount < nDestIndices; acount++) {
227         int p = CkArrayID::CkLocalBranch(dest_aid)->
228             lastKnown(dest_elements[acount]);        
229         
230         for(count = 0; count < ndestpes; count ++)
231             if(destpelist[count] == p)
232                 break;
233         
234         if(count == ndestpes) {
235             destpelist[ndestpes ++] = p; 
236         }       
237     }                            
238 }
239
240 void ComlibArrayInfo::getSourcePeList(int *&srcpelist, int &nsrcpes) {
241     
242     int count = 0, acount =0;
243
244     if(nSrcIndices < 0) {
245         srcpelist = 0;
246         nsrcpes = 0;
247         return;
248     }
249
250     nsrcpes = CkNumPes();
251     srcpelist = new int[nsrcpes];
252
253     memset(srcpelist, 0, nsrcpes * sizeof(int));    
254
255     if(nSrcIndices == 0){
256         for(count =0; count < CkNumPes(); count ++) 
257             srcpelist[count] = count;             
258         return;
259     }
260
261     nsrcpes = 0;
262     for(acount = 0; acount < nSrcIndices; acount++) {
263         int p = CkArrayID::CkLocalBranch(src_aid)->
264             lastKnown(src_elements[acount]);        
265         
266         for(count = 0; count < nsrcpes; count ++)
267             if(srcpelist[count] == p)
268                 break;
269         
270         if(count == nsrcpes) {
271             srcpelist[nsrcpes ++] = p; 
272         }       
273     }                            
274 }
275
276 void ComlibArrayInfo::getCombinedPeList(int *&pelist, int &npes) {
277
278     int count = 0;        
279     pelist = 0;
280     npes = 0;
281     
282     //Both arrays empty;
283     //Sanity check, this should really not happen
284     if(nSrcIndices < 0 && nDestIndices < 0) {
285         CkAbort("Arrays have not been set\n");
286         return;
287     }
288     
289     //One of them is the entire array Hence set the number of
290     //processors to all Currently does not work for the case where
291     //number of array elements less than number of processors
292     //Will fix it later!
293     if(nSrcIndices == 0 || nDestIndices == 0) {
294         npes = CkNumPes();        
295         pelist = new int[npes];
296         for(count = 0; count < CkNumPes(); count ++) 
297             pelist[count] = count;                         
298     }
299     else {
300         getDestinationPeList(pelist, npes);
301         
302         //Destination has not been set
303         //Strategy does not care about destination
304         //Is an error case
305         if(npes == 0)
306             pelist = new int[CkNumPes()];
307         
308         //Add source processors to the destination processors
309         //already obtained
310         for(int acount = 0; acount < nSrcIndices; acount++) {
311             int p = CkArrayID::CkLocalBranch(src_aid)->
312                 lastKnown(src_elements[acount]);
313             
314             for(count = 0; count < npes; count ++)
315                 if(pelist[count] == p)
316                     break;
317             if(count == npes)
318                 pelist[npes ++] = p;
319         }                        
320     }
321 }
322
323 void ComlibArrayInfo::localBroadcast(envelope *env) {
324     ComlibArrayInfo::localMulticast(&localDestIndexVec, env);
325 }
326
327 /*
328   This method multicasts the message to all the indices in vec.  It
329   also takes care to check if the entry method is readonly or not? If
330   readonly (nokeep) the message is not copied.
331
332   It also makes sure that the entry methods are logged in projections
333   and that the array manager is notified about array element
334   migrations.  Hence this function should be used extensively in the
335   communication library strategies */
336
337 #include "register.h"
338 void ComlibArrayInfo::localMulticast(CkVec<CkArrayIndexMax>*vec,
339                                      envelope *env){
340
341     //Multicast the messages to all elements in vec
342     int nelements = vec->size();
343     if(nelements == 0) {
344         CmiFree(env);
345         return;
346     }
347
348     void *msg = EnvToUsr(env);
349     int ep = env->getsetArrayEp();
350     CkUnpackMessage(&env);
351
352     CkArrayID dest_aid = env->getsetArrayMgr();
353     env->setPacked(0);
354     env->getsetArrayHops()=1;
355     env->setUsed(0);
356
357     for(int count = 0; count < nelements; count ++){
358         CkArrayIndexMax idx = (*vec)[count];
359         
360         //if(comm_debug) idx.print();
361
362         env->getsetArrayIndex() = idx;
363         
364         CkArray *a=(CkArray *)_localBranch(dest_aid);
365         if(_entryTable[ep]->noKeep)
366             a->deliver((CkArrayMessage *)msg, CkDeliver_inline, CK_MSG_KEEP);
367         else {
368             void *newmsg = CkCopyMsg(&msg);
369             a->deliver((CkArrayMessage *)newmsg, CkDeliver_queue);
370         }
371
372     }
373
374     CmiFree(env);
375 }
376
377 /* Delivers a message to an array element, making sure that
378    projections is notified */
379 void ComlibArrayInfo::deliver(envelope *env){
380     
381     env->setUsed(0);
382     env->getsetArrayHops()=1;
383     CkUnpackMessage(&env);
384     
385     CkArray *a=(CkArray *)_localBranch(env->getsetArrayMgr());
386     a->deliver((CkArrayMessage *)EnvToUsr(env), CkDeliver_queue);    
387 }