|
|
/*
** Copyright 1994, Silicon Graphics, Inc. ** All Rights Reserved. ** ** This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.; ** the contents of this file may not be disclosed to third parties, copied or ** duplicated in any form, in whole or in part, without the prior written ** permission of Silicon Graphics, Inc. ** ** RESTRICTED RIGHTS LEGEND: ** Use, duplication or disclosure by the Government is subject to restrictions ** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data ** and Computer Software clause at DFARS 252.227-7013, and/or in similar or ** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished - ** rights reserved under the Copyright Laws of the United States. ** ** Author: Eric Veach, July 1994. */
#ifdef NT
#include <glos.h>
#endif
#include "memalloc.h"
#include <assert.h>
#ifdef NO_MALLOPT
#define memalign(a,n) malloc(n)
#define mallopt(t,v)
#endif
#define Pool mPool
typedef struct Pool { char *prevAlloc; char *lastAlloc; int usedCount; int chunkSize; } Pool;
typedef struct Chunk { Pool *pool; } Chunk;
static Pool **Pools; static size_t MaxFast;
#define POOL_SIZE 200
#define CHUNK_PAD sizeof(Chunk)
#define ALIGN_SHIFT 3
#define ALIGN (1 << ALIGN_SHIFT)
#define CHUNK_SIZE(n) (((n) + CHUNK_PAD + ALIGN - 1) & (-ALIGN))
#define ALIGNED_CHUNK_PAD ((CHUNK_PAD + ALIGN - 1) & (-ALIGN))
static int NewPool( size_t n, int poolSize ) { Pool *p; char *base;
/* We want the *returned* chunks to be aligned on ALIGN boundaries.
* The Chunk structures will be located just before these boundaries. */ p = (Pool *)malloc( CHUNK_SIZE(sizeof(Pool)) + poolSize * n ); if (p == NULL) { return 0; } base = (char *)p + CHUNK_SIZE(sizeof(Pool)) - CHUNK_PAD; p->prevAlloc = base - n; p->lastAlloc = base + (poolSize-1) * n; p->usedCount = poolSize; p->chunkSize = n; Pools[n>>ALIGN_SHIFT] = p;
return 1; }
int __gl_memInit( size_t maxFast ) { int i, numPools;
if( Pools == NULL ) { #ifdef MEMORY_DEBUG
mallopt( M_DEBUG, 1 ); #endif
MaxFast = CHUNK_SIZE(maxFast) - CHUNK_PAD; numPools = ((MaxFast + CHUNK_PAD) >> ALIGN_SHIFT) + 1; Pools = (struct Pool **)malloc( numPools * sizeof(Pools[0]) ); if (Pools == NULL) return 0;
/* Create a tiny pool for every size, to avoid a check for NULL
* in memAlloc(). */ for( i = 1; i < numPools; ++i ) { if (NewPool( i << ALIGN_SHIFT, 1 ) == 0) { return 0; } } } return 1; }
void *__gl_memAlloc( size_t n ) { Pool *p; Chunk *c;
if( n <= MaxFast ) { n = CHUNK_SIZE( n ); p = Pools[n >> ALIGN_SHIFT]; assert ( p->chunkSize == n ); c = (Chunk *)(p->prevAlloc + n); p->prevAlloc = (char *) c; c->pool = p; if( c >= (Chunk *) p->lastAlloc ) { if (NewPool( n, POOL_SIZE ) == 0) { return 0; } } assert( ((size_t)(c + 1) & (ALIGN - 1)) == 0 ); } else { char* v; /* v = (char*) malloc( n + ALIGNED_CHUNK_PAD ) + ALIGNED_CHUNK_PAD;*/ v = (char*) malloc( n + ALIGNED_CHUNK_PAD ); if (v == NULL) { return 0; } v = v + ALIGNED_CHUNK_PAD;
c = ((Chunk*) v) - 1; c->pool = NULL; assert( ((size_t)(c + 1) & (ALIGN - 1)) == 0 ); } return (c + 1); }
extern void *__gl_memRealloc( void *v1, size_t n ) { Chunk *c = ((Chunk *) v1) - 1; Pool *p = c->pool; void *v2; #ifdef NT
size_t len; #else
int len; #endif
if( p == NULL ) { char* v; /* v = (char*) realloc( (char*)v1 - ALIGNED_CHUNK_PAD, n + ALIGNED_CHUNK_PAD )
+ ALIGNED_CHUNK_PAD; */ v = (char*) realloc( (char*)v1 - ALIGNED_CHUNK_PAD, n + ALIGNED_CHUNK_PAD); if (v == NULL) { return 0; } v = v + ALIGNED_CHUNK_PAD; c = ((Chunk*) v) - 1; assert( ((size_t)(c + 1) & (ALIGN - 1)) == 0 ); return (c+1); } len = p->chunkSize - CHUNK_PAD; if( n <= len ) { return v1; }
v2 = memAlloc( n ); if (v2 == NULL) { return 0; } (void) memcpy( v2, v1, len ); memFree( v1 ); return v2; }
extern void __gl_memFree( void *v ) { Chunk *c = ((Chunk *) v) - 1; Pool *p = c->pool;
if( p == NULL ) { free( ((char*) v) - ALIGNED_CHUNK_PAD ); } else { if( --p->usedCount <= 0 ) { free( p ); } } }
|