~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/kr_malloc.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: kr_malloc.c,v 1.24 2006-09-12 23:21:21 andriy Exp $ */
6
 
#if HAVE_STDIO_H
7
 
#   include <stdio.h>
8
 
#endif
9
 
#include "kr_malloc.h"
10
 
#include "armcip.h" /* for DEBUG purpose only. remove later */
11
 
#include "locks.h"
12
 
 
13
 
#define DEBUG 0
14
 
 
15
 
/* Storage allocator basically copied from ANSI K&R and corrupted */
16
 
 
17
 
extern char *armci_allocate(); /* Used to get memory from the system */
18
 
#if !defined(armci_die)
19
 
extern void armci_die();
20
 
#endif
21
 
static char *kr_malloc_shmem(size_t nbytes, context_t *ctx);
22
 
static void kr_free_shmem(char *ap, context_t *ctx);
23
 
 
24
 
/**
25
 
 * DEFAULT_NALLOC: No. of units of length ALIGNMENT to get in every 
26
 
 * request to the system for memory (8MB/64 => 128*1024units)
27
 
 * DEFAULT_MAX_NALLOC: Maximum number of units that can get i.e.1GB 
28
 
 * (if unit size=64bytes, then max units=1024MB/64 = 16*1024*1024)
29
 
 */
30
 
#define DEFAULT_NALLOC       (4*128*1024)  
31
 
#define DEFAULT_NALLOC_ALIGN 1024  
32
 
#define DEFAULT_MAX_NALLOC   (4*1024*1024*16) 
33
 
 
34
 
/* mutual exclusion defs go here */
35
 
#define LOCKED   100
36
 
#define UNLOCKED 101
37
 
static int lock_mode=UNLOCKED;
38
 
 
39
 
/* enable locking only after armci is initailized as locks (and lock
40
 
   data structures) are initialized in PARMCI_Init */
41
 
#define  LOCKIT(p) \
42
 
    if(_armci_initialized && lock_mode==UNLOCKED) { \
43
 
       NAT_LOCK(0,p); lock_mode=LOCKED;             \
44
 
    }
45
 
#define  UNLOCKIT(p) \
46
 
    if(_armci_initialized && lock_mode==LOCKED) {   \
47
 
       NAT_UNLOCK(0,p); lock_mode=UNLOCKED;         \
48
 
    }
49
 
 
50
 
static int do_verify = 0;       /* Flag for automatic heap verification */
51
 
 
52
 
#define VALID1  0xaaaaaaaa      /* For validity check on headers */
53
 
#define VALID2  0x55555555
54
 
 
55
 
#define USEDP 0 /* CHECK. By default anable this. */
56
 
 
57
 
static void kr_error(char *s, unsigned long i, context_t *ctx) {
58
 
char string[256];
59
 
    sprintf(string,"kr_malloc: %s %ld(0x%lx)\n", s, i, i);
60
 
#if 0
61
 
    kr_malloc_print_stats(ctx);
62
 
#endif
63
 
    armci_die(string, i);
64
 
}
65
 
 
66
 
