~ubuntu-branches/ubuntu/trusty/nwchem/trusty-proposed

« back to all changes in this revision

Viewing changes to src/tools/ga-5-2/armci/src/memory/shmem.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
/* $Id: shmem.c,v 1.87.2.2 2007-09-10 23:31:32 manoj Exp $ */
 
6
/* System V shared memory allocation and managment
 
7
 *
 
8
 * Interface:
 
9
 * ~~~~~~~~~
 
10
 *  char *Create_Shared_Region(long *idlist, long size, long *offset)
 
11
 *       . to be called by just one process. 
 
12
 *       . calls kr_malloc,  malloc-like memory allocator from the K&R book. 
 
13
 *         kr_malloc inturn calls armci_allocate() that does shmget() and shmat(). 
 
14
 *       . idlist might be just a pointer to integer or a true array in the
 
15
 *         MULTIPLE_REGIONS versions (calling routine has to take care of it) 
 
16
 *  char *Attach_Shared_Region(long *idlist, long size, long offset)
 
17
 *       . called by any other process to attach to existing shmem region or
 
18
 *         if attached just calculate the address based on the offset
 
19
 *       . has to be called after shmem region was created
 
20
 *  void  Free_Shmem_Ptr(long id, long size, char* addr)
 
21
 *       . called ONLY by the process that created shmem region (id) to return
 
22
 *         pointer to kr_malloc (shmem is not destroyed)
 
23
 *  void  Delete_All_Regions()
 
24
 *       . destroys all shared memory regions
 
25
 *       . can be called by any process assuming that all processes attached
 
26
 *         to alllocated shmem regions 
 
27
 *       . needs to by called by cleanup procedure(s)
 
28
 *
 
29
 * Jarek Nieplocha, 06.13.94
 
30
 * 
 
31
 */
 
32
 
 
33
#ifdef SYSV
 
34
 
 
35
 
 
36
#define DEBUG_ 0
 
37
#define DEBUG1 0
 
38
#define DEBUG2_ 0
 
39
 
 
40
/* For debugging purposes at the beginning of the shared memory region
 
41
 * creator process can write a stamp which then is read by attaching processes
 
42
 * NOTE: on clusters we cannot use it anymore since ARMCI node master
 
43
 * uses it since Nov 99 to write the value of address it attached at
 
44
 * This feature is used in the ARMCI memlock table.
 
45
 */
 
46
#define STAMP 0
 
47
 
 
48
 
 
49
#if HAVE_SYS_TYPES_H
 
50
#   include <sys/types.h>
 
51
#endif
 
52
#if HAVE_SYS_IPC_H
 
53
#   include <sys/ipc.h>
 
54
#endif
 
55
#if HAVE_SYS_SHM_H
 
56
#   include <sys/shm.h>
 
57
#endif
 
58
#if HAVE_SYS_PARAM_H
 
59
#   include <sys/param.h>
 
60
#endif
 
61
#if HAVE_ERRNO_H
 
62
#   include <errno.h>
 
63
#endif
 
64
#if HAVE_STDIO_H
 
65
#   include <stdio.h>
 
66
#endif
 
67
#if HAVE_STDLIB_H
 
68
#   include <stdlib.h>
 
69
#endif
 
70
#include "shmem.h"
 
71
#include "kr_malloc.h"
 
72
#include "shmlimit.h"
 
73
#include "message.h"
 
74
#include "armcip.h"
 
75
 
 
76
#ifdef   ALLOC_MUNMAP
 
77
#if HAVE_SYS_MMAN_H
 
78
#   include <sys/mman.h>
 
79
#endif
 
80
#if HAVE_UNISTD_H
 
81
#   include <unistd.h>
 
82
#endif
 
83
static  size_t pagesize=0;
 
84
static  int logpagesize=0;
 
85
/* allow only that big shared memory segment (in MB)- incresed from 128 11/02 */
 
86
#define MAX_ALLOC_MUNMAP 128
 
87
#define MAX_ALLOC_MUNMAP_ 368
 
88
static long max_alloc_munmap=MAX_ALLOC_MUNMAP;
 
89
#endif
 
90
 
 
91
#if defined(SUN)
 
92
  extern char *shmat();
 
93
#endif
 
94
 
 
95
#define SHM_UNIT (1024)
 
96
 
 
97
 
 
98
/* Need to determine the max shmem segment size. There are 2 alternatives:
 
99
 * 1. use predefined SHMMAX if available or set some reasonable values, or
 
100
 * 2. trial-and-error search for a max value (default)
 
101
 *    case a) fork a process to determine shmmax size (more accurate)
 
102
 *    case b) search w/o forking until success (less accurate)
 
103
 */
 
104
 
 
105
/* under Myrinet GM, we cannot fork */
 
106
#if defined(GM) || defined(VAPI)
 
107
#   define SHMMAX_SEARCH_NO_FORK 
 
108
#endif
 
109
#if defined(LAPI) || defined(AIX) || defined(SHMMAX_SEARCH_NO_FORK)
 
110
#   define NO_SHMMAX_SEARCH
 
111
#endif
 
112
 
 
113
/* on some platforms with tiny shmmax can try to glue multiple regions */
 
114
#if (defined(SUN) || defined(SOLARIS)) && !defined(SHMMAX_SEARCH_NO_FORK)
 
115
#    define MULTIPLE_REGIONS
 
116
#endif
 
117
 
 
118
/* Limits for the largest shmem segment are in Kilobytes to avoid passing
 
119
 * Gigavalues to kr_malloc
 
120
 * the limit for the KSR is lower than SHMMAX in sys/param.h because
 
121
 * shmat would fail -- SHMMAX cannot be trusted (a bug)
 
122
 */
 
123
#define _SHMMAX 4*1024
 
124
 
 
125
#if defined(SUN)||defined(SOLARIS)
 
126
#  undef _SHMMAX
 
127
#  define _SHMMAX (1024)  /* memory in KB */
 
128
#elif defined(SGI64) || defined(AIX) || defined(CONVEX)
 
129
#  undef _SHMMAX
 
130
#  define _SHMMAX ((unsigned long)512*1024)
 
131
#elif defined(SGI) && !defined(SGI64)
 
132
#  undef _SHMMAX
 
133
#  define _SHMMAX ((unsigned long)128*1024)
 
134
#elif defined(KSR)
 
135
#  undef _SHMMAX
 
136
#  define _SHMMAX ((unsigned long)512*1024)
 
137
#elif defined(HPUX)
 
138
#  undef _SHMMAX
 
139
#  define _SHMMAX ((unsigned long)64*1024)
 
140
#elif defined(__FreeBSD__)
 
141
#  undef _SHMMAX
 
142
#  define _SHMMAX ((unsigned long)3*1024)
 
143
#elif defined(LINUX) 
 
144
#  if !defined(SHMMAX) /* Red Hat does not define SHMMAX */
 
145
#     undef _SHMMAX
 
146
#     if defined(__sparc__) || defined(__powerpc__) 
 
147
#       define _SHMMAX ((unsigned long)16*1024)
 
148
#     elif defined(__alpha__)
 
149
#       define _SHMMAX ((unsigned long)4072)
 
150
#     else
 
151
        /* Intel */
 
152
#       define _SHMMAX ((unsigned long)32*1024)
 
153
#     endif
 
154
#  endif
 
