~ubuntu-branches/ubuntu/utopic/nwchem/utopic

« back to all changes in this revision

Viewing changes to src/tools/ga-5-1/armci/src/devices/lapi/lapi.c

  • Committer: Package Import Robot
  • Author(s): Michael Banck, Daniel Leidert, Andreas Tille, Michael Banck
  • Date: 2013-07-04 12:14:55 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20130704121455-5tvsx2qabor3nrui
Tags: 6.3-1
* New upstream release.
* Fixes anisotropic properties (Closes: #696361).
* New features include:
  + Multi-reference coupled cluster (MRCC) approaches
  + Hybrid DFT calculations with short-range HF 
  + New density-functionals including Minnesota (M08, M11) and HSE hybrid
    functionals
  + X-ray absorption spectroscopy (XAS) with TDDFT
  + Analytical gradients for the COSMO solvation model
  + Transition densities from TDDFT 
  + DFT+U and Electron-Transfer (ET) methods for plane wave calculations
  + Exploitation of space group symmetry in plane wave geometry optimizations
  + Local density of states (LDOS) collective variable added to Metadynamics
  + Various new XC functionals added for plane wave calculations, including
    hybrid and range-corrected ones
  + Electric field gradients with relativistic corrections 
  + Nudged Elastic Band optimization method
  + Updated basis sets and ECPs 

[ Daniel Leidert ]
* debian/watch: Fixed.

[ Andreas Tille ]
* debian/upstream: References

[ Michael Banck ]
* debian/upstream (Name): New field.
* debian/patches/02_makefile_flags.patch: Refreshed.
* debian/patches/06_statfs_kfreebsd.patch: Likewise.
* debian/patches/07_ga_target_force_linux.patch: Likewise.
* debian/patches/05_avoid_inline_assembler.patch: Removed, no longer needed.
* debian/patches/09_backported_6.1.1_fixes.patch: Likewise.
* debian/control (Build-Depends): Added gfortran-4.7 and gcc-4.7.
* debian/patches/10_force_gcc-4.7.patch: New patch, explicitly sets
  gfortran-4.7 and gcc-4.7, fixes test suite hang with gcc-4.8 (Closes:
  #701328, #713262).
* debian/testsuite: Added tests for COSMO analytical gradients and MRCC.
* debian/rules (MRCC_METHODS): New variable, required to enable MRCC methods.

Show diffs side-by-side

added added

removed removed

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