static Header *morecore(size_t nu, context_t *ctx) {
67
 
    char *cp;
68
 
    Header *up;
69
 
 
70
 
#if DEBUG
71
 
    (void) printf("%d: morecore 1: Getting %ld more units of length %d nalloc=%d\n", armci_me, (long)nu, sizeof(Header),ctx->nalloc);
72
 
    (void) fflush(stdout);
73
 
#endif
74
 
 
75
 
    if (ctx->total >= ctx->max_nalloc) {
76
 
#      if DEBUG
77
 
         armci_die("kr_malloc: morecore: maximum allocation reached",armci_me);
78
 
#      endif
79
 
       return (Header *) NULL;   /* Enforce upper limit on core usage */
80
 
    }
81
 
 
82
 
#if 1
83
 
    /* 07/03 ctx->nalloc is now the minimum # units we ask from OS */
84
 
    nu = DEFAULT_NALLOC_ALIGN*((nu-1)/DEFAULT_NALLOC_ALIGN+1);
85
 
    if(nu < ctx->nalloc) nu = ctx->nalloc; 
86
 
#else
87
 
    nu = ctx->nalloc*((nu-1)/ctx->nalloc+1); /* nu must by a multiplicity of nalloc */
88
 
#endif
89
 
 
90
 
#if DEBUG
91
 
    (void) printf("%d: morecore: Getting %ld more units of length %d\n",
92
 
                  armci_me, (long)nu, sizeof(Header));
93
 
    (void) fflush(stdout);
94
 
#endif
95
 
    
96
 
    if ((cp =(char *)(*ctx->alloc_fptr)((size_t)nu * sizeof(Header))) == (char *)NULL)
97
 
      return (Header *) NULL;
98
 
 
99
 
    ctx->total += nu;   /* Have just got nu more units */
100
 
    ctx->nchunk++;      /* One more chunk */
101
 
    ctx->nfrags++;      /* Currently one more frag */
102
 
    ctx->inuse += nu;   /* Inuse will be decremented by kr_free */
103
 
    
104
 
    up = (Header *) cp;
105
 
    up->s.size = nu;
106
 
    up->s.valid1 = VALID1;
107
 
    up->s.valid2 = VALID2;
108
 
 
109
 
    /* Insert into linked list of blocks in use so that kr_free works
110
 
       ... for debug only */
111
 
    up->s.ptr = ctx->usedp;
112
 
    ctx->usedp = up;
113
 
 
114
 
    kr_free((char *)(up+1), ctx);  /* Try to join into the free list */
115
 
    return ctx->freep;
116
 
}
117
 
 
118
 
void kr_malloc_init(size_t usize, /* unit size in bytes */
119
 
                    size_t nalloc,
120
 
                    size_t max_nalloc,
121
 
                    void * (*alloc_fptr)(), /* memory alloc routine */
122
 
                    int debug,
123
 
                    context_t *ctx) {
124
 
    int scale;
125
 
 
126
 
    if(usize <= 0) usize = sizeof(Header);
127
 
    
128
 
    scale = usize>>LOG_ALIGN;
129
 
    if(scale<1)fprintf(stderr,"Error: kr_malloc_init !!!\n");
130
 
    
131
 
    if(nalloc==0) nalloc = DEFAULT_NALLOC;
132
 
    if(max_nalloc==0) max_nalloc = DEFAULT_MAX_NALLOC;
133
 
 
134
 
    ctx->usize      = sizeof(Header);
135
 
    ctx->nalloc     = nalloc * scale;
136
 
    ctx->max_nalloc = max_nalloc * scale;
137
 
    ctx->alloc_fptr = alloc_fptr;
138
 
    ctx->freep = NULL;
139
 
    ctx->usedp = NULL;
140
 
    ctx->shmid = -1;
141
 
    ctx->shmoffset = 0;
142
 
    ctx->shmsize   = 0;
143
 
    ctx->ctx_type  = -1;
144
 
    do_verify = debug;
145
 
}
146
 
 
147
 
 
148
 