155
#elif defined(SHMMAX)
 
156
#  undef _SHMMAX
 
157
#  define _SHMMAX (((unsigned long)SHMMAX)>>10)
 
158
#endif
 
159
 
 
160
static  unsigned long MinShmem_per_core = 0;
 
161
static  unsigned long MaxShmem_per_core = 0;
 
162
static  unsigned long MinShmem = _SHMMAX;  
 
163
static  unsigned long MaxShmem = MAX_REGIONS*_SHMMAX;
 
164
static  context_t ctx_shmem; /* kr_malloc context */ 
 
165
static  context_t *ctx_shmem_global; /* kr_malloc context stored in shmem */
 
166
static  int create_call=0;
 
167
 
 
168
#ifdef  SHMMAX_SEARCH_NO_FORK
 
169
static  char *ptr_search_no_fork = (char*)0;
 
170
static  int id_search_no_fork=0;
 
171
#endif
 
172
 
 
173
 
 
174
#ifdef LINUX
 
175
#define CLEANUP_CMD(command) sprintf(command,"/usr/bin/ipcrm shm %d",id);
 
176
#elif  defined(SOLARIS) 
 
177
#define CLEANUP_CMD(command) sprintf(command,"/bin/ipcrm -m %d",id);
 
178
#elif  defined(SGI) 
 
179
#define CLEANUP_CMD(command) sprintf(command,"/usr/sbin/ipcrm -m %d",id);
 
180
#else
 
181
#define CLEANUP_CMD(command) sprintf(command,"/usr/bin/ipcrm -m %d",id);
 
182
#endif
 
183
 
 
184
 
 
185
#ifdef   ALLOC_MUNMAP
 
186
#ifdef QUADRICS
 
187
#  include <elan/elan.h>
 
188
#  include <elan3/elan3.h>
 
189
   static  char *armci_elan_starting_address = (char*)0;
 
190
 
 
191
#  ifdef __ia64__
 
192
#    define ALLOC_MUNMAP_ALIGN 1024*1024
 
193
#  else
 
194
#    define ALLOC_MUNMAP_ALIGN 64*1024
 
195
#  endif
 
196
 
 
197
#  define ALGN_MALLOC(s,a) elan_allocMain(elan_base->state, (a), (s))
 
198
#else 
 
199
#  define ALGN_MALLOC(s,a) malloc((s))
 
200
#endif
 
201
 
 
202
static char* alloc_munmap(size_t size)
 
203
{
 
204
char *tmp;
 
205
unsigned long iptr;
 
206
size_t bytes = size+pagesize-1;
 
207
 
 
208
    if(armci_elan_starting_address){
 
209
       tmp = armci_elan_starting_address;
 
210
       armci_elan_starting_address += size; 
 
211
#      ifdef ALLOC_MUNMAP_ALIGN
 
212
         armci_elan_starting_address += ALLOC_MUNMAP_ALIGN;
 
213
#      endif
 
214
       if(DEBUG_) {printf("%d: address for shm attachment is %p size=%ld\n",
 
215
                         armci_me,tmp,(long)size); fflush(stdout); }
 
216
    } else {
 
217
      tmp = ALGN_MALLOC(bytes, getpagesize());
 
218
      if(tmp){
 
219
        iptr = (unsigned long)tmp + pagesize-1;
 
220
        iptr >>= logpagesize; iptr <<= logpagesize;
 
221
        if(DEBUG_) printf("%d:unmap ptr=%p->%p size=%d pagesize=%d\n",armci_me, 
 
222
                          tmp,(char*)iptr,(int)size,pagesize);
 
223
        tmp = (char*)iptr;
 
224
        if(munmap(tmp, size) == -1) armci_die("munmap failed",0);
 
225
        if(DEBUG_){printf("%d: unmap OK\n",armci_me); fflush(stdout);}
 
226
      }else armci_die("alloc_munmap: malloc failed",(int)size);
 
227
    }
 
228
    return tmp;
 
229
}
 
230
#endif
 
231
 
 
232
/*\ A wrapper to shmget. Just to be sure that ID is not 0.
 
233
\*/
 
234
static int armci_shmget(size_t size,char *from)
 
235
{
 
236
int id;
 
237
 
 
238
    id = shmget(IPC_PRIVATE, size, (IPC_CREAT | 00600));
 
239
 
 
240
    /*attaching with id 0 somehow fails (Seen on pentium4+linux24+gm163)
 
241
     *so if id=0, shmget again. */
 
242
    while(id==0){
 
243
       /* free id=0 and get a new one */
 
244
       if(shmctl((int)id,IPC_RMID,(struct shmid_ds *)NULL)) {
 
245
         fprintf(stderr,"id=%d \n",id);
 
246
         armci_die("allocate: failed to _delete_ shared region ",id);
 
247
       }
 
248
       id = shmget(IPC_PRIVATE, size, (IPC_CREAT | 00600));
 
249
    }
 
250
    if(DEBUG_){
 
251
       printf("\n%d:armci_shmget sz=%ld caller=%s id=%d\n",armci_me,(long)size,
 
252
               from,id);
 
253
       fflush(stdout);
 
254
    }
 
255
    return(id);
 
256
}
 
257
 
 
258
 
 
259
/*\ test is a shared memory region of a specified size can be allocated
 
260
 *  return 0 (no) or 1 (yes)
 
261
\*/
 
262
int armci_test_allocate(long size)
 
263
{
 
264
   char *ptr;
 
265
   int id = armci_shmget((size_t)size,"armci_test_allocate");
 
266
   if (id <0) return 0;
 
267
 
 
268
   /* attach to segment */
 
269
   ptr =  shmat(id, (char *) NULL, 0);
 
270
 
 
271
   /* delete segment id */
 
272
   if(shmctl( id, IPC_RMID, (struct shmid_ds *)NULL))
 
273
      fprintf(stderr,"failed to remove shm id=%d\n",id);
 
274
 
 
275
   /* test pointer */
 
276
   if (((long)ptr) == -1L) return 0;
 
277
   else return 1;
 
278
}
 
279
 
 
280
 
 
281
#ifdef  SHMMAX_SEARCH_NO_FORK
 
282
/*\ try to allocate a shared memory region of a specified size; return pointer
 
283
\*/
 
284
static int armci_shmalloc_try(long size)
 
285
{
 
286
   char *ptr;
 
287
   int id = armci_shmget((size_t) size,"armci_shmalloc_try");
 
288
   if (id <0) return 0;
 
289
 
 
290
   /* attach to segment */
 
291
   ptr =  shmat(id, (char *) NULL, 0);
 
292
 
 
293
   /* test pointer */
 
294
   if (((long)ptr) == -1L) return 0;
 
295
 
 
296
   ptr_search_no_fork = ptr;
 
297
   id_search_no_fork = id;
 
298
   return 1;
 
299
}
 
300
#endif
 
301
 
 
302
 
 
303
 
 
304
 
 
305
/* parameters that define range and granularity of search for shm segment size
 
306
 * UBOUND is chosen to be < 2GB to avoid overflowing on 32-bit systems
 
307
 * smaller PAGE gives more accurate results but with more search steps
 
308
 * LBOUND  is set to minimum amount for our purposes
 
309
 * change UBOUND=512MB if you need larger arrays than 512 MB
 
310
 */
 
311
#define PAGE (16*65536L)
 
