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

« back to all changes in this revision

Viewing changes to src/tools/ga-5-2/armci/src-portals/bufalloc.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: bufalloc.c,v 1.2 2001-06-07 23:23:23 d3h325 Exp $ 
 
6
 * storage manager for a chunk of memory passed by user in armci_init_buf_alloc
 
7
 * derived from K&R that manages a chunk of memory
 
8
 */
 
9
 
 
10
#include <stdio.h>
 
11
 
 
12
#define USAGE_ 
 
13
 
 
14
extern char *buf_allocate(); /* Used to get memory from the system */
 
15
extern void armci_die();
 
16
 
 
17
#define VALID1  0xaaaaaaaa      /* For validity check on headers */
 
18
#define VALID2  0x55555555
 
19
#define LOG_ALIGN 6
 
20
#define ALIGNMENT (1 << LOG_ALIGN)
 
21
#define DEFAULT_NALLOC (1024 - ALIGNMENT)
 
22
 
 
23
#ifdef USAGE
 
24
static struct shmalloc_struct {
 
25
  size_t total;                 /* Amount request from system in units */
 
26
  long nchunk;                  /* No. of chunks of system memory */
 
27
  long inuse;                   /* Amount in use in units */
 
28
  long maxuse;                  /* Maximum value of inuse */
 
29
  long nfrags;                  /* No. of fragments divided into */
 
30
  long nmcalls;                 /* No. of calls to shmalloc */
 
31
  long nfcalls;                 /* No. of calls to buf_free */
 
32
} usage;
 
33
#endif
 
34
 
 
35
union header{
 
36
  struct {
 
37
    unsigned valid1;            /* Token to check if is not overwritten */
 
38
    union header *ptr;          /* next block if on free list */
 
39
    size_t size;                /* size of this block*/
 
40
    unsigned valid2;            /* Another token acting as a guard */
 
41
  } s;
 
42
  char align[ALIGNMENT];        /* Align to ALIGNMENT byte boundary */
 
43
};
 
44
typedef union header Header;
 
45
 
 
46
static Header base;             /* empty list to get started */
 
47
static Header *freep = NULL;    /* start of free list */
 
48
static Header *usedp = NULL;    /* start of used list */
 
49
static size_t nalloc = DEFAULT_NALLOC;
 
50
static size_t max_nalloc = DEFAULT_NALLOC;
 
51
static int do_verify = 0;       /* Flag for automatic heap verification */
 
52
static int initialized=0;
 
53
 
 
54
 
 
55
static void buf_error(char* s, unsigned long i)
 
56
{
 
57
  void buf_alloc_print_stats();
 
58
  fflush(stdout);
 
59
  fprintf(stderr,"buf_alloc error: %s %ld(0x%lx)\n", s, i, i);
 
60
  fflush(stderr);
 
61
#ifdef USAGE
 
62
  buf_alloc_print_stats();
 
63
#endif
 
64
  armci_die("buf_alloc: fatal error", i);
 
65
}
 
66
 
 
67
void armci_buf_alloc_request(size_t size, size_t maxsize)
 
68
{
 
69
  nalloc = (size+ALIGNMENT-1) >> LOG_ALIGN;
 
70
  max_nalloc = (maxsize+ALIGNMENT-1) >> LOG_ALIGN;
 
71
}
 
72
 
 
73
void armci_buf_alloc_debug(int code)
 
74
{
 
75
  do_verify = code;
 
76
}
 
77
 
 
78
 
 
79
void armci_buf_alloc_verify()
 
80
{
 
81
  Header *p;
 
82
 
 
83
  if ( freep ) {
 
84
 
 
85
    /* Check the used list */
 
86
    for (p=usedp; p; p=p->s.ptr) {
 
87
      if (p->s.valid1 != VALID1 || p->s.valid2 != VALID2)
 
88
        buf_error("invalid header on usedlist", (unsigned long) p->s.valid1);
 
89
 
 
90
#ifdef USAGE
 
91
      if (p->s.size > usage.total)
 
92
        buf_error("invalid size in header usedlist",(unsigned long)p->s.size);
 
93
#endif
 
94
    }
 
95
 
 
96
    /* Check the free list */
 
97
    p = base.s.ptr;
 
98
    while (p != &base) {
 
99
      if (p->s.valid1 != VALID1 || p->s.valid2 != VALID2)
 
100
        buf_error("invalid header on freelist", (unsigned long) p->s.valid1);
 
101
 
 
102
#ifdef USAGE
 
103
      if (p->s.size > usage.total)
 
104
        buf_error("invalid size in header freelist",(unsigned long)p->s.size);
 
105
#endif
 
106
 
 
107
      p = p->s.ptr;
 
108
    }
 
109
  } /* end if */
 
110
}
 
