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