312
#define LBOUND  1048576L
 
313
#if defined(MULTI_CTX) && defined(QUADRICS)
 
314
#define UBOUND 256*LBOUND
 
315
#else
 
316
#define UBOUND 512*LBOUND
 
317
#endif
 
318
 
 
319
#define ARMCI_STRINGIFY(str) #str
 
320
#define ARMCI_CONCAT(str) strL
 
321
#ifndef ARMCI_DEFAULT_SHMMAX_UBOUND
 
322
#define ARMCI_DEFAULT_SHMMAX_UBOUND 8192
 
323
#endif
 
324
static long get_user_shmmax()
 
325
{
 
326
char *uval;
 
327
int x=0;
 
328
     uval = getenv("ARMCI_DEFAULT_SHMMAX"); 
 
329
     if(uval != NULL){
 
330
       sscanf(uval,"%d",&x);
 
331
       if(x<1 || x> ARMCI_DEFAULT_SHMMAX_UBOUND){ 
 
332
          fprintf(stderr,
 
333
                  "incorrect ARMCI_DEFAULT_SHMMAX should be <1,"
 
334
                  ARMCI_STRINGIFY(ARMCI_DEFAULT_SHMMAX)
 
335
                  ">mb and 2^N Found=%ld\n",x);
 
336
          x=0;
 
337
       }
 
338
     }
 
339
     return ((long)x)*1048576L; /* return value in bytes */
 
340
}
 
341
 
 
342
/*\ determine the max shmem segment size using bisection
 
343
\*/
 
344
int armci_shmem_test()
 
345
{
 
346
long x;
 
347
int  i,rc;
 
348
long upper_bound=UBOUND;
 
349
long lower_bound=0;
 
350
 
 
351
     x = get_user_shmmax();
 
352
     if(!x) x = upper_bound;
 
353
     else upper_bound =x;
 
354
     
 
355
     if(DEBUG_){printf("%d: x = %ld upper_bound=%ld\n",armci_me, x, upper_bound); fflush(stdout);}
 
356
 
 
357
     for(i=1;;i++){
 
358
        long step;
 
359
        rc = armci_test_allocate(x);
 
360
        if(DEBUG_) 
 
361
           printf("%d:test %d size=%ld bytes status=%d\n",armci_me,i,x,rc);
 
362
        if(rc){
 
363
          lower_bound = x;
 
364
          step = (upper_bound -x)>>1;
 
365
          if(step < PAGE) break;
 
366
          x += step;
 
367
        }else{
 
368
          upper_bound = x;
 
369
          step = (x-lower_bound)>>1;
 
370
          if(step<PAGE) break;
 
371
          x -= step;
 
372
        }
 
373
        /* round it up to a full base-2 MB */
 
374
        x += 1048576L -1L;
 
375
        x >>=20;
 
376
        x <<=20; 
 
377
      }
 
378
 
 
379
      if(!lower_bound){
 
380
          /* try if can get LBOUND - necessary if search starts from UBOUND */
 
381
          lower_bound=LBOUND;
 
382
          rc = armci_test_allocate(lower_bound);
 
383
          if(!rc) return(0);
 
384
      }
 
385
 
 
386
      if(DEBUG_) printf("%ld bytes segment size, %d calls \n",lower_bound,i);
 
387
      return (int)( lower_bound>>20); /* return shmmax in mb */
 
388
}
 
389
 
 
390
 
 
391
#ifdef SHMMAX_SEARCH_NO_FORK
 
392
/*\ determine the max shmem segment size by halving
 
393
\*/
 
394
static int armci_shmem_test_no_fork()                          
 
395
{
 
396
long x;                                                     
 
397
int  i,rc;
 
398
long lower_bound=_SHMMAX*SHM_UNIT;
 
399
#define UBOUND_SEARCH_NO_FORK (256*SHM_UNIT*SHM_UNIT)
 
400
 
 
401
     x = get_user_shmmax();
 
402
     if(!x) x = UBOUND_SEARCH_NO_FORK;
 
403
 
 
404
     for(i=1;;i++){
 
405
 
 
406
        rc = armci_shmalloc_try(x);
 
407
        if(DEBUG_)
 
408
           printf("%d:test by halving size=%ld bytes rc=%d\n",armci_me,x,rc);
 
409
 
 
410
        if(rc){
 
411
          lower_bound = x;
 
412
          break;
 
413
        }else{
 
414
          x >>= 1 ;
 
415
          if(x<lower_bound) break;
 
416
        }
 
417
     }
 
418
 
 
419
     if(DEBUG_) printf("%ld: shmax test no fork: bytes segment size, %d calls \n",lower_bound,i);
 
420
     return (int)( lower_bound>>20); /* return shmmax in mb */
 
421
}
 
422
#endif
 
423
 
 
424
 
 
425
#ifdef MULTI_CTX
 
426
void armci_nattach_preallocate_info(int* segments, int *segsize)
 
427
{
 
428
     int x;
 
429
     char *uval;
 
430
     uval = getenv("LIBELAN_NATTACH");
 
431
     if(uval != NULL){
 
432
        sscanf(uval,"%d",&x);
 
433
        if(x<2 || x>8) armci_die("Error in LIBELAN_NATTACH <8, >1 ",(int)x);
 
434
     }else
 
435
        armci_die("Inconsistent configuration: ARMCI needs LIBELAN_NATTACH",0);
 
436
     *segments =x;
 
437
     *segsize = (int) (SHM_UNIT * MinShmem);
 
438
 
 
439
}
 
440
#endif
 
441
        
 
442
/* Create shared region to store kr_malloc context in shared memory */
 
443
void armci_krmalloc_init_ctxshmem() {
 
444
    void *myptr=NULL;
 
445
    long idlist[SHMIDLEN];
 
446
    long size; 
 
447
    int offset = sizeof(void*)/sizeof(int);
 
448
 
 
449
    /* to store shared memory context and  myptr */
 
450
    size = SHMEM_CTX_MEM;
 
451
    
 
452
    if(armci_me == armci_master ){
 
453
       myptr = Create_Shared_Region(idlist+1,size,idlist);
 
454
       if(!myptr && size>0 ) armci_die("armci_krmalloc_init_ctxshmem: could not create", (int)(size>>10));
 
455
       if(size) *(volatile void**)myptr = myptr;
 
456
       if(DEBUG_){
 
457
          printf("%d:armci_krmalloc_init_ctxshmem addr mptr=%p ref=%p size=%ld\n", armci_me, myptr, *(void**)myptr, size);
 
458
          fflush(stdout);
 
459
       }
 
460
       
 
461
       /* Bootstrapping: allocate storage for ctx_shmem_global. NOTE:there is 
 
462
          offset,as master places its address at begining for others to see */
 
463
       ctx_shmem_global = (context_t*) ( ((int*)myptr)+offset );
 
464
       *ctx_shmem_global = ctx_shmem; /*master copies ctx into shared region */
 
465
    }
 
466
 
 
467
    /* broadcast shmem id to other processes on the same cluster node */
 
468
    armci_msg_clus_brdcst(idlist, SHMIDLEN*sizeof(long));
 
469
 
 
470
    if(armci_me != armci_master){
 
471
       myptr=(double*)Attach_Shared_Region(idlist+1,size,idlist[0]);
 
472
       if(!myptr)armci_die("armci_krmalloc_init_ctxshmem: could not attach", (int)(size>>10));
 
473
       
 
474
       /* now every process in a SMP node needs to find out its offset
 
475
        * w.r.t. master - this offset is necessary to use memlock table
 
476
        */
 
477
       if(size) armci_set_mem_offset(myptr);
 
478
       if(DEBUG_){
 
479
          printf("%d:armci_krmalloc_init_ctxshmem attached addr mptr=%p ref=%p size=%ld\n", armci_me,myptr, *(void**)myptr,size); fflush(stdout);
 
480
       }
 
481
       /* store context info */
 
482
       ctx_shmem_global = (context_t*) ( ((int*)myptr)+offset );
 
483
       if(DEBUG_){
 
484
          printf("%d:armci_krmalloc_init_ctxshmem: shmid=%d off=%ld size=%ld\n", armci_me, ctx_shmem_global->shmid, ctx_shmem_global->shmoffset,
 
485
                 (long)ctx_shmem_global->shmsize);
 
486
          fflush(stdout);
 
487
       }
 
488
    }
 
489
}
 
