windows-nt/Source/XPSP1/NT/multimedia/opengl/glu/libtess/memalloc.c
2020-09-26 16:20:57 +08:00

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 );
}
}
}