char *kr_malloc(size_t nbytes, context_t *ctx) {
149
 
    Header *p, *prevp;
150
 
    size_t nunits;
151
 
    char *return_ptr;
152
 
 
153
 
#if !((defined(SUN) || defined(SOLARIS)) && !defined(SHMMAX_SEARCH_NO_FORK))
154
 
    if(ctx->ctx_type == KR_CTX_SHMEM) return kr_malloc_shmem(nbytes,ctx);
155
 
#endif
156
 
    
157
 
    /* If first time in need to initialize the free list */
158
 
    if ((prevp = ctx->freep) == NULL) {
159
 
 
160
 
       if (sizeof(Header) != ALIGNMENT)
161
 
          kr_error("Alignment is not valid", (unsigned long) ALIGNMENT, ctx);
162
 
 
163
 
       ctx->total  = 0;  /* Initialize statistics */
164
 
       ctx->nchunk = 0;
165
 
       ctx->inuse  = 0;
166
 
       ctx->nfrags = 0;
167
 
       ctx->maxuse = 0;
168
 
       ctx->nmcalls= 0;
169
 
       ctx->nfcalls= 0;
170
 
       /* Initialize linked list */
171
 
       ctx->base.s.ptr = ctx->freep = prevp = &(ctx->base);
172
 
       ctx->base.s.size = 0;
173
 
       ctx->base.s.valid1 = VALID1;
174
 
       ctx->base.s.valid2 = VALID2;
175
 
    }
176
 
 
177
 
    ctx->nmcalls++;
178
 
 
179
 
    if (do_verify)
180
 
       kr_malloc_verify(ctx);
181
 
 
182
 
    /* Rather than divide make the alignment a known power of 2 */
183
 
 
184
 
    nunits = ((nbytes + sizeof(Header) - 1)>>LOG_ALIGN) + 1;
185
 
 
186
 
    for (p=prevp->s.ptr; ; prevp = p, p = p->s.ptr) {
187
 
 
188
 
       if (p->s.size >= nunits) {        /* Big enuf */
189
 
          if (p->s.size == nunits)        /* exact fit */
190
 
             prevp->s.ptr = p->s.ptr;
191
 
          else {                  /* allocate tail end */
192
 
             p->s.size -= nunits;
193
 
             p += p->s.size;
194
 
             p->s.size = nunits;
195
 
             p->s.valid1 = VALID1;
196
 
             p->s.valid2 = VALID2;
197
 
             ctx->nfrags++;  /* Have just increased the fragmentation */
198
 
          }
199
 
 
200
 
          /* Insert into linked list of blocks in use ... for debug only */
201
 
          p->s.ptr = ctx->usedp;
202
 
          ctx->usedp = p;
203
 
 
204
 
          ctx->inuse += nunits;  /* Record usage */
205
 
          if (ctx->inuse > ctx->maxuse)
206
 
             ctx->maxuse = ctx->inuse;
207
 
          ctx->freep = prevp;
208
 
          return_ptr = (char *) (p+1);
209
 
          break;
210
 
       }
211
 
 
212
 
       if (p == ctx->freep) {       /* wrapped around the free list */
213
 
          if ((p = morecore(nunits, ctx)) == (Header *) NULL) {
214
 
             return_ptr = (char *) NULL;
215
 
             break;
216
 
          }
217
 
       }
218
 
    }
219
 
 
220
 
    return return_ptr;
221
 
 
222
 
}
223
 
 
224
 
 
225
 
void kr_free(char *ap, context_t *ctx) {
226
 
    Header *bp, *p, **up;
227
 
    
228
 
#if !((defined(SUN) || defined(SOLARIS)) && !defined(SHMMAX_SEARCH_NO_FORK))
229
 
    if(ctx->ctx_type == KR_CTX_SHMEM) { kr_free_shmem(ap,ctx); return; }
230
 
#endif
231
 
    
232
 
    ctx->nfcalls++;
233
 
 
234
 
 
235
 
    if (do_verify)
236
 
       kr_malloc_verify(ctx);
237
 
 
238
 
    /* only do something if pointer is not NULL */
239
 
 
240
 
    if ( ap ) {
241
 
 
242
 
       bp = (Header *) ap - 1;  /* Point to block header */
243
 
 
244
 
       if (bp->s.valid1 != VALID1 || bp->s.valid2 != VALID2)
245
 
          kr_error("kr_free: pointer not from kr_malloc",
246
 
                   (unsigned long) ap, ctx);
247
 
 
248
 
       ctx->inuse -= bp->s.size; /* Decrement memory ctx->usage */
249
 
 
250
 
       /* Extract the block from the used linked list
251
 
          ... for debug only */
252
 
 
253
 
       for (up=&(ctx->usedp); ; up = &((*up)->s.ptr)) {
254
 
          if (!*up)
255
 
             kr_error("kr_free: block not found in used list\n",
256
 
                      (unsigned long) ap, ctx);
257
 
          if (*up == bp) {
258
 
             *up = bp->s.ptr;
259
 
             break;
260
 
          }
261
 
       }
262
 
 
263
 
       /* Join the memory back into the free linked list */
264
 
 
265
 
       for (p=ctx->freep; !(bp > p && bp < p->s.ptr); p = p->s.ptr)
266
 
          if (p >= p->s.ptr && (bp > p || bp < p->s.ptr))
267
 
             break; /* Freed block at start or end of arena */
268
 
 
269
 
       if (bp + bp->s.size == p->s.ptr) {/* join to upper neighbour */
270
 
          bp->s.size += p->s.ptr->s.size;
271
 
          bp->s.ptr = p->s.ptr->s.ptr;
272
 
          ctx->nfrags--;                 /* Lost a fragment */
273
 
       } else
274
 
          bp->s.ptr = p->s.ptr;
275
 
 
276
 
       if (p + p->s.size == bp) { /* Join to lower neighbour */
277
 
          p->s.size += bp->s.size;
278
 
          p->s.ptr = bp->s.ptr;
279
 
          ctx->nfrags--;          /* Lost a fragment */
280
 
       } else
281
 
          p->s.ptr = bp;
282
 
       ctx->freep = p;
283
 
 
284
 
    } /* end if on ap */
285
 
}
286
 
 
287
 
