/*************************************************************************/ /* */ /* Copyright (c) 1994 Stanford University */ /* */ /* All rights reserved. */ /* */ /* Permission is given to use, copy, and modify this software for any */ /* non-commercial purpose as long as this copyright notice is not */ /* removed. All other uses, including redistribution in whole or in */ /* part, are forbidden without prior written permission. */ /* */ /* This software is provided with absolutely no warranty and no */ /* support. */ /* */ /*************************************************************************/ /* this version guarentees that all blocks are zeroed, and it expects that all returned blocks are zero */ EXTERN_ENV #include #include "matrix.h" #define ALIGN 8 #define MAXFAST 16 #define MAXFASTBL (1<<(MAXFAST-1)) #define SIZE(block) (block[-1]) /* in all blocks */ #define HOME(block) (block[-2]) /* in all blocks */ #define NEXTFREE(block) (*((long **) block)) /* in free blocks */ struct MemPool { LOCKDEC(memoryLock) long *volatile*freeBlock; long tally, touched, maxm; } *mem_pool; long mallocP = 1, machineP = 1; extern struct GlobalMemory *Global; void MallocInit(long P) { long p; mallocP = P; mem_pool = (struct MemPool *) G_MALLOC((mallocP+1)*sizeof(struct MemPool), 0); mem_pool++; /****** access to mem_pool[-1] is valid ******/ for (p = -1; p 0) { mem_pool[p].freeBlock = (long **) G_MALLOC((MAXFAST+1)*sizeof(long *), p); MigrateMem((void *)mem_pool[p].freeBlock, (MAXFAST+1)*sizeof(long *), p); } else { mem_pool[p].freeBlock = (long **) G_MALLOC((MAXFAST+1)*sizeof(long *), 0); MigrateMem((void *)mem_pool[p].freeBlock, (MAXFAST+1)*sizeof(long *), DISTRIBUTED); } for (j=0; j<=MAXFAST; j++) mem_pool[p].freeBlock[j] = NULL; mem_pool[p].tally = mem_pool[p].maxm = mem_pool[p].touched = 0; } void MallocStats() { long i; printf("Malloc max: "); for (i=0; i 0) printf("%ld* ", mem_pool[i].maxm); else printf("%ld ", mem_pool[i].maxm); printf("\n"); } /* returns first bucket where 2^bucket >= size */ long FindBucket(long size) { long bucket; if (size > MAXFASTBL) bucket = MAXFAST; else { bucket = 1; while (1<= alloc_size) { /* Found one! */ leftover = block_size - alloc_size - 2*sizeof(long); result = d + (leftover/sizeof(long)) + 2; SIZE(result) = alloc_size; HOME(result) = home; if (leftover > MAXFASTBL) { SIZE(d) = leftover; } else { /* don't leave a block */ /* unlink 'd' */ if (prev) NEXTFREE(prev) = NEXTFREE(d); else mem_pool[home].freeBlock[MAXFAST] = NEXTFREE(d); if (leftover > 0) { SIZE(d) = leftover; MyFreeNow(d); } } break; } prev = d; d = NEXTFREE(d); } UNLOCK(mem_pool[home].memoryLock) } if (result) { NEXTFREE(result) = 0; /* in case it was set earlier */ } else { /* grab a big block, free it, then retry request */ block_size = max(alloc_size, 4*(1<memLock); freespace = (long *) G_MALLOC(block_size+2*sizeof(long), home); MigrateMem(freespace, block_size+2*sizeof(long), home); mem_pool[home].touched++; UNLOCK(Global->memLock); freespace+=2; SIZE(freespace) = block_size; HOME(freespace) = home; for (i=0; i mem_pool[home].maxm) { mem_pool[home].maxm = mem_pool[home].tally; } MyFree(freespace); result = (long *) MyMalloc(alloc_size, home); } } mem_pool[home].tally += SIZE(result); if (mem_pool[home].tally > mem_pool[home].maxm) { mem_pool[home].maxm = mem_pool[home].tally; } if (SIZE(result) < size) printf("*** Bad size from malloc %ld, %ld\n", size, SIZE(result)); return((char *) result); } void MigrateMem(long *start, long length, long home) { /* unsigned long *finish; unsigned long currpage, endpage; long i; long j;*/ /* POSSIBLE ENHANCEMENT: Here is where one might distribute the memory pages across physically distributed memories as desired. One way to do this is as follows: finish = (unsigned long *) (((char *) start) + length); currpage = (unsigned long) start; endpage = (unsigned long) finish; if ((home == DISTRIBUTED) || (home < 0) || (home >= mallocP)) { j = 0; while (currpage < endpage) { Place all addresses x such that (currpage <= x < currpage + PAGE_SIZE) on node j j++; currpage += PAGE_SIZE; } } else { Place all addresses x such that (currpage <= x < endpage) on node home } */ } void MyFree(long *block) { long home; home = HOME(block); LOCK(mem_pool[home].memoryLock) MyFreeNow(block); UNLOCK(mem_pool[home].memoryLock) } void MyFreeNow(long *block) { long bucket, size, home; size = SIZE(block); home = HOME(block); if (size <= 0) { printf("Bad size %ld\n", size); exit(-1); } if (home < -1 || home >= mallocP) { printf("Bad home %ld\n", home); exit(-1); } if (size > MAXFASTBL) bucket = MAXFAST; else { bucket = FindBucket(size); if (size < 1<