490
 
 
491
void armci_shmem_init()
 
492
{
 
493
 
 
494
#ifdef ALLOC_MUNMAP
 
495
 
 
496
#if defined(QUADRICS) 
 
497
#   if (defined(__ia64__) || defined(__alpha)) && !defined(DECOSF) 
 
498
 
 
499
      /* this is to determine size of Elan Main memory allocator for munmap */
 
500
      long x;
 
501
      char *uval;
 
502
      uval = getenv("LIBELAN_ALLOC_SIZE");
 
503
      if(uval != NULL){
 
504
        sscanf(uval,"%ld",&x);
 
505
        if((x>80000000) && (x< 4*1024*1024*1024L)){ 
 
506
          max_alloc_munmap = (x>>20) - 72;
 
507
          if(DEBUG_){
 
508
            printf("%d: max_alloc_munmap is %ld\n",armci_me,max_alloc_munmap);
 
509
            fflush(stdout);
 
510
          }
 
511
        }
 
512
      }
 
513
 
 
514
      /* an alternative approach is to use MMAP area where we get
 
515
         the address from the Elan environment variable in qsnetlibs 1.4+  */
 
516
      uval = getenv("LIBELAN3_MMAPBASE");
 
517
      if(uval != NULL){
 
518
         sscanf(uval,"%p",&armci_elan_starting_address);
 
519
      }
 
520
 
 
521
#   endif
 
522
#   if defined(__ia64__)
 
523
       /* need aligment on 1MB boundary rather than the actual pagesize */
 
524
       pagesize = 1024*1024;
 
525
       logpagesize = 20;
 
526
#   else
 
527
       /* determine log2(pagesize) needed for address alignment */
 
528
       int tp=512;
 
529
       logpagesize = 9;
 
530
       pagesize = getpagesize();
 
531
       if(tp>pagesize)armci_die("armci_shmem_init:pagesize",pagesize);
 
532
 
 
533
       while(tp<pagesize){
 
534
         tp <<= 1;
 
535
         logpagesize++;
 
536
       }
 
537
       if(tp!=pagesize)armci_die("armci_shmem_init:pagesize pow 2",pagesize);
 
538
#   endif
 
539
 
 
540
   if(DEBUG_) {
 
541
     printf("page size =%d log=%d\n",pagesize,logpagesize); fflush(stdout); }
 
542
 
 
543
#endif
 
544
#endif
 
545
 
 
546
   if(armci_me == armci_master){
 
547
#if !defined(NO_SHMMAX_SEARCH) || defined(SHMMAX_SEARCH_NO_FORK)
 
548
#       ifdef SHMMAX_SEARCH_NO_FORK
 
549
          int x = armci_shmem_test_no_fork();
 
550
#       else
 
551
          int x = armci_child_shmem_init();
 
552
#       endif
 
553
 
 
554
        if(x<1)
 
555
          armci_die("no usable amount of shared memory available: only got \n",
 
556
          (int)LBOUND);
 
557
 
 
558
#       if defined(ALLOC_MUNMAP)
 
559
          /* cap down for special memory allocator unless ARMCI_DEFAULT_SHMMAX
 
560
             not set - the user knows what is doing*/
 
561
#         if !defined(REGION_ALLOC)
 
562
          if(!getenv("ARMCI_DEFAULT_SHMMAX"))
 
563
            if(x>max_alloc_munmap && !armci_elan_starting_address) x=max_alloc_munmap;
 
564
#         else
 
565
            x = 10; /* mb */
 
566
#         endif
 
567
#       endif
 
568
 
 
569
        if(DEBUG_){
 
570
           printf("%d:shmem_init: %d mbytes max segment size\n",armci_me,x);fflush(stdout);}
 
571
 
 
572
        MinShmem = (long)(x<<10); /* make sure it is in kb: mb <<10 */ 
 
573
        MaxShmem = MAX_REGIONS*MinShmem;
 
574
#       ifdef REPORT_SHMMAX
 
575
              printf("%d using x=%d SHMMAX=%ldKB\n", armci_me,x, MinShmem);
 
576
              fflush(stdout);
 
577
#       endif
 
578
#else
 
579
 
 
580
      /* nothing to do here - limits were given */
 
581
 
 
582
#endif
 
583
    }
 
584
 
 
585
    armci_krmalloc_init_ctxshmem();
 
586
    if(DEBUG_)printf("%d: out of shmem_init\n",armci_me);
 
587
}
 
588
 
 
589
void armci_set_shmem_limit_per_node(int nslaves)
 
590
{
 
591
     if (MaxShmem_per_core > 0) MaxShmem = nslaves*MaxShmem_per_core;
 
592
     if (MinShmem_per_core > 0) MinShmem = nslaves*MinShmem_per_core;
 
593
}
 
594
 
 
595
void armci_set_shmem_limit_per_core(unsigned long shmemlimit)
 
596
{
 
597
     MaxShmem_per_core = (shmemlimit + SHM_UNIT - 1)/SHM_UNIT;
 
598
     MinShmem_per_core = (shmemlimit + SHM_UNIT - 1)/SHM_UNIT;
 
599
}
 
600
 
 
601
/*\ application can reset the upper limit (bytes) for memory allocation
 
602
\*/
 
603
void armci_set_shmem_limit(unsigned long shmemlimit)
 
604
{
 
605
     unsigned long kbytes;
 
606
     kbytes = (shmemlimit + SHM_UNIT -1)/SHM_UNIT;
 
607
     if(MaxShmem > kbytes) MaxShmem = kbytes;
 
608
     if(MinShmem > kbytes) MinShmem = kbytes;
 
609
}
 
610
 
 
611
 
 
612
static void shmem_errmsg(size_t size)
 