/*
288
 
  Print to standard output the usage statistics.
289
 
*/
290
 
void kr_malloc_print_stats(context_t *ctx) {
291
 
    fflush(stderr);
292
 
    printf("\nkr_malloc statistics\n-------------------\n\n");
293
 
    
294
 
    printf("Total memory from system ... %ld bytes\n", 
295
 
           (long)(ctx->total*ctx->usize));
296
 
    printf("Current memory usage ....... %ld bytes\n", 
297
 
           (long)(ctx->inuse*ctx->usize));
298
 
    printf("Maximum memory usage ....... %ld bytes\n", 
299
 
           (long)(ctx->maxuse*ctx->usize));
300
 
    printf("No. chunks from system ..... %ld\n", ctx->nchunk);
301
 
    printf("No. of fragments ........... %ld\n", ctx->nfrags);
302
 
    printf("No. of calls to kr_malloc ... %ld\n", ctx->nmcalls);
303
 
    printf("No. of calls to kr_free ..... %ld\n", ctx->nfcalls);
304
 
    printf("\n");
305
 
    
306
 
    fflush(stdout);
307
 
}
308
 
 
309
 
/*
310
 
  Currently assumes that are working in a single region.
311
 
*/
312
 
void kr_malloc_verify(context_t *ctx) {
313
 
    Header *p;
314
 
    
315
 
    if(_armci_initialized && lock_mode==UNLOCKED) {
316
 
       LOCKIT(armci_master); lock_mode=LOCKED;
317
 
    }
318
 
 
319
 
    if ( ctx->freep ) {
320
 
      
321
 
      /* Check the used list */
322
 
      
323
 
      for (p=ctx->usedp; p; p=p->s.ptr) {
324
 
        if (p->s.valid1 != VALID1 || p->s.valid2 != VALID2)
325
 
          kr_error("invalid header on usedlist", 
326
 
                   (unsigned long) p->s.valid1, ctx);
327
 
        
328
 
        if (p->s.size > ctx->total)
329
 
          kr_error("invalid size in header on usedlist", 
330
 
                   (unsigned long) p->s.size, ctx);
331
 
      }
332
 
      
333
 
      /* Check the free list */
334
 
      
335
 
      p = ctx->base.s.ptr;
336
 
      while (p != &(ctx->base)) {
337
 
        if (p->s.valid1 != VALID1 || p->s.valid2 != VALID2)
338
 
          kr_error("invalid header on freelist", 
339
 
                   (unsigned long) p->s.valid1, ctx);
340
 
        
341
 
        if (p->s.size > ctx->total)
342
 
          kr_error("invalid size in header on freelist", 
343
 
                   (unsigned long) p->s.size, ctx);
344
 
        
345
 
        p = p->s.ptr;
346
 
      }
347
 
    } /* end if */
348
 
    
349
 
    if(_armci_initialized && lock_mode==LOCKED) {
350
 
       UNLOCKIT(armci_master); lock_mode=UNLOCKED;
351
 
    }
352
 
}
353
 
 
354
 
