5
/* $Id: kr_malloc.c,v 1.24 2006-09-12 23:21:21 andriy Exp $ */
10
#include "armcip.h" /* for DEBUG purpose only. remove later */
15
/* Storage allocator basically copied from ANSI K&R and corrupted */
17
extern char *armci_allocate(); /* Used to get memory from the system */
18
#if !defined(armci_die)
19
extern void armci_die();
21
static char *kr_malloc_shmem(size_t nbytes, context_t *ctx);
22
static void kr_free_shmem(char *ap, context_t *ctx);
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)
30
#define DEFAULT_NALLOC (4*128*1024)
31
#define DEFAULT_NALLOC_ALIGN 1024
32
#define DEFAULT_MAX_NALLOC (4*1024*1024*16)
34
/* mutual exclusion defs go here */
37
static int lock_mode=UNLOCKED;
39
/* enable locking only after armci is initailized as locks (and lock
40
data structures) are initialized in PARMCI_Init */
42
if(_armci_initialized && lock_mode==UNLOCKED) { \
43
NAT_LOCK(0,p); lock_mode=LOCKED; \
46
if(_armci_initialized && lock_mode==LOCKED) { \
47
NAT_UNLOCK(0,p); lock_mode=UNLOCKED; \
50
static int do_verify = 0; /* Flag for automatic heap verification */
52
#define VALID1 0xaaaaaaaa /* For validity check on headers */
53
#define VALID2 0x55555555
55
#define USEDP 0 /* CHECK. By default anable this. */
57
static void kr_error(char *s, unsigned long i, context_t *ctx) {
59
sprintf(string,"kr_malloc: %s %ld(0x%lx)\n", s, i, i);
61
kr_malloc_print_stats(ctx);
66
static Header *morecore(size_t nu, context_t *ctx) {
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);
75
if (ctx->total >= ctx->max_nalloc) {
77
armci_die("kr_malloc: morecore: maximum allocation reached",armci_me);
79
return (Header *) NULL; /* Enforce upper limit on core usage */
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;
87
nu = ctx->nalloc*((nu-1)/ctx->nalloc+1); /* nu must by a multiplicity of nalloc */
91
(void) printf("%d: morecore: Getting %ld more units of length %d\n",
92
armci_me, (long)nu, sizeof(Header));
93
(void) fflush(stdout);
96
if ((cp =(char *)(*ctx->alloc_fptr)((size_t)nu * sizeof(Header))) == (char *)NULL)
97
return (Header *) NULL;
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 */
106
up->s.valid1 = VALID1;
107
up->s.valid2 = VALID2;
109
/* Insert into linked list of blocks in use so that kr_free works
110
... for debug only */
111
up->s.ptr = ctx->usedp;
114
kr_free((char *)(up+1), ctx); /* Try to join into the free list */
118
void kr_malloc_init(size_t usize, /* unit size in bytes */
121
void * (*alloc_fptr)(), /* memory alloc routine */
126
if(usize <= 0) usize = sizeof(Header);
128
scale = usize>>LOG_ALIGN;
129
if(scale<1)fprintf(stderr,"Error: kr_malloc_init !!!\n");
131
if(nalloc==0) nalloc = DEFAULT_NALLOC;
132
if(max_nalloc==0) max_nalloc = DEFAULT_MAX_NALLOC;
134
ctx->usize = sizeof(Header);
135
ctx->nalloc = nalloc * scale;
136
ctx->max_nalloc = max_nalloc * scale;
137
ctx->alloc_fptr = alloc_fptr;
148
char *kr_malloc(size_t nbytes, context_t *ctx) {
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);
157
/* If first time in need to initialize the free list */
158
if ((prevp = ctx->freep) == NULL) {
160
if (sizeof(Header) != ALIGNMENT)
161
kr_error("Alignment is not valid", (unsigned long) ALIGNMENT, ctx);
163
ctx->total = 0; /* Initialize statistics */
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;
180
kr_malloc_verify(ctx);
182
/* Rather than divide make the alignment a known power of 2 */
184
nunits = ((nbytes + sizeof(Header) - 1)>>LOG_ALIGN) + 1;
186
for (p=prevp->s.ptr; ; prevp = p, p = p->s.ptr) {
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 */
195
p->s.valid1 = VALID1;
196
p->s.valid2 = VALID2;
197
ctx->nfrags++; /* Have just increased the fragmentation */
200
/* Insert into linked list of blocks in use ... for debug only */
201
p->s.ptr = ctx->usedp;
204
ctx->inuse += nunits; /* Record usage */
205
if (ctx->inuse > ctx->maxuse)
206
ctx->maxuse = ctx->inuse;
208
return_ptr = (char *) (p+1);
212
if (p == ctx->freep) { /* wrapped around the free list */
213
if ((p = morecore(nunits, ctx)) == (Header *) NULL) {
214
return_ptr = (char *) NULL;
225
void kr_free(char *ap, context_t *ctx) {
226
Header *bp, *p, **up;
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; }
236
kr_malloc_verify(ctx);
238
/* only do something if pointer is not NULL */
242
bp = (Header *) ap - 1; /* Point to block header */
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);
248
ctx->inuse -= bp->s.size; /* Decrement memory ctx->usage */
250
/* Extract the block from the used linked list
251
... for debug only */
253
for (up=&(ctx->usedp); ; up = &((*up)->s.ptr)) {
255
kr_error("kr_free: block not found in used list\n",
256
(unsigned long) ap, ctx);
263
/* Join the memory back into the free linked list */
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 */
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 */
274
bp->s.ptr = p->s.ptr;
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 */
288
Print to standard output the usage statistics.
290
void kr_malloc_print_stats(context_t *ctx) {
292
printf("\nkr_malloc statistics\n-------------------\n\n");
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);
310
Currently assumes that are working in a single region.
312
void kr_malloc_verify(context_t *ctx) {
315
if(_armci_initialized && lock_mode==UNLOCKED) {
316
LOCKIT(armci_master); lock_mode=LOCKED;
321
/* Check the used list */
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);
328
if (p->s.size > ctx->total)
329
kr_error("invalid size in header on usedlist",
330
(unsigned long) p->s.size, ctx);
333
/* Check the free list */
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);
341
if (p->s.size > ctx->total)
342
kr_error("invalid size in header on freelist",
343
(unsigned long) p->s.size, ctx);
349
if(_armci_initialized && lock_mode==LOCKED) {
350
UNLOCKIT(armci_master); lock_mode=UNLOCKED;
354
/********************** BEGIN: kr_malloc for ctx_shmem *********************/
355
#if defined(SYSV) || defined(MMAP)
359
extern int armci_get_shmem_info(char *addrp, int* shmid, long *shmoffset,
361
extern Header *armci_get_shmem_ptr(int shmid, long shmoffset, size_t shmsize);
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)
368
* kr_malloc_shmem: memory allocator for shmem context (i.e ctx_shmem)
370
static char *kr_malloc_shmem(size_t nbytes, context_t *ctx) {
372
size_t nunits, prev_shmsize=0;
375
long prev_shmoffset=0;
377
LOCKIT(armci_master);
379
/* Rather than divide make the alignment a known power of 2 */
380
nunits = ((nbytes + sizeof(Header) - 1)>>LOG_ALIGN) + 1;
382
/* If first time in need to initialize the free list */
383
if ((prevp = ctx->freep) == NULL) {
385
if (sizeof(Header) != ALIGNMENT)
386
kr_error("kr_malloc_shmem: Alignment is not valid",
387
(unsigned long) ALIGNMENT, ctx);
389
ctx->total = 0; /* Initialize statistics */
390
ctx->nchunk = ctx->inuse = ctx->maxuse = 0;
391
ctx->nfrags = ctx->nmcalls = ctx->nfcalls = 0;
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 */
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,
412
if (do_verify) kr_malloc_verify(ctx);
414
for (p=SHM_PTR(prevp); ; prevp = p, p = SHM_PTR(p)) {
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;
423
else { /* allocate tail end */
427
p->s.valid1 = VALID1;
428
p->s.valid2 = VALID2;
429
ctx->nfrags++; /* Have just increased the fragmentation */
432
/* Insert into linked list of blocks in use ... for debug only */
433
p->s.ptr = ctx->usedp;
437
ctx->inuse += nunits; /* Record usage */
438
if (ctx->inuse > ctx->maxuse)
439
ctx->maxuse = ctx->inuse;
441
ctx->shmid = prev_shmid;
442
ctx->shmoffset = prev_shmoffset;
443
ctx->shmsize = prev_shmsize;
444
return_ptr = (char *) (p+1);
448
prev_shmid = prevp->s.shmid;
449
prev_shmoffset = prevp->s.shmoffset;
450
prev_shmsize = prevp->s.shmsize;
452
if (p == ctx->freep) { /* wrapped around the free list */
453
if ((p = morecore(nunits, ctx)) == (Header *) NULL) {
454
return_ptr = (char *) NULL;
457
prev_shmid = ctx->shmid;
458
prev_shmoffset = ctx->shmoffset;
459
prev_shmsize = ctx->shmsize;
463
UNLOCKIT(armci_master);
468
static void kr_free_shmem(char *ap, context_t *ctx) {
469
Header *bp, *p, *nextp;
477
LOCKIT(armci_master);
482
kr_malloc_verify(ctx);
484
/* only do something if pointer is not NULL */
488
bp = (Header *) ap - 1; /* Point to block header */
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);
494
ctx->inuse -= bp->s.size; /* Decrement memory ctx->usage */
497
/* Extract the block from the used linked list
498
... for debug only */
500
for (up=&(ctx->usedp); ; up = &((*up)->s.ptr)) {
502
kr_error("kr_free_shmem: block not found in used list\n",
503
(unsigned long) ap, ctx);
512
armci_get_shmem_info((char*)bp, &ctx->shmid, &ctx->shmoffset,
515
ctx->base.s.shmid = ctx->shmid;
516
ctx->base.s.shmsize = ctx->shmsize;
517
ctx->base.s.shmoffset = ctx->shmoffset;
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;
526
UNLOCKIT(armci_master);
530
ctx->freep = armci_get_shmem_ptr(ctx->shmid, ctx->shmoffset,
534
shmoffset = ctx->shmoffset;
535
shmsize = ctx->shmsize;
537
/* Join the memory back into the free linked list */
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 */
546
shmoffset = p->s.shmoffset;
547
shmsize = p->s.shmsize;
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;
559
bp->s.shmid = p->s.shmid;
560
bp->s.shmoffset = p->s.shmoffset;
561
bp->s.shmsize = p->s.shmsize;
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;
573
armci_get_shmem_info((char*)bp, &p->s.shmid, &p->s.shmoffset,
579
ctx->shmoffset = shmoffset;
580
ctx->shmsize = shmsize;
583
UNLOCKIT(armci_master);
585
#else /* #ifdef SYSV */
586
/* What are doing here */
587
static char *kr_malloc_shmem(size_t nbytes, context_t *ctx)
589
armci_die("kr_malloc_shmem(): Invalid Function Call", 0L);
591
static void kr_free_shmem(char *ap, context_t *ctx)
593
armci_die("kr_free_shmem(): Invalid Function Call", 0L);
595
#endif /* #ifdef SYSV */
596
/********************** END: kr_malloc for ctx_shmem *********************/
601
1. do usage statistics only if debug/DEBUG is enabled