613
{
 
614
long sz=(long)size;
 
615
    printf("******************* ARMCI INFO ************************\n");
 
616
    printf("The application attempted to allocate a shared memory segment ");
 
617
    printf("of %ld bytes in size. This might be in addition to segments ",sz);
 
618
    printf("that were allocated succesfully previously. ");
 
619
    printf("The current system configuration does not allow enough ");
 
620
    printf("shared memory to be allocated to the application.\n");
 
621
    printf("This is most often caused by:\n1) system parameter SHMMAX ");
 
622
    printf("(largest shared memory segment) being too small or\n");
 
623
    printf("2) insufficient swap space.\n");
 
624
    printf("Please ask your system administrator to verify if SHMMAX ");
 
625
    printf("matches the amount of memory needed by your application and ");
 
626
    printf("the system has sufficient amount of swap space. ");
 
627
    printf("Most UNIX systems can be easily reconfigured ");
 
628
    printf("to allow larger shared memory segments,\n");
 
629
    printf("see http://www.emsl.pnl.gov/docs/global/support.shtml\n");
 
630
    printf("In some cases, the problem might be caused by insufficient swap space.\n");
 
631
    printf("*******************************************************\n");
 
632
}
 
633
 
 
634
 
 
635
static struct shm_region_list{
 
636
   char     *addr;
 
637
   long     id;
 
638
   long     sz;
 
639
   long     attached;
 
640
}region_list[MAX_REGIONS];
 
641
static int alloc_regions=0;
 
642
static long occup_blocks=0;
 
643
 
 
644
/* Terminology
 
645
 *   region - actual piece of shared memory allocated from OS
 
646
 *   block  - a part of allocated shmem that is given to the requesting process
 
647
 */
 
648
 
 
649
 
 
650
#if defined(MULTIPLE_REGIONS)
 
651
/********************************* MULTIPLE_REGIONS *******************/
 
652
/* allocate contiguous shmem -- glue pieces together -- works on SUN 
 
653
 * SUN max shmem segment is only 1MB so we might need several to satisfy request
 
654
 */
 
655
 
 
656
 
 
657
/* SHM_OP is an operator to calculate shmem address to attach 
 
658
 * might be + or - depending on the system 
 
659
 */
 
660
#if defined(DECOSF) || defined(LINUX)
 
661
#define SHM_OP +
 
662
#else
 
663
#define SHM_OP -
 
664
#endif
 
665
 
 
666
static int prev_alloc_regions=0;
 
667
 
 
668
 
 
669
unsigned long armci_max_region()
 
670
{
 
671
  /* we assume that at least two regions can be glued */
 
672
  return MinShmem*2;
 
673
}
 
674
 
 
675
/*\
 
676
 *   assembles the list of shmem id for the block 
 
677
\*/
 
678
int find_regions(char *addrp,  long* idlist, int *first)
 
679
{
 
680
int reg, nreg, freg=-1, min_reg, max_reg;
 
681
 
 
682
       /* find the region where addrp belongs */
 
683
       for(reg = 0; reg < alloc_regions-1; reg++){
 
684
          if(region_list[reg].addr < region_list[reg+1].addr){
 
685
             min_reg = reg; max_reg = reg+1;
 
686
          }else{
 
687
             min_reg = reg+1; max_reg = reg;
 
688
          }
 
689
          if(region_list[min_reg].addr <= addrp  && 
 
690
             region_list[max_reg].addr > addrp){
 
691
             freg = min_reg;
 
692
             break;
 
693
          }
 
694
       }
 
695
       /* if not found yet, it must be the last region */
 
696
       if(freg < 0) freg=alloc_regions-1;
 
697
 
 
698
       if( alloc_regions == prev_alloc_regions){
 
699
           /* no new regions were allocated this time - just get the id */
 
700
           idlist[0] = 1;
 
701
           idlist[1] = region_list[freg].id;
 
702
       }else{
 
703
           /* get ids of the allocated regions */
 
704
           idlist[0] = alloc_regions - prev_alloc_regions;
 
705
           if(idlist[0] < 0)armci_die("armci find_regions error ",0);
 
706
           for(reg =prev_alloc_regions,nreg=1; reg <alloc_regions;reg++,nreg++){
 
707
               idlist[nreg] = region_list[reg].id;
 
708
           }
 
709
           prev_alloc_regions = alloc_regions;
 
710
       }
 
711
       *first = freg;
 
712
       return idlist[0];
 
713
}
 
714
 
 
715
int armci_get_shmem_info(char *addrp,  int* shmid, long *shmoffset,
 
716
                         size_t *shmsize)
 
717
{
 
718
    armci_die("armci_get_shmem_info: Fix Me",0L);
 
719
    return 0;
 
720
}
 
721
 
 
722
Header *armci_get_shmem_ptr(int shmid, long shmoffset, size_t shmsize) 
 
723
{
 
724
    armci_die("armci_get_shmem_ptr: Fix Me",0L);
 
725
    return NULL;
 
726
}
 
727
 
 
728
char *Attach_Shared_Region(idlist, size, offset)
 
729
     long *idlist, offset, size;
 
730
{
 
731
int ir, reg,  found, first;
 
732
char *temp = (char*)0, *pref_addr=(char*)0;
 
733
 
 
734
  if(DEBUG_){
 
735
      printf("%d:AttachSharedRegion %d:size=%ld\n",armci_me,create_call++,size);
 
736
      fflush(stdout);
 
737
  }
 
738
 
 
739
  if(alloc_regions>=MAX_REGIONS)
 
740
       armci_die("Attach_Shared_Region: too many regions ",0L);
 
741
 
 
742
  /* first time needs to initialize region_list structure */
 
743
  if(!alloc_regions){
 
744
      for(reg=0;reg<MAX_REGIONS;reg++){
 
745
        region_list[reg].addr=(char*)0;
 
746
        region_list[reg].attached=0;
 
747
        region_list[reg].id=0;
 
748
      }
 
749
      MinShmem= idlist[SHMIDLEN-2];
 
750
  }
 
751
 
 
752
 /* 
 
753
  * Now, process the idlist list:
 
754
  *    . for every shemem ID make sure that it is attached
 
755
  *    . calulate shmem address by adding offset to the address for 1st region
 
756
  *    . idlist[0] has the number of shmem regions to process
 
757
  *    . idlist is assumed to be ordered -- first region comes first etc.
 
758
  */
 
759
  pref_addr = (char*)0;   /* first time let the OS choose address */
 
760
  for (ir = 0; ir< idlist[0]; ir++){
 
761
      /* search region_list for the current shmem id */
 
762
      for(found =0, reg=0; reg < MAX_REGIONS;reg++)
 
763
         if(found=(region_list[reg].id == idlist[1+ir])) break;
 
764
 
 
765
      if(!found){
 
766
         /* shmem id is not on the list */ 
 
767
         reg = alloc_regions;
 
768
         region_list[reg].id =idlist[1+ir];
 
769
 
 
770
      }
 
771
 
 
772
      /* attach if not attached yet */
 
773
      if(!region_list[reg].attached){
 
774
        /* make sure the next shmem region will be adjacent to previous one */
 
775
 
 
776
         if(temp) pref_addr= temp SHM_OP (MinShmem*SHM_UNIT);
 
777
#ifdef   ALLOC_MUNMAP
 
778
         else
 
779
              pref_addr = alloc_munmap((size_t) (MinShmem*SHM_UNIT));
 
780
#        endif
 
781
 
 
782
         if(DEBUG_)
 
783
            fprintf(stderr,"%d:trying id=%d pref=%ld tmp=%ld u=%d\n",armci_me,
 
784
                 idlist[1+ir],pref_addr,temp,MinShmem);
 
785
 
 
786
         if ((long)(temp = (char*)shmat((int)idlist[1+ir], pref_addr, 0))==-1L){
 
787
           fprintf(stderr,"%d:shmat err:id=%d pref=%ld off=%d\n",
 
788
                   armci_me, idlist[1+ir],pref_addr,offset);
 
789
           shmem_errmsg(size);
 
790
           armci_die("AttachSharedRegion:failed to attach",(long)idlist[1+ir]);
 
791
         }
 
792
         POST_ALLOC_CHECK(temp,MinShmem*SHM_UNIT);
 
793
 
 
794
         region_list[reg].addr = temp; 
 
795
         region_list[reg].attached = 1;
 
796
         alloc_regions++;
 
797
 
 
798
         if(DEBUG_){
 
799
           printf("%d: Attach_Shared_Region: id=%d pref=%ld got addr=%ld\n",
 
800
                           armci_me, idlist[1+ir], pref_addr, temp);
 
801
           fflush(stdout);
 
802
         }
 
803
      }
 
804
 
 
805
      /* now we have this region attached and ready to go */
 
806
 
 
807
      if(!ir)first = reg;  /* store the first region */
 
808
  }
 
809
 
 
810
  reg = first; /* first region on the list */ 
 
811
 
 
812
  if(DEBUG_) 
 
813
    fprintf(stderr,
 
814
            "AttachSharedRegion: reg=%d id= %d off=%d addr=%p addr+off=%p\n",
 
815
            reg,region_list[reg].id, offset, region_list[reg].addr, 
 
816
            region_list[reg].addr+ offset);
 
817
 
 
818
  /* check stamp to make sure that we are attached in the right place */
 
819
  if(STAMP) if(*((int*)(region_list[reg].addr+ offset))!= alloc_regions-1){
 
820
      fprintf(stderr, "attach: region=%d  ",alloc_regions);
 
821
      armci_die("Attach_Shared_Region: wrong stamp value !", 
 
822
                *((int*)(region_list[reg].addr+ offset)));
 
823
  }
 
824
  occup_blocks++;
 
825
 
 
826
  return (region_list[0].addr + offset);
 
827
}
 
