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