67a74cd8cccf273feefd22756bc47b3de2e01e39
[charm.git] / src / arch / gemini_gni / machine-persistent.c
1 /** @file
2  * Elan persistent communication
3  * @ingroup Machine
4 */
5
6 /*
7   included in machine.c
8   Gengbin Zheng, 9/6/2011
9 */
10
11 /*
12   machine specific persistent comm functions:
13   * LrtsSendPersistentMsg
14   * CmiSyncSendPersistent
15   * PumpPersistent
16   * PerAlloc PerFree      // persistent message memory allocation/free functions
17   * persist_machine_init  // machine specific initialization call
18 */
19
20 #if USE_LRTS_MEMPOOL
21 #define LRTS_GNI_RDMA_PUT_THRESHOLD  2048
22 #else
23 #define LRTS_GNI_RDMA_PUT_THRESHOLD  16384
24 #endif
25
26 void LrtsSendPersistentMsg(PersistentHandle h, int destNode, int size, void *m)
27 {
28     gni_post_descriptor_t *pd;
29     gni_return_t status;
30     RDMA_REQUEST        *rdma_request_msg;
31     
32     CmiAssert(h!=NULL);
33     PersistentSendsTable *slot = (PersistentSendsTable *)h;
34     CmiAssert(slot->used == 1);
35     CmiAssert(CmiNodeOf(slot->destPE) == destNode);
36     if (size > slot->sizeMax) {
37         CmiPrintf("size: %d sizeMax: %d\n", size, slot->sizeMax);
38         CmiAbort("Abort: Invalid size\n");
39     }
40
41     // CmiPrintf("[%d] LrtsSendPersistentMsg h=%p hdl=%d destNode=%d destAddress=%p size=%d\n", CmiMyPe(), h, CmiGetHandler(m), destNode, slot->destBuf[0].destAddress, size);
42
43     if (slot->destBuf[0].destAddress) {
44         // uGNI part
45         MallocPostDesc(pd);
46         if(size <= LRTS_GNI_RDMA_PUT_THRESHOLD) {
47             pd->type            = GNI_POST_FMA_PUT;
48         }
49         else
50         {
51             pd->type            = GNI_POST_RDMA_PUT;
52         }
53         pd->cq_mode         = GNI_CQMODE_GLOBAL_EVENT;
54         pd->dlvr_mode       = GNI_DLVMODE_PERFORMANCE;
55         pd->length          = ALIGN64(size);
56         pd->local_addr      = (uint64_t) m;
57        
58         pd->remote_addr     = (uint64_t)slot->destBuf[0].destAddress;
59         pd->remote_mem_hndl = slot->destBuf[0].mem_hndl;
60         pd->src_cq_hndl     = 0;//post_tx_cqh;     /* smsg_tx_cqh;  */
61         pd->rdma_mode       = 0;
62         pd->cqwrite_value   = PERSIST_SEQ;
63         pd->amo_cmd         = 0;
64
65         SetMemHndlZero(pd->local_mem_hndl);
66 #if CMK_SMP
67         bufferRdmaMsg(destNode, pd, -1);
68 #else
69         status = registerMessage((void*)(pd->local_addr), pd->length, pd->cqwrite_value, &pd->local_mem_hndl);
70         if (status == GNI_RC_SUCCESS) 
71         {
72         if(pd->type == GNI_POST_RDMA_PUT) 
73             status = GNI_PostRdma(ep_hndl_array[destNode], pd);
74         else
75             status = GNI_PostFma(ep_hndl_array[destNode],  pd);
76         }
77         else
78             status = GNI_RC_ERROR_RESOURCE;
79         if(status == GNI_RC_ERROR_RESOURCE|| status == GNI_RC_ERROR_NOMEM )
80         {
81             bufferRdmaMsg(destNode, pd, -1);
82         }else
83             GNI_RC_CHECK("AFter posting", status);
84 #endif
85     }
86   else {
87 #if 1
88     if (slot->messageBuf != NULL) {
89       CmiPrintf("Unexpected message in buffer on %d\n", CmiMyPe());
90       CmiAbort("");
91     }
92     slot->messageBuf = m;
93     slot->messageSize = size;
94 #else
95     /* normal send */
96     PersistentHandle  *phs_tmp = phs;
97     int phsSize_tmp = phsSize;
98     phs = NULL; phsSize = 0;
99     CmiPrintf("[%d]Slot sending message directly\n", CmiMyPe());
100     CmiSyncSendAndFree(slot->destPE, size, m);
101     phs = phs_tmp; phsSize = phsSize_tmp;
102 #endif
103   }
104 }
105
106 #if 0
107 void CmiSyncSendPersistent(int destPE, int size, char *msg, PersistentHandle h)
108 {
109   CmiState cs = CmiGetState();
110   char *dupmsg = (char *) CmiAlloc(size);
111   memcpy(dupmsg, msg, size);
112
113   /*  CmiPrintf("Setting root to %d\n", 0); */
114   CMI_SET_BROADCAST_ROOT(dupmsg, 0);
115
116   if (cs->pe==destPE) {
117     CQdCreate(CpvAccess(cQdState), 1);
118     CdsFifo_Enqueue(CpvAccess(CmiLocalQueue),dupmsg);
119   }
120   else
121     LrtsSendPersistentMsg(h, destPE, size, dupmsg);
122 }
123 #endif
124
125 extern void CmiReference(void *blk);
126
127 #if 0
128
129 /* called in PumpMsgs */
130 int PumpPersistent()
131 {
132   int status = 0;
133   PersistentReceivesTable *slot = persistentReceivesTableHead;
134   while (slot) {
135     char *msg = slot->messagePtr[0];
136     int size = *(slot->recvSizePtr[0]);
137     if (size)
138     {
139       int *footer = (int*)(msg + size);
140       if (footer[0] == size && footer[1] == 1) {
141 /*CmiPrintf("[%d] PumpPersistent messagePtr=%p size:%d\n", CmiMyPe(), slot->messagePtr, size);*/
142
143 #if 0
144       void *dupmsg;
145       dupmsg = CmiAlloc(size);
146                                                                                 
147       _MEMCHECK(dupmsg);
148       memcpy(dupmsg, msg, size);
149       memset(msg, 0, size+2*sizeof(int));
150       msg = dupmsg;
151 #else
152       /* return messagePtr directly and user MUST make sure not to delete it. */
153       /*CmiPrintf("[%d] %p size:%d rank:%d root:%d\n", CmiMyPe(), msg, size, CMI_DEST_RANK(msg), CMI_BROADCAST_ROOT(msg));*/
154
155       CmiReference(msg);
156       swapRecvSlotBuffers(slot);
157 #endif
158
159       CmiPushPE(CMI_DEST_RANK(msg), msg);
160 #if CMK_BROADCAST_SPANNING_TREE
161       if (CMI_BROADCAST_ROOT(msg))
162           SendSpanningChildren(size, msg);
163 #endif
164       /* clear footer after message used */
165       *(slot->recvSizePtr[0]) = 0;
166       footer[0] = footer[1] = 0;
167
168 #if 0
169       /* not safe at all! */
170       /* instead of clear before use, do it earlier */
171       msg=slot->messagePtr[0];
172       size = *(slot->recvSizePtr[0]);
173       footer = (int*)(msg + size);
174       *(slot->recvSizePtr[0]) = 0;
175       footer[0] = footer[1] = 0;
176 #endif
177       status = 1;
178       }
179     }
180     slot = slot->next;
181   }
182   return status;
183 }
184
185 #endif
186
187 void *PerAlloc(int size)
188 {
189 //  return CmiAlloc(size);
190   gni_return_t status;
191   void *res = NULL;
192   size = ALIGN64(size) + sizeof(CmiChunkHeader);
193   if (0 != posix_memalign(&res, 64, size))
194       CmiAbort("PerAlloc: failed to allocate memory.");
195   //printf("[%d] PerAlloc %p. \n", myrank, res);
196   char *ptr = (char*)res+sizeof(CmiChunkHeader);
197   SIZEFIELD(ptr)=size;
198   REFFIELD(ptr)=1;
199   MEMORY_REGISTER(onesided_hnd, nic_hndl,  res, size , &MEMHFIELD(ptr), &omdh, NULL, status);
200   GNI_RC_CHECK("Mem Register before post", status);
201   return ptr;
202 }
203                                                                                 
204 void PerFree(char *msg)
205 {
206 //  CmiFree(msg);
207   char *ptr = msg-sizeof(CmiChunkHeader);
208   MEMORY_DEREGISTER(onesided_hnd, nic_hndl, &MEMHFIELD(msg) , &omdh, SIZEFIELD(msg));
209   free(ptr);
210 }
211
212 /* machine dependent init call */
213 void persist_machine_init(void)
214 {
215 }
216
217 void setupRecvSlot(PersistentReceivesTable *slot, int maxBytes)
218 {
219   int i;
220   for (i=0; i<PERSIST_BUFFERS_NUM; i++) {
221     char *buf = PerAlloc(maxBytes+sizeof(int)*2);
222     _MEMCHECK(buf);
223     memset(buf, 0, maxBytes+sizeof(int)*2);
224     slot->destBuf[i].mem_hndl = MEMHFIELD(buf);
225     slot->destBuf[i].destAddress = buf;
226     /* note: assume first integer in elan converse header is the msg size */
227     slot->destBuf[i].destSizeAddress = (unsigned int*)buf;
228 #if USE_LRTS_MEMPOOL
229     // assume already registered from mempool
230     // slot->destBuf[i].mem_hndl = GetMemHndl(buf);
231 #endif
232     // FIXME:  assume always succeed
233   }
234   slot->sizeMax = maxBytes;
235 }
236
237