828
 
 
829
 
 
830
/*\ allocates shmem, to be called by kr_malloc that is called by process that
 
831
 *  creates shmem region
 
832
\*/
 
833
void *armci_allocate(long size)
 
834
{
 
835
#define min(a,b) ((a)>(b)? (b): (a))
 
836
char *temp = (char*)0, *pref_addr=(char*)0, *ftemp;
 
837
int id, newreg, i;
 
838
size_t sz;
 
839
 
 
840
    if(DEBUG1){
 
841
       printf("%d:Shmem allocate: size %ld bytes\n",armci_me,size); 
 
842
       fflush(stdout);
 
843
    }
 
844
 
 
845
    newreg = (size+(SHM_UNIT*MinShmem)-1)/(SHM_UNIT*MinShmem);
 
846
 
 
847
    if( (alloc_regions + newreg)> MAX_REGIONS)
 
848
       armci_die("allocate: to many regions already allocated ",(long)newreg);
 
849
 
 
850
    prev_alloc_regions = alloc_regions; 
 
851
 
 
852
    if(DEBUG_)fprintf(stderr, "in allocate size=%ld\n",size);
 
853
 
 
854
#ifdef  ALLOC_MUNMAP
 
855
    pref_addr = alloc_munmap((size_t) size);
 
856
#else
 
857
    pref_addr = (char*)0;   /* first time let the OS choose address */
 
858
#endif
 
859
 
 
860
    /* allocate shmem in as many segments as neccesary */
 
861
    for(i =0; i< newreg; i++){ 
 
862
       long szl;
 
863
       szl =(i==newreg-1)?size-i*MinShmem*SHM_UNIT: min(size,SHM_UNIT*MinShmem);
 
864
       sz = (size_t) szl;
 
865
 
 
866
       if ( (int)(id = armci_shmget(sz,"MULTIPLE_REGIONarmci_allocate")) < 0){
 
867
          fprintf(stderr,"%d:id=%d size=%d MAX=%ld\n",armci_me,id,szl,MinShmem);
 
868
          alloc_regions++;
 
869
          shmem_errmsg(size);
 
870
          armci_die("allocate: failed to create shared region ",id);
 
871
       }
 
872
 
 
873
       /* make sure the next shmem region will be adjacent to previous one */
 
874
       if(temp) pref_addr= temp SHM_OP (MinShmem*SHM_UNIT);
 
875
 
 
876
       if(DEBUG_)printf("calling shmat:id=%d adr=%p sz=%ld\n",id,pref_addr,szl);
 
877
 
 
878
       if ( (long)(temp = (char*)shmat(id, pref_addr, 0)) == -1L){
 
879
          char command[64];
 
880
          CLEANUP_CMD(command);
 
881
          if(system(command) == -1) 
 
882
            printf("Please clean shared memory (id=%d): see man ipcrm\n",id);
 
883
          if(pref_addr){
 
884
             printf("ARMCI shared memory allocator was unable to obtain from ");
 
885
             printf("the operating system multiple segments adjacent to ");
 
886
             printf("each other in order to combine them into a one large ");
 
887
             printf("segment together\n");
 
888
             shmem_errmsg(size);
 
889
             armci_die("allocate: failed to attach to shared region",  0L);
 
890
         }
 
891
       }
 
892
       POST_ALLOC_CHECK(temp,MinShmem*SHM_UNIT);
 
893
 
 
894
       region_list[alloc_regions].addr = temp;
 
895
       region_list[alloc_regions].id = id;
 
896
       region_list[alloc_regions].attached=1;
 
897
 
 
898
       if(DEBUG_) fprintf(stderr," allocate:attach: id=%d addr=%p \n",id, temp);
 
899
       alloc_regions++;
 
900
       if(i==0)ftemp = temp;
 
901
    }
 
902
    return (void*)(min(ftemp,temp));
 
903
}
 
904
    
 
905
/************************** END of MULTIPLE_REGIONS *******************/
 
906
 
 
907
#else /* Now, the machines where shm segments are not glued together */ 
 
908
 
 
909
static int last_allocated=-1;
 
910
 
 
911
 
 
912
unsigned long armci_max_region()
 
913
{
 
914
  return MinShmem;
 
915
}
 
916
 
 
917
 
 
918
int find_regions(char *addrp,  long* id, int *region)
 
919
{
 
920
int nreg, reg;
 
921
 
 
922
    if(last_allocated!=-1){
 
923
       reg=last_allocated;
 
924
       last_allocated = -1;
 
925
    } else{
 
926
       
 
927
       for(reg=-1,nreg=0;nreg<alloc_regions; nreg++)
 
928
       {
 
929
          if(addrp >= region_list[nreg].addr &&
 
930
             addrp < (region_list[nreg].addr + region_list[nreg].sz))
 
931
          {
 
932
             reg = nreg;
 
933
             break;
 
934
          }
 
935
       }
 
936
       
 
937
       if(reg == -1)
 
938
          armci_die("find_regions: failed to locate shared region", 0L);
 
939
    }
 
940
 
 
941
    *region = reg;
 
942
    *id = region_list[reg].id;
 
943
 
 
944
    return 1;
 
945
}
 
946
 
 
947
/* returns the shmem info based on the addr */
 
948
int armci_get_shmem_info(char *addrp,  int* shmid, long *shmoffset, 
 
949
                         size_t *shmsize) 
 
