1 #if HAVE_CONFIG_H
2 #   include "config.h"
3 #endif
4 
5 /* initialization of data structures and setup of lapi internal parameters */
6 
7 #include <pthread.h>
8 #if HAVE_STDIO_H
9 #   include <stdio.h>
10 #endif
11 #if HAVE_STRINGS_H
12 #   include <strings.h>
13 #endif
14 #include "lapidefs.h"
15 #include "armcip.h"
16 #include "copy.h"
17 #ifdef AIX
18 #include <sys/atomic_op.h>
19 #endif
20 #if (defined(PPC) || defined(__PPC__) || defined(__PPC))
21 #   include "asm-ppc.h"
22 #endif
23 
24 #define DEBUG_ 0
25 #define ERROR(str,val) armci_die((str),(val))
26 #define BUF_TO_EVBUF(buf) ((lapi_cmpl_t*)(((char*)buf) - sizeof(lapi_cmpl_t)))
27 
28 char err_msg_buf[LAPI_MAX_ERR_STRING]; /* for error msg returned by LAPI */
29 
30 /*
31 ** macro to check return code of function calls. keeps return
32 ** code checking logic from needing to be in main logic
33 */
34 #define CHECK(func_and_args)                                      \
35 {                                                                 \
36     int rc;                                                       \
37     if ((rc = (func_and_args)) != LAPI_SUCCESS) {                 \
38         LAPI_Msg_string(rc, err_msg_buf);                         \
39         fprintf(stderr,                                           \
40                 "LAPI ERROR: %s, rc = %d\n", err_msg_buf, rc);    \
41         armci_die("LAPI Error", 0);                               \
42     }                                                             \
43 }
44 
45 #if ARMCI_ENABLE_GPC_CALLS
46     extern gpc_buf_t *gpc_req;
47 #endif
48 int lapi_max_uhdr_data_sz; /* max  data payload */
49 lapi_cmpl_t *cmpl_arr;     /* completion state array, dim=NPROC */
50 lapi_cmpl_t  hdr_cntr;     /* AM header buffer counter  */
51 lapi_cmpl_t  buf_cntr;     /* AM data buffer counter    */
52 lapi_cmpl_t*  ack_cntr;    /* ACK counter used in handshaking protocols
53                               between origin and target */
54 lapi_cmpl_t*  get_cntr;    /* counter used with lapi_get  */
55 lapi_user_cxt_t *lapi_remote_cxt; /* Remote context for RDMA call */
56 
57 int intr_status;
58 lapi_info_t     lapi_info;
59 #ifndef TCGMSG
60 lapi_handle_t   lapi_handle;
61 #endif
62 pthread_mutex_t _armci_mutex_thread=PTHREAD_MUTEX_INITIALIZER;
63 
64 
65 double _armci_rcv_buf[MSG_BUFLEN_DBL];
66 char* MessageRcvBuffer = (char*)_armci_rcv_buf;
67 char* MessageSndBuffer = (char*)0;
68 
69 extern void armci_waitsome(int factor);
70 
71 /************* LAPI Active Message handlers *******************************/
72 
73 volatile static int hndlcnt=0, header_cnt=0;
74 static int hhnum=0;
75 static long num_malloc=0;   /* trace and limit the number malloc calls in HH */
76 #define MAX_NUM_MALLOC 100
77 
78 /* trace state of accumulate lock */
79 int kevin_ok=1; /* "1" indicates that no other thread is holding the lock */
80 
81 
armci_completion_handler(lapi_handle_t * t_hndl,void * save)82 void armci_completion_handler(lapi_handle_t *t_hndl, void *save)
83 {
84     lapi_handle_t hndl = *t_hndl;
85     int need_data;
86     void *message;
87     int whofrom, msglen;
88     request_header_t *msginfo = (request_header_t *)save;
89     char *descr= (char*)(msginfo+1), *buf=MessageRcvBuffer;
90     int buflen=MSG_BUFLEN;
91 #if ARMCI_ENABLE_GPC_CALLS
92     extern pthread_t data_server;
93     data_server = pthread_self();
94 #endif
95 
96     if(DEBUG_)
97         fprintf(stderr,"%d:CH:op=%d from=%d datalen=%d dscrlen=%d\n", armci_me,
98                 msginfo->operation, msginfo->from,msginfo->datalen,msginfo->dscrlen);
99 
100     /*** assure that descriptor and data are in the right format and place ***/
101     if(  msginfo->dscrlen < 0 || msginfo->datalen <0 ){
102         /* for large put/acc/scatter need to get the data */
103         int rc;
104         lapi_cntr_t req_cntr;
105         int bytes=0;
106         char *origin_ptr = msginfo->tag.buf;
107 
108         if (msginfo->dscrlen<0) {
109             descr =MessageRcvBuffer;
110             msginfo->dscrlen = -msginfo->dscrlen;
111             buf = descr + msginfo->dscrlen;
112             buflen += msginfo->dscrlen;
113             bytes += msginfo->dscrlen;
114 
115         }
116         if (msginfo->datalen <0){
117             msginfo->datalen = -msginfo->datalen;
118             bytes += msginfo->datalen;
119         }
120 
121         if(rc=LAPI_Setcntr(hndl, &req_cntr, 0)) ERROR("CH:setcntr failed",rc);
122         if(rc=LAPI_Get(hndl, (uint)msginfo->from, bytes,
123                     origin_ptr, MessageRcvBuffer,
124                     msginfo->tag.cntr,&req_cntr))ERROR("CH:LAPI_Get failed",rc);
125 
126         if(rc=LAPI_Waitcntr(hndl, &req_cntr,1,NULL))ERROR("CH:Waitcntr failed",rc);
127 
128 
129     } else{
130 
131         /* desc is in save, data could be but not for GET */
132         if(msginfo->operation !=GET)buf = descr + msginfo->dscrlen;
133         buflen = MSG_BUFLEN;
134     }
135 
136     /*   fprintf(stderr,"CH: val=%lf\n",*(double*)(buf+msginfo->datalen -8));*/
137 
138 
139     /*** dispatch request to the appropriate handler function ***/
140     switch(msginfo->operation){
141         case LOCK:   armci_server_lock(msginfo);
142                      break;
143         case UNLOCK: armci_server_unlock(msginfo, descr);
144                      break;
145         default:
146                      if(msginfo->format == STRIDED)
147                          armci_server(msginfo, descr, buf, buflen);
148                      else
149                          armci_server_vector(msginfo, descr, buf, buflen);
150     }
151 
152     free(msginfo);
153 #ifdef LINUX
154     (void)fetch_and_add(&num_malloc, (long)-1);
155 #else
156     (void)fetch_and_addlp(&num_malloc, (long)-1);
157 #endif
158 }
159 
160 
161 
162 
armci_header_handler(lapi_handle_t * t_hndl,void * uhdr,uint * t_uhdrlen,uint * msglen,compl_hndlr_t ** handler,void ** psave)163 void* armci_header_handler(lapi_handle_t *t_hndl, void *uhdr, uint *t_uhdrlen,
164         uint *msglen, compl_hndlr_t **handler, void** psave)
165 {
166     lapi_handle_t hndl = *t_hndl;
167     uint uhdrlen = *t_uhdrlen;
168     request_header_t *msginfo = (request_header_t *)uhdr;
169 
170     if(DEBUG_)
171         fprintf(stderr,"%d:HH: op=%d from %d\n",armci_me,msginfo->operation,
172                 msginfo->from);
173     if(msginfo->to != armci_me)
174         armci_die("wrong message delivered",msginfo->to);
175 
176     /* process small requests that do not require comms in header handler */
177     if(msginfo->datalen >0 && msginfo->dscrlen>0 && msginfo->operation != GET
178             && msginfo->operation != LOCK && msginfo->operation != UNLOCK){
179 
180         /* If another thread is in accumulate use compl. handler path:
181          * Try to avoid blocking inside HH which degrades Lapi performance.
182          * The completion handler path requires malloc to save request info.
183          * Only up to approx. MAX_NUM_MALLOC requests can be rescheduled to
184          * run in CH instead of HH.
185          * MAX_NUM_MALLOC is a soft limit to avoid cost of locking when reading
186          */
187 
188         if( msginfo->operation==PUT || num_malloc>MAX_NUM_MALLOC || kevin_ok){
189 
190             char *descr = (char*)(msginfo+1);
191             char *buf   = descr + msginfo->dscrlen;
192             int buflen = uhdrlen - sizeof(request_header_t) - msginfo->dscrlen;
193 
194             if(DEBUG_)
195                 fprintf(stderr,"%d:HH: buf =%lf\n",armci_me,*(double*)buf);
196             if(msginfo->format == STRIDED)
197                 armci_server(msginfo, descr, buf, buflen);
198             else
199                 armci_server_vector(msginfo, descr, buf, buflen);
200 
201             /*             fprintf(stderr,"%d:HH: getting out of server\n",armci_me);*/
202             *psave = NULL;
203             *handler = NULL;
204             return(NULL);
205         }
206     }
207 
208 #ifdef LINUX
209     (void)fetch_and_add(&num_malloc, (long)1);
210 #else
211     (void)fetch_and_addlp(&num_malloc, (long)1); /* AIX atomic increment */
212 #endif
213 
214     msginfo  = (request_header_t*) malloc(uhdrlen); /* recycle pointer */
215     if(!msginfo) ERROR("HH: malloc failed in header handler",num_malloc);
216 
217     /* save the request info for processing in compl. handler */
218     memcpy((char*)msginfo, uhdr, uhdrlen);
219     *psave = msginfo;
220     *handler = armci_completion_handler;
221 
222     return(NULL);
223 }
224 
225 
armci_send_req(int proc,request_header_t * msginfo,int len)226 void armci_send_req(int proc, request_header_t* msginfo, int len)
227 {
228     int msglen = sizeof(request_header_t);
229     lapi_cntr_t *pcmpl_cntr, *pcntr = &(BUF_TO_EVBUF(msginfo)->cntr);
230     int rc;
231 
232     msginfo->tag.cntr= pcntr;
233 #if ARMCI_ENABLE_GPC_CALLS
234     if(msginfo->operation==GET && msginfo->format==VECTOR && msginfo->ehlen){
235         msginfo->tag.buf = (char *)(msginfo+1)+msginfo->dscrlen;
236     }
237     else
238 #endif
239         msginfo->tag.buf = msginfo+1;
240 
241     if(msginfo->operation==GET || msginfo->operation==LOCK){
242 
243         SET_COUNTER(*(lapi_cmpl_t*)pcntr,1);/*dataarrive in same buf*/
244         /*The GPC case. Note that we don't use the parameter len*/
245         if(msginfo->format==VECTOR && msginfo->ehlen > 0)
246             msglen += msginfo->datalen;
247         if(lapi_max_uhdr_data_sz < msginfo->dscrlen){
248 
249             msginfo->dscrlen = -msginfo->dscrlen; /* no room for descriptor */
250             pcntr = NULL; /* GET(descr) from CH will increment buf cntr */
251 
252         }else msglen += msginfo->dscrlen;
253 
254         /*
255            we should send the mutex, too. When op==LOCK, Value of len parameter
256            is already sizeof(reqest_header_t)+sizeof(int), since we dont use
257            len but construct our own msglen, we need to add sizeof(int).
258            */
259         if(msginfo->operation==LOCK) msglen += sizeof(int);
260 
261         pcmpl_cntr=NULL; /* don't trace completion status for load ops */
262 
263     }else if (msginfo->operation==UNLOCK){
264 
265         msglen += msginfo->dscrlen;
266         pcmpl_cntr=NULL; /* don't trace completion status for unlock */
267 
268     }else{
269 
270         if(lapi_max_uhdr_data_sz < (msginfo->datalen + msginfo->dscrlen)){
271 
272             msginfo->datalen = -msginfo->datalen;
273             msginfo->dscrlen = -msginfo->dscrlen;
274             pcntr = NULL; /* GET/LOCK from CH will increment buf cntr */
275 
276         }else msglen += msginfo->dscrlen+msginfo->datalen;
277 
278         /* trace completion of store ops */
279         pcmpl_cntr = &cmpl_arr[msginfo->to].cntr;
280 
281     }
282 
283     if(msginfo->operation==PUT || ARMCI_ACC(msginfo->operation))
284         UPDATE_FENCE_STATE(msginfo->to, msginfo->operation, 1);
285 
286     if((rc=LAPI_Amsend(lapi_handle,(uint)msginfo->to,
287                     (void*)armci_header_handler, msginfo, msglen, NULL, 0,
288                     NULL, pcntr, pcmpl_cntr))) armci_die("AM failed",rc);
289 
290     if(DEBUG_) fprintf(stderr,"%d sending req=%d to %d\n",
291             armci_me, msginfo->operation, proc);
292 }
293 
294 
295 
296 /*\ client sends strided data + request to server
297   \*/
armci_send_strided(int proc,request_header_t * msginfo,char * bdata,void * ptr,int strides,int stride_arr[],int count[])298 void armci_send_strided(int proc, request_header_t *msginfo, char *bdata,
299         void *ptr, int strides, int stride_arr[], int count[])
300 {
301 
302     armci_write_strided(ptr, strides, stride_arr, count, bdata);
303     armci_send_req(proc,msginfo,msginfo->bytes + sizeof(request_header_t));
304 }
305 
306 
307 /*\ server sends data back to client
308   \*/
armci_send_data(request_header_t * msginfo,void * data)309 void armci_send_data(request_header_t* msginfo, void *data)
310 {
311     armci_lapi_send(msginfo->tag, data, msginfo->datalen, msginfo->from);
312 }
313 
314 
315 /*\ server sends strided data back to client
316   \*/
armci_send_strided_data(int proc,request_header_t * msginfo,char * bdata,void * ptr,int strides,int stride_arr[],int count[])317 void armci_send_strided_data(int proc,  request_header_t *msginfo, char *bdata,
318         void *ptr, int strides, int stride_arr[], int count[])
319 {
320     armci_write_strided(ptr, strides, stride_arr, count, bdata);
321     armci_lapi_send(msginfo->tag, bdata, msginfo->datalen, msginfo->from);
322 }
323 
324 
armci_rcv_data(int proc,request_header_t * msginfo)325 char* armci_rcv_data(int proc, request_header_t *msginfo)
326 {
327     lapi_cmpl_t *pcntr=BUF_TO_EVBUF(msginfo);
328     CLEAR_COUNTER((*pcntr));
329 #if ARMCI_ENABLE_GPC_CALLS
330     if(msginfo->operation==GET && msginfo->format==VECTOR && msginfo->ehlen){
331         return((char *)(msginfo+1)+msginfo->dscrlen);
332     }
333     else
334 #endif
335         return (char*)(msginfo+1);
336 }
337 
338 
339 
340 /*\ client receives strided data from server
341   \*/
armci_rcv_strided_data(int proc,request_header_t * msginfo,int datalen,void * ptr,int strides,int stride_arr[],int count[])342 void armci_rcv_strided_data(int proc, request_header_t* msginfo, int datalen,
343         void *ptr, int strides, int stride_arr[], int count[])
344 {
345     lapi_cmpl_t *pcntr=BUF_TO_EVBUF(msginfo);
346     CLEAR_COUNTER((*pcntr));
347     armci_read_strided(ptr, strides, stride_arr, count, (char*)(msginfo+1));
348 }
349 
350 
351 
352 /*\ client receives vector data from server to buffer and unpacks it
353   \*/
armci_rcv_vector_data(int proc,request_header_t * msginfo,armci_giov_t darr[],int len)354 void armci_rcv_vector_data(int proc, request_header_t* msginfo,
355         armci_giov_t darr[], int len)
356 {
357     char *buf;
358     buf = armci_rcv_data(proc,msginfo);
359     armci_vector_from_buf(darr, len, buf);
360 }
361 
362 
363 /*\ initialization of LAPI related data structures
364   \*/
armci_init_lapi()365 void armci_init_lapi()
366 {
367     int rc, p;
368     int lapi_max_uhdr_sz;
369     lapi_cmpl_t *pcntr;
370     lapi_remote_cxt_t util_cxt;  /* For call to obtain rCxt */
371 
372 #ifndef TCGMSG
373     rc = LAPI_Init(&lapi_handle, &lapi_info);
374     if(rc) ERROR("lapi_init failed",rc);
375 #endif
376 
377     /* set the max limit for AM header data length */
378     rc = LAPI_Qenv(lapi_handle,MAX_UHDR_SZ, &lapi_max_uhdr_sz);
379     if(rc) ERROR("armci_init_lapi:  LAPI_Qenv failed", rc);
380 
381     /*     fprintf(stderr,"max header size = %d\n",lapi_max_uhdr_sz);*/
382 
383     /* how much data can fit into AM header ? */
384     lapi_max_uhdr_data_sz = lapi_max_uhdr_sz - sizeof(request_header_t);
385 
386     /* allocate memory for completion state array */
387     cmpl_arr = (lapi_cmpl_t*)malloc(armci_nproc*sizeof(lapi_cmpl_t));
388     if(cmpl_arr==NULL) ERROR("armci_init_lapi:malloc for cmpl_arr failed",0);
389 
390     /* allocate memory for ack and get counters, 1 if not thread safe */
391 #ifdef THREAD_SAFE
392     ack_cntr = calloc(armci_user_threads.max, sizeof(lapi_cmpl_t));
393     get_cntr = calloc(armci_user_threads.max, sizeof(lapi_cmpl_t));
394 #else
395     ack_cntr = calloc(1, sizeof(lapi_cmpl_t));
396     get_cntr = calloc(1, sizeof(lapi_cmpl_t));
397 #endif
398     if (!(ack_cntr && get_cntr))
399         ERROR("armci_init_lapi:calloc for ack or get counters failed",0);
400 
401     /* initialize completion state array */
402     for(p = 0; p< armci_nproc; p++){
403         rc = LAPI_Setcntr(lapi_handle, &cmpl_arr[p].cntr, 0);
404         if(rc) ERROR("armci_init_lapi: LAPI_Setcntr failed (arr)",rc);
405         cmpl_arr[p].oper = -1;
406         cmpl_arr[p].val = 0;
407     }
408 
409     /* initialize ack/buf/hdr counters */
410 #ifdef THREAD_SAFE
411 #   define N armci_user_threads.max
412 #else
413 #   define N 1
414 #endif
415     for (p = 0; p < N; p++) {
416         rc = LAPI_Setcntr(lapi_handle, &(ack_cntr[p].cntr), 0);
417         if(rc) ERROR("armci_init_lapi: LAPI_Setcntr failed (ack)",rc);
418         ack_cntr[p].val = 0;
419 
420         rc = LAPI_Setcntr(lapi_handle, &(get_cntr[p].cntr), 0);
421         if(rc) ERROR("armci_init_lapi: LAPI_Setcntr failed (get)",rc);
422         get_cntr[p].val = 0;
423     }
424     rc = LAPI_Setcntr(lapi_handle, &hdr_cntr.cntr, 0);
425     if(rc) ERROR("armci_init_lapi: LAPI_Setcntr failed (hdr)",rc);
426     hdr_cntr.val = 0;
427     rc = LAPI_Setcntr(lapi_handle, &buf_cntr.cntr, 0);
428     if(rc) ERROR("armci_init_lapi: LAPI_Setcntr failed (buf)",rc);
429     buf_cntr.val = 0;
430 #if 0
431     pcntr = (lapi_cmpl_t*)MessageSndBuffer;
432     rc = LAPI_Setcntr(lapi_handle, &pcntr->cntr, 0);
433     if(rc) ERROR("armci_init_lapi: LAPI_Setcntr failed (bufcntr)",rc);
434     pcntr->val = 0;
435 #endif
436 
437 #ifdef LAPI_RDMA
438     /* allocate rCxt */
439     lapi_remote_cxt = (lapi_user_cxt_t*)malloc(armci_nproc *
440             sizeof(lapi_user_cxt_t));
441     if(lapi_remote_cxt==NULL) ERROR("armci_init_lapi: rCxt malloc failed",0);
442 
443     /* obtain remote context "rCxt" for RDMA Operation of all procs */
444     for(p = 0; p< armci_nproc; p++){
445         if(p==armci_me) continue;
446         util_cxt.Util_type   = LAPI_REMOTE_RCXT;
447         util_cxt.operation   = LAPI_RDMA_ACQUIRE;
448         util_cxt.dest        = p;
449         CHECK(LAPI_Util(lapi_handle, (lapi_util_t *) &util_cxt));
450         lapi_remote_cxt[p]   =  util_cxt.usr_rcxt;
451     }
452 #endif
453 
454 #if  !defined(LAPI2)
455 
456     /* for high performance, disable LAPI internal error checking */
457     LAPI_Senv(lapi_handle, ERROR_CHK, 0);
458 
459 #endif
460 
461     /* make sure that interrupt mode is on */
462     LAPI_Senv(lapi_handle, INTERRUPT_SET, 1);
463 
464     /* initialize buffer managment module */
465     _armci_buf_init();
466 
467 #ifdef LAPI_RDMA
468     CHECK((LAPI_Gfence(lapi_handle)));
469 #endif
470 #if ARMCI_ENABLE_GPC_CALLS
471     gpc_req = (gpc_buf_t *)malloc(sizeof(gpc_buf_t)*MAX_GPC_REQ);
472     if(gpc_req==NULL)armci_die("malloc for gpc failed",sizeof(gpc_buf_t));
473     gpc_init();
474 #endif
475 }
476 
477 
armci_term_lapi()478 void armci_term_lapi()
479 {
480     int p;
481     lapi_remote_cxt_t util_cxt;  /* For call to obtain rCxt */
482 
483 #ifdef LAPI_RDMA
484     CHECK((LAPI_Gfence(lapi_handle)));
485 
486     /* release remote context "rCxt" for RDMA Operation of all procs */
487     for(p = 0; p< armci_nproc; p++){
488         if(p==armci_me) continue;
489         util_cxt.Util_type   = LAPI_REMOTE_RCXT;
490         util_cxt.operation   = LAPI_RDMA_RELEASE;
491         util_cxt.dest        = p;
492         util_cxt.usr_rcxt    = lapi_remote_cxt[p];
493         CHECK(LAPI_Util(lapi_handle, (lapi_util_t *) &util_cxt));
494     }
495     free(lapi_remote_cxt);
496 #endif
497 
498 #ifndef TCGMSG
499     CHECK((LAPI_Term(lapi_handle))); /* terminate the LAPI handle */
500 #endif
501     free(cmpl_arr);
502     free(ack_cntr);
503     free(get_cntr);
504 }
505 
506 /* primitive pseudo message-passing on top of lapi */
507 
508 /* send data to remote process using p specified message tag */
509 /* tag contains address of receive buffer guarded by cntr at process p */
armci_lapi_send(msg_tag_t tag,void * data,int len,int p)510 void armci_lapi_send(msg_tag_t tag, void* data, int len, int p)
511 {
512     int rc;
513     lapi_cntr_t org_cntr;
514     void *buf = tag.buf;
515     lapi_cntr_t *cntr = tag.cntr;
516     if(!buf)ERROR("armci_lapi_send: NULL tag(buf) error",0);
517     if(!cntr)ERROR("armci_lapi_send:  NULL tag(cntr) error",0);
518 
519     rc=LAPI_Setcntr(lapi_handle, &org_cntr, 0);
520     if(rc) ERROR("armci_lapi_send:setcntr failed",rc);
521     rc=LAPI_Put(lapi_handle, (uint)p, (uint)len, buf, data,
522             cntr, &org_cntr, NULL);
523     if(rc) ERROR("armci_lapi_send:put failed",rc);
524     rc+=LAPI_Waitcntr(lapi_handle, &org_cntr, 1, NULL);
525     if(rc) ERROR("armci_lapi_send:waitcntr failed",rc);
526 }
527 
528 /* subroutine versions of macros disabling and enabling interrupts */
intr_off_()529 void intr_off_()
530 {
531     INTR_OFF;
532 }
533 
intr_on_()534 void intr_on_()
535 {
536     INTR_ON;
537 }
538 
539 
print_counters_()540 void print_counters_()
541 {
542     int i;
543     printf("bufcntr: val =%d cntr=%d\n", buf_cntr.val, buf_cntr.cntr);
544     for(i=0; i< armci_nproc;i++){
545         printf("cmpl_arr: val=%d cntr=%d oper=%d\n",cmpl_arr[i].val,
546                 cmpl_arr[i].cntr, cmpl_arr[i].oper);
547     }
548     fflush(stdout);
549 }
550 
551 #ifdef LAPI_RDMA
552 /* LAPI Put RDMA */
armci_client_direct_send(int p,void * src_buf,void * dst_buf,int len,void ** contextptr,int nbtag,ARMCI_MEMHDL_T * lochdl,ARMCI_MEMHDL_T * remhdl)553 void armci_client_direct_send(int p, void *src_buf, void *dst_buf,
554         int len, void** contextptr, int nbtag,
555         ARMCI_MEMHDL_T *lochdl,ARMCI_MEMHDL_T *remhdl) {
556 
557     lapi_xfer_t      xfer_struct;   /* Data structure for the xfer call */
558     lapi_rdma_tag_t  lapi_rdma_tag; /* RDMA notification tag */
559     uint src_offset, tgt_offset;
560     int  val, rc;
561 
562     /* can be any number that fits in ushort */
563     lapi_rdma_tag = 22;
564 
565     /* CHECK: offset problem. what if client and server attached (shmat) at
566        diff address */
567     src_offset = (char *)src_buf- (char *)lochdl->start;
568     tgt_offset = (char *)dst_buf - (char *)remhdl->start;
569 
570 #if DEBUG_
571     printf("%d: Doing LAPI_Xfer (RDMA Put): dst=%d srchdl_start=%p remhdl_start=%p (bytes=%ld src_off=%d tgt_off=%d)\n", armci_me, p, lochdl->start, remhdl->start, len, src_offset, tgt_offset); fflush(stdout);
572 #endif
573 
574     bzero(&xfer_struct, sizeof(xfer_struct));
575     xfer_struct.HwXfer.Xfer_type    = LAPI_RDMA_XFER;
576     xfer_struct.HwXfer.tgt          = p;
577     /*xfer_struct.HwXfer.op         = LAPI_RDMA_PUT|LAPI_RCNTR_UPDATE;*/
578     xfer_struct.HwXfer.op           = LAPI_RDMA_PUT;
579     xfer_struct.HwXfer.rdma_tag     = lapi_rdma_tag;
580     xfer_struct.HwXfer.remote_cxt   = lapi_remote_cxt[p];
581     xfer_struct.HwXfer.src_pvo      = lochdl->pvo;
582     xfer_struct.HwXfer.tgt_pvo      = remhdl->pvo;
583     xfer_struct.HwXfer.src_offset   = src_offset;
584     xfer_struct.HwXfer.tgt_offset   = tgt_offset;
585     xfer_struct.HwXfer.len          = (ulong) (len);
586     xfer_struct.HwXfer.shdlr        = (scompl_hndlr_t *) NULL;
587     xfer_struct.HwXfer.sinfo        = (void *) NULL;
588     xfer_struct.HwXfer.org_cntr     = &(ack_cntr->cntr);
589 
590     /* Initiate RDMA Xfer */
591     if((rc = LAPI_Xfer(lapi_handle, &xfer_struct)) != LAPI_SUCCESS) {
592         LAPI_Msg_string(rc, err_msg_buf);
593         fprintf(stderr, "LAPI ERROR: %s, rc = %d\n", err_msg_buf, rc);
594         armci_die("LAPI_Xfer (RDMA Put) failed", 0);
595     }
596 
597     /* wait for RDMA completion */
598     rc = LAPI_Waitcntr(lapi_handle, &(ack_cntr->cntr),1,&val);
599     if(rc != LAPI_SUCCESS) {
600         LAPI_Msg_string(rc, err_msg_buf);
601         fprintf(stderr, "LAPI ERROR: %s, rc = %d\n", err_msg_buf, rc);
602         armci_die("LAPI_Waitcntr (RDMA Put) failed", 0);
603     }
604 
605     /* CHECK((LAPI_Fence(lapi_handle))); */
606 
607 #if DEBUG_
608     printf("%d: Completed LAPI_Xfer RDMA (Put): dst=%d\n", armci_me, p);
609 #endif
610 }
611 
612 /* LAPI Get RDMA */
armci_client_direct_get(int p,void * src_buf,void * dst_buf,int len,void ** cptr,int nbtag,ARMCI_MEMHDL_T * lochdl,ARMCI_MEMHDL_T * remhdl)613 void armci_client_direct_get(int p, void *src_buf, void *dst_buf,
614         int len, void** cptr, int nbtag,
615         ARMCI_MEMHDL_T *lochdl, ARMCI_MEMHDL_T *remhdl) {
616 
617     lapi_xfer_t      xfer_struct;   /* Data structure for the xfer call */
618     lapi_rdma_tag_t  lapi_rdma_tag; /* RDMA notification tag */
619     uint src_offset, tgt_offset;
620     int  val, rc;
621 
622     /* can be any number that fits in ushort */
623     lapi_rdma_tag = 21;
624 
625     /* CHECK: offset problem. what if client and server attached (shmat) at
626        diff address */
627     src_offset = (char *)dst_buf- (char *)lochdl->start;
628     tgt_offset = (char *)src_buf - (char *)remhdl->start;
629 
630 #if DEBUG_
631     printf("%d: Doing LAPI_Xfer (RDMA Get): dst=%d srchdl_start=%p remhdl_start=%p (bytes=%ld src_off=%d tgt_off=%d)\n", armci_me, p, lochdl->start, remhdl->start, len, src_offset, tgt_offset); fflush(stdout);
632 #endif
633     bzero(&xfer_struct, sizeof(xfer_struct));
634     xfer_struct.HwXfer.Xfer_type    = LAPI_RDMA_XFER;
635     xfer_struct.HwXfer.tgt          = p;
636     /*xfer_struct.HwXfer.op         = LAPI_RDMA_GET|LAPI_RCNTR_UPDATE;*/
637     xfer_struct.HwXfer.op           = LAPI_RDMA_GET;
638     xfer_struct.HwXfer.rdma_tag     = lapi_rdma_tag;
639     xfer_struct.HwXfer.remote_cxt   = lapi_remote_cxt[p];
640     xfer_struct.HwXfer.src_pvo      = lochdl->pvo;
641     xfer_struct.HwXfer.tgt_pvo      = remhdl->pvo;
642     xfer_struct.HwXfer.src_offset   = src_offset;
643     xfer_struct.HwXfer.tgt_offset   = tgt_offset;
644     xfer_struct.HwXfer.len          = (ulong) (len);
645     xfer_struct.HwXfer.shdlr        = (scompl_hndlr_t *) NULL;
646     xfer_struct.HwXfer.sinfo        = (void *) NULL;
647     xfer_struct.HwXfer.org_cntr     = &(get_cntr->cntr);
648 
649     /* Initiate RDMA Xfer */
650     if((rc = LAPI_Xfer(lapi_handle, &xfer_struct)) != LAPI_SUCCESS) {
651         LAPI_Msg_string(rc, err_msg_buf);
652         fprintf(stderr, "LAPI ERROR: %s, rc = %d\n", err_msg_buf, rc);
653         armci_die("LAPI_Xfer (RDMA Get) failed", 0);
654     }
655 
656     /* wait for RDMA completion */
657     rc = LAPI_Waitcntr(lapi_handle, &(get_cntr->cntr),1,&val);
658     if(rc != LAPI_SUCCESS) {
659         LAPI_Msg_string(rc, err_msg_buf);
660         fprintf(stderr, "LAPI ERROR: %s, rc = %d\n", err_msg_buf, rc);
661         armci_die("LAPI_Waitcntr (RDMA Get) failed", 0);
662     }
663 
664 #if DEBUG_
665     printf("%d: Completed LAPI_Xfer (RDMA Get): dst=%d\n", armci_me, p);
666 #endif
667 
668 }
669 
armci_pin_contig_hndl(void * ptr,int bytes,ARMCI_MEMHDL_T * memhdl)670 int armci_pin_contig_hndl(void *ptr, int bytes, ARMCI_MEMHDL_T *memhdl)
671 {
672 
673     lapi_get_pvo_t util_pvo;     /* For call to obtain PVO */
674     int rc;
675 
676     /* translate and pin the buffer to the adapter */
677     util_pvo.Util_type = LAPI_XLATE_ADDRESS;
678     util_pvo.length    = bytes;
679     util_pvo.usr_pvo   = 0;
680     util_pvo.address   = ptr;
681     util_pvo.operation = LAPI_RDMA_ACQUIRE;
682     /*bzero(ptr, bytes);*/ /* CHECK: Is touching the entire shmem sgement feasible */
683     if((rc=LAPI_Util(lapi_handle, (lapi_util_t *) &util_pvo)) != LAPI_SUCCESS) {
684         return 0;
685     }
686 
687     memhdl->pvo   = util_pvo.usr_pvo;
688     memhdl->start = ptr;
689 
690 #if DEBUG_
691     printf("\n%d:armci_pin_contig_hndl(): memhdl(pvo)=%ld ptr=%p bytes=%ld\n",
692             armci_me, (long)memhdl->pvo, ptr, bytes);fflush(stdout);
693 #endif
694 
695     return 1;
696 }
697 
armci_network_client_deregister_memory(ARMCI_MEMHDL_T * mh)698 void armci_network_client_deregister_memory(ARMCI_MEMHDL_T *mh)
699 {
700     fprintf(stderr," armci_network_client_deregister_memory not available\n");
701     fflush(stderr);
702 }
703 
704 
armci_network_server_deregister_memory(ARMCI_MEMHDL_T * mh)705 void armci_network_server_deregister_memory(ARMCI_MEMHDL_T *mh)
706 {
707     fprintf(stderr," armci_network_client_deregister_memory not available\n");
708     fflush(stderr);
709 }
710 #endif /* LAPI_RDMA */
711 
712 #ifdef AIX
713 
714 #define LOCKED 1
armci_lapi_lock(int * lock)715 void armci_lapi_lock(int *lock)
716 {
717     atomic_p word_addr = (atomic_p)lock;
718     int spin = 1;
719 
720 
721     while(1){
722 
723         if(_check_lock(word_addr, 0, LOCKED) == FALSE )
724             break; /* we got the lock */
725 
726         if(spin){
727             armci_waitsome(1);
728             spin = 0;
729         }else{
730 
731             /* yield processor to another thread */
732             /* cannot yield w/o affecting thread priority - better sleep */
733             /* yield(); */
734 
735             /* call usleep to notify scheduler */
736             (void)usleep(5);
737         }
738     }
739 }
740 
741 
armci_lapi_unlock(int * lock)742 void armci_lapi_unlock(int *lock)
743 {
744     atomic_p word_addr = (atomic_p)lock;
745 
746     if(_check_lock(word_addr, LOCKED, 0) == TRUE )
747         armci_die("somebody else unlocked",0);
748 }
749 #endif
750 
751 #ifdef LAPI2
752 #include "lapi2.c"
753 #endif
754 
755