/********************** BEGIN: kr_malloc for ctx_shmem *********************/
355
 
#if defined(SYSV) || defined(MMAP)
356
 
 
357
 
#include "shmem.h"
358
 
 
359
 
extern int armci_get_shmem_info(char *addrp,  int* shmid, long *shmoffset,
360
 
                                size_t *shmsize);
361
 
extern Header *armci_get_shmem_ptr(int shmid, long shmoffset, size_t shmsize);
362
 
 
363
 
/* returns, address of the shared memory region based on shmid, offset.
364
 
 * (i.e. return_addr = stating address of shmid + offset) */
365
 
#define SHM_PTR(hdr) armci_get_shmem_ptr((hdr)->s.shmid, (hdr)->s.shmoffset, (hdr)->s.shmsize)
366
 
 
367
 
/*
368
 
 * kr_malloc_shmem: memory allocator for shmem context (i.e ctx_shmem)
369
 
 */
370
 
static char *kr_malloc_shmem(size_t nbytes, context_t *ctx) {
371
 
    Header *p, *prevp;
372
 
    size_t nunits, prev_shmsize=0;
373
 
    char *return_ptr;
374
 
    int prev_shmid=-1;
375
 
    long prev_shmoffset=0;
376
 
 
377
 
    LOCKIT(armci_master);
378
 
 
379
 
    /* Rather than divide make the alignment a known power of 2 */
380
 
    nunits = ((nbytes + sizeof(Header) - 1)>>LOG_ALIGN) + 1;
381
 
    
382
 
    /* If first time in need to initialize the free list */ 
383
 
    if ((prevp = ctx->freep) == NULL) { 
384
 
      
385
 
      if (sizeof(Header) != ALIGNMENT)
386
 
        kr_error("kr_malloc_shmem: Alignment is not valid",
387
 
                 (unsigned long) ALIGNMENT, ctx);
388
 
      
389
 
      ctx->total  = 0; /* Initialize statistics */
390
 
      ctx->nchunk = ctx->inuse   = ctx->maxuse  = 0;  
391
 
      ctx->nfrags = ctx->nmcalls = ctx->nfcalls = 0;
392
 
      
393
 
      /* Initialize linked list */
394
 
      ctx->base.s.size = 0;
395
 
      ctx->base.s.shmid     = -1;
396
 
      ctx->base.s.shmoffset = 0;
397
 
      ctx->base.s.shmsize   = 0;
398
 
      ctx->base.s.valid1 = VALID1;
399
 
      ctx->base.s.valid2 = VALID2;
400
 
      if ((p = morecore(nunits, ctx)) == (Header *) NULL) return NULL;
401
 
      ctx->base.s.ptr = prevp = ctx->freep; /* CHECK */
402
 
    }
403
 
 
404
 
    prev_shmid     = ctx->shmid;
405
 
    prev_shmoffset = ctx->shmoffset;
406
 
    prev_shmsize   = ctx->shmsize;
407
 
    prevp = ctx->freep = armci_get_shmem_ptr(ctx->shmid, ctx->shmoffset,
408
 
                                             ctx->shmsize);
409
 
 
410
 
    ctx->nmcalls++;
411
 
    
412
 
    if (do_verify)  kr_malloc_verify(ctx);
413
 
    
414
 
    for (p=SHM_PTR(prevp); ; prevp = p, p = SHM_PTR(p)) {
415
 
 
416
 
      if (p->s.size >= nunits) {        /* Big enuf */
417
 
        if (p->s.size == nunits) {      /* exact fit */
418
 
          prevp->s.ptr = p->s.ptr;
419
 
          prevp->s.shmid     = p->s.shmid;
420
 
          prevp->s.shmoffset = p->s.shmoffset;
421
 
          prevp->s.shmsize   = p->s.shmsize;
422
 
        }
423
 
        else {                  /* allocate tail end */
424
 
           p->s.size -= nunits;
425
 
           p += p->s.size;
426
 
           p->s.size = nunits;
427
 
           p->s.valid1 = VALID1;
428
 
           p->s.valid2 = VALID2;
429
 
           ctx->nfrags++;  /* Have just increased the fragmentation */
430
 
        }
431
 
#if USEDP
432
 
        /* Insert into linked list of blocks in use ... for debug only */
433
 
        p->s.ptr = ctx->usedp;
434
 
        ctx->usedp = p;
435
 
#endif
436
 
        
437
 
        ctx->inuse += nunits;  /* Record usage */
438
 
        if (ctx->inuse > ctx->maxuse)
439
 
          ctx->maxuse = ctx->inuse;
440
 
        ctx->freep = prevp;
441
 
        ctx->shmid     = prev_shmid;
442
 
        ctx->shmoffset = prev_shmoffset;
443
 
        ctx->shmsize   = prev_shmsize;
444
 
        return_ptr = (char *) (p+1);
445
 
        break;
446
 
      }
447
 
 
448
 
      prev_shmid     = prevp->s.shmid;
449
 
      prev_shmoffset = prevp->s.shmoffset;
450
 
      prev_shmsize   = prevp->s.shmsize;
451
 
      
452
 
      if (p == ctx->freep)      {       /* wrapped around the free list */
453
 
        if ((p = morecore(nunits, ctx)) == (Header *) NULL) {
454
 
          return_ptr = (char *) NULL;
455
 
          break;
456
 
        }
457
 
        prev_shmid     = ctx->shmid;
458
 
        prev_shmoffset = ctx->shmoffset;
459
 
        prev_shmsize   = ctx->shmsize;
460
 
      }
461
 
    }
462
 
    
463
 
    UNLOCKIT(armci_master);
464
 
    return return_ptr;    
465
 
}
466
 
 
467
 
 
468
 