950
{    
 
951
    int region; long id;
 
952
 
 
953
    find_regions(addrp, &id, &region);
 
954
    *shmid     = id;
 
955
    *shmoffset = (long)(addrp - region_list[region].addr);
 
956
    *shmsize   = region_list[region].sz;
 
957
 
 
958
    return 1;
 
959
}
 
960
 
 
961
long armci_shm_reg_size(int i, long id)
 
962
{
 
963
     if(i<0 || i>= MAX_REGIONS)armci_die("armci_shmem_reg_size: bad i",i); 
 
964
     return region_list[i].sz;
 
965
}
 
966
 
 
967
void* armci_shm_reg_ptr(int i)
 
968
{
 
969
     if(i<0 || i>= MAX_REGIONS)armci_die("armci_shmem_reg_ptr: bad i",i); 
 
970
     return (void *)region_list[i].addr;
 
971
}
 
972
 
 
973
Header *armci_get_shmem_ptr(int shmid, long shmoffset, size_t shmsize) 
 
974
{
 
975
/* returns, address of the shared memory region based on shmid, offset.
 
976
 * (i.e. return_addr = stating address of shmid + offset)*/
 
977
    long idlist[SHMIDLEN];
 
978
    Header *p = NULL;
 
979
 
 
980
    idlist[1] = (long)shmid;
 
981
    idlist[0] = shmoffset;
 
982
    idlist[IDLOC+1] = shmsize; /* CHECK : idlist in CreateShmem????*/
 
983
 
 
984
    if(!(p=(Header*)Attach_Shared_Region(idlist+1, shmsize, idlist[0])))
 
985
       armci_die("kr_malloc:could not attach",(int)(p->s.shmsize>>10));
 
986
#if DEBUG_
 
987
    printf("%d: armci_get_shmem_ptr: %d %ld %ld %p\n",
 
988
           armci_me, idlist[1], idlist[0], shmsize, p);
 
989
    fflush(stdout);    
 
990
#endif
 
991
    return p;
 
992
}
 
993
 
 
994
 
 
995
char *Attach_Shared_Region(id, size, offset)
 
996
     long *id, offset, size;
 
997
{
 
998
int reg, found, shmflag=0;
 
999
static char *temp;
 
1000
 
 
1001
#if defined(SGI_N32) && defined(SHM_SGI_ANYADDR)
 
1002
  shmflag= SHM_SGI_ANYADDR;
 
1003
#endif
 
1004
  
 
1005
  if(alloc_regions>=MAX_REGIONS)
 
1006
       armci_die("Attach_Shared_Region: to many regions ",0);
 
1007
 
 
1008
  if(DEBUG_){
 
1009
      printf("%d:AttachSharedRegion %d:size=%ld id=%ld\n",
 
1010
             armci_me, create_call++, size,*id);
 
1011
      fflush(stdout);
 
1012
  }
 
1013
 
 
1014
 
 
1015
  /* under Linux we can get valid id=0 */
 
1016
#ifndef LINUX
 
1017
  if(!*id) armci_die("Attach_Shared_Region: shmem ID=0 ",(int)*id);
 
1018
#endif
 
1019
 
 
1020
  /* first time needs to initialize region_list structure */
 
1021
  if(!alloc_regions){
 
1022
      for(reg=0;reg<MAX_REGIONS;reg++){
 
1023
        region_list[reg].addr=(char*)0;
 
1024
        region_list[reg].attached=0;
 
1025
        region_list[reg].id=0;
 
1026
      }
 
1027
      MinShmem= id[SHMIDLEN-2];
 
1028
      if(DEBUG2_){
 
1029
         printf("%d:attach: allocation unit: %ldK\n",armci_me,MinShmem);
 
1030
         fflush(stdout);
 
1031
      }
 
1032
  }
 
1033
 
 
1034
  /* search region_list for the current shmem id */
 
1035
  for(found = 0, reg=0; reg < MAX_REGIONS;reg++)
 
1036
      if((found=(region_list[reg].id == *id)))break;
 
1037
 
 
1038
  if(!found){
 
1039
     reg = alloc_regions;
 
1040
     region_list[reg].id =*id;
 
1041
     alloc_regions++;
 
1042
  }
 
1043
 
 
1044
  /* we need to use the actual shared memory segment not user req size */ 
 
1045
  size = id[IDLOC];
 
1046
 
 
1047
  /* attach if not attached yet */
 
1048
  if(!region_list[reg].attached){
 
1049
 
 
1050
#   ifdef ALLOC_MUNMAP
 
1051
       char *pref_addr = alloc_munmap((size_t) (size));
 
1052
#   else
 
1053
       char *pref_addr = (char*)0;
 
1054
#   endif
 
1055
    if ( (long) (temp = shmat((int) *id, pref_addr, shmflag)) == -1L){
 
1056
       fprintf(stderr,"%d:attach error:id=%ld off=%ld seg=%ld\n",armci_me,*id,offset,MinShmem);
 
1057
       shmem_errmsg((size_t)MinShmem*1024);
 
1058
       armci_die("Attach_Shared_Region:failed to attach to segment id=",(int)*id);
 
1059
    }
 
1060
    if(DEBUG_){
 
1061
        printf("%d:attached: id=%d address=%p\n",armci_me,(int)*id, temp);
 
1062
        fflush(stdout);
 
1063
    }
 
1064
    POST_ALLOC_CHECK(temp,size);
 
1065
    region_list[reg].addr = temp; 
 
1066
    region_list[reg].attached = 1;
 
1067
    region_list[reg].sz= size;
 
1068
#if defined(OPENIB)
 
1069
    /*SK: Tested only for OPENIB*/
 
1070
/*     armci_region_register_loc(temp, size); */
 
1071
#endif
 
1072
  }
 
1073
 
 
1074
  if(STAMP)
 
1075
  /* check stamp to make sure that we are attached in the right place */
 
1076
  if(*((int*)(region_list[reg].addr+ offset))!= alloc_regions-1)
 
1077
      armci_die("Attach_Shared_Region: wrong stamp value !", 
 
1078
                *((int*)(region_list[reg].addr+ offset)));
 
1079
  occup_blocks++;
 
1080
  return (region_list[reg].addr+ offset);
 
1081
}
 
1082
 
 
1083
#ifdef ALLOW_PIN
 
1084
extern void armci_region_register_shm(void *start, long size);
 
1085
#endif
 
1086
 
 
1087
/*\ allocates shmem, to be called by krmalloc that is called by process that
 
1088
 *  creates shmem region
 
1089
\*/
 
1090
void *armci_allocate(long size)
 
