0450b6729645f26963922974d4ad2c60ba9a156c
[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 #if PRINT_SYH
606     lrts_send_msg_id++;
607     CmiPrintf("Large LrtsSend PE:%d==>%d, size=%d, messageid:%d LMSG\n", myrank, destNode, size, lrts_send_msg_id);
608 #endif
609     if(smsg_msglist_head == 0)
610     {
611         status = MEMORY_REGISTER(onesided_hnd, nic_hndl,msg, ALIGN4(size), &(control_msg_tmp->source_mem_hndl), &omdh);
612         if(status == GNI_RC_SUCCESS)
613         {
614             status = GNI_SmsgSendWTag(ep_hndl_array[destNode], 0, 0, control_msg_tmp, sizeof(CONTROL_MSG), 0, LMSG_INIT_TAG);
615             if(status == GNI_RC_SUCCESS)
616             {
617 #if PRINT_SYH
618                 lrts_smsg_success++;
619                 if(lrts_smsg_success == lrts_send_msg_id)
620                     CmiPrintf("GOOD [%d==>%d] sent done%d (msgs=%d)\n", myrank, destNode, lrts_smsg_success, lrts_send_msg_id);
621                 else
622                     CmiPrintf("BAD [%d==>%d] sent done%d (msgs=%d)\n", myrank, destNode, lrts_smsg_success, lrts_send_msg_id);
623 #endif
624                 FreeControlMsg(control_msg_tmp);
625                 return 1;
626             }
627
628         } else if (status == GNI_RC_INVALID_PARAM || status == GNI_RC_PERMISSION_ERROR)
629         {
630             CmiAbort("Memory registor for large msg\n");
631         }
632     }
633     control_msg_tmp->source_mem_hndl.qword1 = 0;
634     control_msg_tmp->source_mem_hndl.qword2 = 0;
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     while(pending_rdma_head != 0)
922     {
923         RDMA_REQUEST *ptr=pending_rdma_head;
924         gni_post_descriptor_t *pd = ptr->pd;
925         // register memory first
926         if( pd->local_mem_hndl.qword1  == 0 && pd->local_mem_hndl.qword2  == 0)
927         {
928             status = MEMORY_REGISTER(onesided_hnd, nic_hndl, pd->local_addr, pd->length, &(pd->local_mem_hndl), &omdh);
929         }
930         if(status == GNI_RC_SUCCESS)
931         {
932             if(pd->type == GNI_POST_RDMA_GET) 
933                 status = GNI_PostRdma(ep_hndl_array[ptr->destNode], pd);
934             else
935                 status = GNI_PostFma(ep_hndl_array[ptr->destNode],  pd);
936             if(status == GNI_RC_SUCCESS)
937             {
938                 pending_rdma_head = pending_rdma_head->next; 
939                 //FreePostDesc(pd);
940                 FreeRdmaRequest(ptr);
941             }
942             else
943                 return 1;
944         }else
945             return 1;
946     } //end while
947     return 0;
948 }
949
950 static int SendBufferMsg()
951 {
952     MSG_LIST            *ptr;
953     CONTROL_MSG         *control_msg_tmp;
954     gni_return_t        status;
955     //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");}
956     /* can add flow control here to control the number of messages sent before handle message */
957     while(smsg_msglist_head != 0)
958     {
959         if(useStaticSMSG)
960         {
961             ptr = smsg_msglist_head;
962             CmiAssert(ptr!=NULL);
963             if(ptr->tag == SMALL_DATA_TAG)
964             {
965                 status = GNI_SmsgSendWTag(ep_hndl_array[ptr->destNode], NULL, 0, ptr->msg, ptr->size, 0, SMALL_DATA_TAG);
966                // CmiPrintf("[%d==>%d] buffer send call(%d)%s\n", myrank, ptr->destNode, lrts_smsg_success, gni_err_str[status] );
967                 if(status == GNI_RC_SUCCESS) {
968 #if PRINT_SYH
969                     lrts_smsg_success++;
970                     if(lrts_smsg_success == lrts_send_msg_id)
971                         CmiPrintf("GOOD [%d==>%d] sent done%d (msgs=%d)\n", myrank, ptr->destNode, lrts_smsg_success, lrts_send_msg_id);
972                     else
973                         CmiPrintf("BAD [%d==>%d] sent done%d (msgs=%d)\n", myrank, ptr->destNode, lrts_smsg_success, lrts_send_msg_id);
974 #endif
975                     CmiFree(ptr->msg);
976                 }
977             }
978             else if(ptr->tag == LMSG_INIT_TAG)
979             {
980                 control_msg_tmp = (CONTROL_MSG*)ptr->msg;
981 #if PRINT_SYH
982                 CmiPrintf("[%d==>%d] LMSG buffer send call(%d)%s\n", myrank, ptr->destNode, lrts_smsg_success, gni_err_str[status] );
983 #endif
984                 if(control_msg_tmp->source_mem_hndl.qword1 == 0 && control_msg_tmp->source_mem_hndl.qword2 == 0)
985                 {
986                     MEMORY_REGISTER(onesided_hnd, nic_hndl, control_msg_tmp->source_addr, control_msg_tmp->length, &(control_msg_tmp->source_mem_hndl), &omdh);
987                     if(status != GNI_RC_SUCCESS)
988                         break;
989                 }
990                 status = GNI_SmsgSendWTag(ep_hndl_array[ptr->destNode], 0, 0, ptr->msg, sizeof(CONTROL_MSG), 0, LMSG_INIT_TAG);
991                 if(status == GNI_RC_SUCCESS) {
992 #if PRINT_SYH
993                     lrts_smsg_success++;
994                     CmiPrintf("[%d==>%d] sent LMSG done%d\n", myrank, ptr->destNode, lrts_smsg_success);
995 #endif
996                     FreeControlMsg((CONTROL_MSG*)(ptr->msg));
997                 }
998             }else if (ptr->tag == ACK_TAG)
999             {
1000 #if PRINT_SYH
1001                 CmiPrintf("[%d==>%d] ACK buffer send call(%d)%s\n", myrank, ptr->destNode, lrts_smsg_success, gni_err_str[status] );
1002 #endif
1003                 status = GNI_SmsgSendWTag(ep_hndl_array[ptr->destNode], 0, 0, ptr->msg, sizeof(CONTROL_MSG), 0, ACK_TAG);
1004                 if(status == GNI_RC_SUCCESS) {
1005 #if PRINT_SYH
1006                     lrts_smsg_success++;
1007                     if(lrts_smsg_success == lrts_send_msg_id)
1008                         CmiPrintf("GOOD [%d==>%d] sent done%d (msgs=%d)\n", myrank, ptr->destNode, lrts_smsg_success, lrts_send_msg_id);
1009                     else
1010                         CmiPrintf("BAD [%d==>%d] sent done%d (msgs=%d)\n", myrank, ptr->destNode, lrts_smsg_success, lrts_send_msg_id);
1011 #endif
1012                     FreeControlMsg((CONTROL_MSG*)ptr->msg);
1013                 }
1014             }else
1015             {
1016                 CmiPrintf("Weird tag\n");
1017                 CmiAbort("should not happen\n");
1018             }
1019         } 
1020         if(status == GNI_RC_SUCCESS)
1021         {
1022             smsg_msglist_head = smsg_msglist_head->next;
1023             FreeMsgList(ptr);
1024 #if PRINT_SYH
1025             buffered_smsg_counter--;
1026             if(lrts_smsg_success == lrts_send_msg_id)
1027                 CmiPrintf("GOOD send buff [%d==>%d] send buffer sent done%d (msgs=%d)\n", myrank, ptr->destNode, lrts_smsg_success, lrts_send_msg_id);
1028             else
1029                 CmiPrintf("BAD send buff [%d==>%d] sent done%d (msgs=%d)\n", myrank, ptr->destNode, lrts_smsg_success, lrts_send_msg_id);
1030 #endif
1031         }else {
1032             return 0;
1033         }
1034     }   // end of for
1035 #if PRINT_SYH
1036     if(lrts_send_msg_id-lrts_smsg_success !=0)
1037         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));
1038 #endif
1039     return 1;
1040 }
1041
1042 static void LrtsAdvanceCommunication()
1043 {
1044     /*  Receive Msg first */
1045     //CmiPrintf("Calling Lrts Pump Msg PE:%d\n", CmiMyPe());
1046     PumpNetworkSmsg();
1047     //CmiPrintf("Calling Lrts Pump RdmaMsg PE:%d\n", CmiMyPe());
1048     //PumpNetworkRdmaMsgs();
1049     /* Release Sent Msg */
1050     //CmiPrintf("Calling Lrts Rlease Msg PE:%d\n", CmiMyPe());
1051     //PumpLocalSmsgTransactions();
1052     //CmiPrintf("Calling Lrts Rlease RdmaMsg PE:%d\n", CmiMyPe());
1053     PumpLocalRdmaTransactions();
1054     //CmiPrintf("Calling Lrts Send Buffmsg PE:%d\n", CmiMyPe());
1055     /* Send buffered Message */
1056     SendBufferMsg();
1057     SendRdmaMsg();
1058 }
1059
1060 static void _init_static_smsg()
1061 {
1062     gni_smsg_attr_t      *smsg_attr;
1063     gni_smsg_attr_t      *smsg_attr_vec;
1064     unsigned int         smsg_memlen;
1065     gni_mem_handle_t     my_smsg_mdh_mailbox;
1066     register    int      i;
1067     gni_return_t status;
1068     uint32_t              vmdh_index = -1;
1069
1070     if(mysize <=1024)
1071     {
1072         SMSG_MAX_MSG = 1024;
1073         log2_SMSG_MAX_MSG = 10;
1074     }else if (mysize > 1024 && mysize <= 16384)
1075     {
1076         SMSG_MAX_MSG = 512;
1077         log2_SMSG_MAX_MSG = 9;
1078
1079     }else {
1080         SMSG_MAX_MSG = 256;
1081         log2_SMSG_MAX_MSG = 8;
1082     }
1083
1084      smsg_attr = (gni_smsg_attr_t *)malloc(mysize*sizeof(gni_smsg_attr_t));
1085     _MEMCHECK(smsg_attr);
1086
1087     smsg_attr[0].msg_type = GNI_SMSG_TYPE_MBOX_AUTO_RETRANSMIT;
1088     smsg_attr[0].mbox_maxcredit = SMSG_MAX_CREDIT;
1089     smsg_attr[0].msg_maxsize = SMSG_MAX_MSG;
1090     status = GNI_SmsgBufferSizeNeeded(&smsg_attr[0], &smsg_memlen);
1091     GNI_RC_CHECK("GNI_GNI_MemRegister mem buffer", status);
1092     smsg_mailbox_base = memalign(64, smsg_memlen*(mysize-1));
1093     _MEMCHECK(smsg_mailbox_base);
1094     bzero(smsg_mailbox_base, smsg_memlen*(mysize-1));
1095     status = GNI_MemRegister(nic_hndl, (uint64_t)smsg_mailbox_base,
1096             smsg_memlen*(mysize-1), smsg_rx_cqh,
1097             GNI_MEM_READWRITE | GNI_MEM_USE_GART | GNI_MEM_PI_FLUSH,   
1098             vmdh_index,
1099             &my_smsg_mdh_mailbox);
1100
1101     GNI_RC_CHECK("GNI_GNI_MemRegister mem buffer", status);
1102
1103     for(i=0; i<mysize; i++)
1104     {
1105         if(i==myrank)
1106             continue;
1107         smsg_attr[i].msg_type = GNI_SMSG_TYPE_MBOX_AUTO_RETRANSMIT;
1108         smsg_attr[i].mbox_maxcredit = SMSG_MAX_CREDIT;
1109         smsg_attr[i].msg_maxsize = SMSG_MAX_MSG;
1110         if(i<myrank)
1111             smsg_attr[i].mbox_offset = i*smsg_memlen;
1112         else
1113             smsg_attr[i].mbox_offset = (i-1)*smsg_memlen;
1114
1115         smsg_attr[i].msg_buffer = smsg_mailbox_base;
1116         smsg_attr[i].buff_size = smsg_memlen;
1117         smsg_attr[i].mem_hndl = my_smsg_mdh_mailbox;
1118     }
1119     smsg_attr_vec = (gni_smsg_attr_t*)malloc(mysize * mysize * sizeof(gni_smsg_attr_t));
1120     _MEMCHECK(smsg_attr_vec);
1121    
1122     allgather(smsg_attr, smsg_attr_vec,  mysize*sizeof(gni_smsg_attr_t));
1123     for(i=0; i<mysize; i++)
1124     {
1125         if (myrank == i) continue;
1126         /* initialize the smsg channel */
1127         status = GNI_SmsgInit(ep_hndl_array[i], &smsg_attr[i], &smsg_attr_vec[i*mysize+myrank]);
1128         GNI_RC_CHECK("SMSG Init", status);
1129     } //end initialization
1130     free(smsg_attr);
1131     free(smsg_attr_vec);
1132
1133     status = GNI_SmsgSetMaxRetrans(nic_hndl, 4096);
1134     GNI_RC_CHECK("SmsgSetMaxRetrans Init", status);
1135
1136
1137 static void _init_static_msgq()
1138 {
1139     gni_return_t status;
1140     /* 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 */
1141     msgq_attrs.max_msg_sz = MSGQ_MAXSIZE;
1142     msgq_attrs.smsg_q_sz = 1;
1143     msgq_attrs.rcv_pool_sz = 1;
1144     msgq_attrs.num_msgq_eps = 2;
1145     msgq_attrs.nloc_insts = 8;
1146     msgq_attrs.modes = 0;
1147     msgq_attrs.rcv_cq_sz = REMOTE_QUEUE_ENTRIES ;
1148
1149     status = GNI_MsgqInit(nic_hndl, NULL, NULL, NULL, &msgq_attrs, &msgq_handle);
1150     GNI_RC_CHECK("MSGQ Init", status);
1151
1152
1153 }
1154
1155 static void _init_DMA_buffer()
1156 {
1157     gni_return_t            status = GNI_RC_SUCCESS;
1158     /*AUTO tuning */
1159     /* suppose max_smsg is 1024, DMA buffer is split into 2048, 4096, 8192, ... */
1160     /*  This method might be better for SMP, but it is bad for Nonsmp since msgs are sharing same slots */
1161     /*
1162      * DMA_slots = 19-log2_SMSG_MAX_MSG;
1163     DMA_incoming_avail_tag = malloc(DMA_slots);
1164     DMA_buffer_size = 2*(DMA_max_single_msg - SMSG_MAX_MSG); 
1165     DMA_incoming_base_addr =  memalign(ALIGNBUF, DMA_buffer_size);
1166     DMA_outgoing_base_addr =  memalign(ALIGNBUF, DMA_buffer_size);
1167     
1168     status = GNI_MemRegister(nic_hndl, (uint64_t)DMA_incoming_base_addr,
1169             DMA_buffer_size, smsg_rx_cqh,
1170             GNI_MEM_READWRITE | GNI_MEM_USE_GART | GNI_MEM_PI_FLUSH,   
1171             vmdh_index,
1172             &);
1173             */
1174     // one is reserved to avoid deadlock
1175     DMA_slots           = 17; // each one is 8K  16*8K + 1 slot reserved to avoid deadlock
1176     DMA_buffer_size     = DMA_max_single_msg + 8192;
1177     DMA_buffer_base_mdh_addr.addr = (uint64_t)memalign(ALIGNBUF, DMA_buffer_size);
1178     status = GNI_MemRegister(nic_hndl, DMA_buffer_base_mdh_addr.addr,
1179         DMA_buffer_size, smsg_rx_cqh,
1180         GNI_MEM_READWRITE | GNI_MEM_USE_GART | GNI_MEM_PI_FLUSH,   
1181         -1,
1182         &(DMA_buffer_base_mdh_addr.mdh));
1183     GNI_RC_CHECK("GNI_MemRegister", status);
1184     DMA_buffer_base_mdh_addr_vec = (mdh_addr_t*) malloc(sizeof(mdh_addr_t) * mysize);
1185
1186     allgather(&DMA_buffer_base_mdh_addr, DMA_buffer_base_mdh_addr_vec, sizeof(mdh_addr_t) );
1187 }
1188
1189 static void LrtsInit(int *argc, char ***argv, int *numNodes, int *myNodeID)
1190 {
1191     register int            i;
1192     int                     rc;
1193     int                     device_id = 0;
1194     unsigned int            remote_addr;
1195     gni_cdm_handle_t        cdm_hndl;
1196     gni_return_t            status = GNI_RC_SUCCESS;
1197     uint32_t                vmdh_index = -1;
1198     uint8_t                 ptag;
1199     unsigned int            local_addr, *MPID_UGNI_AllAddr;
1200     int                     first_spawned;
1201     int                     physicalID;
1202     //void (*local_event_handler)(gni_cq_entry_t *, void *)       = &LocalEventHandle;
1203     //void (*remote_smsg_event_handler)(gni_cq_entry_t *, void *) = &RemoteSmsgEventHandle;
1204     //void (*remote_bte_event_handler)(gni_cq_entry_t *, void *)  = &RemoteBteEventHandle;
1205     
1206     //useStaticSMSG = CmiGetArgFlag(*argv, "+useStaticSmsg");
1207     //useStaticMSGQ = CmiGetArgFlag(*argv, "+useStaticMsgQ");
1208     
1209     status = PMI_Init(&first_spawned);
1210     GNI_RC_CHECK("PMI_Init", status);
1211
1212     status = PMI_Get_size(&mysize);
1213     GNI_RC_CHECK("PMI_Getsize", status);
1214
1215     status = PMI_Get_rank(&myrank);
1216     GNI_RC_CHECK("PMI_getrank", status);
1217
1218     //physicalID = CmiPhysicalNodeID(myrank);
1219     
1220     //printf("Pysical Node ID:%d for PE:%d\n", physicalID, myrank);
1221
1222     *myNodeID = myrank;
1223     *numNodes = mysize;
1224   
1225     if(myrank == 0)
1226     {
1227         printf("Charm++> Running on Gemini (GNI) using %d  cores\n", mysize);
1228     }
1229 #ifdef USE_ONESIDED
1230     onesided_init(NULL, &onesided_hnd);
1231
1232     // this is a GNI test, so use the libonesided bypass functionality
1233     onesided_gni_bypass_get_nih(onesided_hnd, &nic_hndl);
1234     local_addr = gniGetNicAddress();
1235 #else
1236     ptag = get_ptag();
1237     cookie = get_cookie();
1238     
1239     //Create and attach to the communication  domain */
1240     status = GNI_CdmCreate(myrank, ptag, cookie, modes, &cdm_hndl);
1241     GNI_RC_CHECK("GNI_CdmCreate", status);
1242     //* device id The device id is the minor number for the device
1243     //that is assigned to the device by the system when the device is created.
1244     //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
1245     //where X is the device number 0 default 
1246     status = GNI_CdmAttach(cdm_hndl, device_id, &local_addr, &nic_hndl);
1247     GNI_RC_CHECK("GNI_CdmAttach", status);
1248     local_addr = get_gni_nic_address(0);
1249 #endif
1250     MPID_UGNI_AllAddr = (unsigned int *)malloc(sizeof(unsigned int) * mysize);
1251     _MEMCHECK(MPID_UGNI_AllAddr);
1252     allgather(&local_addr, MPID_UGNI_AllAddr, sizeof(unsigned int));
1253     /* create the local completion queue */
1254     /* 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*/
1255     status = GNI_CqCreate(nic_hndl, LOCAL_QUEUE_ENTRIES, 0, GNI_CQ_NOBLOCK, NULL, NULL, &smsg_tx_cqh);
1256     GNI_RC_CHECK("GNI_CqCreate (tx)", status);
1257     
1258     //status = GNI_CqCreate(nic_hndl, LOCAL_QUEUE_ENTRIES, 0, GNI_CQ_NOBLOCK, NULL, NULL, &post_tx_cqh);
1259     //GNI_RC_CHECK("GNI_CqCreate post (tx)", status);
1260     /* create the destination completion queue for receiving micro-messages, make this queue considerably larger than the number of transfers */
1261
1262     status = GNI_CqCreate(nic_hndl, REMOTE_QUEUE_ENTRIES, 0, GNI_CQ_NOBLOCK, NULL, NULL, &smsg_rx_cqh);
1263     GNI_RC_CHECK("Create CQ (rx)", status);
1264     
1265     //status = GNI_CqCreate(nic_hndl, REMOTE_QUEUE_ENTRIES, 0, GNI_CQ_NOBLOCK, NULL, NULL, &post_rx_cqh);
1266     //GNI_RC_CHECK("Create Post CQ (rx)", status);
1267     
1268     //status = GNI_CqCreate(nic_hndl, REMOTE_QUEUE_ENTRIES, 0, GNI_CQ_NOBLOCK, NULL, NULL, &rdma_cqh);
1269     //GNI_RC_CHECK("Create BTE CQ", status);
1270
1271     /* create the endpoints. they need to be bound to allow later CQWrites to them */
1272     ep_hndl_array = (gni_ep_handle_t*)malloc(mysize * sizeof(gni_ep_handle_t));
1273     _MEMCHECK(ep_hndl_array);
1274
1275     for (i=0; i<mysize; i++) {
1276         if(i == myrank) continue;
1277         status = GNI_EpCreate(nic_hndl, smsg_tx_cqh, &ep_hndl_array[i]);
1278         GNI_RC_CHECK("GNI_EpCreate ", status);   
1279         remote_addr = MPID_UGNI_AllAddr[i];
1280         status = GNI_EpBind(ep_hndl_array[i], remote_addr, i);
1281         GNI_RC_CHECK("GNI_EpBind ", status);   
1282     }
1283     /* Depending on the number of cores in the job, decide different method */
1284     /* SMSG is fastest but not scale; Msgq is scalable, FMA is own implementation for small message */
1285     if(useStaticSMSG == 1)
1286     {
1287         _init_static_smsg(mysize);
1288     }else if(useStaticMSGQ == 1)
1289     {
1290         _init_static_msgq();
1291     }
1292
1293     /* init DMA buffer for medium message */
1294
1295     //_init_DMA_buffer();
1296     free(MPID_UGNI_AllAddr);
1297 }
1298
1299
1300 void* LrtsAlloc(int n_bytes, int header)
1301 {
1302     if(n_bytes <= SMSG_MAX_MSG)
1303     {
1304         int totalsize = n_bytes+header;
1305         return malloc(totalsize);
1306     }else 
1307     {
1308         CmiAssert(header <= ALIGNBUF);
1309         n_bytes = ALIGN4(n_bytes);           /* make sure size if 4 aligned */
1310         char *res = memalign(ALIGNBUF, n_bytes+ALIGNBUF);
1311         return res + ALIGNBUF - header;
1312     }
1313 }
1314
1315 void  LrtsFree(void *msg)
1316 {
1317     int size = SIZEFIELD((char*)msg+sizeof(CmiChunkHeader));
1318     if (size <= SMSG_MAX_MSG)
1319       free(msg);
1320     else
1321       free((char*)msg + sizeof(CmiChunkHeader) - ALIGNBUF);
1322 }
1323
1324 static void LrtsExit()
1325 {
1326     /* free memory ? */
1327     PMI_Finalize();
1328     exit(0);
1329 }
1330
1331 static void LrtsDrainResources()
1332 {
1333     while (!SendBufferMsg()) {
1334         PumpNetworkSmsg();
1335         PumpNetworkRdmaMsgs();
1336         PumpLocalSmsgTransactions();
1337         PumpLocalRdmaTransactions();
1338     }
1339 }
1340
1341 void CmiAbort(const char *message) {
1342
1343     CmiPrintf("CmiAbort is calling on PE:%d\n", myrank);
1344     PMI_Abort(-1, message);
1345 }
1346
1347 /**************************  TIMER FUNCTIONS **************************/
1348 #if CMK_TIMER_USE_SPECIAL
1349 /* MPI calls are not threadsafe, even the timer on some machines */
1350 static CmiNodeLock  timerLock = 0;
1351 static int _absoluteTime = 0;
1352 static int _is_global = 0;
1353 static struct timespec start_ns;
1354
1355 inline int CmiTimerIsSynchronized() {
1356     return 1;
1357 }
1358
1359 inline int CmiTimerAbsolute() {
1360     return _absoluteTime;
1361 }
1362
1363 double CmiStartTimer() {
1364     return 0.0;
1365 }
1366
1367 double CmiInitTime() {
1368     return (double)(start_ts.tv_sec)+(double)start_ts.tv_nsec/1000000000.0;
1369 }
1370
1371 void CmiTimerInit(char **argv) {
1372     _absoluteTime = CmiGetArgFlagDesc(argv,"+useAbsoluteTime", "Use system's absolute time as wallclock time.");
1373     if (_absoluteTime && CmiMyPe() == 0)
1374         printf("Charm++> absolute  timer is used\n");
1375     
1376     _is_global = CmiTimerIsSynchronized();
1377
1378
1379     if (_is_global) {
1380         if (CmiMyRank() == 0) {
1381             clock_gettime(CLOCK_MONOTONIC, &start_ts)
1382         }
1383     } else { /* we don't have a synchronous timer, set our own start time */
1384         CmiBarrier();
1385         CmiBarrier();
1386         CmiBarrier();
1387         clock_gettime(CLOCK_MONOTONIC, &start_ts)
1388     }
1389     CmiNodeAllBarrier();          /* for smp */
1390 }
1391
1392 /**
1393  * Since the timerLock is never created, and is
1394  * always NULL, then all the if-condition inside
1395  * the timer functions could be disabled right
1396  * now in the case of SMP.
1397  */
1398 double CmiTimer(void) {
1399     struct timespec now_ts;
1400     clock_gettime(CLOCK_MONOTONIC, &now_ts)
1401     return _absoluteTime?((double)(now_ts.tv_sec)+(double)now_ts.tv_nsec/1000000000.0)
1402         : (double)( now_ts.tv_sec - start_ts.tv_sec ) + (((double) now_ts.tv_nsec - (double) start_ts.tv_nsec)  / 1000000000.0);
1403 }
1404
1405 double CmiWallTimer(void) {
1406     struct timespec now_ts;
1407     clock_gettime(CLOCK_MONOTONIC, &now_ts)
1408     return _absoluteTime?((double)(now_ts.tv_sec)+(double)now_ts.tv_nsec/1000000000.0)
1409         : (double)( now_ts.tv_sec - start_ts.tv_sec ) + (((double) now_ts.tv_nsec - (double) start_ts.tv_nsec)  / 1000000000.0);
1410 }
1411
1412 double CmiCpuTimer(void) {
1413     struct timespec now_ts;
1414     clock_gettime(CLOCK_MONOTONIC, &now_ts)
1415     return _absoluteTime?((double)(now_ts.tv_sec)+(double)now_ts.tv_nsec/1000000000.0)
1416         : (double)( now_ts.tv_sec - start_ts.tv_sec ) + (((double) now_ts.tv_nsec - (double) start_ts.tv_nsec)  / 1000000000.0);
1417 }
1418
1419 #endif
1420 /************Barrier Related Functions****************/
1421
1422 int CmiBarrier()
1423 {
1424     int status;
1425     status = PMI_Barrier();
1426     return status;
1427
1428 }