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