188 lines
4.2 KiB
C
188 lines
4.2 KiB
C
/*
|
|
** 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 );
|
|
}
|
|
}
|
|
}
|
|
|