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