111
 
 
112
 
 
113
static void addtofree(char* ap)
 
114
{
 
115
  Header *bp, *p, **up;
 
116
 
 
117
#ifdef USAGE
 
118
  usage.nfcalls++;
 
119
#endif
 
120
  if (do_verify) armci_buf_alloc_verify();
 
121
 
 
122
  /* only do something if pointer is not NULL */
 
123
  if ( ap ) {
 
124
 
 
125
     bp = (Header *) ap - 1;  /* Point to block header */
 
126
 
 
127
     if (bp->s.valid1 != VALID1 || bp->s.valid2 != VALID2)
 
128
       buf_error("buf_free: pointer not from buf_alloc", (unsigned long) ap);
 
129
 
 
130
#ifdef USAGE
 
131
     usage.inuse -= bp->s.size; /* Decrement memory usage */
 
132
#endif
 
133
 
 
134
     /* Extract the block from the used linked list ... for debug only */
 
135
     for (up=&usedp; ; up = &((*up)->s.ptr)) {
 
136
       if (!*up)
 
137
         buf_error("buf_free:block not found in used list\n",(unsigned long)ap);
 
138
       if (*up == bp) {
 
139
         *up = bp->s.ptr;
 
140
         break;
 
141
       }
 
142
     }
 
143
 
 
144
     /* Join the memory back into the free linked list */
 
145
     for (p=freep; !(bp > p && bp < p->s.ptr); p = p->s.ptr)
 
146
       if (p >= p->s.ptr && (bp > p || bp < p->s.ptr))
 
147
         break; /* Freed block at start or end of arena */
 
148
 
 
149
     if (bp + bp->s.size == p->s.ptr) {/* join to upper neighbour */
 
150
       bp->s.size += p->s.ptr->s.size;
 
151
       bp->s.ptr = p->s.ptr->s.ptr;
 
152
#ifdef USAGE
 
153
       usage.nfrags--;                 /* Lost a fragment */
 
154
#endif
 
155
     } else
 
156
       bp->s.ptr = p->s.ptr;
 
157
 
 
158
     if (p + p->s.size == bp) { /* Join to lower neighbour */
 
159
       p->s.size += bp->s.size;
 
160
       p->s.ptr = bp->s.ptr;
 
161
#ifdef USAGE
 
162
       usage.nfrags--;          /* Lost a fragment */
 
163
#endif
 
164
     } else
 
165
       p->s.ptr = bp;
 
166
 
 
167
     freep = p;
 
168
 
 
169
   } /* end if on ap */
 
170
}
 
171
 
 
172
 
 
173
void armci_init_buf_alloc(size_t len, void* buffer)
 
174
{
 
175
  char *cp;
 
176
  Header *up, *prevp;
 
177
  size_t nu;
 
178
  /* need to initialize the free list */
 
179
    if (sizeof(Header) != ALIGNMENT)
 
180
      buf_error("Alignment is not valid", (unsigned long) ALIGNMENT);
 
181
 
 
182
  if(initialized)armci_die("armci_init_buf_alloc: already initialized",0);
 
183
 
 
184
#ifdef USAGE
 
185
    usage.total  = 0;  /* Initialize statistics */
 
186
    usage.nchunk = 0;
 
187
    usage.inuse  = 0;
 
188
    usage.nfrags = 0;
 
189
    usage.maxuse = 0;
 
190
    usage.nmcalls= 0;
 
191
    usage.nfcalls= 0;
 
192
#endif
 
193
 
 
194
    base.s.ptr = freep = prevp = &base;  /* Initialize linked list */
 
195
    base.s.size = 0;
 
196
    base.s.valid1 = VALID1;
 
197
    base.s.valid2 = VALID2;
 
198
 
 
199
  nu = len/sizeof(Header); /* nu must by a multiplicity of nalloc */
 
200
  max_nalloc = nu*nalloc;
 
201
  if(nu<1) armci_die("buffer less than nalloc",(int)len);
 
202
  cp = (char*)buffer;
 
203
 
 
204
#ifdef USAGE
 
205
  usage.total += nu;   /* Have just got nu more units */
 
206
  usage.nchunk++;      /* One more chunk */
 
207
  usage.nfrags++;      /* Currently one more frag */
 
208
  usage.inuse += nu;   /* Inuse will be decremented by buf_free */
 
209
#endif
 
210
 
 
211
  up = (Header *) cp;
 
212
  up->s.size = nu;
 
213
  up->s.valid1 = VALID1;
 
214
  up->s.valid2 = VALID2;
 
215
 
 
216
  /* Insert into linked list of blocks in use so that buf_free works 
 
217
     ...  for debug only */
 
218
  up->s.ptr = usedp;
 
219
  usedp = up;
 
220
 
 
221
  addtofree((char *)(up+1));  /* Try to join into the free list */
 
222
}
 
