fixes for Cpkvs, and for BigSim, avoid calling CmiHandleMessages() since this is...
[charm.git] / src / ck-com / ComlibStrategy.C
1
2 #include "charm++.h"
3 #include "envelope.h"
4
5 //calls ComlibNotifyMigrationDone(). Even compiles when -module comlib
6 //is not included. Hack to make loadbalancer work without comlib
7 //currently.
8 CkpvDeclare(int, migrationDoneHandlerID);
9
10 //Class that defines the entry methods that a Charm level strategy
11 //must define.  To write a new strategy inherit from this class and
12 //define the virtual methods.  Every strategy can also define its own
13 //constructor and have any number of arguments. Also call the parent
14 //class methods in those methods.
15
16 void CharmStrategy::insertMessage(MessageHolder *mh){
17     insertMessage((CharmMessageHolder *)mh);
18 }
19
20 void CharmStrategy::pup(PUP::er &p) {
21     Strategy::pup(p);
22     p | nginfo;
23     p | ginfo;
24     p | ainfo;
25     p | forwardOnMigration;
26 }
27
28 CharmMessageHolder::CharmMessageHolder(char * msg, int proc) 
29     : MessageHolder((char *)UsrToEnv(msg), proc, 
30                     UsrToEnv(msg)->getTotalsize()){
31     
32     sec_id = NULL;    
33 }
34
35 CharmMessageHolder::~CharmMessageHolder() { 
36 }
37
38 char * CharmMessageHolder::getCharmMessage(){
39     return (char *)EnvToUsr((envelope *) data);
40 }
41
42 void CharmMessageHolder::pup(PUP::er &p) {
43
44     //    CkPrintf("In CharmMessageHolder::pup \n"); 
45
46     MessageHolder::pup(p);
47
48     //Sec ID depends on the message
49     //Currently this pup is only being used for remote messages
50     sec_id = NULL;
51 }
52
53 PUPable_def(CharmStrategy);
54 PUPable_def(CharmMessageHolder);
55
56 ComlibNodeGroupInfo::ComlibNodeGroupInfo() {
57     isNodeGroup = 0;
58     ngid.setZero();
59 };
60
61 void ComlibNodeGroupInfo::pup(PUP::er &p) {
62     p | isNodeGroup;
63     p | ngid;
64 }
65
66 ComlibGroupInfo::ComlibGroupInfo() {
67     
68     isSrcGroup = 0;
69     isDestGroup = 0;
70     nsrcpes = 0;
71     ndestpes = 0;
72     srcpelist = NULL;
73     destpelist = NULL;
74     sgid.setZero();
75     dgid.setZero();
76 };
77
78 ComlibGroupInfo::~ComlibGroupInfo() {
79     if(nsrcpes > 0 && srcpelist != NULL)
80         delete [] srcpelist;
81
82     if(ndestpes > 0 && destpelist != NULL)
83         delete [] destpelist;
84 }
85
86 void ComlibGroupInfo::pup(PUP::er &p){
87
88     p | sgid;
89     p | dgid;
90     p | nsrcpes;
91     p | ndestpes;
92
93     p | isSrcGroup;
94     p | isDestGroup;
95
96     if(p.isUnpacking()) {
97         if(nsrcpes > 0) 
98             srcpelist = new int[nsrcpes];
99
100         if(ndestpes > 0) 
101             destpelist = new int[ndestpes];
102     }
103
104     if(nsrcpes > 0) 
105         p(srcpelist, nsrcpes);
106
107     if(ndestpes > 0) 
108         p(destpelist, ndestpes);
109 }
110
111 void ComlibGroupInfo::setSourceGroup(CkGroupID gid, int *pelist, 
112                                          int npes) {
113     this->sgid = gid;
114     srcpelist = pelist;
115     nsrcpes = npes;
116     isSrcGroup = 1;
117
118     if(nsrcpes == 0) {
119         nsrcpes = CkNumPes();
120         srcpelist = new int[nsrcpes];
121         for(int count =0; count < nsrcpes; count ++)
122             srcpelist[count] = count;
123     }
124 }
125
126 void ComlibGroupInfo::getSourceGroup(CkGroupID &gid, int *&pelist, 
127                                          int &npes){
128     gid = this->sgid;
129     npes = nsrcpes;
130
131     pelist = new int [nsrcpes];
132     memcpy(pelist, srcpelist, npes * sizeof(int));
133 }
134
135 void ComlibGroupInfo::getSourceGroup(CkGroupID &gid){
136     gid = this->sgid;
137 }
138
139 void ComlibGroupInfo::setDestinationGroup(CkGroupID gid, int *pelist, 
140                                          int npes) {
141     this->dgid = gid;
142     destpelist = pelist;
143     ndestpes = npes;
144     isDestGroup = 1;
145
146     if(ndestpes == 0) {
147         ndestpes = CkNumPes();
148         destpelist = new int[ndestpes];
149         for(int count =0; count < ndestpes; count ++)
150             destpelist[count] = count;
151     }
152 }
153
154 void ComlibGroupInfo::getDestinationGroup(CkGroupID &gid, int *&pelist, 
155                                          int &npes){
156     gid = this->dgid;
157     npes = ndestpes;
158
159     pelist = new int [ndestpes];
160     memcpy(pelist, destpelist, npes * sizeof(int));
161 }
162
163 void ComlibGroupInfo::getDestinationGroup(CkGroupID &gid){
164     gid = this->dgid;
165 }
166
167 void ComlibGroupInfo::getCombinedPeList(int *&pelist, int &npes) {
168     int count = 0;        
169     pelist = 0;
170     npes = 0;
171
172     pelist = new int[CkNumPes()];
173     if(nsrcpes == 0 || ndestpes == 0) {
174         npes = CkNumPes();        
175         for(count = 0; count < CkNumPes(); count ++) 
176             pelist[count] = count;                         
177     }
178     else {        
179         npes = ndestpes;
180         memcpy(pelist, destpelist, npes * sizeof(int));
181         
182         //Add source processors to the destination processors
183         //already obtained
184         for(int count = 0; count < nsrcpes; count++) {
185             int p = srcpelist[count];
186
187             for(count = 0; count < npes; count ++)
188                 if(pelist[count] == p)
189                     break;
190
191             if(count == npes)
192                 pelist[npes ++] = p;
193         }                        
194     }
195 }
196
197 ComlibArrayInfo::ComlibArrayInfo() {
198
199     src_aid.setZero();
200     nSrcIndices = -1;
201     src_elements = NULL;
202     isSrcArray = 0;
203
204     dest_aid.setZero();
205     nDestIndices = -1;
206     dest_elements = NULL;
207     isDestArray = 0;
208 };
209
210 ComlibArrayInfo::~ComlibArrayInfo() {
211     //CkPrintf("in comlibarrayinfo destructor\n");
212
213     if(nSrcIndices > 0)
214         delete [] src_elements;
215
216     if(nDestIndices > 0)
217         delete [] dest_elements;
218 }
219
220 void ComlibArrayInfo::setSourceArray(CkArrayID aid, 
221                                          CkArrayIndexMax *e, int nind){
222     src_aid = aid;
223     isSrcArray = 1;    
224     nSrcIndices = nind;
225     if(nind > 0) {
226         src_elements = new CkArrayIndexMax[nind];
227         memcpy(src_elements, e, sizeof(CkArrayIndexMax) * nind);
228     }
229 }
230
231
232 void ComlibArrayInfo::getSourceArray(CkArrayID &aid, 
233                                          CkArrayIndexMax *&e, int &nind){
234     aid = src_aid;
235     nind = nSrcIndices;
236     e = src_elements;
237 }
238
239
240 void ComlibArrayInfo::setDestinationArray(CkArrayID aid, 
241                                           CkArrayIndexMax *e, int nind){
242     dest_aid = aid;
243     isDestArray = 1;    
244     nDestIndices = nind;
245     if(nind > 0) {
246         dest_elements = new CkArrayIndexMax[nind];
247         memcpy(dest_elements, e, sizeof(CkArrayIndexMax) * nind);
248     }
249 }
250
251
252 void ComlibArrayInfo::getDestinationArray(CkArrayID &aid, 
253                                           CkArrayIndexMax *&e, int &nind){
254     aid = dest_aid;
255     nind = nDestIndices;
256     e = dest_elements;
257 }
258
259
260 //Each strategy must define his own Pup interface.
261 void ComlibArrayInfo::pup(PUP::er &p){ 
262     p | src_aid;
263     p | nSrcIndices;
264     p | isSrcArray;
265     
266     p | dest_aid;
267     p | nDestIndices;
268     p | isDestArray;
269     
270     if(p.isUnpacking() && nSrcIndices > 0) 
271         src_elements = new CkArrayIndexMax[nSrcIndices];
272     
273     if(p.isUnpacking() && nDestIndices > 0) 
274         dest_elements = new CkArrayIndexMax[nDestIndices];        
275     
276     if(nSrcIndices > 0)
277         p((char *)src_elements, nSrcIndices * sizeof(CkArrayIndexMax));    
278     else
279         src_elements = NULL;
280
281     if(nDestIndices > 0)
282         p((char *)dest_elements, nDestIndices * sizeof(CkArrayIndexMax));    
283     else
284         dest_elements = NULL;
285
286     localDestIndexVec.resize(0);
287 }
288
289 //Get the list of destination processors
290 void ComlibArrayInfo::getDestinationPeList(int *&destpelist, int &ndestpes) {
291     
292     int count = 0, acount =0;
293     
294     //Destination has not been set
295     if(nDestIndices < 0) {
296         destpelist = 0;
297         ndestpes = 0;
298         return;
299     }
300
301     //Create an array of size CkNumPes()
302     //Inefficient in space
303     ndestpes = CkNumPes();
304     destpelist = new int[ndestpes];
305
306     memset(destpelist, 0, ndestpes * sizeof(int));    
307
308     if(nDestIndices == 0){
309         for(count =0; count < CkNumPes(); count ++) 
310             destpelist[count] = count;             
311         return;
312     }
313
314     ndestpes = 0;
315
316     //Find the last known processors of the array elements
317     for(acount = 0; acount < nDestIndices; acount++) {
318
319         int p = ComlibGetLastKnown(dest_aid, dest_elements[acount]); 
320         
321         for(count = 0; count < ndestpes; count ++)
322             if(destpelist[count] == p)
323                 break;
324         
325         if(count == ndestpes) {
326             destpelist[ndestpes ++] = p; 
327         }       
328     }                            
329 }
330
331 void ComlibArrayInfo::getSourcePeList(int *&srcpelist, int &nsrcpes) {
332     
333     int count = 0, acount =0;
334
335     if(nSrcIndices < 0) {
336         srcpelist = 0;
337         nsrcpes = 0;
338         return;
339     }
340
341     nsrcpes = CkNumPes();
342     srcpelist = new int[nsrcpes];
343
344     memset(srcpelist, 0, nsrcpes * sizeof(int));    
345
346     if(nSrcIndices == 0){
347         for(count =0; count < CkNumPes(); count ++) 
348             srcpelist[count] = count;             
349         return;
350     }
351
352     nsrcpes = 0;
353     for(acount = 0; acount < nSrcIndices; acount++) {
354         
355         int p = ComlibGetLastKnown(src_aid, src_elements[acount]); 
356         
357         for(count = 0; count < nsrcpes; count ++)
358             if(srcpelist[count] == p)
359                 break;
360         
361         if(count == nsrcpes) {
362             srcpelist[nsrcpes ++] = p; 
363         }       
364     }                            
365 }
366
367 void ComlibArrayInfo::getCombinedPeList(int *&pelist, int &npes) {
368
369     int count = 0;        
370     pelist = 0;
371     npes = 0;
372     
373     //Both arrays empty;
374     //Sanity check, this should really not happen
375     if(nSrcIndices < 0 && nDestIndices < 0) {
376         CkAbort("Arrays have not been set\n");
377         return;
378     }
379     
380     //One of them is the entire array Hence set the number of
381     //processors to all Currently does not work for the case where
382     //number of array elements less than number of processors
383     //Will fix it later!
384     if(nSrcIndices == 0 || nDestIndices == 0) {
385         npes = CkNumPes();        
386         pelist = new int[npes];
387         for(count = 0; count < CkNumPes(); count ++) 
388             pelist[count] = count;                         
389     }
390     else {
391         getDestinationPeList(pelist, npes);
392         
393         //Destination has not been set
394         //Strategy does not care about destination
395         //Is an error case
396         if(npes == 0)
397             pelist = new int[CkNumPes()];
398         
399         //Add source processors to the destination processors
400         //already obtained
401         for(int acount = 0; acount < nSrcIndices; acount++) {
402             int p = ComlibGetLastKnown(src_aid, src_elements[acount]);
403
404             for(count = 0; count < npes; count ++)
405                 if(pelist[count] == p)
406                     break;
407             if(count == npes)
408                 pelist[npes ++] = p;
409         }                        
410     }
411 }
412
413 void ComlibArrayInfo::localBroadcast(envelope *env) {
414     //Insert all local elements into a vector
415     if(localDestIndexVec.size()==0 && !dest_aid.isZero()) {
416         CkArray *dest_array = CkArrayID::CkLocalBranch(dest_aid);
417         
418         if(nDestIndices == 0){            
419             dest_array->getComlibArrayListener()->getLocalIndices
420                 (localDestIndexVec);
421         }
422         else {
423             for(int count = 0; count < nDestIndices; count++) {
424                 if(ComlibGetLastKnown(dest_aid, dest_elements[count])
425                    == CkMyPe())
426                     localDestIndexVec.insertAtEnd(dest_elements[count]);
427             }
428         }
429     }
430
431     ComlibArrayInfo::localMulticast(&localDestIndexVec, env);
432 }
433
434 /*
435   This method multicasts the message to all the indices in vec.  It
436   also takes care to check if the entry method is readonly or not? If
437   readonly (nokeep) the message is not copied.
438
439   It also makes sure that the entry methods are logged in projections
440   and that the array manager is notified about array element
441   migrations.  Hence this function should be used extensively in the
442   communication library strategies */
443
444 #include "register.h"
445 void ComlibArrayInfo::localMulticast(CkVec<CkArrayIndexMax>*vec,
446                                      envelope *env){
447
448     //Multicast the messages to all elements in vec
449     int nelements = vec->size();
450     if(nelements == 0) {
451         CmiFree(env);
452         return;
453     }
454
455     void *msg = EnvToUsr(env);
456     int ep = env->getsetArrayEp();
457     CkUnpackMessage(&env);
458
459     CkArrayID dest_aid = env->getsetArrayMgr();
460     env->setPacked(0);
461     env->getsetArrayHops()=1;
462     env->setUsed(0);
463
464     for(int count = 0; count < nelements; count ++){
465         CkArrayIndexMax idx = (*vec)[count];
466         
467         //if(comm_debug) idx.print();
468
469         env->getsetArrayIndex() = idx;
470         
471         CkArray *a=(CkArray *)_localBranch(dest_aid);
472         if(_entryTable[ep]->noKeep)
473             a->deliver((CkArrayMessage *)msg, CkDeliver_inline, CK_MSG_KEEP);
474         else {
475             void *newmsg = CkCopyMsg(&msg);
476             a->deliver((CkArrayMessage *)newmsg, CkDeliver_queue);
477         }
478
479     }
480
481     CmiFree(env);
482 }
483
484 /* Delivers a message to an array element, making sure that
485    projections is notified */
486 void ComlibArrayInfo::deliver(envelope *env){
487     
488     env->setUsed(0);
489     env->getsetArrayHops()=1;
490     CkUnpackMessage(&env);
491     
492     CkArray *a=(CkArray *)_localBranch(env->getsetArrayMgr());
493     a->deliver((CkArrayMessage *)EnvToUsr(env), CkDeliver_queue);    
494 }
495
496 void ComlibNotifyMigrationDone() {
497     if(CkpvInitialized(migrationDoneHandlerID)) 
498         if(CkpvAccess(migrationDoneHandlerID) > 0) {
499             char *msg = (char *)CmiAlloc(CmiReservedHeaderSize);
500             CmiSetHandler(msg, CkpvAccess(migrationDoneHandlerID));
501 #if CMK_BLUEGENE_CHARM
502             // bluegene charm should avoid directly calling converse
503             CmiSyncSendAndFree(CkMyPe(), CmiReservedHeaderSize, msg);
504 #else
505             CmiHandleMessage(msg);
506 #endif
507         }
508 }
509
510
511 //Stores the location of many array elements used by the
512 //strategies.  Since hash table returns a reference to the object
513 //and for an int that will be 0, the actual value stored is pe +
514 //CkNumPes so 0 would mean processor -CkNumPes which is invalid.
515 CkpvDeclare(ClibLocationTableType *, locationTable);
516
517 int ComlibGetLastKnown(CkArrayID aid, CkArrayIndexMax idx) {
518     //CProxy_ComlibManager cgproxy(CkpvAccess(cmgrID));
519     //return (cgproxy.ckLocalBranch())->getLastKnown(aid, idx);
520
521     if(!CpvInitialized(locationTable)) {
522         CkAbort("Uninitialized table\n");
523     }
524
525     if(CkpvAccess(locationTable) == NULL)
526         CkAbort("comlib location table is NULL\n");
527
528     ClibGlobalArrayIndex cidx;
529     cidx.aid = aid;
530     cidx.idx = idx;
531     int pe = CkpvAccess(locationTable)->get(cidx);
532     
533     if(pe == 0) {
534         //Array element does not exist in the table
535         
536         CkArray *array = CkArrayID::CkLocalBranch(aid);
537         pe = array->lastKnown(idx) + CkNumPes();
538         CkpvAccess(locationTable)->put(cidx) = pe;
539     }
540     //CkPrintf("last pe = %d \n", pe - CkNumPes());
541     
542     return pe - CkNumPes();
543 }