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