223
 
 
224
 
 
225
/*\ return a chunk memory of given size
 
226
\*/
 
227
char *armci_buf_alloc(size_t nbytes)
 
228
{
 
229
  Header *p, *prevp;
 
230
  size_t nunits;
 
231
  char *return_ptr;
 
232
 
 
233
  /* need to initialize the free list */ 
 
234
  if ((prevp = freep) == NULL)  armci_die("not initialized", 0);
 
235
    
 
236
#ifdef USAGE
 
237
  usage.nmcalls++;
 
238
#endif
 
239
  
 
240
  if (do_verify) armci_buf_alloc_verify();
 
241
  
 
242
  /* Rather than divide make the alignment a known power of 2 */
 
243
  nunits = ((nbytes + sizeof(Header) - 1)>>LOG_ALIGN) + 1;
 
244
 
 
245
  for (p=prevp->s.ptr; ; prevp = p, p = p->s.ptr) {
 
246
    if (p->s.size >= nunits) {  /* Big enuf */
 
247
      if (p->s.size == nunits)  /* exact fit */
 
248
        prevp->s.ptr = p->s.ptr;
 
249
      else {                    /* allocate tail end */
 
250
        p->s.size -= nunits;
 
251
        p += p->s.size;
 
252
        p->s.size = nunits;
 
253
        p->s.valid1 = VALID1;
 
254
        p->s.valid2 = VALID2;
 
255
#ifdef USAGE
 
256
        usage.nfrags++;  /* Have just increased the fragmentation */
 
257
#endif
 
258
      }
 
259
 
 
260
      /* Insert into linked list of blocks in use ... for debug only */
 
261
      p->s.ptr = usedp;
 
262
      usedp = p;
 
263
 
 
264
#ifdef USAGE
 
265
      usage.inuse += nunits;  /* Record usage */
 
266
      if (usage.inuse > usage.maxuse)
 
267
        usage.maxuse = usage.inuse;
 
268
#endif
 
269
      freep = prevp;
 
270
      return_ptr = (char *) (p+1);
 
271
      break;
 
272
    }
 
273
    
 
274
    if (p == freep){            /* wrapped around the free list */
 
275
        return_ptr = (char *) NULL;
 
276
        break;
 
277
    }
 
278
  }
 
279
  return return_ptr;
 
280
}
 
281
 
 
282
 
 
283
void armci_buf_free(char *ap)
 
284
{
 
285
  Header *bp, *p, **up;
 
286
#ifdef USAGE
 
287
  usage.nfcalls++;
 
288
#endif
 
289
  if (do_verify) armci_buf_alloc_verify();
 
290
 
 
291
 /* only do something if pointer is not NULL */
 
292
 
 
293
  if ( ap ) {
 
294
 
 
295
      bp = (Header *) ap - 1;  /* Point to block header */
 
296
 
 
297
      if (bp->s.valid1 != VALID1 || bp->s.valid2 != VALID2)
 
298
        buf_error("buf_free: pointer not from buf_alloc", (unsigned long) ap);
 
299
  
 
300
#ifdef USAGE
 
301
      usage.inuse -= bp->s.size; /* Decrement memory usage */
 
302
#endif
 
303
 
 
304
      /* Extract the block from the used linked list for debug only */
 
305
      for (up=&usedp; ; up = &((*up)->s.ptr)) {
 
306
        if (!*up)
 
307
          buf_error("buf_free:block not found in used list\n",(unsigned long)ap);
 
308
        if (*up == bp) {
 
309
          *up = bp->s.ptr;
 
310
          break;
 
311
        }
 
312
      }
 
313
 
 
314
      /* Join the memory back into the free linked list */
 
315
      for (p=freep; !(bp > p && bp < p->s.ptr); p = p->s.ptr)
 
316
        if (p >= p->s.ptr && (bp > p || bp < p->s.ptr))
 
317
                          break; /* Freed block at start or end of arena */
 
318
 
 
319
      if (bp + bp->s.size == p->s.ptr) {/* join to upper neighbour */
 
320
                    bp->s.size += p->s.ptr->s.size;
 
321
                    bp->s.ptr = p->s.ptr->s.ptr;
 
322
#ifdef USAGE
 
323
                    usage.nfrags--;                 /* Lost a fragment */
 
324
#endif
 
325
      } else
 
326
                    bp->s.ptr = p->s.ptr;
 
327
 
 
328
      if (p + p->s.size == bp) { /* Join to lower neighbour */
 
329
                    p->s.size += bp->s.size;
 
330
                    p->s.ptr = bp->s.ptr;
 
331
#ifdef USAGE
 
332
                    usage.nfrags--;          /* Lost a fragment */
 
333
#endif
 
334
      } else
 
335
                    p->s.ptr = bp;
 
336
 
 
337
      freep = p;
 
338
 
 
339
    } /* end if on ap */
 
340
}
 
