dfd472cc5bb75f7a319deb8eb7c0f9d61b89a8b1
[charm.git] / src / arch / gemini_gni / machine.c
1 /*****************************************************************************
2  * $Source$
3  * $Author$  Yanhua Sun
4  * $Date$  07-01-2011
5  * $Revision$ 
6  *****************************************************************************/
7
8 /** @file
9  * Gemini GNI machine layer
10  */
11 /*@{*/
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <errno.h>
16 #include <malloc.h>
17 #include "converse.h"
18
19 #include "gni_pub.h"
20 #include "mpi.h"
21 #include "pmi.h"
22 /*Support for ++debug: */
23 #if defined(_WIN32) && ! defined(__CYGWIN__)
24 #include <windows.h>
25 #include <wincon.h>
26 #include <sys/types.h>
27 #include <sys/timeb.h>
28 static void sleep(int secs) {
29     Sleep(1000*secs);
30 }
31 #else
32 #include <unistd.h> /*For getpid()*/
33 #endif
34 #include <stdlib.h> /*For sleep()*/
35
36 #include "machine.h"
37
38 #include "pcqueue.h"
39
40 #define DEBUY_PRINT
41
42 #ifdef DEBUY_PRINT
43 #define PRINT_INFO(msg) {fprintf(stdout, "%s\n", msg); fflush(stdout);}
44 #else
45 #define PRINT_INFO(msg)
46 #endif
47 /* =======Beginning of Definitions of Performance-Specific Macros =======*/
48 static int useSMSG   = 1;
49 static int useDynamicSmsg = 0;
50 static int useMsgq = 0;
51 static int size, rank;
52 #define FMA_PER_CORE  1024
53 #define FMA_BUFFER_SIZE 1024
54 #define SMSG_PER_MSG    1024
55 #define SMSG_MAX_CREDIT 16
56 #define SMSG_BUFFER_SIZE        10240
57 #define FMA_BTE_THRESHOLD  4096
58 #define MSGQ_MAXSIZE       4096
59
60 #define DEBUG
61
62 #ifdef GNI_RC_CHECK
63 #undef GNI_RC_CHECK
64 #endif
65
66 #ifdef DEBUG
67 #define GNI_RC_CHECK(msg,rc) do { if(rc != GNI_RC_SUCCESS) {           printf("%s; err=%s\n",msg,gni_err_str[rc]); exit(911); } } while(0)
68 #else
69 #define GNI_RC_CHECK(msg,rc)
70 #endif
71
72 static gni_nic_handle_t      nic_hndl;
73 static unsigned int         *MPID_UGNI_AllAddr;
74 static gni_smsg_attr_t      *smsg_attr;
75 static gni_smsg_attr_t      *smsg_attr_vec;
76 static char                 *smsg_mem_buffer = NULL;
77 static uint32_t             smsg_memlen;
78
79 gni_msgq_attr_t         msgq_attrs;
80 gni_msgq_handle_t       msgq_handle;
81 gni_msgq_ep_attr_t      msgq_ep_attrs;
82 gni_msgq_ep_attr_t      msgq_ep_attrs_size;
83
84 #define REMOTE_QUEUE_ENTRIES  1048576
85 #define LOCAL_QUEUE_ENTRIES 1024
86 /* SMSG is data message */
87 #define DATA_TAG        0
88 /* SMSG is a control message to initialize a BTE */
89 #define LMSG_INIT_TAG        1 
90 /* =====Beginning of Declarations of Machine Specific Variables===== */
91 static int cookie;
92 static int modes = 0;
93 static gni_cq_handle_t       rx_cqh = NULL;
94 static gni_cq_handle_t       remote_bte_cq_hndl = NULL;
95 static gni_cq_handle_t       tx_cqh = NULL;
96 static gni_ep_handle_t       *ep_hndl_array;
97
98 /* preallocated memory buffer for FMA for short message and control message */
99 static char            *fma_buffer;
100 static int              fma_buffer_len_eachcore = FMA_BUFFER_SIZE;
101 typedef struct {
102     gni_mem_handle_t mdh;
103     uint64_t addr;
104 } mdh_addr_t;
105
106 static mdh_addr_t            my_mdh_addr;
107 static mdh_addr_t            *fma_buffer_mdh_addr_base;
108 static gni_mem_handle_t      fma_buffer_mdh_addr;
109 static gni_mem_handle_t      my_smsg_mdh_mailbox;
110 /* =====Beginning of Declarations of Machine Specific Functions===== */
111
112 typedef struct msg_list
113 {
114     int destNode;
115     int size;
116     void *msg;
117     struct msg_list *next;
118
119 }MSG_LIST;
120
121 typedef struct control_msg
122 {
123     int             source;   //source rank
124     uint64_t        source_addr;
125     gni_mem_handle_t    source_mem_hndl;
126     uint64_t            length;
127 }CONTROL_MSG;
128
129 /* LrtsSent is called but message can not be sent by SMSGSend because of mailbox full or no credit */
130 static MSG_LIST *buffered_smsg_head= 0;
131 static MSG_LIST *buffered_smsg_tail= 0;
132 /* SmsgSend return success but message sent is not confirmed by remote side */
133
134 static MSG_LIST *buffered_fma_head = 0;
135 static MSG_LIST *buffered_fma_tail = 0;
136
137 static unsigned int get_gni_nic_address(int device_id)
138 {
139     unsigned int address, cpu_id;
140     gni_return_t status;
141     int i, alps_dev_id=-1,alps_address=-1;
142     char *token, *p_ptr;
143
144     p_ptr = getenv("PMI_GNI_DEV_ID");
145     if (!p_ptr) {
146         status = GNI_CdmGetNicAddress(device_id, &address, &cpu_id);
147        
148         GNI_RC_CHECK("GNI_CdmGetNicAddress", status);
149     } else {
150         while ((token = strtok(p_ptr,":")) != NULL) {
151             alps_dev_id = atoi(token);
152             if (alps_dev_id == device_id) {
153                 break;
154             }
155             p_ptr = NULL;
156         }
157         CmiAssert(alps_dev_id != -1);
158         p_ptr = getenv("PMI_GNI_LOC_ADDR");
159         CmiAssert(p_ptr != NULL);
160         i = 0;
161         while ((token = strtok(p_ptr,":")) != NULL) {
162             if (i == alps_dev_id) {
163                 alps_address = atoi(token);
164                 break;
165             }
166             p_ptr = NULL;
167             ++i;
168         }
169         CmiAssert(alps_address != -1);
170         address = alps_address;
171     }
172     return address;
173 }
174 static void* gather_nic_addresses(void)
175 {
176     unsigned int local_addr,*alladdrs;
177     int size,rc;
178     size_t addr_len;
179
180     MPI_Comm_size(MPI_COMM_WORLD,&size);
181
182     /*
183      * * just assume a single gemini device
184      */
185     local_addr = get_gni_nic_address(0);
186
187     addr_len = sizeof(unsigned int);
188
189     alladdrs = (unsigned int *)malloc(addr_len * size);
190     CmiAssert(alladdrs != NULL);
191
192     MPI_Allgather(&local_addr, addr_len, MPI_BYTE, alladdrs, addr_len, MPI_BYTE, MPI_COMM_WORLD);
193
194     return (void *)alladdrs;
195
196 }
197
198 static uint8_t get_ptag(void)
199 {
200     char *p_ptr, *token;
201     uint8_t ptag;
202
203     p_ptr = getenv("PMI_GNI_PTAG");
204     CmiAssert(p_ptr != NULL);
205     token = strtok(p_ptr, ":");
206     ptag = (uint8_t)atoi(token);
207     return ptag;
208         
209 }
210
211 static uint32_t get_cookie(void)
212 {
213     uint32_t cookie;
214     char *p_ptr, *token;
215
216     p_ptr = getenv("PMI_GNI_COOKIE");
217     CmiAssert(p_ptr != NULL);
218     token = strtok(p_ptr, ":");
219     cookie = (uint32_t)atoi(token);
220
221     return cookie;
222 }
223
224 /*
225  * Local side event handler
226  *
227  */
228
229 void LocalEventHandle(gni_cq_entry_t *cq_entry, void *userdata)
230 {
231
232     int type;
233
234     type = GNI_CQ_GET_TYPE(*cq_entry);
235
236     if(type == GNI_CQ_EVENT_TYPE_SMSG)
237     {
238
239     }
240 }
241
242 void RemoteSmsgEventHandle(gni_cq_entry_t *cq_entry, void *userdata)
243 {
244 }
245
246 void RemoteBteEventHandle(gni_cq_entry_t *cq_entry, void *userdata)
247 {
248 }
249 /* =====Beginning of Definitions of Message-Corruption Related Macros=====*/
250 /* TODO: add any that are related */
251 /* =====End of Definitions of Message-Corruption Related Macros=====*/
252
253
254 #include "machine-common.h"
255 #include "machine-common.c"
256
257 /* Network progress function is used to poll the network when for
258    messages. This flushes receive buffers on some  implementations*/
259 #if CMK_MACHINE_PROGRESS_DEFINED
260 void CmiMachineProgressImpl() {
261 }
262 #endif
263
264
265 /* 
266  * The message can be copied to registered memory buffer and be sent
267  * This message memory can be registered to network. It depends on which one is cheaper
268  *
269  * register might be better when the msg is large
270  */
271
272 static int send_with_fma(int destNode, int size, char *msg)
273 {
274     gni_post_descriptor_t   pd;
275     gni_return_t status;
276     CONTROL_MSG *control_msg_tmp;
277     MSG_LIST *msg_tmp;
278     if(buffered_fma_head != 0)
279     {
280         msg_tmp = (MSG_LIST *)LrtsAlloc(sizeof(MSG_LIST));
281         msg_tmp->msg = msg;
282         msg_tmp->destNode = destNode;
283         msg_tmp ->size = size;
284         buffered_smsg_tail->next = msg_tmp;
285         buffered_smsg_tail = msg_tmp;
286         return 0;
287     } else
288     {
289         pd.type            = GNI_POST_FMA_PUT;
290         pd.cq_mode         = GNI_CQMODE_GLOBAL_EVENT | GNI_CQMODE_REMOTE_EVENT;
291         pd.dlvr_mode       = GNI_DLVMODE_PERFORMANCE;
292         pd.length          = 8;
293         pd.remote_addr     = fma_buffer_mdh_addr_base[destNode].addr + fma_buffer_len_eachcore*destNode;
294         pd.remote_mem_hndl = fma_buffer_mdh_addr_base[destNode].mdh;
295         if(size < FMA_BUFFER_SIZE)
296         {
297             /* send the message */
298             pd.local_addr      = (uint64_t) msg;
299         }else
300         {
301             /* construct a control message and send */
302             control_msg_tmp = (CONTROL_MSG *)LrtsAlloc((int)sizeof(CONTROL_MSG));
303             GNI_MemRegister(nic_hndl, (uint64_t)msg, 
304                 size, remote_bte_cq_hndl,
305                 GNI_MEM_READ_ONLY | GNI_MEM_USE_GART,
306                 -1, &(control_msg_tmp->source_mem_hndl));
307             
308             control_msg_tmp->source = _Cmi_mynode;
309             control_msg_tmp->source_addr = (uint64_t)msg;
310             msg_tmp = (MSG_LIST *)LrtsAlloc(sizeof(MSG_LIST));
311             msg_tmp->msg = control_msg_tmp;
312             msg_tmp->destNode = destNode;
313             msg_tmp ->size = size;
314         }
315         status = GNI_PostFma(ep_hndl_array[destNode], &pd);
316         if(status == GNI_RC_SUCCESS)
317             return 1;
318         else if(status == GNI_RC_NOT_DONE || status == GNI_RC_ERROR_RESOURCE) 
319         {
320             /* store into buffer fma_list and send later */
321             buffered_fma_head = msg_tmp;
322             buffered_fma_tail = msg_tmp;
323             return 0;
324         }
325     }
326 }
327 static int send_with_smsg(int destNode, int size, char *msg)
328 {
329     gni_return_t status;
330     MSG_LIST *msg_tmp;
331     CONTROL_MSG *control_msg_tmp;
332     uint8_t             tag_data = DATA_TAG;
333     uint8_t             tag_control= LMSG_INIT_TAG ;
334
335     /* No mailbox available */
336     if(buffered_smsg_head != 0)
337     {
338         msg_tmp = (MSG_LIST *)LrtsAlloc(sizeof(MSG_LIST));
339         msg_tmp->msg = msg;
340         msg_tmp->destNode = destNode;
341         msg_tmp ->size = size;
342         buffered_smsg_tail->next = msg_tmp;
343         buffered_smsg_tail = msg_tmp;
344         return 0;
345     }else
346     {
347         /* Can use SMSGSend */
348         if(size < SMSG_PER_MSG)
349         {
350             /* send the msg itself */
351             msg_tmp = (MSG_LIST *)LrtsAlloc(sizeof(MSG_LIST));
352             msg_tmp->msg = msg;
353             msg_tmp->destNode = destNode;
354             msg_tmp ->size = size;
355             status = GNI_SmsgSendWTag(ep_hndl_array[destNode], &(msg_tmp->size), (uint32_t)sizeof(int), msg, (uint32_t)size, 0, tag_data);
356         }else
357         {
358             /* construct a control message and send */
359             control_msg_tmp = (CONTROL_MSG *)LrtsAlloc(sizeof(CONTROL_MSG));
360             
361             GNI_MemRegister(nic_hndl, (uint64_t)msg, 
362                 size, remote_bte_cq_hndl,
363                 GNI_MEM_READ_ONLY | GNI_MEM_USE_GART,
364                 -1, &(control_msg_tmp->source_mem_hndl));
365             
366             control_msg_tmp->source = _Cmi_mynode;
367             control_msg_tmp->source_addr = (uint64_t)msg;
368         
369             msg_tmp = (MSG_LIST *)LrtsAlloc(sizeof(MSG_LIST));
370             msg_tmp->msg = control_msg_tmp;
371             msg_tmp->destNode = destNode;
372             msg_tmp ->size = size;
373             
374             status = GNI_SmsgSendWTag(ep_hndl_array[destNode], 0, 0, control_msg_tmp, sizeof(CONTROL_MSG), 0, tag_control);
375         }
376         if(status == GNI_RC_SUCCESS)
377         {
378             return 1;
379         }else if(status == GNI_RC_NOT_DONE || status == GNI_RC_ERROR_RESOURCE) 
380         {
381             /* store into buffer smsg_list and send later */
382             buffered_smsg_head = msg_tmp;
383             buffered_smsg_tail = msg_tmp;
384             return 0;
385         }
386     }
387 }
388
389 static CmiCommHandle LrtsSendFunc(int destNode, int size, char *msg, int mode)
390 {
391     PRINT_INFO("Calling LrtsSend")
392     if(useSMSG)
393     {
394         send_with_smsg(destNode, size, msg); 
395     }else
396     {
397         send_with_fma(destNode, size, msg); 
398     }
399     return 0;
400 }
401
402 static void LrtsPreCommonInit(int everReturn){}
403 static void LrtsPostCommonInit(int everReturn){}
404 static void LrtsDrainResources() /* used when exit */
405 {}
406
407 void LrtsPostNonLocal(){}
408 /* pooling CQ to receive network message */
409 static void PumpMsgs()
410 {
411     void *header;
412     uint8_t             tag_data;
413     uint8_t             tag_control;
414     gni_return_t status;
415     uint64_t source_data, source_control, type, inst_id, data;
416     gni_cq_entry_t event_data;
417     int msg_nbytes;
418     void *msg_data;
419     CONTROL_MSG *request_msg;
420     gni_post_descriptor_t pd;
421
422     status = GNI_CqGetEvent(rx_cqh, &event_data);
423
424     if(status == GNI_RC_SUCCESS)
425     {
426         type = GNI_CQ_GET_TYPE(event_data);
427         inst_id = GNI_CQ_GET_INST_ID(event_data);
428     
429     }else
430         return;
431     /* Check local queue about RDMA_GET */
432     if((status = GNI_SmsgGetNextWTag(ep_hndl_array[inst_id], &header, &tag_data)) == GNI_RC_SUCCESS)
433     {
434         /* copy msg out and then put into queue */
435         memcpy(&msg_nbytes, header, sizeof(int));   
436         msg_data = CmiAlloc(msg_nbytes);
437         handleOneRecvedMsg(msg_nbytes, msg_data);
438         GNI_SmsgRelease(ep_hndl_array[inst_id]);
439     } else if ((status = GNI_SmsgGetNextWTag(ep_hndl_array[inst_id], &header, &tag_control)) == GNI_RC_SUCCESS)
440     {
441         /* initial a get to transfer data from the sender side */
442         request_msg = (CONTROL_MSG *) header;
443         msg_data = CmiAlloc(request_msg->length); //need align checking
444         /* register this memory */
445         if(request_msg->length <= FMA_BTE_THRESHOLD) 
446             pd.type            = GNI_POST_FMA_GET;
447         else
448             pd.type            = GNI_POST_RDMA_GET;
449
450         pd.cq_mode         = GNI_CQMODE_GLOBAL_EVENT |            GNI_CQMODE_REMOTE_EVENT;
451         pd.dlvr_mode       = GNI_DLVMODE_PERFORMANCE;
452         pd.length          = request_msg->length;
453         pd.local_addr      = (uint64_t) request_msg;
454         pd.remote_addr     = request_msg->source_addr;
455         pd.remote_mem_hndl = request_msg->source_mem_hndl;
456      // rdma specific
457         pd.src_cq_hndl     = tx_cqh;
458         pd.rdma_mode       = 0;
459
460         if(pd.type == GNI_POST_RDMA_PUT) 
461             status = GNI_PostRdma(ep_hndl_array[request_msg->source], &pd);
462         else
463             status = GNI_PostFma(ep_hndl_array[request_msg->source], &pd);
464
465         if(status = GNI_RC_SUCCESS)
466         {
467             /* put into receive buffer queue */
468         }else
469         {
470         }
471
472         GNI_SmsgRelease(ep_hndl_array[inst_id]);
473     }
474
475 }
476
477 /* Check whether message send or get is confirmed by remote */
478 static void ReleaseSentMessages()
479 {
480     gni_cq_entry_t ev;
481     gni_return_t status;
482     uint64_t type, source, inst_id, data_addr;
483     gni_post_descriptor_t *tmp_pd;
484     MSG_LIST  *ptr;
485     status = GNI_CqGetEvent(tx_cqh, &ev);
486     if(status == GNI_RC_SUCCESS)
487     {
488         type        = GNI_CQ_GET_TYPE(ev);
489         inst_id     = GNI_CQ_GET_INST_ID(ev);
490         data_addr   = GNI_CQ_GET_DATA(ev);
491     }else
492         return;
493
494     if(type == GNI_CQ_EVENT_TYPE_POST)
495     {
496         status = GNI_GetCompleted(tx_cqh, ev, &tmp_pd);
497     }
498     /* memory leak here , need to realease struct MSG_list */ 
499     CmiFree((void *)data_addr);
500 }
501
502 static void SendBufferMsg()
503 {
504     int ret;
505     while(buffered_smsg_head != 0)
506     {
507         if(useSMSG)
508         {
509             ret = send_with_smsg(buffered_smsg_head->destNode, buffered_smsg_head->size, buffered_smsg_head->msg); 
510         }else
511         {
512             ret = send_with_fma(buffered_smsg_head->destNode, buffered_smsg_head->size, buffered_smsg_head->msg); 
513         }
514         if(ret == GNI_RC_SUCCESS) 
515         {
516             buffered_smsg_head = buffered_smsg_head->next;
517         }else
518             break;
519     }
520 }
521 static void LrtsAdvanceCommunication()
522 {
523     /*  Receive Msg first */
524
525     //CmiPrintf("Calling Lrts Pump Msg PE:%d\n", CmiMyPe());
526     PumpMsgs();
527     /* Release Sent Msg */
528     //CmiPrintf("Calling Lrts Rlease Msg PE:%d\n", CmiMyPe());
529     ReleaseSentMessages();
530     //CmiPrintf("Calling Lrts Send Buffmsg PE:%d\n", CmiMyPe());
531     /* Send buffered Message */
532     SendBufferMsg();
533 }
534
535 void remoteEventHandle(gni_cq_entry_t *event_data, void *context)
536 {
537     gni_return_t status, source_data, source_control;
538     uint64_t            source;
539     void                *header;
540     uint8_t             tag_data;
541     uint8_t             tag_control;
542
543     tag_data = DATA_TAG;
544     tag_control = LMSG_INIT_TAG;
545     /* pool the CQ to check which smsg endpoint to get the data */
546     //status = GNI_CqGetEvent(remote_cq_hndl, &event_data);
547         
548     /* check whether it is data or control information */
549     source = GNI_CQ_GET_SOURCE(*event_data);
550
551     if((status = GNI_SmsgGetNextWTag(ep_hndl_array[source], &header, &tag_data)) == GNI_RC_SUCCESS)
552     {
553         /* copy msg out and then put into queue */
554
555     } else if ((status = GNI_SmsgGetNextWTag(ep_hndl_array[source], &header, &tag_control)) == GNI_RC_SUCCESS)
556     {
557         /* initial a get to transfer data from the sender side */
558     } else
559     {
560
561     }
562
563 }
564
565 /* CDM initialization, register cache, two CQs created, DMA buffer, free list of transaction management structure.  
566  * SMSG - all endpoint pairs created, buffer allocated, connection built (static)
567  * MSQ */
568 static void LrtsInit(int *argc, char ***argv, int *numNodes, int *myNodeID)
569 {
570     register int          i;
571     int                   rc;
572     int                   device_id = 0;
573     int                   events_returned;
574     int                   test_id;
575     unsigned int          local_addr;
576     unsigned int          remote_addr;
577     gni_cdm_handle_t      cdm_hndl;
578     gni_nic_handle_t      nic_hndl;
579     gni_return_t          status = GNI_RC_SUCCESS;
580     uint32_t              vmdh_index = -1;
581     uint64_t              *recv_buffer;
582     uint8_t                  ptag;
583     int first_spawned;
584     int                      size, rank;
585
586     void (*local_event_handler)(gni_cq_entry_t *, void *) = &LocalEventHandle;
587     void (*remote_smsg_event_handler)(gni_cq_entry_t *, void *) = &RemoteSmsgEventHandle;
588     void (*remote_bte_event_handler)(gni_cq_entry_t *, void *) = &RemoteBteEventHandle;
589     
590     //useDynamicSmsg = CmiGetArgFlag(argv, "+useDynamicSmsg");
591     //useMsgq = CmiGetArgFlag(argv, "+useMsgq");
592
593
594     MPI_Init(argc, argv);
595     MPI_Comm_rank(MPI_COMM_WORLD,myNodeID);
596     MPI_Comm_size(MPI_COMM_WORLD,numNodes);
597
598
599     size = *numNodes;
600     rank = *myNodeID;
601     
602     ptag = get_ptag();
603     cookie = get_cookie();
604     
605     /* Create and attach to the communication  domain */
606
607     status = GNI_CdmCreate(rank, ptag, cookie, modes, &cdm_hndl);
608     GNI_RC_CHECK("GNI_CdmCreate", status);
609     /* device id The device id is the minor number for the device that is assigned to the device by the system when the device is created. 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, where X is the device number
610     0 default */
611     status = GNI_CdmAttach(cdm_hndl, device_id, &local_addr, &nic_hndl);
612     GNI_RC_CHECK("GNI_CdmAttach", status);
613    
614     /* create the local completion queue */
615     /* adaptive control TODO more option */
616     /* 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*/
617     status = GNI_CqCreate(nic_hndl, LOCAL_QUEUE_ENTRIES, 0, GNI_CQ_NOBLOCK, NULL, NULL, &tx_cqh);
618     //status = GNI_CqCreate(nic_hndl, LOCAL_QUEUE_ENTRIES, 0, GNI_CQ_NOBLOCK, &local_event_handler, NULL, &tx_cqh);
619     GNI_RC_CHECK("GNI_CqCreate (tx)", status);
620     
621     /* create the destination completion queue for receiving micro-messages, make this queue considerably larger than the number of transfers */
622
623     status = GNI_CqCreate(nic_hndl, REMOTE_QUEUE_ENTRIES, 0, GNI_CQ_NOBLOCK, NULL, NULL, &rx_cqh);
624     status = GNI_CqCreate(nic_hndl, REMOTE_QUEUE_ENTRIES, 0, GNI_CQ_NOBLOCK, NULL, NULL, &remote_bte_cq_hndl);
625
626     GNI_RC_CHECK("Create CQ (rx)", status);
627
628     /* create the endpoints. they need to be bound to allow later CQWrites to them */
629     ep_hndl_array = (gni_ep_handle_t*)malloc(size * sizeof(gni_ep_handle_t));
630     CmiAssert(ep_hndl_array != NULL);
631
632     MPID_UGNI_AllAddr = (unsigned int *)gather_nic_addresses();
633     /* include self */
634     for (i=0; i<size; i++) {
635         if(i == rank) continue;
636         status = GNI_EpCreate(nic_hndl, tx_cqh, &ep_hndl_array[i]);
637         GNI_RC_CHECK("GNI_EpCreate ", status);   
638         remote_addr = MPID_UGNI_AllAddr[i];
639         status = GNI_EpBind(ep_hndl_array[i], remote_addr, i);
640         
641         GNI_RC_CHECK("GNI_EpBind ", status);   
642     }
643     /* Allocate a dma buffer to hook the destination cq to */
644     
645     fma_buffer = (char *)calloc(FMA_PER_CORE*size, 1);
646     CmiAssert(fma_buffer != NULL);
647
648     status = GNI_MemRegister(nic_hndl, (uint64_t)fma_buffer,
649         FMA_PER_CORE*size, rx_cqh, 
650         GNI_MEM_READWRITE | GNI_MEM_USE_GART, vmdh_index,
651         &fma_buffer_mdh_addr);
652
653     GNI_RC_CHECK("Memregister DMA ", status);
654     /* Gather up all of the mdh's over the socket network, 
655      * this also serves as a barrier */
656     fma_buffer_mdh_addr_base = (mdh_addr_t*)malloc(size* sizeof(mdh_addr_t));
657     CmiAssert(fma_buffer_mdh_addr_base);
658
659     my_mdh_addr.addr = (uint64_t)recv_buffer;
660     my_mdh_addr.mdh = fma_buffer_mdh_addr;
661
662     MPI_Allgather(&my_mdh_addr, sizeof(mdh_addr_t), MPI_BYTE, fma_buffer_mdh_addr_base, sizeof(mdh_addr_t), MPI_BYTE, MPI_COMM_WORLD);
663    
664     /*  If use SMSG mode (1) register memory buffer as mailbox (2)gather the buffer on remote peers */
665     if(useMsgq==0 && useSMSG==1 ){
666         PRINT_INFO("Using static SMSG")
667         smsg_memlen = SMSG_BUFFER_SIZE ;
668         smsg_mem_buffer = (char*)calloc(smsg_memlen, 1);
669         status = GNI_MemRegister(nic_hndl, (uint64_t)smsg_mem_buffer,
670                                 smsg_memlen, rx_cqh,
671                                 GNI_MEM_READWRITE | GNI_MEM_USE_GART,   
672                                 vmdh_index,
673                                 &my_smsg_mdh_mailbox);
674        
675         GNI_RC_CHECK("GNI_GNI_MemRegister mem buffer", status);
676
677         smsg_attr = (gni_smsg_attr_t *)malloc(size*sizeof(gni_smsg_attr_t));
678
679         if(!useDynamicSmsg){
680             for(i=0; i<size; i++)
681             {
682                 smsg_attr[i].msg_type = GNI_SMSG_TYPE_MBOX;
683                 smsg_attr[i].msg_buffer = smsg_mem_buffer;
684                 smsg_attr[i].buff_size = smsg_memlen;
685                 smsg_attr[i].mem_hndl = my_smsg_mdh_mailbox;
686                 smsg_attr[i].mbox_offset = smsg_memlen/size*rank;
687                 smsg_attr[i].mbox_maxcredit = SMSG_MAX_CREDIT;
688                 smsg_attr[i].msg_maxsize = SMSG_PER_MSG;
689             }
690             smsg_attr_vec = (gni_smsg_attr_t*)malloc(size * sizeof(gni_smsg_attr_t));
691             CmiAssert(smsg_attr_vec);
692             MPI_Alltoall(smsg_attr, sizeof(gni_smsg_attr_t), MPI_BYTE, smsg_attr_vec, sizeof(gni_smsg_attr_t), MPI_BYTE, MPI_COMM_WORLD);
693             for(i=0; i<size; i++)
694             {
695                 if (rank == i) continue;
696                 /* initialize the smsg channel */
697                 status = GNI_SmsgInit(ep_hndl_array[i], &smsg_attr[i], 
698                     &smsg_attr_vec[i]);
699
700                 GNI_RC_CHECK("SMSG Init", status);
701             } //end initialization
702         } //end static 
703         /* do nothing if dynamic connection */
704     } //end smsg
705     else {
706
707         /* 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 */
708         msgq_attrs.max_msg_sz = MSGQ_MAXSIZE;
709         msgq_attrs.smsg_q_sz = 1;
710         msgq_attrs.rcv_pool_sz = 1;
711         msgq_attrs.num_msgq_eps = 2;
712         msgq_attrs.nloc_insts = 8;
713         msgq_attrs.modes = 0;
714         msgq_attrs.rcv_cq_sz = REMOTE_QUEUE_ENTRIES ;
715
716         status = GNI_MsgqInit(nic_hndl, NULL, NULL, NULL, &msgq_attrs, &msgq_handle);
717         GNI_RC_CHECK("MSGQ Init", status);
718     } //end MSGQ
719
720     PRINT_INFO("Done with LrtsInit")
721 }
722
723 static void* LrtsAlloc(int n_bytes)
724 {
725
726     if(n_bytes <= SMSG_PER_MSG)
727     {
728         return malloc(n_bytes);
729     }else if(n_bytes <= FMA_BTE_THRESHOLD)
730     {
731         return malloc(n_bytes);
732     }else 
733     {
734         return memalign(64, n_bytes);
735     }
736 }
737
738 static void  LrtsFree(void *msg)
739 {
740     free(msg);
741 }
742
743
744 static void LrtsExit()
745 {
746     /* free memory ? */
747     MPI_Finalize();
748 }
749 /***********************************************************************
750  *
751  * Abort function:
752  *
753  ************************************************************************/
754
755 void CmiAbort(const char *message) {
756
757     MPI_Abort(MPI_COMM_WORLD, -1);
758 }
759
760 /**************************  TIMER FUNCTIONS **************************/
761
762 #if CMK_TIMER_USE_SPECIAL
763
764 /* MPI calls are not threadsafe, even the timer on some machines */
765 static CmiNodeLock  timerLock = 0;
766                                 static int _absoluteTime = 0;
767                                                            static double starttimer = 0;
768                                                                                       static int _is_global = 0;
769
770 int CmiTimerIsSynchronized() {
771     int  flag;
772     void *v;
773
774     /*  check if it using synchronized timer */
775     if (MPI_SUCCESS != MPI_Attr_get(MPI_COMM_WORLD, MPI_WTIME_IS_GLOBAL, &v, &flag))
776         printf("MPI_WTIME_IS_GLOBAL not valid!\n");
777     if (flag) {
778         _is_global = *(int*)v;
779         if (_is_global && CmiMyPe() == 0)
780             printf("Charm++> MPI timer is synchronized\n");
781     }
782     return _is_global;
783 }
784
785 int CmiTimerAbsolute() {
786     return _absoluteTime;
787 }
788
789 double CmiStartTimer() {
790     return 0.0;
791 }
792
793 double CmiInitTime() {
794     return starttimer;
795 }
796
797 void CmiTimerInit(char **argv) {
798     _absoluteTime = CmiGetArgFlagDesc(argv,"+useAbsoluteTime", "Use system's absolute time as wallclock time.");
799     if (_absoluteTime && CmiMyPe() == 0)
800         printf("Charm++> absolute MPI timer is used\n");
801
802     _is_global = CmiTimerIsSynchronized();
803
804     if (_is_global) {
805         if (CmiMyRank() == 0) {
806             double minTimer;
807 #if CMK_TIMER_USE_XT3_DCLOCK
808             starttimer = dclock();
809 #else
810             starttimer = MPI_Wtime();
811 #endif
812
813             MPI_Allreduce(&starttimer, &minTimer, 1, MPI_DOUBLE, MPI_MIN,
814                           MPI_COMM_WORLD );
815             starttimer = minTimer;
816         }
817     } else { /* we don't have a synchronous timer, set our own start time */
818         CmiBarrier();
819         CmiBarrier();
820         CmiBarrier();
821 #if CMK_TIMER_USE_XT3_DCLOCK
822         starttimer = dclock();
823 #else
824         starttimer = MPI_Wtime();
825 #endif
826     }
827
828 #if 0 && CMK_SMP && CMK_MPI_INIT_THREAD
829     if (CmiMyRank()==0 && _thread_provided == MPI_THREAD_SINGLE)
830         timerLock = CmiCreateLock();
831 #endif
832     CmiNodeAllBarrier();          /* for smp */
833 }
834
835 /**
836  * Since the timerLock is never created, and is
837  * always NULL, then all the if-condition inside
838  * the timer functions could be disabled right
839  * now in the case of SMP. --Chao Mei
840  */
841 double CmiTimer(void) {
842     double t;
843 #if 0 && CMK_SMP
844     if (timerLock) CmiLock(timerLock);
845 #endif
846
847 #if CMK_TIMER_USE_XT3_DCLOCK
848     t = dclock();
849 #else
850     t = MPI_Wtime();
851 #endif
852
853 #if 0 && CMK_SMP
854     if (timerLock) CmiUnlock(timerLock);
855 #endif
856
857     return _absoluteTime?t: (t-starttimer);
858 }
859
860 double CmiWallTimer(void) {
861     double t;
862 #if 0 && CMK_SMP
863     if (timerLock) CmiLock(timerLock);
864 #endif
865
866 #if CMK_TIMER_USE_XT3_DCLOCK
867     t = dclock();
868 #else
869     t = MPI_Wtime();
870 #endif
871
872 #if 0 && CMK_SMP
873     if (timerLock) CmiUnlock(timerLock);
874 #endif
875
876     return _absoluteTime? t: (t-starttimer);
877 }
878
879 double CmiCpuTimer(void) {
880     double t;
881 #if 0 && CMK_SMP
882     if (timerLock) CmiLock(timerLock);
883 #endif
884 #if CMK_TIMER_USE_XT3_DCLOCK
885     t = dclock() - starttimer;
886 #else
887     t = MPI_Wtime() - starttimer;
888 #endif
889 #if 0 && CMK_SMP
890     if (timerLock) CmiUnlock(timerLock);
891 #endif
892     return t;
893 }
894
895 #endif
896
897 /************Barrier Related Functions****************/
898
899 int CmiBarrier()
900 {
901     int status;
902     status = MPI_Barrier(MPI_COMM_WORLD);
903     return status;
904
905 }
906 /*@}*/
907
908 /*******************************************
909  *
910  * internal function only to this file 
911  */