1091
{
 
1092
char * temp;
 
1093
int id,shmflag=0;
 
1094
size_t sz = (size_t)size;
 
1095
#ifdef ALLOC_MUNMAP
 
1096
       char *pref_addr = alloc_munmap((size_t) (MinShmem*SHM_UNIT));
 
1097
#else
 
1098
       char *pref_addr = (char*)0;
 
1099
#endif
 
1100
#if defined(SGI_N32) && defined(SHM_SGI_ANYADDR)
 
1101
  shmflag= SHM_SGI_ANYADDR;
 
1102
#endif
 
1103
 
 
1104
    if(DEBUG1){
 
1105
       printf("%d:allocate: Shmem allocate size %ld bytes\n",armci_me,size); 
 
1106
       fflush(stdout);
 
1107
    }
 
1108
 
 
1109
    if( alloc_regions >= MAX_REGIONS)
 
1110
       armci_die("Create_Shared_Region:allocate:too many regions allocated ",0);
 
1111
 
 
1112
    last_allocated = alloc_regions;
 
1113
 
 
1114
#ifdef SHMMAX_SEARCH_NO_FORK
 
1115
    if (ptr_search_no_fork){
 
1116
        temp = ptr_search_no_fork;
 
1117
        id   = id_search_no_fork;
 
1118
        ptr_search_no_fork = (char*)0; /* do not look at it again */
 
1119
    }else 
 
1120
#endif
 
1121
    {
 
1122
       if ( (id = armci_shmget(sz,"armci_allocate")) < 0 ) {
 
1123
          fprintf(stderr,"id=%d size=%ld\n",id, size);
 
1124
          shmem_errmsg(sz);
 
1125
          armci_die("allocate: failed to create shared region ",id);
 
1126
       }
 
1127
 
 
1128
       if ( (long)( (temp = shmat(id, pref_addr, shmflag))) == -1L){
 
1129
          char command[64];
 
1130
          CLEANUP_CMD(command);
 
1131
          if(system(command) == -1) 
 
1132
            printf("Please clean shared memory (id=%d): see man ipcrm\n",id);
 
1133
          armci_die("allocate: failed to attach to shared region id=",id);
 
1134
       }
 
1135
       if(DEBUG_){
 
1136
         printf("%d:allocate:attach:id=%d paddr=%p size=%ld\n",armci_me,id,temp,size);
 
1137
         fflush(stdout);
 
1138
       }
 
1139
#if !defined(AIX) && !defined(HPUX64)
 
1140
       /* delete segment id so that OS cleans it when all attached processes are gone */
 
1141
       if(shmctl( id, IPC_RMID, (struct shmid_ds *)NULL))
 
1142
          fprintf(stderr,"failed to remove shm id=%d\n",id);
 
1143
#endif
 
1144
 
 
1145
    }
 
1146
    POST_ALLOC_CHECK(temp,sz);
 
1147
 
 
1148
    region_list[alloc_regions].addr = temp;
 
1149
    region_list[alloc_regions].id = id;
 
1150
    region_list[alloc_regions].attached=1;
 
1151
    region_list[alloc_regions].sz=sz;
 
1152
    alloc_regions++;
 
1153
 
 
1154
    if(DEBUG2_){
 
1155
      printf("%d:allocate:id=%d addr=%p size=%ld\n",armci_me,id,temp,size);
 
1156
      fflush(stdout);
 
1157
    }
 
1158
 
 
1159
#ifdef ALLOW_PIN
 
1160
    armci_region_register_shm(temp, size);
 
1161
#endif
 
1162
 
 
1163
    return (void*) (temp);
 
1164
}
 
1165
    
 
1166
#endif
 
1167
 
 
1168
/******************** common code for the two versions *********************/
 
1169
 
 
1170
 
 
1171
/*\ Allocate a block of shared memory - called by master process
 
1172
\*/
 
1173
char *Create_Shared_Region(long *id, long size, long *offset)
 
1174
{
 
1175
  char *temp;  
 
1176
int  reg, refreg=0,nreg;
 
1177
  
 
1178
    if(alloc_regions>=MAX_REGIONS)
 
1179
       armci_die("Create_Shared_Region: to many regions ",0);
 
1180
 
 
1181
    if(DEBUG_){
 
1182
      printf("%d:CreateSharedRegion %d:size=%ld\n",armci_me,create_call++,size);
 
1183
      fflush(stdout);
 
1184
    }
 
1185
 
 
1186
    /*initialization: 1st allocation request */
 
1187
    if(!alloc_regions){
 
1188
       for(reg=0;reg<MAX_REGIONS;reg++){
 
1189
          region_list[reg].addr=(char*)0;
 
1190
          region_list[reg].attached=0;
 
1191
          region_list[reg].id=0;
 
1192
       }
 
1193
       if(DEBUG_){
 
1194
          printf("%d:1st CreateSharedRegion: allocation unit:%ldK,shmax:%ldK\n",
 
1195
                 armci_me,MinShmem,MaxShmem);
 
1196
          fflush(stdout);
 
1197
       }
 
1198
 
 
1199
       kr_malloc_init(SHM_UNIT, (size_t)MinShmem, (size_t)MaxShmem, 
 
1200
                      armci_allocate, 0, &ctx_shmem);
 
1201
       ctx_shmem.ctx_type = KR_CTX_SHMEM;
 
1202
       id[SHMIDLEN-2]=MinShmem;
 
1203
    }
 
1204
 
 
1205
    if(!alloc_regions)  temp = kr_malloc((size_t)size, &ctx_shmem);
 
1206
    else temp = kr_malloc((size_t)size, ctx_shmem_global);
 
1207
 
 
1208
    if(temp == (char*)0 )
 
1209
       armci_die("CreateSharedRegion:kr_malloc failed KB=",(int)size>>10);
 
1210
    
 
1211
    if(!(nreg=find_regions(temp,id,&reg)))
 
1212
        armci_die("CreateSharedRegion: allocation inconsitent",0);
 
1213
 
 
1214
#ifndef MULTIPLE_REGIONS
 
1215
    refreg = reg;
 
1216
#endif
 
1217
 
 
1218
    if(STAMP) *((int*)temp) = alloc_regions-1;
 
1219
    *offset = (long) (temp - region_list[refreg].addr);
 
1220
    id[IDLOC]=region_list[reg].sz; /* elan post check */
 
1221
    occup_blocks++;
 
1222
  
 
1223
    if(DEBUG_){ 
 
1224
      printf("%d:CreateShmReg:reg=%d id=%ld off=%ld ptr=%p adr=%p s=%d n=%d sz=%ld\n",
 
1225
           armci_me,reg,region_list[reg].id,*offset,region_list[reg].addr,
 
1226
           temp,(int)size,nreg,id[IDLOC]);
 
1227
      fflush(stdout);
 
1228
    }
 
1229
 
 
1230
    return temp;
 
1231
}
 
1232
 
 
1233
 
 
1234
 
 
1235
/*\ only process that created shared region returns the pointer to kr_malloc 
 
1236
\*/
 
1237
void Free_Shmem_Ptr( id, size, addr)
 
1238
     long id, size;
 
1239
     char *addr;
 
1240
{
 
1241
  kr_free(addr, ctx_shmem_global);
 
1242
}
 
1243
 
 
1244
 
 
1245
void Delete_All_Regions()
 
1246
{
 
1247
int reg;
 
1248
int code=0;
 
1249
 
 
1250
  for(reg = 0; reg < MAX_REGIONS; reg++){
 
1251
    if(region_list[reg].addr != (char*)0){
 
1252
      code += shmctl((int)region_list[reg].id,IPC_RMID,(struct shmid_ds *)NULL);
 
1253
      region_list[reg].addr = (char*)0;
 
1254
      region_list[reg].attached = 0;
 
1255
      if(DEBUG_)
 
1256
         fprintf(stderr,"%d Delete_All_Regions id=%d code=%d\n",armci_me, 
 
1257
                (int)region_list[reg].id, code);
 
1258
    }
 
1259
  }
 
1260
}
 
1261
 
 
1262
 
 
1263
 
 
1264
#else
 
1265
 what are doing here ?
 
1266
#endif