341
 
 
342
 
 
343
#ifdef USAGE
 
344
/*
 
345
  Return stats on buf_alloc performance. Use arg list instead of
 
346
  returning structure so that FORTRAN can eventually use it
 
347
*/
 
348
void buf_alloc_stats(size_t *total, long* nchunk, size_t * inuse,
 
349
                     size_t * maxuse, long* nfrags, long* nmcalls,long* nfcalls)
 
350
{
 
351
  *total  = usage.total * sizeof(Header);
 
352
  *nchunk = usage.nchunk;
 
353
  *inuse  = (size_t)usage.inuse * sizeof(Header);
 
354
  *maxuse = (size_t)usage.maxuse* sizeof(Header);
 
355
  *nfrags = usage.nfrags;
 
356
  *nmcalls= usage.nmcalls;
 
357
  *nfcalls= usage.nfcalls;
 
358
}
 
359
 
 
360
/*
 
361
  Print to standard output the usage statistics.
 
362
*/
 
363
void buf_alloc_print_stats()
 
364
{
 
365
  size_t total, inuse, maxuse;
 
366
  long nchunk, nfrags, nmcalls, nfcalls;
 
367
 
 
368
  buf_alloc_stats(&total, &nchunk, &inuse, &maxuse, &nfrags,
 
369
                 &nmcalls, &nfcalls);
 
370
 
 
371
  fflush(stderr);
 
372
  printf("\nbuf_alloc statistics\n-------------------\n\n");
 
373
  printf("Total memory from system ... %ld bytes\n", (long)total);
 
374
  printf("Current memory usage ....... %ld bytes\n", (long)inuse);
 
375
  printf("Maximum memory usage ....... %ld bytes\n", (long)maxuse);
 
376
  printf("No. chunks from system ..... %ld\n", nchunk);
 
377
  printf("No. of fragments ........... %ld\n", nfrags);
 
378
  printf("No. of calls to buf_alloc ... %ld\n", nmcalls);
 
379
  printf("No. of calls to buf_free ..... %ld\n", nfcalls);
 
380
  printf("\n");
 
381
  fflush(stdout);
 
382
}
 
383
#endif
 
384
 
 
385
 
 
386
#if 0
 
387
void armci_die(char *str, int c)
 
388
{
 
389
fprintf(stderr,"%s %d\n",str,c);
 
390
_exit(1);
 
391
}
 
392
 
 
393
 
 
394
#define LEN (16*1024)
 
395
char buf[LEN];
 
396
 
 
397
main (int argc, char **argv)
 
398
{
 
399
int i,k,total=0,size=1024;
 
400
char *ar[100];
 
401
    armci_init_buf_alloc(LEN, buf);
 
402
    
 
403
    for(i=0; i<100; i++)ar[i]=(char*)0;
 
404
 
 
405
    for(i=0; i<100; i++){
 
406
     ar[i] =armci_buf_alloc(size);
 
407
     if(!ar[i]){
 
408
        printf("i =%d total=%d\n", i, total);
 
409
        buf_alloc_print_stats(); 
 
410
        k=i;
 
411
        break;
 
412
     }
 
413
     total+=size;
 
414
    }
 
415
    for(i=0; i<k/2; i++){
 
416
      armci_buf_free(ar[i]);
 
417
      ar[i]=(char*)0;
 
418
    } 
 
419
 
 
420
    printf("relased %d blocks\n",k/2);
 
421
    buf_alloc_print_stats(); 
 
422
    size *=2;
 
423
    for(i=k; i<100; i++){
 
424
     ar[i] =armci_buf_alloc(size);
 
425
     if(!ar[i]){
 
426
        printf("i =%d total=%d\n", i, total);
 
427
        buf_alloc_print_stats(); 
 
428
        break;
 
429
     }
 
430
    }
 
431
    for(i=0; i<100; i++) if(ar[i])armci_buf_free(ar[i]);
 
432
    printf("relased all blocks\n");
 
433
    buf_alloc_print_stats(); 
 
434
}
 
435
#endif
 
436