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

« back to all changes in this revision

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