static void kr_free_shmem(char *ap, context_t *ctx) {
469
 
    Header *bp, *p, *nextp;
470
 
#if USEDP
471
 
    Header **up;
472
 
#endif
473
 
    int shmid=-1;
474
 
    long shmoffset=0;
475
 
    size_t shmsize=0;
476
 
 
477
 
    LOCKIT(armci_master);
478
 
    
479
 
    ctx->nfcalls++;
480
 
    
481
 
    if (do_verify)
482
 
      kr_malloc_verify(ctx);
483
 
    
484
 
    /* only do something if pointer is not NULL */
485
 
    
486
 
    if ( ap ) {
487
 
      
488
 
      bp = (Header *) ap - 1;  /* Point to block header */
489
 
      
490
 
      if (bp->s.valid1 != VALID1 || bp->s.valid2 != VALID2)
491
 
        kr_error("kr_free_shmem: pointer not from kr_malloc", 
492
 
                 (unsigned long) ap, ctx);
493
 
      
494
 
      ctx->inuse -= bp->s.size; /* Decrement memory ctx->usage */
495
 
      
496
 
#if USEDP
497
 
      /* Extract the block from the used linked list
498
 
         ... for debug only */
499
 
      
500
 
      for (up=&(ctx->usedp); ; up = &((*up)->s.ptr)) {
501
 
        if (!*up)
502
 
          kr_error("kr_free_shmem: block not found in used list\n", 
503
 
                   (unsigned long) ap, ctx);
504
 
        if (*up == bp) {
505
 
          *up = bp->s.ptr;
506
 
          break;
507
 
        }
508
 
      }
509
 
#endif
510
 
 
511
 
      if(ctx->shmid==-1) { 
512
 
         armci_get_shmem_info((char*)bp, &ctx->shmid, &ctx->shmoffset,
513
 
                              &ctx->shmsize);
514
 
 
515
 
         ctx->base.s.shmid     = ctx->shmid;
516
 
         ctx->base.s.shmsize   = ctx->shmsize;
517
 
         ctx->base.s.shmoffset = ctx->shmoffset;
518
 
 
519
 
         p = ctx->freep = bp;
520
 
         p->s.ptr  = bp;
521
 
         p->s.size-=SHMEM_CTX_UNITS; /*memory to store shmem info in context*/
522
 
         p->s.shmid     = ctx->shmid;
523
 
         p->s.shmsize   = ctx->shmsize;
524
 
         p->s.shmoffset = ctx->shmoffset;
525
 
         
526
 
         UNLOCKIT(armci_master);
527
 
         return;
528
 
      }
529
 
 
530
 
      ctx->freep = armci_get_shmem_ptr(ctx->shmid, ctx->shmoffset,
531
 
                                       ctx->shmsize);
532
 
 
533
 
      shmid     = ctx->shmid;
534
 
      shmoffset = ctx->shmoffset;
535
 
      shmsize   = ctx->shmsize;
536
 
 
537
 
      /* Join the memory back into the free linked list */
538
 
      p = ctx->freep;
539
 
      nextp = SHM_PTR(p);
540
 
 
541
 
      for ( ; !(bp > p && bp < nextp); p=nextp, nextp=SHM_PTR(p)) {
542
 
         if (p >= nextp && (bp > p || bp < nextp))
543
 
            break; /* Freed block at start or end of arena */
544
 
         nextp = SHM_PTR(p);
545
 
         shmid     = p->s.shmid;
546
 
         shmoffset = p->s.shmoffset;
547
 
         shmsize   = p->s.shmsize;
548
 
      }
549
 
 
550
 
      if (bp + bp->s.size == nextp) {/* join to upper neighbour */
551
 
        bp->s.size += nextp->s.size;
552
 
        bp->s.ptr = nextp->s.ptr;
553
 
        ctx->nfrags--;                 /* Lost a fragment */
554
 
        bp->s.shmid     = nextp->s.shmid;
555
 
        bp->s.shmoffset = nextp->s.shmoffset;
556
 
        bp->s.shmsize   = nextp->s.shmsize;        
557
 
      } else {
558
 
         bp->s.ptr = nextp;
559
 
         bp->s.shmid     = p->s.shmid;
560
 
         bp->s.shmoffset = p->s.shmoffset;
561
 
         bp->s.shmsize   = p->s.shmsize;
562
 
      }
563
 
 
564
 
      if (p + p->s.size == bp) { /* Join to lower neighbour */
565
 
         p->s.size += bp->s.size;
566
 
         p->s.ptr = bp->s.ptr;
567
 
         ctx->nfrags--;          /* Lost a fragment */
568
 
         p->s.shmid     = bp->s.shmid;
569
 
         p->s.shmoffset = bp->s.shmoffset;
570
 
         p->s.shmsize   = bp->s.shmsize;
571
 
      } else {
572
 
         p->s.ptr = bp;
573
 
         armci_get_shmem_info((char*)bp, &p->s.shmid, &p->s.shmoffset,
574
 
                              &p->s.shmsize);
575
 
      }
576
 
      
577
 
      ctx->freep = p;
578
 
      ctx->shmid     = shmid;
579
 
      ctx->shmoffset = shmoffset;
580
 
      ctx->shmsize   = shmsize;
581
 
    } /* end if on ap */
582
 
    
583
 
    UNLOCKIT(armci_master);
584
 
}
585
 
#else /* #ifdef SYSV */
586
 
/* What are doing here */
587
 
static char *kr_malloc_shmem(size_t nbytes, context_t *ctx) 
588
 
{
589
 
    armci_die("kr_malloc_shmem(): Invalid Function Call", 0L);
590
 
}
591
 
static void kr_free_shmem(char *ap, context_t *ctx) 
592
 
{
593
 
    armci_die("kr_free_shmem(): Invalid Function Call", 0L);
594
 
}
595
 
#endif /* #ifdef SYSV */
596
 
/********************** END: kr_malloc for ctx_shmem *********************/
597
 
 
598
 
 
599
 
/**
600
 
issues:
601
 
1. do usage statistics only if debug/DEBUG is enabled 
602
 
*/