many changes including adding size field to header
[charm.git] / src / arch / gemini_gni / machine.c
1 /*****************************************************************************
2  * $Source$
3  * $Author$  Yanhua Sun
4  * $Date$  07-01-2011
5  * $Revision$ 
6  *****************************************************************************/
7
8 /** @file
9  * Gemini GNI machine layer
10  */
11 /*@{*/
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <errno.h>
16 #include <malloc.h>
17 #include "converse.h"
18
19 #include "gni_pub.h"
20 #include "pmi.h"
21 /*Support for ++debug: */
22 #if defined(_WIN32) && ! defined(__CYGWIN__)
23 #include <windows.h>
24 #include <wincon.h>
25 #include <sys/types.h>
26 #include <sys/timeb.h>
27
28 static void sleep(int secs) {
29     Sleep(1000*secs);
30 }
31 #else
32 #include <unistd.h> /*For getpid()*/
33 #endif
34
35 //#define  USE_ONESIDED 1
36 #ifdef USE_ONESIDED
37 #include "onesided.h"
38 #endif
39
40 #include "machine.h"
41
42 #include "pcqueue.h"
43
44 #define CmiGetMsgSize(m)  ((CmiMsgHeaderExt*)m)->size
45 #define CmiSetMsgSize(m,s)  do {((((CmiMsgHeaderExt*)m)->size)=(s));} while(0)
46
47 #define DEBUY_PRINT
48
49 #ifdef DEBUY_PRINT
50 #define PRINT_INFO(msg) {fprintf(stdout, "[%d] %s\n", CmiMyPe(), msg); fflush(stdout);}
51 #else
52 #define PRINT_INFO(msg)
53 #endif
54 /* =======Beginning of Definitions of Performance-Specific Macros =======*/
55 /* If SMSG is not used */
56 #define FMA_PER_CORE  1024
57 #define FMA_BUFFER_SIZE 1024
58 /* If SMSG is used */
59 #define SMSG_MAX_MSG    1024
60 #define SMSG_MAX_CREDIT 16
61
62 #define MSGQ_MAXSIZE       4096
63 /* large message transfer with FMA or BTE */
64 #define LRTS_GNI_RDMA_THRESHOLD  16384
65
66 #define REMOTE_QUEUE_ENTRIES  1048576
67 #define LOCAL_QUEUE_ENTRIES   1024
68 /* SMSG is data message */
69 #define DATA_TAG          0x38
70 /* SMSG is a control message to initialize a BTE */
71 #define LMSG_INIT_TAG     0x39 
72 #define ACK_TAG           0x37
73
74 #define DEBUG
75 #ifdef GNI_RC_CHECK
76 #undef GNI_RC_CHECK
77 #endif
78 #ifdef DEBUG
79 #define GNI_RC_CHECK(msg,rc) do { if(rc != GNI_RC_SUCCESS) {           CmiPrintf("[%d] %s; err=%s\n",CmiMyPe(),msg,gni_err_str[rc]); CmiAbort("GNI_RC_CHECK"); } } while(0)
80 #else
81 #define GNI_RC_CHECK(msg,rc)
82 #endif
83
84 #ifdef USE_ONESIDED
85 onesided_hnd_t   onesided_hnd;
86 onesided_md_t    omdh;
87 #endif
88
89 #define ALIGN4(x)        (size_t)((~3)&((x)+3)) 
90
91 static int useStaticSMSG   = 1;
92 static int useStaticMSGQ = 0;
93 static int useStaticFMA = 0;
94 static int mysize, myrank;
95 static gni_nic_handle_t      nic_hndl;
96
97
98 static void             **smsg_attr_ptr;
99 gni_msgq_attr_t         msgq_attrs;
100 gni_msgq_handle_t       msgq_handle;
101 gni_msgq_ep_attr_t      msgq_ep_attrs;
102 gni_msgq_ep_attr_t      msgq_ep_attrs_size;
103 /* =====Beginning of Declarations of Machine Specific Variables===== */
104 static int cookie;
105 static int modes = 0;
106 static gni_cq_handle_t       rx_cqh = NULL;
107 static gni_cq_handle_t       remote_bte_cq_hndl = NULL;
108 static gni_cq_handle_t       tx_cqh = NULL;
109 static gni_ep_handle_t       *ep_hndl_array;
110
111 /* preallocated memory buffer for FMA for short message and control message */
112 typedef struct {
113     gni_mem_handle_t mdh;
114     uint64_t addr;
115 } mdh_addr_t;
116
117 static mdh_addr_t            *fma_buffer_mdh_addr_base;
118 typedef struct msg_list
119 {
120     uint32_t destNode;
121     uint32_t size;
122     void *msg;
123     struct msg_list *next;
124     uint8_t tag;
125 }MSG_LIST;
126
127 typedef struct control_msg
128 {
129     uint64_t            source_addr;
130     int                 source;               /* source rank */
131     int                 length;
132     gni_mem_handle_t    source_mem_hndl;
133     struct control_msg *next;
134 }CONTROL_MSG;
135
136 typedef struct  rmda_msg
137 {
138     int                   destNode;
139     gni_post_descriptor_t *pd;
140     struct  rmda_msg      *next;
141 }RDMA_REQUEST;
142
143 /* reuse PendingMsg memory */
144 static CONTROL_MSG          *control_freelist=0;
145 static MSG_LIST             *msglist_freelist=0;
146 static RDMA_REQUEST         *rdma_freelist = 0;
147 #define FreeControlMsg(d)       \
148   do {  \
149   (d)->next = control_freelist;\
150   control_freelist = d;\
151   } while (0); 
152
153 #define MallocControlMsg(d) \
154   d = control_freelist;\
155   if (d==0) {d = ((CONTROL_MSG*)malloc(sizeof(CONTROL_MSG)));\
156              _MEMCHECK(d);\
157   } else control_freelist = d->next;
158
159
160 #define FreeMsgList(d)       \
161   do {  \
162   (d)->next = msglist_freelist;\
163   msglist_freelist = d;\
164   } while (0); 
165
166 #define MallocMsgList(d) \
167   d = msglist_freelist;\
168   if (d==0) {d = ((MSG_LIST*)malloc(sizeof(MSG_LIST)));\
169              _MEMCHECK(d);\
170   } else msglist_freelist = d->next;
171
172 #define FreeRdmaRequest(d)       \
173   do {  \
174   (d)->next = rdma_freelist;\
175   rdma_freelist = d;\
176   } while (0); 
177
178 #define MallocRdmaRequest(d) \
179   d = rdma_freelist;\
180   if (d==0) {d = ((RDMA_REQUEST*)malloc(sizeof(RDMA_REQUEST)));\
181              _MEMCHECK(d);\
182   } else rdma_freelist = d->next;
183
184 /* reuse gni_post_descriptor_t */
185 static gni_post_descriptor_t *post_freelist=NULL;
186
187 #if 1
188 #define FreePostDesc(d)       \
189   do {  \
190     (d)->next_descr = post_freelist;\
191     post_freelist = d;\
192   } while (0); 
193
194 #define MallocPostDesc(d) \
195   d = post_freelist;\
196   if (d==0) { \
197      d = ((gni_post_descriptor_t*)malloc(sizeof(gni_post_descriptor_t)));\
198      _MEMCHECK(d);\
199   } else post_freelist = d->next_descr;
200 #else
201
202 #define FreePostDesc(d)     free(d);
203 #define MallocPostDesc(d)   d = ((gni_post_descriptor_t*)malloc(sizeof(gni_post_descriptor_t))); _MEMCHECK(d);
204
205 #endif
206
207 static int send_pending = 0;
208
209 /* LrtsSent is called but message can not be sent by SMSGSend because of mailbox full or no credit */
210 static MSG_LIST *buffered_smsg_head= 0;
211 static MSG_LIST *buffered_smsg_tail= 0;
212
213 /* SmsgSend return success but message sent is not confirmed by remote side */
214
215 static RDMA_REQUEST  *pending_rdma_head = 0;
216 static RDMA_REQUEST  *pending_rdma_tail = 0;
217
218 static MSG_LIST *buffered_fma_head = 0;
219 static MSG_LIST *buffered_fma_tail = 0;
220
221 /* functions  */
222
223 static void
224 allgather(void *in,void *out, int len)
225 {
226     //PMI_Allgather is out of order
227     int i,rc, extend_len;
228     int  rank_index;
229     char *out_ptr, *out_ref;
230     char *in2;
231
232     extend_len = sizeof(int) + len;
233     in2 = (char*)malloc(extend_len);
234
235     memcpy(in2, &myrank, sizeof(int));
236     memcpy(in2+sizeof(int), in, len);
237
238     out_ptr = (char*)malloc(mysize*extend_len);
239
240     rc = PMI_Allgather(in2, out_ptr, extend_len);
241     GNI_RC_CHECK("allgather", rc);
242
243     out_ref = out;
244
245     for(i=0;i<mysize;i++) {
246         //rank index 
247         memcpy(&rank_index, &(out_ptr[extend_len*i]), sizeof(int));
248         //copy to the rank index slot
249         memcpy(&out_ref[rank_index*len], &out_ptr[extend_len*i+sizeof(int)], len);
250     }
251
252     free(out_ptr);
253     free(in2);
254
255 }
256
257 static unsigned int get_gni_nic_address(int device_id)
258 {
259     unsigned int address, cpu_id;
260     gni_return_t status;
261     int i, alps_dev_id=-1,alps_address=-1;
262     char *token, *p_ptr;
263
264     p_ptr = getenv("PMI_GNI_DEV_ID");
265     if (!p_ptr) {
266         status = GNI_CdmGetNicAddress(device_id, &address, &cpu_id);
267        
268         GNI_RC_CHECK("GNI_CdmGetNicAddress", status);
269     } else {
270         while ((token = strtok(p_ptr,":")) != NULL) {
271             alps_dev_id = atoi(token);
272             if (alps_dev_id == device_id) {
273                 break;
274             }
275             p_ptr = NULL;
276         }
277         CmiAssert(alps_dev_id != -1);
278         p_ptr = getenv("PMI_GNI_LOC_ADDR");
279         CmiAssert(p_ptr != NULL);
280         i = 0;
281         while ((token = strtok(p_ptr,":")) != NULL) {
282             if (i == alps_dev_id) {
283                 alps_address = atoi(token);
284                 break;
285             }
286             p_ptr = NULL;
287             ++i;
288         }
289         CmiAssert(alps_address != -1);
290         address = alps_address;
291     }
292     return address;
293 }
294
295 static uint8_t get_ptag(void)
296 {
297     char *p_ptr, *token;
298     uint8_t ptag;
299
300     p_ptr = getenv("PMI_GNI_PTAG");
301     CmiAssert(p_ptr != NULL);
302     token = strtok(p_ptr, ":");
303     ptag = (uint8_t)atoi(token);
304     return ptag;
305         
306 }
307
308 static uint32_t get_cookie(void)
309 {
310     uint32_t cookie;
311     char *p_ptr, *token;
312
313     p_ptr = getenv("PMI_GNI_COOKIE");
314     CmiAssert(p_ptr != NULL);
315     token = strtok(p_ptr, ":");
316     cookie = (uint32_t)atoi(token);
317
318     return cookie;
319 }
320
321 /*
322  * Local side event handler
323  *
324  */
325
326 void LocalEventHandle(gni_cq_entry_t *cq_entry, void *userdata)
327 {
328
329     int type;
330
331     type = GNI_CQ_GET_TYPE(*cq_entry);
332
333     if(type == GNI_CQ_EVENT_TYPE_SMSG)
334     {
335
336     }
337 }
338
339 void RemoteSmsgEventHandle(gni_cq_entry_t *cq_entry, void *userdata)
340 {
341 }
342
343 void RemoteBteEventHandle(gni_cq_entry_t *cq_entry, void *userdata)
344 {
345 }
346 /* =====Beginning of Definitions of Message-Corruption Related Macros=====*/
347 /* TODO: add any that are related */
348 /* =====End of Definitions of Message-Corruption Related Macros=====*/
349
350
351 #include "machine-lrts.h"
352 #include "machine-common-core.c"
353
354 /* Network progress function is used to poll the network when for
355    messages. This flushes receive buffers on some  implementations*/
356 #if CMK_MACHINE_PROGRESS_DEFINED
357 void CmiMachineProgressImpl() {
358 }
359 #endif
360
361 inline
362 static void delay_send_small_msg(void *msg, int size, int destNode, uint8_t tag)
363 {
364     MSG_LIST        *msg_tmp;
365     MallocMsgList(msg_tmp);
366     msg_tmp->destNode = destNode;
367     msg_tmp->size   = size;
368     msg_tmp->msg    = msg;
369     msg_tmp->tag    = tag;
370     msg_tmp->next   = NULL;
371     if (buffered_smsg_tail == NULL) {
372       buffered_smsg_head  = buffered_smsg_tail  = msg_tmp;
373     }
374     else {
375       buffered_smsg_tail->next    = msg_tmp;
376       buffered_smsg_tail          = msg_tmp;
377     }
378 }
379
380 static int send_with_smsg(int destNode, int size, char *msg)
381 {
382     gni_return_t        status  =   GNI_RC_SUCCESS;
383     CONTROL_MSG         *control_msg_tmp;
384     const uint8_t       tag_data    = DATA_TAG;
385     const uint8_t       tag_control = LMSG_INIT_TAG ;
386     uint32_t            vmdh_index  = -1;
387
388     CmiSetMsgSize(msg, size);
389
390     /* No mailbox available, buffer this msg and its info */
391     if(buffered_smsg_head != 0)
392     {
393         if(size <=SMSG_MAX_MSG)
394         {
395             delay_send_small_msg(msg, size, destNode, tag_data);
396         }
397         else
398         {
399             MallocControlMsg(control_msg_tmp);
400             /*
401 #ifdef USE_ONESIDED
402             onesided_mem_register(onesided_hnd, (uint64_t)msg, size, 0, &(control_msg_tmp->source_mem_hndl));
403 #else
404             status = GNI_MemRegister(nic_hndl, (uint64_t)msg, 
405                 size, rx_cqh,
406                 GNI_MEM_READ_ONLY | GNI_MEM_USE_GART,
407                 vmdh_index, &(control_msg_tmp->source_mem_hndl));
408 #endif 
409             GNI_RC_CHECK("MemRegister fails at ", status);
410             */
411             control_msg_tmp->source_addr    = (uint64_t)msg;
412             control_msg_tmp->source         = myrank;
413             control_msg_tmp->length         =size; 
414             control_msg_tmp->source_mem_hndl.qword1 = 0;
415             control_msg_tmp->source_mem_hndl.qword2 = 0;
416             delay_send_small_msg((char*)control_msg_tmp, sizeof(CONTROL_MSG), destNode, tag_control);
417         }
418         return 0;
419     }
420     else {
421         /* Can use SMSGSend */
422         if(size <= SMSG_MAX_MSG)
423         {
424             /* send the msg itself */
425             status = GNI_SmsgSendWTag(ep_hndl_array[destNode], NULL, 0, msg, size, 0, tag_data);
426             //CmiPrintf("[%d] send_with_smsg sends a data msg to PE %d status: %s\n", myrank, destNode, gni_err_str[status]);
427             if (status == GNI_RC_SUCCESS)
428             {
429                 send_pending++;
430                 CmiFree(msg);
431                 return 1;
432             }
433             else if(status == GNI_RC_NOT_DONE || status == GNI_RC_ERROR_RESOURCE)
434             {
435                 //CmiPrintf("[%d] data msg add to send queue\n", myrank);
436                 delay_send_small_msg(msg, size, destNode, tag_data);
437                 return 0;
438             }
439             else
440                 GNI_RC_CHECK("GNI_SmsgSendWTag", status);
441         }else
442         {
443             /* construct a control message and send */
444             //control_msg_tmp = (CONTROL_MSG *)malloc(sizeof(CONTROL_MSG));
445             MallocControlMsg(control_msg_tmp);
446             control_msg_tmp->source_addr    = (uint64_t)msg;
447             control_msg_tmp->source         = myrank;
448             control_msg_tmp->length         = size;
449 #ifdef USE_ONESIDED
450             onesided_mem_register(onesided_hnd, (uint64_t)msg, size, 0, &(control_msg_tmp->source_mem_hndl));
451 #else
452             status = GNI_MemRegister(nic_hndl, (uint64_t)msg, 
453                 size, rx_cqh,
454                 GNI_MEM_READ_ONLY | GNI_MEM_USE_GART,
455                 vmdh_index, &(control_msg_tmp->source_mem_hndl));
456 #endif 
457             if(status == GNI_RC_ERROR_RESOURCE || status == GNI_RC_ERROR_NOMEM)
458             {
459                 control_msg_tmp->source_mem_hndl.qword1 = 0;
460                 control_msg_tmp->source_mem_hndl.qword2 = 0;
461             }else if(status == GNI_RC_SUCCESS)
462             {
463                 status = GNI_SmsgSendWTag(ep_hndl_array[destNode], 0, 0, control_msg_tmp, sizeof(CONTROL_MSG), 0, tag_control);
464                 CmiPrintf("[%d] send_with_smsg sends a control msg to PE %d status: %d\n", myrank, destNode, status);
465                 if(status == GNI_RC_SUCCESS)
466                 {
467                     send_pending ++;
468                     FreeControlMsg(control_msg_tmp);
469                     return 1;
470                 }
471             }
472             else
473             {
474                 GNI_RC_CHECK("MemRegister fails at ", status);
475             }
476             
477             if(status == GNI_RC_INVALID_PARAM)
478                 GNI_RC_CHECK("MemRegister fails at ", status);
479             
480             // Memory register fails or send fails 
481             //CmiPrintf("[%d] control msg add to send queue\n", myrank);
482             /* store into buffer smsg_list and send later */
483             delay_send_small_msg((char*)control_msg_tmp, sizeof(CONTROL_MSG), destNode, tag_control);
484             return 0;
485         }
486     }
487 }
488
489 static CmiCommHandle LrtsSendFunc(int destNode, int size, char *msg, int mode)
490 {
491     //PRINT_INFO("Calling LrtsSend")
492     if(useStaticSMSG)
493     {
494         send_with_smsg(destNode, size, msg); 
495     }
496     else {
497         CmiAssert(0);
498     }
499     return 0;
500 }
501
502 static void LrtsPreCommonInit(int everReturn){}
503
504 /* Idle-state related functions: called in non-smp mode */
505 void CmiNotifyIdleForGemini(void) {
506     LrtsAdvanceCommunication();
507 }
508
509 static void LrtsPostCommonInit(int everReturn)
510 {
511 #if CMK_SMP
512     CcdCallOnConditionKeep(CcdPROCESSOR_BEGIN_IDLE,(CcdVoidFn)CmiNotifyBeginIdle,(void *)s);
513     CcdCallOnConditionKeep(CcdPROCESSOR_STILL_IDLE,(CcdVoidFn)CmiNotifyStillIdle,(void *)s);
514 #else
515     CcdCallOnConditionKeep(CcdPROCESSOR_STILL_IDLE,(CcdVoidFn)CmiNotifyIdleForGemini,NULL);
516 #endif
517
518 }
519
520
521 void LrtsPostNonLocal(){}
522 /* pooling CQ to receive network message */
523 static void PumpNetworkMsgs()
524 {
525     void                *header;
526     uint8_t             msg_tag;
527     const uint8_t       data_tag = DATA_TAG;
528     const uint8_t       control_tag = LMSG_INIT_TAG;
529     const uint8_t       ack_tag = ACK_TAG;
530     gni_return_t        status;
531     uint64_t            inst_id;
532     gni_cq_entry_t      event_data;
533     int                 msg_nbytes;
534     void                *msg_data;
535     gni_mem_handle_t    msg_mem_hndl;
536     CONTROL_MSG         *request_msg;
537     RDMA_REQUEST        *rdma_request_msg;
538     gni_post_descriptor_t *pd;
539
540     while (1) {
541     status = GNI_CqGetEvent(rx_cqh, &event_data);
542     if(status == GNI_RC_SUCCESS)
543     {
544         inst_id = GNI_CQ_GET_INST_ID(event_data);
545     }else if (status == GNI_RC_NOT_DONE)
546     {
547         return;
548     }else
549     {
550         GNI_RC_CHECK("CQ Get event", status);
551     }
552   
553     //printf("[%d]  PumpNetworkMsgs GNI_CQ_GET_TYPE %d from %d. \n", myrank, GNI_CQ_GET_TYPE(event_data), inst_id);
554
555     msg_tag = GNI_SMSG_ANY_TAG;
556     status = GNI_SmsgGetNextWTag(ep_hndl_array[inst_id], &header, &msg_tag);
557
558     if(status  == GNI_RC_SUCCESS)
559     {
560         /* copy msg out and then put into queue */
561         if(msg_tag == data_tag)
562         {
563             //CmiPrintf("[%d] PumpNetwork data msg is received\n", myrank);
564             //memcpy(&msg_nbytes, header, sizeof(int));
565             //msg_nbytes = *(int*)header;
566             msg_nbytes = CmiGetMsgSize(header);
567             msg_data    = CmiAlloc(msg_nbytes);
568             //CmiPrintf("[%d] PumpNetworkMsgs: get datamsg, size: %d msg id:%d\n", myrank, msg_nbytes, GNI_CQ_GET_MSG_ID(event_data));
569             memcpy(msg_data, (char*)header, msg_nbytes);
570             handleOneRecvedMsg(msg_nbytes, msg_data);
571             GNI_SmsgRelease(ep_hndl_array[inst_id]);
572         }
573         else if(msg_tag == control_tag) 
574         {
575             //CmiPrintf("[%d] PumpNetwork control msg is received\n", myrank);
576             /* initial a get to transfer data from the sender side */
577             request_msg = (CONTROL_MSG *) header;
578             msg_data = CmiAlloc(request_msg->length);
579             _MEMCHECK(msg_data);
580 #ifdef USE_ONESIDED
581             onesided_mem_register(onesided_hnd, (uint64_t)msg_data, request_msg->length, 0, &msg_mem_hndl);
582 #else
583             status = GNI_MemRegister(nic_hndl, (uint64_t)msg_data,
584                 request_msg->length, rx_cqh, 
585                 GNI_MEM_READWRITE | GNI_MEM_USE_GART, -1,
586                 &msg_mem_hndl);
587 #endif
588
589             if (status == GNI_RC_INVALID_PARAM || status == GNI_RC_PERMISSION_ERROR) 
590             {
591                 GNI_SmsgRelease(ep_hndl_array[inst_id]);
592                 GNI_RC_CHECK("Mem Register before post", status);
593             }
594
595             //buffer this request and send later
596             MallocPostDesc(pd);
597             if(request_msg->length < LRTS_GNI_RDMA_THRESHOLD) 
598                 pd->type            = GNI_POST_FMA_GET;
599             else
600                 pd->type            = GNI_POST_RDMA_GET;
601
602             pd->cq_mode         = GNI_CQMODE_GLOBAL_EVENT |  GNI_CQMODE_REMOTE_EVENT;
603             pd->dlvr_mode       = GNI_DLVMODE_PERFORMANCE;
604             pd->length          = ALIGN4(request_msg->length);
605             pd->local_addr      = (uint64_t) msg_data;
606             pd->remote_addr     = request_msg->source_addr;
607             pd->remote_mem_hndl = request_msg->source_mem_hndl;
608             pd->src_cq_hndl     = 0;     /* tx_cqh;  */
609             pd->rdma_mode       = 0;
610
611             //memory registration successful
612             if(status == GNI_RC_SUCCESS)
613             {
614                 pd->local_mem_hndl  = msg_mem_hndl;
615                 if(pd->type == GNI_POST_RDMA_GET) 
616                     status = GNI_PostRdma(ep_hndl_array[request_msg->source], pd);
617                 else
618                     status = GNI_PostFma(ep_hndl_array[request_msg->source],  pd);
619             }else
620             {
621                 pd->local_mem_hndl.qword1  = 0; 
622                 pd->local_mem_hndl.qword1  = 0; 
623             }
624             GNI_SmsgRelease(ep_hndl_array[inst_id]);
625             if(status == GNI_RC_ERROR_RESOURCE|| status == GNI_RC_ERROR_NOMEM )
626             {
627                 MallocRdmaRequest(rdma_request_msg);
628                 rdma_request_msg->next = 0;
629                 rdma_request_msg->destNode = inst_id;
630                 if(pending_rdma_head == 0)
631                 {
632                     pending_rdma_head = rdma_request_msg;
633                 }else
634                 {
635                     pending_rdma_tail->next = rdma_request_msg;
636                 }
637                 pending_rdma_tail = rdma_request_msg;
638                 return;
639             }else
640                 GNI_RC_CHECK("AFter posting", status);
641         }
642         else if(msg_tag == ack_tag) {
643             CmiPrintf("[%d] PumpNetwork tag msg is received\n", myrank);
644             /* Get is done, release message . Now put is not used yet*/
645             request_msg = (CONTROL_MSG *) header;
646             //CmiPrintf("++++## ACK msg is received on PE:%d message size=%d, addr=%p\n", myrank, request_msg->length, (void*)request_msg->source_addr);
647 #ifdef USE_ONESIDED
648             onesided_mem_deregister(onesided_hnd, &request_msg->source_mem_hndl);
649 #else
650             GNI_MemDeregister(nic_hndl, &request_msg->source_mem_hndl);
651 #endif
652             CmiFree((void*)request_msg->source_addr);
653             GNI_SmsgRelease(ep_hndl_array[inst_id]);
654             SendRdmaMsg();
655         }else{
656             GNI_SmsgRelease(ep_hndl_array[inst_id]);
657             CmiPrintf("weird tag problem\n");
658             CmiAbort("Unknown tag\n");
659         }
660     }  //else not match smsg, maybe larger message
661     else {
662        // CmiPrintf("[%d] GNI_SmsgGetNextWTag returns %s\n", myrank, gni_err_str[status]);
663     }
664     }   // end of while loop
665 }
666
667 /* Check whether message send or get is confirmed by remote */
668 static void PumpLocalTransactions()
669 {
670     gni_cq_entry_t ev;
671     gni_return_t status;
672     uint64_t type, inst_id, data_addr;
673     uint8_t         ack_tag = ACK_TAG;
674     gni_post_descriptor_t *tmp_pd;
675     //gni_post_descriptor_t   ack_pd;
676     MSG_LIST  *ptr;
677     CONTROL_MSG *ack_msg_tmp;
678
679     while (1) 
680     {
681
682         status = GNI_CqGetEvent(tx_cqh, &ev);
683         if(status == GNI_RC_SUCCESS)
684         {
685             type        = GNI_CQ_GET_TYPE(ev);
686             inst_id     = GNI_CQ_GET_INST_ID(ev);
687             data_addr   = GNI_CQ_GET_DATA(ev);
688         }else if (status == GNI_RC_NOT_DONE)
689         {
690             return;
691         }else
692         {
693             GNI_RC_CHECK("CQ Get event", status);
694         }
695
696         // printf("[%d]  PumpLocalTransactions GNI_CQ_GET_TYPE %d. \n", myrank, GNI_CQ_GET_TYPE(ev));
697
698         if (type == GNI_CQ_EVENT_TYPE_SMSG) {
699             send_pending --;
700             //CmiPrintf("[%d] PumpLocalTransactions smsg pending: %d\n", myrank, send_pending);
701         }
702         else if(type == GNI_CQ_EVENT_TYPE_POST)
703         {
704             status = GNI_GetCompleted(tx_cqh, ev, &tmp_pd);
705             GNI_RC_CHECK("Local CQ completed ", status);
706             //Message is sent, free message , put is not used now
707             if(tmp_pd->type == GNI_POST_RDMA_PUT || tmp_pd->type == GNI_POST_FMA_PUT)
708             {
709                 CmiFree((void *)tmp_pd->local_addr);
710             }else if(tmp_pd->type == GNI_POST_RDMA_GET || tmp_pd->type == GNI_POST_FMA_GET)
711             {
712                 /* Send an ACK to remote side */
713                 //CmiPrintf("\nPE:%d Received large message by get , sizefield=%d, length=%d, addr=%p\n", myrank, SIZEFIELD((void*)tmp_pd->local_addr), tmp_pd->length, tmp_pd->remote_addr); 
714                 ////CmiPrintf("\n+PE:%d Received large message by get , sizefield=%d, length=%d, addr=%p\n", myrank, remote_length , tmp_pd->length, (void*)remote_addr); 
715                 MallocControlMsg(ack_msg_tmp);
716                 ack_msg_tmp->source = myrank;
717                 //CmiPrintf("\n++PE:%d Received large message by get , sizefield=%d, length=%d, addr=%p\n", myrank, SIZEFIELD((void*)tmp_pd->local_addr), tmp_pd->length, tmp_pd->remote_addr); 
718                 ////CmiPrintf("\n+++PE:%d Received large message by get , sizefield=%d, length=%d, addr=%p\n", myrank, remote_length , tmp_pd->length, (void*)remote_addr); 
719                 ack_msg_tmp->source_addr = tmp_pd->remote_addr;
720                 ack_msg_tmp->length=tmp_pd->length; 
721                 ack_msg_tmp->source_mem_hndl = tmp_pd->remote_mem_hndl;
722                 //CmiPrintf("PE:%d sending ACK back addr=%p \n", myrank, ack_msg_tmp->source_addr); 
723            
724                 if(buffered_smsg_head!=0)
725                 {
726                     //CmiPrintf("[%d] PumpLocalTransactions: smsg buffered.\n", myrank);
727                     delay_send_small_msg(ack_msg_tmp, sizeof(CONTROL_MSG), inst_id, ack_tag);
728                 }else
729                 {
730                     //CmiPrintf("PE:%d sending ACK back addr=%p \n", myrank, ack_msg_tmp->source_addr); 
731                     status = GNI_SmsgSendWTag(ep_hndl_array[inst_id], 0, 0, ack_msg_tmp, sizeof(CONTROL_MSG), 0, ack_tag);
732                     if(status == GNI_RC_SUCCESS)
733                     {
734                         send_pending++;
735                         FreeControlMsg(ack_msg_tmp);
736                     }else if(status == GNI_RC_NOT_DONE || status == GNI_RC_ERROR_RESOURCE)
737                     {
738                         // CmiPrintf("[%d] PumpLocalTransactions: ack smsg buffered.\n", myrank);
739                         delay_send_small_msg(ack_msg_tmp, sizeof(CONTROL_MSG), inst_id, ack_tag);
740                     }
741                     else
742                         GNI_RC_CHECK("GNI_SmsgSendWTag", status);
743                 }
744 #ifdef USE_ONESIDED
745                 onesided_mem_deregister(onesided_hnd, &tmp_pd->local_mem_hndl);
746 #else
747                 GNI_MemDeregister(nic_hndl, &tmp_pd->local_mem_hndl);
748 #endif
749                 handleOneRecvedMsg(SIZEFIELD((void*)tmp_pd->local_addr), (void*)tmp_pd->local_addr); 
750                 SendRdmaMsg(); 
751             }
752             FreePostDesc(tmp_pd);
753         }
754     }   /* end of while loop */
755 }
756
757 static int SendRdmaMsg()
758 {
759
760     RDMA_REQUEST            *ptr;
761     gni_post_descriptor_t   *pd;
762     gni_return_t            status = GNI_RC_SUCCESS;
763     gni_mem_handle_t        msg_mem_hndl;
764     while(pending_rdma_head != 0)
765     {
766         ptr=pending_rdma_head;
767         pd = ptr->pd;
768         // register memory first
769         if( pd->local_mem_hndl.qword1  == 0 && pd->local_mem_hndl.qword2  == 0)
770         {
771 #ifdef USE_ONESIDED
772             onesided_mem_register(onesided_hnd, (uint64_t)pd->local_addr, pd->length, 0, &(pd->local_mem_hndl));
773 #else
774             status = GNI_MemRegister(nic_hndl, (uint64_t)pd->local_addr,
775                 pd->length, rx_cqh, 
776                 GNI_MEM_READWRITE | GNI_MEM_USE_GART, -1,
777                 &(pd->local_mem_hndl));
778 #endif
779         }
780         if(status == GNI_RC_SUCCESS)
781         {
782             if(pd->type == GNI_POST_RDMA_GET) 
783                 status = GNI_PostRdma(ep_hndl_array[ptr->destNode], pd);
784             else
785                 status = GNI_PostFma(ep_hndl_array[ptr->destNode],  pd);
786             if(status == GNI_RC_SUCCESS)
787             {
788                 pending_rdma_head = pending_rdma_head->next; 
789                 FreePostDesc(pd);
790                 FreeRdmaRequest(ptr);
791             }
792             else
793                 return 1;
794         }else
795             return 1;
796     } //end while
797     return 0;
798 }
799 static int SendBufferMsg()
800 {
801     MSG_LIST            *ptr;
802     CONTROL_MSG         *control_msg_tmp;
803     uint8_t             tag_data, tag_control, tag_ack;
804     gni_return_t        status;
805
806     tag_data    = DATA_TAG;
807     tag_control = LMSG_INIT_TAG;
808     tag_ack     = ACK_TAG;
809     /* can add flow control here to control the number of messages sent before handle message */
810     while(buffered_smsg_head != 0)
811     {
812         if(useStaticSMSG)
813         {
814             ptr = buffered_smsg_head;
815             if(ptr->tag == tag_data)
816             {
817                 status = GNI_SmsgSendWTag(ep_hndl_array[ptr->destNode], NULL, 0, ptr->msg, ptr->size, 0, tag_data);
818                 //CmiPrintf("[%d] SendBufferMsg sends a data msg to PE %d status: %s\n", myrank, ptr->destNode, gni_err_str[status]);
819                 if(status == GNI_RC_SUCCESS) {
820                     send_pending++;
821                     CmiFree(ptr->msg);
822                 }
823             }
824             else if(ptr->tag ==tag_control)
825             {
826                 control_msg_tmp = (CONTROL_MSG*)ptr->msg;
827                 if(control_msg_tmp->source_mem_hndl.qword1 == 0 && control_msg_tmp->source_mem_hndl.qword2 == 0)
828                 {
829 #ifdef USE_ONESIDED
830                     onesided_mem_register(onesided_hnd, (uint64_t)control_msg_tmp->source_addr, control_msg_tmp->length, 0, &(control_msg_tmp->source_mem_hndl));
831 #else
832                     status = GNI_MemRegister(nic_hndl, (uint64_t)control_msg_tmp->source_addr, 
833                         control_msg_tmp->length, rx_cqh,
834                         GNI_MEM_READ_ONLY | GNI_MEM_USE_GART | GNI_MEM_PI_FLUSH,
835                         -1, &(control_msg_tmp->source_mem_hndl));
836 #endif 
837                     if(status != GNI_RC_SUCCESS)
838                         break;
839                 }
840                 status = GNI_SmsgSendWTag(ep_hndl_array[ptr->destNode], 0, 0, ptr->msg, sizeof(CONTROL_MSG), 0, tag_control);
841                 //CmiPrintf("[%d] SendBufferMsg sends a control msg to PE %d status: %d\n", myrank, ptr->destNode, status);
842                 if(status == GNI_RC_SUCCESS) {
843                     FreeControlMsg((CONTROL_MSG*)(ptr->msg));
844                     send_pending ++;
845                 }
846             }else if (ptr->tag == tag_ack)
847             {
848                 status = GNI_SmsgSendWTag(ep_hndl_array[ptr->destNode], 0, 0, ptr->msg, sizeof(CONTROL_MSG), 0, tag_ack);
849                 //CmiPrintf("[%d] SendBufferMsg sends a tag msg to PE %d status: %d\n", myrank, ptr->destNode, status);
850                 if(status == GNI_RC_SUCCESS) {
851                     FreeControlMsg((CONTROL_MSG*)ptr->msg);
852                     send_pending++;
853                 }
854             }
855         } else if(useStaticMSGQ)
856         {
857             CmiAbort("MSGQ Send not done\n");
858         }else
859         {
860             CmiAbort("FMA Send not done\n");
861         }
862         if(status == GNI_RC_SUCCESS)
863         {
864             buffered_smsg_head = buffered_smsg_head->next;
865             FreeMsgList(ptr);
866         }else
867             return 0;
868     }
869     return 1;
870 }
871
872 static void LrtsAdvanceCommunication()
873 {
874     /*  Receive Msg first */
875     //CmiPrintf("Calling Lrts Pump Msg PE:%d\n", CmiMyPe());
876     PumpNetworkMsgs();
877     /* Release Sent Msg */
878     //CmiPrintf("Calling Lrts Rlease Msg PE:%d\n", CmiMyPe());
879     PumpLocalTransactions();
880     //CmiPrintf("Calling Lrts Send Buffmsg PE:%d\n", CmiMyPe());
881     /* Send buffered Message */
882     SendBufferMsg();
883 }
884
885 void remoteEventHandle(gni_cq_entry_t *event_data, void *context)
886 {
887     gni_return_t status, source_data, source_control;
888     uint64_t            source;
889     void                *header;
890     uint8_t             tag_data;
891     uint8_t             tag_control;
892
893     CmiAssert(0);
894
895     tag_data = DATA_TAG;
896     tag_control = LMSG_INIT_TAG;
897     /* pool the CQ to check which smsg endpoint to get the data */
898     //status = GNI_CqGetEvent(remote_cq_hndl, &event_data);
899         
900     /* check whether it is data or control information */
901     source = GNI_CQ_GET_SOURCE(*event_data);
902
903     if((status = GNI_SmsgGetNextWTag(ep_hndl_array[source], &header, &tag_data)) == GNI_RC_SUCCESS)
904     {
905         /* copy msg out and then put into queue */
906
907     } else if ((status = GNI_SmsgGetNextWTag(ep_hndl_array[source], &header, &tag_control)) == GNI_RC_SUCCESS)
908     {
909         /* initial a get to transfer data from the sender side */
910     } else
911     {
912
913     }
914
915 }
916
917 static void _init_static_smsg()
918 {
919     gni_smsg_attr_t      *smsg_attr;
920     gni_smsg_attr_t      *smsg_attr_vec;
921     unsigned int         smsg_memlen;
922     gni_mem_handle_t     my_smsg_mdh_mailbox;
923     register    int      i;
924     gni_return_t status;
925     uint32_t              vmdh_index = -1;
926
927      smsg_attr = (gni_smsg_attr_t *)malloc(mysize*sizeof(gni_smsg_attr_t));
928     _MEMCHECK(smsg_attr);
929
930     smsg_attr_ptr = malloc(sizeof(void*) *mysize);
931     for(i=0; i<mysize; i++)
932     {
933         if(i==myrank)
934             continue;
935         smsg_attr[i].msg_type = GNI_SMSG_TYPE_MBOX_AUTO_RETRANSMIT;
936         smsg_attr[i].mbox_offset = 0;
937         smsg_attr[i].mbox_maxcredit = SMSG_MAX_CREDIT;
938         smsg_attr[i].msg_maxsize = SMSG_MAX_MSG;
939         status = GNI_SmsgBufferSizeNeeded(&smsg_attr[i], &smsg_memlen);
940         GNI_RC_CHECK("GNI_GNI_MemRegister mem buffer", status);
941
942         smsg_attr_ptr[i] = memalign(64, smsg_memlen);
943         _MEMCHECK(smsg_attr_ptr[i]);
944         bzero(smsg_attr_ptr[i], smsg_memlen);
945         status = GNI_MemRegister(nic_hndl, (uint64_t)smsg_attr_ptr[i],
946             smsg_memlen, rx_cqh,
947             GNI_MEM_READWRITE | GNI_MEM_USE_GART | GNI_MEM_PI_FLUSH,   
948             vmdh_index,
949             &my_smsg_mdh_mailbox);
950
951         GNI_RC_CHECK("GNI_GNI_MemRegister mem buffer", status);
952       
953         smsg_attr[i].msg_buffer = smsg_attr_ptr[i];
954         smsg_attr[i].buff_size = smsg_memlen;
955         smsg_attr[i].mem_hndl = my_smsg_mdh_mailbox;
956     }
957     smsg_attr_vec = (gni_smsg_attr_t*)malloc(mysize * mysize * sizeof(gni_smsg_attr_t));
958     CmiAssert(smsg_attr_vec);
959    
960     allgather(smsg_attr, smsg_attr_vec,  mysize*sizeof(gni_smsg_attr_t));
961     //MPI_Alltoall(smsg_attr, sizeof(gni_smsg_attr_t), MPI_BYTE, smsg_attr_vec, sizeof(gni_smsg_attr_t), MPI_BYTE, MPI_COMM_WORLD);
962     for(i=0; i<mysize; i++)
963     {
964         if (myrank == i) continue;
965         /* initialize the smsg channel */
966         status = GNI_SmsgInit(ep_hndl_array[i], &smsg_attr[i], &smsg_attr_vec[i*mysize+myrank]);
967         GNI_RC_CHECK("SMSG Init", status);
968     } //end initialization
969     free(smsg_attr);
970     free(smsg_attr_vec);
971
972
973 static void _init_static_msgq()
974 {
975     gni_return_t status;
976     /* MSGQ is to send and receive short messages for large jobs (exceeding 200,000 ranks). The          performance scales by the node count rather than rank count */
977     msgq_attrs.max_msg_sz = MSGQ_MAXSIZE;
978     msgq_attrs.smsg_q_sz = 1;
979     msgq_attrs.rcv_pool_sz = 1;
980     msgq_attrs.num_msgq_eps = 2;
981     msgq_attrs.nloc_insts = 8;
982     msgq_attrs.modes = 0;
983     msgq_attrs.rcv_cq_sz = REMOTE_QUEUE_ENTRIES ;
984
985     status = GNI_MsgqInit(nic_hndl, NULL, NULL, NULL, &msgq_attrs, &msgq_handle);
986     GNI_RC_CHECK("MSGQ Init", status);
987
988
989 }
990 static void LrtsInit(int *argc, char ***argv, int *numNodes, int *myNodeID)
991 {
992     register int            i;
993     int                     rc;
994     int                     device_id = 0;
995     unsigned int            remote_addr;
996     gni_cdm_handle_t        cdm_hndl;
997     gni_return_t            status = GNI_RC_SUCCESS;
998     uint32_t                vmdh_index = -1;
999     uint8_t                 ptag;
1000     unsigned int            local_addr, *MPID_UGNI_AllAddr;
1001     int                     first_spawned;
1002
1003     void (*local_event_handler)(gni_cq_entry_t *, void *)       = &LocalEventHandle;
1004     void (*remote_smsg_event_handler)(gni_cq_entry_t *, void *) = &RemoteSmsgEventHandle;
1005     void (*remote_bte_event_handler)(gni_cq_entry_t *, void *)  = &RemoteBteEventHandle;
1006     
1007     //useStaticSMSG = CmiGetArgFlag(*argv, "+useStaticSmsg");
1008     //useStaticMSGQ = CmiGetArgFlag(*argv, "+useStaticMsgQ");
1009     
1010     status = PMI_Init(&first_spawned);
1011     GNI_RC_CHECK("PMI_Init", status);
1012
1013     status = PMI_Get_size(&mysize);
1014     GNI_RC_CHECK("PMI_Getsize", status);
1015
1016     status = PMI_Get_rank(&myrank);
1017     GNI_RC_CHECK("PMI_getrank", status);
1018
1019     *myNodeID = myrank;
1020     *numNodes = mysize;
1021   
1022     if(myrank == 0)
1023     {
1024         printf("Charm++> Running on Gemini (GNI)\n");
1025     }
1026 #ifdef USE_ONESIDED
1027     onesided_init(NULL, &onesided_hnd);
1028
1029     // this is a GNI test, so use the libonesided bypass functionality
1030     onesided_gni_bypass_get_nih(onesided_hnd, &nic_hndl);
1031     local_addr = gniGetNicAddress();
1032 #else
1033     ptag = get_ptag();
1034     cookie = get_cookie();
1035     
1036     //Create and attach to the communication  domain */
1037     status = GNI_CdmCreate(myrank, ptag, cookie, modes, &cdm_hndl);
1038     GNI_RC_CHECK("GNI_CdmCreate", status);
1039     //* device id The device id is the minor number for the device
1040     //that is assigned to the device by the system when the device is created.
1041     //To determine the device number, look in the /dev directory, which contains a list of devices. For a NIC, the device is listed as kgniX
1042     //where X is the device number 0 default 
1043     status = GNI_CdmAttach(cdm_hndl, device_id, &local_addr, &nic_hndl);
1044     GNI_RC_CHECK("GNI_CdmAttach", status);
1045     local_addr = get_gni_nic_address(0);
1046 #endif
1047     MPID_UGNI_AllAddr = (unsigned int *)malloc(sizeof(unsigned int) * mysize);
1048     _MEMCHECK(MPID_UGNI_AllAddr);
1049     allgather(&local_addr, MPID_UGNI_AllAddr, sizeof(unsigned int));
1050     /* create the local completion queue */
1051     /* the third parameter : The number of events the NIC allows before generating an interrupt. Setting this parameter to zero results in interrupt delivery with every event. When using this parameter, the mode parameter must be set to GNI_CQ_BLOCKING*/
1052     status = GNI_CqCreate(nic_hndl, LOCAL_QUEUE_ENTRIES, 0, GNI_CQ_NOBLOCK, NULL, NULL, &tx_cqh);
1053     //status = GNI_CqCreate(nic_hndl, LOCAL_QUEUE_ENTRIES, 0, GNI_CQ_NOBLOCK, &local_event_handler, NULL, &tx_cqh);
1054     GNI_RC_CHECK("GNI_CqCreate (tx)", status);
1055     
1056     /* create the destination completion queue for receiving micro-messages, make this queue considerably larger than the number of transfers */
1057
1058     status = GNI_CqCreate(nic_hndl, REMOTE_QUEUE_ENTRIES, 0, GNI_CQ_NOBLOCK, NULL, NULL, &rx_cqh);
1059     GNI_RC_CHECK("Create CQ (rx)", status);
1060     
1061     //status = GNI_CqCreate(nic_hndl, REMOTE_QUEUE_ENTRIES, 0, GNI_CQ_NOBLOCK, NULL, NULL, &remote_bte_cq_hndl);
1062     //GNI_RC_CHECK("Create BTE CQ", status);
1063
1064     /* create the endpoints. they need to be bound to allow later CQWrites to them */
1065     ep_hndl_array = (gni_ep_handle_t*)malloc(mysize * sizeof(gni_ep_handle_t));
1066     _MEMCHECK(ep_hndl_array);
1067
1068     for (i=0; i<mysize; i++) {
1069         if(i == myrank) continue;
1070         status = GNI_EpCreate(nic_hndl, tx_cqh, &ep_hndl_array[i]);
1071         GNI_RC_CHECK("GNI_EpCreate ", status);   
1072         remote_addr = MPID_UGNI_AllAddr[i];
1073         status = GNI_EpBind(ep_hndl_array[i], remote_addr, i);
1074         GNI_RC_CHECK("GNI_EpBind ", status);   
1075     }
1076     /* Depending on the number of cores in the job, decide different method */
1077     /* SMSG is fastest but not scale; Msgq is scalable, FMA is own implementation for small message */
1078     if(useStaticSMSG == 1)
1079     {
1080         _init_static_smsg(mysize);
1081     }else if(useStaticMSGQ == 1)
1082     {
1083         _init_static_msgq();
1084     }
1085     free(MPID_UGNI_AllAddr);
1086     //PRINT_INFO("\nDone with LrtsInit")
1087 }
1088
1089 #define ALIGNBUF                64
1090
1091 void* LrtsAlloc(int n_bytes, int header)
1092 {
1093     if(n_bytes <= SMSG_MAX_MSG)
1094     {
1095         int totalsize = n_bytes+header;
1096         return malloc(totalsize);
1097 /*
1098     }else if(n_bytes <= LRTS_GNI_RDMA_THRESHOLD)
1099     {
1100         return malloc(n_bytes);
1101 */
1102     }else 
1103     {
1104         CmiAssert(header <= ALIGNBUF);
1105         n_bytes = ALIGN4(n_bytes);           /* make sure size if 4 aligned */
1106         char *res = memalign(ALIGNBUF, n_bytes+ALIGNBUF);
1107         return res + ALIGNBUF - header;
1108     }
1109 }
1110
1111 void  LrtsFree(void *msg)
1112 {
1113     int size = SIZEFIELD((char*)msg+sizeof(CmiChunkHeader));
1114     if (size <= SMSG_MAX_MSG)
1115       free(msg);
1116     else
1117       free((char*)msg + sizeof(CmiChunkHeader) - ALIGNBUF);
1118 }
1119
1120 static void LrtsExit()
1121 {
1122     /* free memory ? */
1123     PMI_Finalize();
1124     exit(0);
1125 }
1126
1127 static void LrtsDrainResources()
1128 {
1129     while (!SendBufferMsg()) {
1130       PumpNetworkMsgs();
1131       PumpLocalTransactions();
1132     }
1133 }
1134
1135 void CmiAbort(const char *message) {
1136
1137     CmiPrintf("CmiAbort is calling on PE:%d\n", myrank);
1138     PMI_Abort(-1, message);
1139 }
1140
1141 #if 0
1142 /**************************  TIMER FUNCTIONS **************************/
1143 #if CMK_TIMER_USE_SPECIAL
1144 /* MPI calls are not threadsafe, even the timer on some machines */
1145 static CmiNodeLock  timerLock = 0;
1146 static int _absoluteTime = 0;
1147 static double starttimer = 0;
1148 static int _is_global = 0;
1149
1150 int CmiTimerIsSynchronized() {
1151     int  flag;
1152     void *v;
1153
1154     /*  check if it using synchronized timer */
1155     if (MPI_SUCCESS != MPI_Attr_get(MPI_COMM_WORLD, MPI_WTIME_IS_GLOBAL, &v, &flag))
1156         printf("MPI_WTIME_IS_GLOBAL not valid!\n");
1157     if (flag) {
1158         _is_global = *(int*)v;
1159         if (_is_global && CmiMyPe() == 0)
1160             printf("Charm++> MPI timer is synchronized\n");
1161     }
1162     return _is_global;
1163 }
1164
1165 int CmiTimerAbsolute() {
1166     return _absoluteTime;
1167 }
1168
1169 double CmiStartTimer() {
1170     return 0.0;
1171 }
1172
1173 double CmiInitTime() {
1174     return starttimer;
1175 }
1176
1177 void CmiTimerInit(char **argv) {
1178     _absoluteTime = CmiGetArgFlagDesc(argv,"+useAbsoluteTime", "Use system's absolute time as wallclock time.");
1179     if (_absoluteTime && CmiMyPe() == 0)
1180         printf("Charm++> absolute MPI timer is used\n");
1181     _is_global = CmiTimerIsSynchronized();
1182
1183     if (_is_global) {
1184         if (CmiMyRank() == 0) {
1185             double minTimer;
1186 #if CMK_TIMER_USE_XT3_DCLOCK
1187             starttimer = dclock();
1188 #else
1189             starttimer = MPI_Wtime();
1190 #endif
1191
1192             MPI_Allreduce(&starttimer, &minTimer, 1, MPI_DOUBLE, MPI_MIN,
1193                 MPI_COMM_WORLD );
1194             starttimer = minTimer;
1195         }
1196     } else { /* we don't have a synchronous timer, set our own start time */
1197         CmiBarrier();
1198         CmiBarrier();
1199         CmiBarrier();
1200 #if CMK_TIMER_USE_XT3_DCLOCK
1201         starttimer = dclock();
1202 #else
1203         starttimer = MPI_Wtime();
1204 #endif
1205     }
1206
1207     CmiNodeAllBarrier();          /* for smp */
1208 }
1209
1210 /**
1211  * Since the timerLock is never created, and is
1212  * always NULL, then all the if-condition inside
1213  * the timer functions could be disabled right
1214  * now in the case of SMP.
1215  */
1216 double CmiTimer(void) {
1217     double t;
1218 #if CMK_TIMER_USE_XT3_DCLOCK
1219     t = dclock();
1220 #else
1221     t = MPI_Wtime();
1222 #endif
1223     return _absoluteTime?t: (t-starttimer);
1224 }
1225
1226 double CmiWallTimer(void) {
1227     double t;
1228 #if CMK_TIMER_USE_XT3_DCLOCK
1229     t = dclock();
1230 #else
1231     t = MPI_Wtime();
1232 #endif
1233     return _absoluteTime? t: (t-starttimer);
1234 }
1235
1236 double CmiCpuTimer(void) {
1237     double t;
1238 #if CMK_TIMER_USE_XT3_DCLOCK
1239     t = dclock() - starttimer;
1240 #else
1241     t = MPI_Wtime() - starttimer;
1242 #endif
1243     return t;
1244 }
1245
1246 #endif
1247 #endif
1248 /************Barrier Related Functions****************/
1249
1250 int CmiBarrier()
1251 {
1252     int status;
1253     status = PMI_Barrier();
1254     return status;
1255
1256 }