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