Remove CMK_CONVERSE_MPI definition from bluegenep dcmf builds
[charm.git] / src / arch / pami / machine.c
1
2 #include <stdio.h>
3 #include <errno.h>
4 #include <stdlib.h>
5 #include <unistd.h>
6 #include <math.h>
7 #include <string.h>
8 #include "machine.h"
9 #include "converse.h"
10 #include "pcqueue.h"
11 #include "assert.h"
12 #include "malloc.h"
13
14 #include <hwi/include/bqc/A2_inlines.h>
15 #include "pami.h"
16 #include "pami_sys.h"
17
18 #if CMK_SMP
19 #define CMK_USE_L2ATOMICS   1
20 #endif
21
22 #if CMK_SMP && CMK_USE_L2ATOMICS
23 #include "L2AtomicQueue.h"
24 #endif
25
26 char *ALIGN_32(char *p) {
27   return((char *)((((unsigned long)p)+0x1f) & (~0x1FUL)));
28 }
29
30 #if CMK_SMP && CMK_USE_L2ATOMICS
31 CpvDeclare(L2AtomicQueue*, broadcast_q);          
32 #else
33 CpvDeclare(PCQueue, broadcast_q);                 //queue to send broadcast messages
34 #endif
35
36 #if CMK_NODE_QUEUE_AVAILABLE
37 CsvDeclare(PCQueue, node_bcastq);
38 CsvDeclare(CmiNodeLock, node_bcastLock);
39 #endif
40
41 //#define ENABLE_BROADCAST_THROTTLE 1
42
43 /*To reduce the buffer used in broadcast and distribute the load from
44   broadcasting node, define CMK_BROADCAST_SPANNING_TREE enforce the use of
45   spanning tree broadcast algorithm.
46   This will use the fourth short in message as an indicator of spanning tree
47   root.
48 */
49 #if CMK_SMP
50 #define CMK_BROADCAST_SPANNING_TREE    1
51 #else
52 #define CMK_BROADCAST_SPANNING_TREE    1
53 #endif /* CMK_SMP */
54
55 #define BROADCAST_SPANNING_FACTOR     4
56
57 //The root of the message infers the type of the message
58 // 1. root is 0, then it is a normal point-to-point message
59 // 2. root is larger than 0 (>=1), then it is a broadcast message across all processors (cores)
60 // 3. root is less than 0 (<=-1), then it is a broadcast message across all nodes
61 #define CMI_BROADCAST_ROOT(msg)          ((CmiMsgHeaderBasic *)msg)->root
62 #define CMI_IS_BCAST_ON_CORES(msg) (CMI_BROADCAST_ROOT(msg) > 0)
63 #define CMI_IS_BCAST_ON_NODES(msg) (CMI_BROADCAST_ROOT(msg) < 0)
64 #define CMI_GET_CYCLE(msg)               ((CmiMsgHeaderBasic *)msg)->root
65
66 #define CMI_DEST_RANK(msg)               ((CmiMsgHeaderBasic *)msg)->rank
67 #define CMI_MAGIC(msg)                   ((CmiMsgHeaderBasic *)msg)->magic
68
69 /* FIXME: need a random number that everyone agrees ! */
70 #define CHARM_MAGIC_NUMBER               126
71
72 #if !CMK_OPTIMIZE
73 static int checksum_flag = 0;
74 extern unsigned char computeCheckSum(unsigned char *data, int len);
75
76 #define CMI_SET_CHECKSUM(msg, len)      \
77         if (checksum_flag)  {   \
78           ((CmiMsgHeaderBasic *)msg)->cksum = 0;        \
79           ((CmiMsgHeaderBasic *)msg)->cksum = computeCheckSum((unsigned char*)msg, len);        \
80         }
81
82 #define CMI_CHECK_CHECKSUM(msg, len)    \
83         if (checksum_flag)      \
84           if (computeCheckSum((unsigned char*)msg, len) != 0)  { \
85             printf("\n\n------------------------------\n\nReceiver %d size %d:", CmiMyPe(), len); \
86             for(count = 0; count < len; count++) { \
87                 printf("%2x", msg[count]);                 \
88             }                                             \
89             printf("------------------------------\n\n"); \
90             CmiAbort("Fatal error: checksum doesn't agree!\n"); \
91           }
92 #else
93 #define CMI_SET_CHECKSUM(msg, len)
94 #define CMI_CHECK_CHECKSUM(msg, len)
95 #endif
96
97 #define CMI_SET_BROADCAST_ROOT(msg, root)  CMI_BROADCAST_ROOT(msg) = (root);
98
99 #  define CMI_SET_CYCLE(msg, cycle)
100
101 int               _Cmi_numpes;
102 int               _Cmi_mynode;    /* Which address space am I */
103 int               _Cmi_mynodesize;/* Number of processors in my address space */
104 int               _Cmi_numnodes;  /* Total number of address spaces */
105 int                Cmi_nodestart; /* First processor in this address space */
106 CpvDeclare(void*, CmiLocalQueue);
107
108
109 #if CMK_NODE_QUEUE_AVAILABLE
110 #define SMP_NODEMESSAGE   (0xFB) // rank of the node message when node queue
111                                  // is available
112 #define NODE_BROADCAST_OTHERS (-1)
113 #define NODE_BROADCAST_ALL    (-2)
114 #endif
115
116
117 typedef struct ProcState {
118     /* PCQueue      sendMsgBuf; */      /* per processor message sending queue */
119 #if CMK_SMP && CMK_USE_L2ATOMICS
120     L2AtomicQueue   atomic_queue;
121 #endif
122     CmiNodeLock  recvLock;              /* for cs->recv */
123     CmiNodeLock bcastLock;
124 } ProcState;
125
126 static ProcState  *procState;
127
128 #if CMK_SMP && !CMK_MULTICORE
129 //static volatile int commThdExit = 0;
130 //static CmiNodeLock commThdExitLock = 0;
131 #endif
132
133 void ConverseRunPE(int everReturn);
134 static void CommunicationServer(int sleepTime);
135 static void CommunicationServerThread(int sleepTime);
136
137 static void CmiNetworkBarrier();
138
139 //So far we dont define any comm threads
140 int Cmi_commthread = 0;
141
142 #include "machine-smp.c"
143 CsvDeclare(CmiNodeState, NodeState);
144 #include "immediate.c"
145
146 void AdvanceCommunications();
147
148
149 #if !CMK_SMP
150 /************ non SMP **************/
151 static struct CmiStateStruct Cmi_state;
152 int _Cmi_mype;
153 int _Cmi_myrank;
154
155 void CmiMemLock(void) {}
156 void CmiMemUnlock(void) {}
157
158 #define CmiGetState() (&Cmi_state)
159 #define CmiGetStateN(n) (&Cmi_state)
160
161 //void CmiYield(void) { sleep(0); }
162
163 static void CmiStartThreads(char **argv) {
164     CmiStateInit(Cmi_nodestart, 0, &Cmi_state);
165     _Cmi_mype = Cmi_nodestart;
166     _Cmi_myrank = 0;
167 }
168 #endif  /* !CMK_SMP */
169
170 //int received_immediate;
171 //int received_broadcast;
172
173 /*Add a message to this processor's receive queue, pe is a rank */
174 void CmiPushPE(int pe,void *msg) {
175     CmiState cs = CmiGetStateN(pe);
176     MACHSTATE2(3,"Pushing message into rank %d's queue %p{",pe, cs->recv);
177 #if CMK_IMMEDIATE_MSG
178     if (CmiIsImmediate(msg)) {
179         /**(CmiUInt2 *)msg = pe;*/
180         //received_immediate = 1;
181         //printf("PushPE: N[%d]P[%d]R[%d] received an imm msg with hdl: %p\n", CmiMyNode(), CmiMyPe(), CmiMyRank(), CmiGetHandler(msg));
182         //CMI_DEST_RANK(msg) = pe;
183         CmiPushImmediateMsg(msg);
184         return;
185     }
186 #endif
187
188 #if CMK_SMP && CMK_USE_L2ATOMICS
189     L2AtomicEnqueue(&procState[pe].atomic_queue, msg);
190 #else
191     PCQueuePush(cs->recv,(char *)msg);
192 #endif
193     //printf("%d: PCQueue length = %d, msg = %x\n", CmiMyPe(), PCQueueLength(cs->recv), msg);
194
195     CmiIdleLock_addMessage(&cs->idle);
196     MACHSTATE1(3,"} Pushing message into rank %d's queue done",pe);
197 }
198
199 #if CMK_NODE_QUEUE_AVAILABLE
200 /*Add a message to this processor's receive queue */
201 static void CmiPushNode(void *msg) {
202     MACHSTATE(3,"Pushing message into NodeRecv queue");
203 #if CMK_IMMEDIATE_MSG
204     if (CmiIsImmediate(msg)) {
205         //printf("PushNode: N[%d]P[%d]R[%d] received an imm msg with hdl: %p\n", CmiMyNode(), CmiMyPe(), CmiMyRank(), CmiGetHandler(msg));
206         //CMI_DEST_RANK(msg) = 0;
207         CmiPushImmediateMsg(msg);
208         return;
209     }
210 #endif
211     CmiLock(CsvAccess(NodeState).CmiNodeRecvLock);
212     PCQueuePush(CsvAccess(NodeState).NodeRecv,msg);
213     CmiUnlock(CsvAccess(NodeState).CmiNodeRecvLock);
214     {
215         CmiState cs=CmiGetStateN(0);
216         CmiIdleLock_addMessage(&cs->idle);
217     }
218 }
219 #endif /* CMK_NODE_QUEUE_AVAILABLE */
220
221 #define MAX_NUM_CONTEXTS  64
222
223 #if CMK_SMP 
224 #define CMK_PAMI_MULTI_CONTEXT  1
225 #else
226 #define CMK_PAMI_MULTI_CONTEXT  0
227 #endif
228
229 #if CMK_PAMI_MULTI_CONTEXT
230 volatile int msgQueueLen [MAX_NUM_CONTEXTS];
231 volatile int outstanding_recvs [MAX_NUM_CONTEXTS];
232 #define THREADS_PER_CONTEXT 4
233 #define LTPS                2 //Log Threads Per Context (TPS)
234 #define  MY_CONTEXT_ID() (CmiMyRank() >> LTPS)
235 #define  MY_CONTEXT()    (cmi_pami_contexts[CmiMyRank() >> LTPS])
236
237 #define  INCR_MSGQLEN()  //(msgQueueLen[CmiMyRank() >> LTPS] ++)
238 #define  DECR_MSGQLEN()  //(msgQueueLen[CmiMyRank() >> LTPS] --)
239 #define  MSGQLEN()       0 //(msgQueueLen[CmiMyRank() >> LTPS])
240 #define  INCR_ORECVS()   //(outstanding_recvs[CmiMyRank() >> LTPS] ++)
241 #define  DECR_ORECVS()   //(outstanding_recvs[CmiMyRank() >> LTPS] --)
242 #define  ORECVS()        0 //(outstanding_recvs[CmiMyRank() >> LTPS])
243 #else
244 volatile int msgQueueLen;
245 volatile int outstanding_recvs;
246 #define  MY_CONTEXT_ID() (0)
247 #define  MY_CONTEXT()    (cmi_pami_contexts[0])
248
249 #define  INCR_MSGQLEN()  (msgQueueLen ++)
250 #define  DECR_MSGQLEN()  (msgQueueLen --)
251 #define  MSGQLEN()       (msgQueueLen)
252 #define  INCR_ORECVS()   (outstanding_recvs ++)
253 #define  DECR_ORECVS()   (outstanding_recvs --)
254 #define  ORECVS()        (outstanding_recvs)
255 #endif
256
257 #if CMK_SMP 
258 #define PAMIX_CONTEXT_LOCK_INIT(x)
259 #define PAMIX_CONTEXT_LOCK(x)        if(LTPS) PAMI_Context_lock(x)
260 #define PAMIX_CONTEXT_UNLOCK(x)      if(LTPS) {ppc_msync(); PAMI_Context_unlock(x);}
261 #define PAMIX_CONTEXT_TRYLOCK(x)     ((LTPS)?(PAMI_Context_trylock(x) == PAMI_SUCCESS):(1))
262 #else
263 #define PAMIX_CONTEXT_LOCK_INIT(x)
264 #define PAMIX_CONTEXT_LOCK(x)
265 #define PAMIX_CONTEXT_UNLOCK(x)
266 #endif
267
268
269 static char     **Cmi_argv;
270 static char     **Cmi_argvcopy;
271 static CmiStartFn Cmi_startfn;   /* The start function */
272 static int        Cmi_usrsched;  /* Continue after start function finishes? */
273
274 extern void ConverseCommonInit(char **argv);
275 extern void ConverseCommonExit(void);
276 extern void CthInit(char **argv);
277
278 static void SendMsgsUntil(int);
279
280
281 void SendSpanningChildren(int size, char *msg);
282 #if CMK_NODE_QUEUE_AVAILABLE
283 void SendSpanningChildrenNode(int size, char *msg);
284 #endif
285
286 typedef struct {
287     int sleepMs; /*Milliseconds to sleep while idle*/
288     int nIdles; /*Number of times we've been idle in a row*/
289     CmiState cs; /*Machine state*/
290 } CmiIdleState;
291
292 static CmiIdleState *CmiNotifyGetState(void) {
293     CmiIdleState *s=(CmiIdleState *)CmiAlloc(sizeof(CmiIdleState));
294     s->sleepMs=0;
295     s->nIdles=0;
296     s->cs=CmiGetState();
297     return s;
298 }
299
300
301 static void send_done(pami_context_t ctxt, void *data, pami_result_t result) 
302 {
303   CmiFree(data);
304   DECR_MSGQLEN();
305 }
306
307
308 static void recv_done(pami_context_t ctxt, void *clientdata, pami_result_t result) 
309 /* recv done callback: push the recved msg to recv queue */
310 {
311     char *msg = (char *) clientdata;
312     int sndlen = ((CmiMsgHeaderBasic *) msg)->size;
313
314     //fprintf (stderr, "%d Recv message done \n", CmiMyPe());
315     /* then we do what PumpMsgs used to do:
316      * push msg to recv queue */
317     int count=0;
318     CMI_CHECK_CHECKSUM(msg, sndlen);
319     if (CMI_MAGIC(msg) != CHARM_MAGIC_NUMBER) { /* received a non-charm msg */
320         CmiAbort("Charm++ Warning: Non Charm++ Message Received. \n");
321         return;
322     }
323
324 #if CMK_BROADCAST_SPANNING_TREE 
325     if (CMI_IS_BCAST_ON_CORES(msg) ) {
326         int pe = CmiMyRank(); //CMI_DEST_RANK(msg);
327         char *copymsg;
328         copymsg = (char *)CmiAlloc(sndlen);
329         CmiMemcpy(copymsg,msg,sndlen);
330
331 #if   CMK_SMP && CMK_USE_L2ATOMICS
332         L2AtomicEnqueue(CpvAccessOther(broadcast_q, pe), copymsg);      
333 #elif CMK_SMP
334         CmiLock(procState[pe].bcastLock);
335         PCQueuePush(CpvAccessOther(broadcast_q, pe), copymsg);  
336         CmiUnlock(procState[pe].bcastLock);
337 #else
338         PCQueuePush(CpvAccess(broadcast_q), copymsg);
339 #endif
340     }
341 #endif
342
343 #if CMK_NODE_QUEUE_AVAILABLE
344 #if CMK_BROADCAST_SPANNING_TREE
345     if (CMI_IS_BCAST_ON_NODES(msg)) {
346         //printf ("%d: Receiving node bcast message from %d with %d bytes for %d\n", CmiMyPe(), CMI_BROADCAST_ROOT(msg), sndlen, CMI_DEST_RANK(msg));
347         char *copymsg = (char *)CmiAlloc(sndlen);
348         CmiMemcpy(copymsg,msg,sndlen);
349         //CmiLock(CsvAccess(NodeState).CmiNodeRecvLock);
350         CmiLock(CsvAccess(node_bcastLock));
351         PCQueuePush(CsvAccess(node_bcastq), copymsg);
352         CmiUnlock(CsvAccess(node_bcastLock));
353         //CmiUnlock(CsvAccess(NodeState).CmiNodeRecvLock);
354     }
355 #endif
356     if (CMI_DEST_RANK(msg) == SMP_NODEMESSAGE)
357       CmiPushNode(msg);
358     else
359 #endif
360       CmiPushPE(CMI_DEST_RANK(msg), (void *)msg);
361
362     DECR_ORECVS();
363 }
364
365 static void pkt_dispatch (pami_context_t       context,      /**< IN: PAMI context */
366                           void               * clientdata,   /**< IN: dispatch cookie */
367                           const void         * header_addr,  /**< IN: header address */
368                           size_t               header_size,  /**< IN: header size */
369                           const void         * pipe_addr,    /**< IN: address of PAMI pipe buffer */
370                           size_t               pipe_size,    /**< IN: size of PAMI pipe buffer */
371                           pami_endpoint_t      origin,
372                           pami_recv_t         * recv)        /**< OUT: receive message structure */
373 {
374     //fprintf (stderr, "Received Message of size %d %p\n", pipe_size, recv);
375     INCR_ORECVS();    
376     int alloc_size = pipe_size;
377     char * buffer  = (char *)CmiAlloc(alloc_size);
378
379     if (recv) {
380       recv->local_fn = recv_done;
381       recv->cookie   = buffer;
382       recv->type     = PAMI_TYPE_BYTE;
383       recv->addr     = buffer;
384       recv->offset   = 0;
385       recv->data_fn  = PAMI_DATA_COPY;
386     }
387     else {
388       memcpy (buffer, pipe_addr, pipe_size);
389       recv_done (NULL, buffer, PAMI_SUCCESS);
390     }
391 }
392
393
394 #if CMK_NODE_QUEUE_AVAILABLE
395 void sendBroadcastMessagesNode() __attribute__((__noinline__));
396 void sendBroadcastMessagesNode() {
397     //node broadcast message could be always handled by any cores (including
398     //comm thd) on this node
399     //CmiLock(CsvAccess(NodeState).CmiNodeRecvLock);
400     CmiLock(CsvAccess(node_bcastLock));
401     char *msg = PCQueuePop(CsvAccess(node_bcastq));
402     CmiUnlock(CsvAccess(node_bcastLock));
403     //CmiUnlock(CsvAccess(NodeState).CmiNodeRecvLock);
404     while (msg) {
405         //printf("sendBroadcastMessagesNode: node %d rank %d with msg root %d\n", CmiMyNode(), CmiMyRank(), CMI_BROADCAST_ROOT(msg));
406         SendSpanningChildrenNode(((CmiMsgHeaderBasic *) msg)->size, msg);
407         CmiFree(msg);
408         //CmiLock(CsvAccess(NodeState).CmiNodeRecvLock);
409         CmiLock(CsvAccess(node_bcastLock));
410         msg = PCQueuePop(CsvAccess(node_bcastq));
411         CmiUnlock(CsvAccess(node_bcastLock));
412         //CmiUnlock(CsvAccess(NodeState).CmiNodeRecvLock);
413     }
414 }
415 #endif
416
417 void sendBroadcastMessages() __attribute__((__noinline__));
418 void sendBroadcastMessages() {
419 #if CMK_SMP && CMK_USE_L2ATOMICS
420     L2AtomicQueue *toPullQ;
421 #else
422     PCQueue toPullQ;
423 #endif
424
425     toPullQ = CpvAccess(broadcast_q);
426     
427 #if CMK_SMP && !CMK_USE_L2ATOMICS
428     CmiLock(procState[CmiMyRank()].bcastLock);
429 #endif
430     
431 #if CMK_SMP && CMK_USE_L2ATOMICS
432     char *msg = (char *) L2AtomicDequeue(toPullQ);
433 #else
434     char *msg = (char *) PCQueuePop(toPullQ);
435 #endif
436     
437 #if CMK_SMP && !CMK_USE_L2ATOMICS
438     CmiUnlock(procState[CmiMyRank()].bcastLock);
439 #endif
440     
441     while (msg) {      
442 #if CMK_BROADCAST_SPANNING_TREE
443         SendSpanningChildren(((CmiMsgHeaderBasic *) msg)->size, msg);
444 #endif
445
446         CmiFree (msg);
447
448 #if CMK_SMP && !CMK_USE_L2ATOMICS
449         CmiLock(procState[CmiMyRank()].bcastLock);
450 #endif
451
452 #if CMK_SMP && CMK_USE_L2ATOMICS
453         msg = (char *) L2AtomicDequeue(toPullQ);
454 #else
455         msg = (char *) PCQueuePop(toPullQ);
456 #endif
457
458 #if CMK_SMP && !CMK_USE_L2ATOMICS
459         CmiUnlock(procState[CmiMyRank()].bcastLock);
460 #endif
461     }
462 }
463
464
465 //approx sleep command
466 size_t mysleep_iter = 0;
467 void mysleep (unsigned long cycles) {
468     unsigned long start = GetTimeBase();
469     unsigned long end = start + cycles;
470
471     while (start < end) {
472       mysleep_iter ++;
473       start = GetTimeBase();
474     }
475
476     return;
477 }
478
479 static void * test_buf;
480 volatile int pami_barrier_flag = 0;
481 typedef pami_result_t (*pamix_proc_memalign_fn) (void**, size_t, size_t, const char*);
482
483 void pami_barrier_done (void *ctxt, void * clientdata, pami_result_t err)
484 {
485   int * active = (int *) clientdata;
486   (*active)--;
487 }
488
489 pami_client_t      cmi_pami_client;
490 pami_context_t   * cmi_pami_contexts;
491 size_t             cmi_pami_numcontexts;
492 pami_geometry_t    world_geometry;
493 pami_xfer_t        pami_barrier;
494 char clientname[] = "Converse";
495
496 #define CMI_PAMI_DISPATCH   10
497
498 #include "malloc.h"
499
500 void *l2atomicbuf;
501
502 void ConverseInit(int argc, char **argv, CmiStartFn fn, int usched, int initret) {
503     int n, i, count;
504
505     /* processor per node */
506     _Cmi_mynodesize = 1;
507     CmiGetArgInt(argv,"+ppn", &_Cmi_mynodesize);
508 #if ! CMK_SMP
509     if (_Cmi_mynodesize > 1 && _Cmi_mynode == 0)
510       CmiAbort("+ppn cannot be used in non SMP version!\n");
511 #endif
512     
513     PAMI_Client_create (clientname, &cmi_pami_client, NULL, 0);
514     size_t _n = 1;
515 #if CMK_PAMI_MULTI_CONTEXT
516     if ((_Cmi_mynodesize % THREADS_PER_CONTEXT) == 0)
517       _n = _Cmi_mynodesize / THREADS_PER_CONTEXT;  //have a context for each four threads
518     else
519       _n = 1 + (_Cmi_mynodesize / THREADS_PER_CONTEXT);  //have a context for each four threads
520 #endif
521
522     cmi_pami_contexts = (pami_context_t *) malloc (sizeof(pami_context_t) * _n);
523     pami_result_t rc = PAMI_Context_createv (cmi_pami_client, NULL, 0, cmi_pami_contexts, _n);
524     if (rc != PAMI_SUCCESS) {
525       fprintf(stderr, "PAMI_Context_createv failed for %d contexts\n", _n);
526       assert(0);
527     }
528     cmi_pami_numcontexts = _n;
529
530     pami_configuration_t configuration;
531     pami_result_t result;
532     
533     configuration.name = PAMI_CLIENT_TASK_ID;
534     result = PAMI_Client_query(cmi_pami_client, &configuration, 1);
535     _Cmi_mynode = configuration.value.intval;
536
537     configuration.name = PAMI_CLIENT_NUM_TASKS;
538     result = PAMI_Client_query(cmi_pami_client, &configuration, 1);
539     _Cmi_numnodes = configuration.value.intval;
540
541     pami_dispatch_hint_t options = (pami_dispatch_hint_t) {0};
542     pami_dispatch_callback_function pfn;
543     pfn.p2p = pkt_dispatch;
544     for (i = 0; i < _n; ++i)
545       PAMI_Dispatch_set (cmi_pami_contexts[i],
546                          CMI_PAMI_DISPATCH,
547                          pfn,
548                          NULL,
549                          options);
550     
551     //fprintf(stderr, "%d Initializing Converse PAMI machine Layer on %d tasks\n", _Cmi_mynode, _Cmi_numnodes);
552
553     ///////////---------------------------------/////////////////////
554     //////////----------- Initialize Barrier -------////////////////
555     size_t               num_algorithm[2];
556     pami_algorithm_t    *always_works_algo = NULL;
557     pami_metadata_t     *always_works_md = NULL;
558     pami_algorithm_t    *must_query_algo = NULL;
559     pami_metadata_t     *must_query_md = NULL;
560     pami_xfer_type_t     xfer_type = PAMI_XFER_BARRIER;
561
562     /* Docs01:  Get the World Geometry */
563     result = PAMI_Geometry_world (cmi_pami_client,&world_geometry);
564     if (result != PAMI_SUCCESS)
565       {
566         fprintf (stderr, "Error. Unable to get world geometry: result = %d\n", result);
567         return;
568       }
569
570     result = PAMI_Geometry_algorithms_num(world_geometry,
571                                           xfer_type,
572                                           (size_t*)num_algorithm);
573
574     if (result != PAMI_SUCCESS || num_algorithm[0]==0)
575       {
576         fprintf (stderr,
577                  "Error. Unable to query algorithm, or no algorithms available result = %d\n",
578                  result);
579         return;
580       }
581
582     always_works_algo = (pami_algorithm_t*)malloc(sizeof(pami_algorithm_t)*num_algorithm[0]);
583     always_works_md  = (pami_metadata_t*)malloc(sizeof(pami_metadata_t)*num_algorithm[0]);
584     must_query_algo   = (pami_algorithm_t*)malloc(sizeof(pami_algorithm_t)*num_algorithm[1]);
585     must_query_md    = (pami_metadata_t*)malloc(sizeof(pami_metadata_t)*num_algorithm[1]);
586
587     /* Docs05:  Query the algorithm lists */
588     result = PAMI_Geometry_algorithms_query(world_geometry,
589                                             xfer_type,
590                                             always_works_algo,
591                                             always_works_md,
592                                             num_algorithm[0],
593                                             must_query_algo,
594                                             must_query_md,
595                                             num_algorithm[1]);
596     pami_barrier.cb_done   = pami_barrier_done;
597     pami_barrier.cookie    = (void*) & pami_barrier_flag;
598     pami_barrier.algorithm = always_works_algo[0];
599
600     /* Docs06:  Query the algorithm lists */
601     if (result != PAMI_SUCCESS)
602       {
603         fprintf (stderr, "Error. Unable to get query algorithm. result = %d\n", result);
604         return;
605       }
606
607     CmiNetworkBarrier();
608     CmiNetworkBarrier();
609     CmiNetworkBarrier();
610
611     _Cmi_numpes = _Cmi_numnodes * _Cmi_mynodesize;
612     Cmi_nodestart = _Cmi_mynode * _Cmi_mynodesize;
613     Cmi_argvcopy = CmiCopyArgs(argv);
614     Cmi_argv = argv;
615     Cmi_startfn = fn;
616     Cmi_usrsched = usched;
617
618     /* checksum flag */
619     if (CmiGetArgFlag(argv,"+checksum")) {
620 #if !CMK_OPTIMIZE
621         checksum_flag = 1;
622         if (_Cmi_mynode == 0) CmiPrintf("Charm++: CheckSum checking enabled! \n");
623 #else
624         if (_Cmi_mynode == 0) CmiPrintf("Charm++: +checksum ignored in optimized version! \n");
625 #endif
626     }
627
628     CsvInitialize(CmiNodeState, NodeState);
629     CmiNodeStateInit(&CsvAccess(NodeState));
630
631 #if CMK_NODE_QUEUE_AVAILABLE
632     CsvInitialize(PCQueue, node_bcastq);
633     CsvAccess(node_bcastq) = PCQueueCreate();
634     CsvInitialize(CmiNodeLock, node_bcastLock);
635     CsvAccess(node_bcastLock) = CmiCreateLock();
636 #endif
637
638     int actualNodeSize = _Cmi_mynodesize;
639
640 #if CMK_SMP && CMK_USE_L2ATOMICS
641     //pami_result_t rc;
642     pami_extension_t l2;
643     pamix_proc_memalign_fn PAMIX_L2_proc_memalign;
644     size_t size = 2 * actualNodeSize * sizeof(L2AtomicState);
645     rc = PAMI_Extension_open(NULL, "EXT_bgq_l2atomic", &l2);
646     CmiAssert (rc == 0);
647     PAMIX_L2_proc_memalign = (pamix_proc_memalign_fn)PAMI_Extension_symbol(l2, "proc_memalign");
648     rc = PAMIX_L2_proc_memalign(&l2atomicbuf, 64, size, NULL);
649     CmiAssert (rc == 0);    
650 #endif
651
652     procState = (ProcState *)CmiAlloc((actualNodeSize) * sizeof(ProcState));
653     for (i=0; i<actualNodeSize; i++) {
654         /*    procState[i].sendMsgBuf = PCQueueCreate();   */
655         procState[i].recvLock = CmiCreateLock();
656         procState[i].bcastLock = CmiCreateLock();
657 #if CMK_SMP && CMK_USE_L2ATOMICS
658         L2AtomicQueueInit ((char *) l2atomicbuf + sizeof(L2AtomicState)*i,
659                            sizeof(L2AtomicState),
660                            &procState[i].atomic_queue);
661 #endif
662     }
663
664     //printf ("Starting Threads\n");
665     CmiStartThreads(argv);
666     ConverseRunPE(initret);
667 }
668
669
670 int PerrorExit (char *err) {
671   fprintf (stderr, "err\n\n");
672     exit (-1);
673     return -1;
674 }
675
676
677 void ConverseRunPE(int everReturn) {
678     //printf ("ConverseRunPE on rank %d\n", CmiMyPe());
679
680     CmiIdleState *s=CmiNotifyGetState();
681     CmiState cs;
682     char** CmiMyArgv;
683     CmiNodeAllBarrier();
684
685     cs = CmiGetState();
686     CpvInitialize(void *,CmiLocalQueue);
687     CpvAccess(CmiLocalQueue) = cs->localqueue;
688
689     if (CmiMyRank())
690         CmiMyArgv=CmiCopyArgs(Cmi_argvcopy);
691     else
692         CmiMyArgv=Cmi_argv;
693
694     CthInit(CmiMyArgv);
695
696 #if CMK_SMP && CMK_USE_L2ATOMICS
697     CpvInitialize(L2AtomicQueue*, broadcast_q);
698     //Initialize broadcastq
699     L2AtomicQueue *l2q = malloc(sizeof(L2AtomicQueue));
700     CpvAccess(broadcast_q) = l2q;
701     L2AtomicQueueInit (l2atomicbuf + sizeof(L2AtomicState)*(_Cmi_mynodesize + CmiMyRank()),
702                        sizeof(L2AtomicState), l2q);
703 #else
704     CpvInitialize(PCQueue, broadcast_q);
705     CpvAccess(broadcast_q) = PCQueueCreate();
706 #endif
707
708     //printf ("Before Converse Common Init\n");
709     ConverseCommonInit(CmiMyArgv);
710
711     CcdCallOnConditionKeep(CcdPROCESSOR_STILL_IDLE,(CcdVoidFn)CmiNotifyIdle,NULL);
712
713     CmiBarrier();
714
715     /* Converse initialization finishes, immediate messages can be processed.
716        node barrier previously should take care of the node synchronization */
717     _immediateReady = 1;
718
719     if (!everReturn) {
720       Cmi_startfn(CmiGetArgc(CmiMyArgv), CmiMyArgv);
721       if (Cmi_usrsched==0) CsdScheduler(-1);
722       ConverseExit();
723     }
724 }
725
726 void ConverseExit(void) {
727
728     while (MSGQLEN() > 0 || ORECVS() > 0) {
729       AdvanceCommunications();
730     }
731     
732     CmiNodeBarrier();
733     ConverseCommonExit();
734
735     if (CmiMyPe() == 0) {
736         printf("End of program\n");
737     }
738
739     CmiNodeBarrier();
740 //  CmiNodeAllBarrier ();
741
742     int rank0 = 0;
743     if (CmiMyRank() == 0) {
744         rank0 = 1;
745         //CmiFree(procState);
746         PAMI_Context_destroyv(cmi_pami_contexts, cmi_pami_numcontexts);
747         PAMI_Client_destroy(&cmi_pami_client);
748     }
749
750     CmiNodeBarrier();
751     //  CmiNodeAllBarrier ();
752     //fprintf(stderr, "Before Exit\n");
753 #if CMK_SMP
754     if (rank0)
755       exit(1);
756     else
757       pthread_exit(0);
758 #else
759     exit(0);
760 #endif
761 }
762
763 /* exit() called on any node would abort the whole program */
764 void CmiAbort(const char * message) {
765     CmiError("------------- Processor %d Exiting: Called CmiAbort ------------\n"
766              "{snd:%d,rcv:%d} Reason: %s\n",CmiMyPe(),
767              MSGQLEN(), ORECVS(), message);
768
769     //CmiPrintStackTrace(0);
770     //while (msgQueueLen > 0 || outstanding_recvs > 0) {
771     //  AdvanceCommunications();
772     //}    
773     //CmiBarrier();
774     assert (0);
775 }
776
777 #if CMK_NODE_QUEUE_AVAILABLE
778 char *CmiGetNonLocalNodeQ(void) {
779     CmiState cs = CmiGetState();
780     char *result = 0;
781     CmiIdleLock_checkMessage(&cs->idle);
782     if (!PCQueueEmpty(CsvAccess(NodeState).NodeRecv)) {
783         MACHSTATE1(3,"CmiGetNonLocalNodeQ begin %d {", CmiMyPe());
784
785         if (CmiTryLock(CsvAccess(NodeState).CmiNodeRecvLock) == 0) {
786             //CmiLock(CsvAccess(NodeState).CmiNodeRecvLock);
787             result = (char *) PCQueuePop(CsvAccess(NodeState).NodeRecv);
788             CmiUnlock(CsvAccess(NodeState).CmiNodeRecvLock);
789         }
790
791         MACHSTATE1(3,"} CmiGetNonLocalNodeQ end %d ", CmiMyPe());
792     }
793     return result;
794 }
795 #endif
796
797
798 void *CmiGetNonLocal() {
799
800     void *msg = NULL;
801     CmiState cs = CmiGetState();
802     CmiIdleLock_checkMessage(&cs->idle);
803
804 #if CMK_SMP && CMK_USE_L2ATOMICS
805     msg = L2AtomicDequeue(&procState[CmiMyRank()].atomic_queue);
806     if (msg == NULL) {
807       AdvanceCommunications();     
808       msg = L2AtomicDequeue(&procState[CmiMyRank()].atomic_queue);
809     }
810 #else
811     if (PCQueueLength(cs->recv)==0)
812       AdvanceCommunications();
813     if (PCQueueLength(cs->recv)==0) return NULL;
814     msg =  PCQueuePop(cs->recv);
815 #endif
816
817     return msg;
818 }
819
820 static void CmiSendSelf(char *msg) {
821 #if CMK_IMMEDIATE_MSG
822     if (CmiIsImmediate(msg)) {
823         /* CmiBecomeNonImmediate(msg); */
824         //printf("In SendSelf, N[%d]P[%d]R[%d] received an imm msg with hdl: %p\n", CmiMyNode(), CmiMyPe(), CmiMyRank(), CmiGetHandler(msg));
825         CmiPushImmediateMsg(msg);
826 #if CMK_MULTICORE
827         CmiHandleImmediate();
828 #endif
829         return;
830     }
831 #endif
832     
833     CdsFifo_Enqueue(CpvAccess(CmiLocalQueue),msg);
834 }
835
836 #if CMK_SMP
837 static void CmiSendPeer (int rank, int size, char *msg) {
838 #if CMK_BROADCAST_SPANNING_TREE
839     if (CMI_BROADCAST_ROOT(msg) != 0) {
840         char *copymsg;
841         copymsg = (char *)CmiAlloc(size);
842         CmiMemcpy(copymsg,msg,size);
843
844 #if CMK_USE_L2ATOMICS
845         L2AtomicEnqueue(CpvAccessOther(broadcast_q, rank), copymsg);
846 #else
847         CmiLock(procState[rank].bcastLock);
848         PCQueuePush(CpvAccessOther(broadcast_q, rank), copymsg);
849         CmiUnlock(procState[rank].bcastLock);
850 #endif
851     }
852 #endif
853     
854     CmiPushPE (rank, msg);
855 }
856 #endif
857
858
859 void CmiGeneralFreeSendN (int node, int rank, int size, char * msg, int to_lock);
860
861
862 /* The general free send function
863  * Send is synchronous, and free msg after posted
864  */
865 void  CmiGeneralFreeSend(int destPE, int size, char* msg) {
866
867   if (destPE < 0 || destPE > CmiNumPes ())
868     printf ("Sending to %d\n", destPE);
869
870   CmiAssert (destPE >= 0 && destPE < CmiNumPes());
871
872     CmiState cs = CmiGetState();
873
874     if (destPE==cs->pe) {
875         CmiSendSelf(msg);
876         return;
877     }
878
879     CmiGeneralFreeSendN (CmiNodeOf (destPE), CmiRankOf (destPE), size, msg, 1);
880 }
881
882 void CmiGeneralFreeSendN (int node, int rank, int size, char * msg, int to_lock) {
883
884     //printf ("%d, %d: Sending Message to node %d rank %d \n", CmiMyPe(),
885     //  CmiMyNode(), node, rank);
886
887 #if CMK_SMP
888     CMI_DEST_RANK(msg) = rank;
889     //CMI_SET_CHECKSUM(msg, size);
890
891     if (node == CmiMyNode()) {
892         CmiSendPeer (rank, size, msg);
893         return;
894     }
895 #endif
896
897     pami_endpoint_t target;
898 #if CMK_PAMI_MULTI_CONTEXT
899     size_t dst_context = (rank != SMP_NODEMESSAGE) ? (rank>>LTPS) : 0;
900 #else
901     size_t dst_context = 0;
902 #endif
903     PAMI_Endpoint_create (cmi_pami_client, (pami_task_t)node, dst_context, &target);
904
905     //CmiAssert ((MY_CONTEXT_ID()) >= 0 &&
906     //         (MY_CONTEXT_ID()) < cmi_pami_numcontexts);
907
908     //fprintf (stderr, "Calling PAMI Send to %d magic %d size %d\n", node, CMI_MAGIC(msg), size);
909     if (size < 128) {
910       pami_send_immediate_t parameters;
911       parameters.dispatch        = CMI_PAMI_DISPATCH;
912       parameters.header.iov_base = NULL;
913       parameters.header.iov_len  = 0;
914       parameters.data.iov_base   = msg;
915       parameters.data.iov_len    = size;
916       parameters.dest = target;
917       
918       pami_context_t my_context = MY_CONTEXT();
919       //CmiAssert (my_context != NULL);
920       
921       if(to_lock)
922         PAMIX_CONTEXT_LOCK(my_context);
923
924       PAMI_Send_immediate (my_context, &parameters);
925
926       if(to_lock)
927         PAMIX_CONTEXT_UNLOCK(my_context);
928       CmiFree(msg);
929     }
930     else {
931       pami_send_t parameters;
932       parameters.send.dispatch        = CMI_PAMI_DISPATCH;
933       parameters.send.header.iov_base = NULL;
934       parameters.send.header.iov_len  = 0;
935       parameters.send.data.iov_base   = msg;
936       parameters.send.data.iov_len    = size;
937       parameters.events.cookie        = msg;
938       parameters.events.local_fn      = send_done;
939       parameters.events.remote_fn     = NULL;
940       memset(&parameters.send.hints, 0, sizeof(parameters.send.hints));
941       parameters.send.dest = target;
942       
943       pami_context_t my_context = MY_CONTEXT();
944       //CmiAssert (my_context != NULL);
945       
946       if (to_lock)
947         PAMIX_CONTEXT_LOCK(my_context);
948       INCR_MSGQLEN();
949       PAMI_Send (my_context, &parameters);
950       if (to_lock)
951         PAMIX_CONTEXT_UNLOCK(my_context);
952     }
953 }
954
955 void CmiSyncSendFn(int destPE, int size, char *msg) {
956     char *copymsg;
957     copymsg = (char *)CmiAlloc(size);
958     CmiAssert(copymsg != NULL);
959     CmiMemcpy(copymsg,msg,size);
960     //if(CmiMyRank()==CmiMyNodeSize()) printf("CmiSyncSendFn on comm thd on node %d\n", CmiMyNode());
961     CmiFreeSendFn(destPE,size,copymsg);
962 }
963
964 void CmiFreeSendFn(int destPE, int size, char *msg) {    
965     CQdCreate(CpvAccess(cQdState), 1);
966     //if(CmiMyRank()==CmiMyNodeSize()) printf("CmiFreeSendFn on comm thd on node %d\n", CmiMyNode());
967
968     CMI_SET_BROADCAST_ROOT(msg,0);
969     CMI_MAGIC(msg) = CHARM_MAGIC_NUMBER;
970     ((CmiMsgHeaderBasic *)msg)->size = size;
971     CMI_SET_CHECKSUM(msg, size);
972
973     CmiGeneralFreeSend(destPE,size,msg);
974 }
975
976 /* same as CmiSyncSendFn, but don't set broadcast root in msg header */
977 void CmiSyncSendFn1(int destPE, int size, char *msg) {
978     char *copymsg;
979     copymsg = (char *)CmiAlloc(size);
980     CmiMemcpy(copymsg, msg, size);
981
982     //  asm volatile("sync" ::: "memory");
983
984     CMI_MAGIC(copymsg) = CHARM_MAGIC_NUMBER;
985     ((CmiMsgHeaderBasic *)copymsg)->size = size;
986     CMI_SET_CHECKSUM(copymsg, size);
987
988     CmiGeneralFreeSend(destPE,size,copymsg);
989 }
990
991 /* send msg to its spanning children in broadcast. G. Zheng */
992 void SendSpanningChildren(int size, char *msg) {
993     int startnode = CMI_BROADCAST_ROOT(msg)-1;
994     int myrank = CMI_DEST_RANK(msg);
995     int i;
996
997     //printf ("%d [%d]: In Send Spanning Tree\n",  CmiMyPe(), CmiMyNode());
998
999     CmiAssert(startnode>=0 && startnode<_Cmi_numnodes);
1000     int dist = CmiMyNode() - startnode;
1001     if (dist < 0) dist+=_Cmi_numnodes;
1002     for (i=1; i <= BROADCAST_SPANNING_FACTOR; i++) {
1003         int p = BROADCAST_SPANNING_FACTOR*dist + i;
1004         if (p > _Cmi_numnodes - 1) break;
1005         p += startnode;
1006         p = p%_Cmi_numnodes;
1007         CmiAssert(p>=0 && p<_Cmi_numnodes && p!= CmiMyNode());
1008
1009         char *copymsg = (char *)CmiAlloc(size);
1010         CmiMemcpy(copymsg, msg, size);
1011
1012         CMI_MAGIC(copymsg) = CHARM_MAGIC_NUMBER;
1013         ((CmiMsgHeaderBasic *)copymsg)->size = size;
1014         CMI_SET_CHECKSUM(copymsg, size);
1015         
1016         CmiGeneralFreeSendN(p,0,size,copymsg,1);        
1017     }    
1018
1019 #if CMK_SMP    
1020     //Send data within the nodes
1021     for (i =0; i < _Cmi_mynodesize; ++i) {
1022       if (i != myrank) {
1023         char *copymsg = (char *)CmiAlloc(size);
1024         CmiMemcpy(copymsg, msg, size);                  
1025         CmiPushPE (i, copymsg);
1026       }
1027     }
1028 #endif
1029 }
1030
1031 void CmiSyncBroadcastFn(int size, char *msg) {
1032     char *copymsg;
1033     copymsg = (char *)CmiAlloc(size);
1034     CmiMemcpy(copymsg,msg,size);
1035     //if(CmiMyRank()==CmiMyNodeSize()) printf("CmiSyncBroadcastFn on comm thd on node %d\n", CmiMyNode());
1036     CmiFreeBroadcastFn(size,copymsg);
1037 }
1038
1039 void CmiFreeBroadcastFn(int size, char *msg) {
1040
1041     //  printf("%d: Calling Broadcast %d\n", CmiMyPe(), size);
1042
1043     CmiState cs = CmiGetState();
1044 #if CMK_BROADCAST_SPANNING_TREE    
1045     CQdCreate(CpvAccess(cQdState), CmiNumPes()-1);
1046     //if(CmiMyRank()==CmiMyNodeSize()) printf("CmiFreeBroadcastFn on comm thd on node %d\n", CmiMyNode());
1047
1048     //printf ("%d: Starting Spanning Tree Broadcast of size %d bytes\n", CmiMyPe(), size);
1049
1050     CMI_SET_BROADCAST_ROOT(msg, CmiMyNode()+1);
1051     CMI_DEST_RANK(msg) = CmiMyRank();
1052     SendSpanningChildren(size, msg);
1053     CmiFree(msg);
1054 #else
1055     int i;
1056
1057     for ( i=cs->pe+1; i<_Cmi_numpes; i++ )
1058         CmiSyncSendFn(i,size,msg);
1059
1060     for ( i=0; i<cs->pe; i++ )
1061         CmiSyncSendFn(i,size,msg);
1062
1063     CmiFree(msg);
1064 #endif
1065 }
1066
1067 void CmiSyncBroadcastAllFn(int size, char *msg) {
1068     char *copymsg;
1069     copymsg = (char *)CmiAlloc(size);
1070     CmiMemcpy(copymsg,msg,size);
1071     //if(CmiMyRank()==CmiMyNodeSize()) printf("CmiSyncBroadcastAllFn on comm thd on node %d\n", CmiMyNode());
1072     CmiFreeBroadcastAllFn(size,copymsg);
1073 }
1074
1075 void CmiFreeBroadcastAllFn(int size, char *msg) {
1076
1077     //printf("%d: Calling All Broadcast %d\n", CmiMyPe(), size);
1078
1079     CmiState cs = CmiGetState();
1080 #if CMK_BROADCAST_SPANNING_TREE
1081
1082     //printf ("%d: Starting Spanning Tree Broadcast of size %d bytes\n", CmiMyPe(), size);
1083     //if(CmiMyRank()==CmiMyNodeSize()) printf("CmiFreeBroadcastAllFn on comm thd on node %d\n", CmiMyNode());
1084
1085     CmiSyncSendFn(cs->pe,size,msg);
1086     
1087     CQdCreate(CpvAccess(cQdState), CmiNumPes()-1);
1088
1089     CMI_SET_BROADCAST_ROOT(msg, CmiMyNode()+1);
1090     CMI_DEST_RANK(msg) = CmiMyRank();
1091     SendSpanningChildren(size, msg);
1092     CmiFree(msg);
1093 #else
1094     int i ;
1095
1096     for ( i=0; i<_Cmi_numpes; i++ ) {
1097         CmiSyncSendFn(i,size,msg);      
1098     }
1099     //SendMsgsUntil (0);
1100
1101     CmiFree(msg);
1102 #endif
1103 }
1104
1105 void AdvanceCommunications() {
1106
1107     pami_context_t my_context = MY_CONTEXT();
1108    
1109 #if CMK_SMP
1110     CmiAssert (my_context != NULL);
1111     //PAMI_Context_trylock_advancev(&my_context, 1, 1);
1112     if (PAMIX_CONTEXT_TRYLOCK(my_context))
1113     {
1114       PAMI_Context_advance(my_context, 1);
1115       PAMIX_CONTEXT_UNLOCK(my_context);
1116     }
1117 #else
1118     PAMI_Context_advance(my_context, 1);
1119 #endif
1120
1121 #if CMK_SMP && CMK_USE_L2ATOMICS
1122     if (!L2AtomicQueueEmpty(CpvAccess(broadcast_q)))
1123 #else        
1124     if (PCQueueLength(CpvAccess(broadcast_q)) > 0)
1125 #endif
1126       sendBroadcastMessages();
1127 #if CMK_NODE_QUEUE_AVAILABLE
1128     if (PCQueueLength(CsvAccess(node_bcastq)) > 0)
1129       sendBroadcastMessagesNode();
1130 #endif
1131     
1132     
1133 #if CMK_IMMEDIATE_MSG && CMK_MULTICORE
1134     CmiHandleImmediate();
1135 #endif
1136 }
1137
1138 #if 0
1139 static void SendMsgsUntil(int targetm) {
1140
1141     pami_context_t my_context = MY_CONTEXT();
1142
1143     while (MSGQLEN() > targetm) {
1144 #if CMK_SMP
1145       PAMI_Context_trylock_advancev(&my_context, 1, 1);
1146 #else
1147       PAMI_Context_advance(my_context, 1);
1148 #endif    
1149     }
1150 }
1151 #endif
1152
1153 void CmiNotifyIdle() {
1154   AdvanceCommunications();
1155 }
1156
1157
1158 /*==========================================================*/
1159 /*==========================================================*/
1160 /*==========================================================*/
1161
1162 /************ Recommended routines ***********************/
1163 /************ You dont have to implement these but they are supported
1164  in the converse syntax and some rare programs may crash. But most
1165  programs dont need them. *************/
1166
1167 CmiCommHandle CmiAsyncSendFn(int dest, int size, char *msg) {
1168     CmiAbort("CmiAsyncSendFn not implemented.");
1169     return (CmiCommHandle) 0;
1170 }
1171
1172 CmiCommHandle CmiAsyncBroadcastFn(int size, char *msg) {
1173     CmiAbort("CmiAsyncBroadcastFn not implemented.");
1174     return (CmiCommHandle) 0;
1175 }
1176
1177 CmiCommHandle CmiAsyncBroadcastAllFn(int size, char *msg) {
1178     CmiAbort("CmiAsyncBroadcastAllFn not implemented.");
1179     return (CmiCommHandle) 0;
1180 }
1181
1182 int           CmiAsyncMsgSent(CmiCommHandle handle) {
1183     CmiAbort("CmiAsyncMsgSent not implemented.");
1184     return 0;
1185 }
1186 void          CmiReleaseCommHandle(CmiCommHandle handle) {
1187     CmiAbort("CmiReleaseCommHandle not implemented.");
1188 }
1189
1190
1191 /*==========================================================*/
1192 /*==========================================================*/
1193 /*==========================================================*/
1194
1195 /* Optional routines which could use common code which is shared with
1196    other machine layer implementations. */
1197
1198 /* MULTICAST/VECTOR SENDING FUNCTIONS
1199
1200  * In relations to some flags, some other delivery functions may be needed.
1201  */
1202
1203 #if ! CMK_MULTICAST_LIST_USE_COMMON_CODE
1204
1205 void CmiSyncListSendFn(int npes, int *pes, int size, char *msg) {
1206     char *copymsg;
1207     copymsg = (char *)CmiAlloc(size);
1208     CmiMemcpy(copymsg,msg,size);
1209     CmiFreeListSendFn(npes, pes, size, msg);
1210 }
1211
1212 //#define OPTIMIZED_MULTICAST  0
1213
1214 void CmiFreeListSendFn(int npes, int *pes, int size, char *msg) {
1215
1216     CMI_SET_BROADCAST_ROOT(msg,0);
1217     CMI_MAGIC(msg) = CHARM_MAGIC_NUMBER;
1218     ((CmiMsgHeaderBasic *)msg)->size = size;
1219     CMI_SET_CHECKSUM(msg, size);
1220
1221     //printf("CmiFreeListSendFn on node %d rank %d\n", CmiMyNode(), CmiMyRank());
1222     //printf("%d: In Free List Send Fn\n", CmiMyPe());
1223     int new_npes = 0;
1224
1225     int i, count = 0, my_loc = -1;
1226     for (i=0; i<npes; i++) {
1227         if (CmiNodeOf(pes[i]) == CmiMyNode()) 
1228             CmiSyncSend(pes[i], size, msg);
1229     }
1230
1231     pami_context_t my_context = MY_CONTEXT();
1232     PAMIX_CONTEXT_LOCK(my_context);
1233
1234     char *copymsg;
1235     for (i=0;i<npes;i++) {
1236       if (CmiNodeOf(pes[i]) == CmiMyNode());
1237         else if (i < npes - 1) {
1238 #if !CMK_SMP
1239             CmiReference(msg);
1240             copymsg = msg;
1241 #else
1242             copymsg = (char *)CmiAlloc(size);
1243             CmiAssert(copymsg != NULL);
1244             CmiMemcpy(copymsg,msg,size);
1245 #endif
1246             CmiGeneralFreeSendN(CmiNodeOf(pes[i]), CmiRankOf(pes[i]), size, copymsg, 0);
1247         }
1248     }
1249
1250     if (npes  && CmiNodeOf(pes[npes-1]) != CmiMyNode())
1251       //CmiSyncSendAndFree(pes[npes-1], size, msg); //Sameto CmiFreeSendFn
1252       CmiGeneralFreeSendN(CmiNodeOf(pes[npes-1]), CmiRankOf(pes[npes-1]), size, msg, 0);
1253     else
1254       CmiFree(msg);    
1255
1256     PAMIX_CONTEXT_UNLOCK(my_context);
1257 }
1258
1259 CmiCommHandle CmiAsyncListSendFn(int npes, int *pes, int size, char *msg) {
1260     CmiAbort("CmiAsyncListSendFn not implemented.");
1261     return (CmiCommHandle) 0;
1262 }
1263 #endif
1264
1265 /** NODE SENDING FUNCTIONS
1266
1267  * If there is a node queue, and we consider also nodes as entity (tipically in
1268  * SMP versions), these functions are needed.
1269  */
1270
1271 #if CMK_NODE_QUEUE_AVAILABLE
1272
1273 void          CmiSyncNodeSendFn(int, int, char *);
1274 CmiCommHandle CmiAsyncNodeSendFn(int, int, char *);
1275 void          CmiFreeNodeSendFn(int, int, char *);
1276
1277 void          CmiSyncNodeBroadcastFn(int, char *);
1278 CmiCommHandle CmiAsyncNodeBroadcastFn(int, char *);
1279 void          CmiFreeNodeBroadcastFn(int, char *);
1280
1281 void          CmiSyncNodeBroadcastAllFn(int, char *);
1282 CmiCommHandle CmiAsyncNodeBroadcastAllFn(int, char *);
1283 void          CmiFreeNodeBroadcastAllFn(int, char *);
1284
1285 #endif
1286
1287
1288 #if CMK_SHARED_VARS_POSIX_THREADS_SMP
1289
1290 int CmiMyPe();
1291 int CmiMyRank();
1292 int CmiNodeFirst(int node);
1293 int CmiNodeSize(int node);
1294 int CmiNodeOf(int pe);
1295 int CmiRankOf(int pe);
1296
1297 int CmiMyPe(void) {
1298     return CmiGetState()->pe;
1299 }
1300
1301 int CmiMyRank(void) {
1302     return CmiGetState()->rank;
1303 }
1304
1305 int CmiNodeFirst(int node) {
1306     return node*_Cmi_mynodesize;
1307 }
1308 int CmiNodeSize(int node)  {
1309     return _Cmi_mynodesize;
1310 }
1311
1312 int CmiNodeOf(int pe)      {
1313     return (pe/_Cmi_mynodesize);
1314 }
1315 int CmiRankOf(int pe)      {
1316     return pe%_Cmi_mynodesize;
1317 }
1318
1319
1320 /* optional, these functions are implemented in "machine-smp.c", so including
1321    this file avoid the necessity to reimplement them.
1322  */
1323 void CmiNodeBarrier(void);
1324 void CmiNodeAllBarrier(void);
1325 CmiNodeLock CmiCreateLock();
1326 void CmiDestroyLock(CmiNodeLock lock);
1327
1328 #endif
1329
1330 /** IMMEDIATE MESSAGES
1331
1332  * If immediate messages are supported, the following function is needed. There
1333  * is an exeption if the machine progress is also defined (see later for this).
1334
1335  * Moreover, the file "immediate.c" should be included, otherwise all its
1336  * functions and variables have to be redefined.
1337 */
1338
1339 #if CMK_CCS_AVAILABLE
1340
1341 #include "immediate.c"
1342
1343 #if ! CMK_MACHINE_PROGRESS_DEFINED /* Hack for some machines */
1344 void CmiProbeImmediateMsg();
1345 #endif
1346
1347 #endif
1348
1349
1350 /* Dummy implementation */
1351 extern int CmiBarrier() {
1352   CmiNodeBarrier();
1353   if (CmiMyRank() == 0)
1354     CmiNetworkBarrier();
1355   CmiNodeBarrier();
1356   return 0;
1357 }
1358
1359 static void CmiNetworkBarrier() {
1360     //mysleep(1000000000UL);
1361
1362     pami_result_t result;
1363     pami_barrier_flag = 1;
1364     pami_context_t my_context = cmi_pami_contexts[0];
1365     PAMIX_CONTEXT_LOCK(my_context);
1366     result = PAMI_Collective(my_context, &pami_barrier);   
1367     PAMIX_CONTEXT_UNLOCK(my_context);
1368     
1369     if (result != PAMI_SUCCESS)
1370     {
1371       fprintf (stderr, "Error. Unable to issue  collective. result = %d\n", result);
1372       return;
1373     }
1374     
1375     PAMIX_CONTEXT_LOCK(my_context);
1376     while (pami_barrier_flag)
1377       result = PAMI_Context_advance (my_context, 100);
1378     PAMIX_CONTEXT_UNLOCK(my_context);
1379 }
1380
1381 #if CMK_NODE_QUEUE_AVAILABLE
1382 static void CmiSendNodeSelf(char *msg) {
1383 #if CMK_IMMEDIATE_MSG
1384     if (CmiIsImmediate(msg)) {
1385         //printf("SendNodeSelf: N[%d]P[%d]R[%d] received an imm msg with hdl: %p\n", CmiMyNode(), CmiMyPe(), CmiMyRank(), CmiGetHandler(msg));
1386         CmiPushImmediateMsg(msg);
1387 #if CMK_MULTICORE
1388         CmiHandleImmediate();
1389 #endif
1390         return;
1391     }
1392 #endif    
1393     CmiLock(CsvAccess(NodeState).CmiNodeRecvLock);
1394     PCQueuePush(CsvAccess(NodeState).NodeRecv, msg);
1395     CmiUnlock(CsvAccess(NodeState).CmiNodeRecvLock);
1396 }
1397
1398 CmiCommHandle CmiAsyncNodeSendFn(int dstNode, int size, char *msg) {
1399     CmiAbort ("Async Node Send not supported\n");
1400 }
1401
1402 void CmiFreeNodeSendFn(int node, int size, char *msg) {
1403
1404     CMI_SET_BROADCAST_ROOT(msg,0);
1405     CMI_MAGIC(msg) = CHARM_MAGIC_NUMBER;
1406     ((CmiMsgHeaderBasic *)msg)->size = size;
1407     CMI_SET_CHECKSUM(msg, size);
1408     //if(CmiMyRank()==CmiMyNodeSize()) printf("CmiFreeNodeSendFn on comm thd on node %d\n", CmiMyNode());
1409     
1410     CQdCreate(CpvAccess(cQdState), 1);
1411
1412     if (node == _Cmi_mynode) {
1413         CmiSendNodeSelf(msg);
1414     } else {
1415       CmiGeneralFreeSendN(node, SMP_NODEMESSAGE, size, msg, 1);
1416     }
1417 }
1418
1419 void CmiSyncNodeSendFn(int p, int s, char *m) {
1420     char *dupmsg;
1421     dupmsg = (char *)CmiAlloc(s);
1422     CmiMemcpy(dupmsg,m,s);
1423     //if(CmiMyRank()==CmiMyNodeSize()) printf("CmiSyncNodeSendFn on comm thd on node %d\n", CmiMyNode());
1424     CmiFreeNodeSendFn(p, s, dupmsg);
1425 }
1426
1427 CmiCommHandle CmiAsyncNodeBroadcastFn(int s, char *m) {
1428     return NULL;
1429 }
1430
1431 void SendSpanningChildrenNode(int size, char *msg) {
1432     int startnode = -CMI_BROADCAST_ROOT(msg)-1;
1433     //printf("on node %d rank %d, send node spanning children with root %d\n", CmiMyNode(), CmiMyRank(), startnode);
1434     assert(startnode>=0 && startnode<CmiNumNodes());
1435
1436     int dist = CmiMyNode()-startnode;
1437     if (dist<0) dist += CmiNumNodes();
1438     int i;
1439     for (i=1; i <= BROADCAST_SPANNING_FACTOR; i++) {
1440         int nid = BROADCAST_SPANNING_FACTOR*dist + i;
1441         if (nid > CmiNumNodes() - 1) break;
1442         nid += startnode;
1443         nid = nid%CmiNumNodes();
1444         assert(nid>=0 && nid<CmiNumNodes() && nid!=CmiMyNode());
1445         char *dupmsg = (char *)CmiAlloc(size);
1446         CmiMemcpy(dupmsg,msg,size);
1447         //printf("In SendSpanningChildrenNode, sending bcast msg (root %d) from node %d to node %d\n", startnode, CmiMyNode(), nid);
1448         CmiGeneralFreeSendN(nid, SMP_NODEMESSAGE, size, dupmsg,1);
1449     }
1450 }
1451
1452 /* need */
1453 void CmiFreeNodeBroadcastFn(int s, char *m) {
1454   //printf("%d: In FreeNodeBroadcastAllFn\n", CmiMyPe());
1455
1456 #if CMK_BROADCAST_SPANNING_TREE
1457     //if(CmiMyRank()==CmiMyNodeSize()) printf("CmiFreeNodeBcastFn on comm thd on node %d\n", CmiMyNode());
1458     
1459     CQdCreate(CpvAccess(cQdState), CmiNumNodes()-1);
1460
1461     int mynode = CmiMyNode();
1462     CMI_SET_BROADCAST_ROOT(m, -mynode-1);
1463     CMI_MAGIC(m) = CHARM_MAGIC_NUMBER;
1464     ((CmiMsgHeaderBasic *)m)->size = s;
1465     CMI_SET_CHECKSUM(m, s);
1466     //printf("In CmiFreeNodeBroadcastFn, sending bcast msg from root node %d\n", CMI_BROADCAST_ROOT(m));
1467
1468     SendSpanningChildrenNode(s, m);
1469 #else
1470     int i;
1471     for (i=0; i<CmiNumNodes(); i++) {
1472         if (i==CmiMyNode()) continue;
1473         char *dupmsg = (char *)CmiAlloc(s);
1474         CmiMemcpy(dupmsg,m,s);
1475         CmiFreeNodeSendFn(i, s, dupmsg);
1476     }
1477 #endif
1478     CmiFree(m);    
1479 }
1480
1481 void CmiSyncNodeBroadcastFn(int s, char *m) {
1482     char *dupmsg;
1483     dupmsg = (char *)CmiAlloc(s);
1484     CmiMemcpy(dupmsg,m,s);
1485     //if(CmiMyRank()==CmiMyNodeSize()) printf("CmiSyncNodeBcastFn on comm thd on node %d\n", CmiMyNode());
1486     CmiFreeNodeBroadcastFn(s, dupmsg);
1487 }
1488
1489 /* need */
1490 void CmiFreeNodeBroadcastAllFn(int s, char *m) {
1491   
1492     char *dupmsg = (char *)CmiAlloc(s);
1493     CmiMemcpy(dupmsg,m,s);
1494     CMI_MAGIC(dupmsg) = CHARM_MAGIC_NUMBER;
1495     ((CmiMsgHeaderBasic *)dupmsg)->size = s;
1496     CMI_SET_CHECKSUM(dupmsg, s);
1497
1498     //if(CmiMyRank()==CmiMyNodeSize()) printf("CmiFreeNodeBcastAllFn on comm thd on node %d\n", CmiMyNode());
1499     
1500     CQdCreate(CpvAccess(cQdState), 1);
1501     CmiSendNodeSelf(dupmsg);
1502
1503     CmiFreeNodeBroadcastFn(s, m);
1504 }
1505
1506 void CmiSyncNodeBroadcastAllFn(int s, char *m) {
1507     char *dupmsg;
1508     dupmsg = (char *)CmiAlloc(s);
1509     CmiMemcpy(dupmsg,m,s);
1510     //if(CmiMyRank()==CmiMyNodeSize()) printf("CmiSyncNodeBcastAllFn on comm thd on node %d\n", CmiMyNode());
1511     CmiFreeNodeBroadcastAllFn(s, dupmsg);
1512 }
1513
1514
1515 CmiCommHandle CmiAsyncNodeBroadcastAllFn(int s, char *m) {
1516     return NULL;
1517 }
1518 #endif //end of CMK_NODE_QUEUE_AVAILABLE
1519
1520
1521 //void bzero (void *__s, size_t __n) {
1522 //  memset(__s, 0, __n);
1523 //}
1524