📄 rcalloc1.c
字号:
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: Resource compiler memory layer 1.
*
****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "rcalloc0.h"
#include "rcalloc1.h"
#include "errors.h"
#include "layer0.h" /* Get consistent definitions for TRUE/FALSE */
#ifdef RCMEM_DEBUG
#include "errprt.h"
#endif
#define NUM_HEAPS 4
const int BlocksPerHeap[] = { 2048, 2048, 2048, 1024 };
const int HeapSizes[] = { 16, 32, 64, 1024 }; /* Ascending order */
HeapHandle *Heaps[ NUM_HEAPS ];
// Need a long instead of a char for Alpha to work,
// as Alpha doesn't allow odd boundary memory accesses for non-chars.
// Pls note that there might be problems (for AXP) of this kind lying around.
// In fact, the RCMEM_DEBUG version is not working for AXP. KH 5/17/95
typedef struct HeapId {
// char id;
long id;
} HeapId;
typedef struct BigMemList {
struct BigMemList *next;
unsigned long size;
} BigMemList;
BigMemList *BigList;
static char RCMemGetHeapIndex( size_t size )
/******************************************/
{
unsigned char i;
for( i = 0; i < NUM_HEAPS; i++ ) {
if( size + sizeof( HeapId ) < HeapSizes[i] ) {
return( i );
}
}
return( BIGLIST_ID );
}
static void FreeBigListNode( void *mem, char freemem )
/****************************************************/
{
BigMemList *travptr;
BigMemList *prevnode;
char *memptr;
unsigned long headersize;
headersize = sizeof( BigMemList ) + sizeof( HeapId );
memptr = (char *)BigList + headersize;
travptr = BigList->next;
if( memptr == mem ) {
if( freemem ) {
free( BigList );
}
BigList = travptr;
return;
}
travptr = BigList;
prevnode = BigList;
while( travptr != NULL ) {
memptr = (char *)travptr + headersize;
if( memptr == mem ) {
prevnode->next = travptr->next;
#ifdef RCMEM_DEBUG
if( *(memptr + travptr->size ) != RCMEM_ENDBYTE ) {
RcFprintf( stderr, NULL,
"(%x) Memory Overrun (biglist)\n", mem );
}
#endif
if( freemem ) {
free( travptr );
}
break;
}
prevnode = travptr;
travptr = travptr->next;
}
if( travptr == NULL ) {
RcFatalError( ERR_INTERNAL, INTERR_MEM_FREE_FAILED );
}
}
extern void RCMemLayer1Init( void )
/*********************************/
{
int i;
for( i = 0; i < NUM_HEAPS; i++ ) {
Heaps[i] = RCMemLayer0NewHeap( HeapSizes[i], BlocksPerHeap[i] );
}
BigList = NULL;
}
extern void *RCMemLayer1Malloc( size_t size )
/*******************************************/
{
char *mem;
BigMemList *memptr;
HeapHandle *handle;
HeapId *idptr;
unsigned char heapindex;
unsigned long headersize;
heapindex = RCMemGetHeapIndex( size );
if( heapindex == BIGLIST_ID ) {
headersize = sizeof( BigMemList ) + sizeof( HeapId );
#ifdef RCMEM_DEBUG
memptr = malloc( size + headersize + 1 );
#else
memptr = malloc( size + headersize );
#endif
if( memptr == NULL ) {
RcFatalError( ERR_OUT_OF_MEMORY );
}
memptr->size = size;
memptr->next = BigList;
idptr = (HeapId *)( (char *)memptr + sizeof( BigMemList ) );
idptr->id = BIGLIST_ID;
#ifdef RCMEM_DEBUG
*((char *)memptr + size + headersize ) = RCMEM_ENDBYTE;
#endif
mem = (char *)memptr + headersize;
BigList = memptr;
} else {
handle = Heaps[ heapindex ];
#ifdef RCMEM_DEBUG
mem = RCMemLayer0Malloc( handle, size + sizeof( HeapId ) );
#else
mem = RCMemLayer0Malloc( handle );
#endif
((HeapId *)mem)->id = heapindex;
mem += sizeof( HeapId );
}
return( mem );
}
extern void RCMemLayer1Free( void *mem )
/**************************************/
{
char *blockptr;
HeapId *heapid;
if( mem == NULL ) {
return;
}
blockptr = (char *)mem - sizeof( HeapId );
heapid = (HeapId *)blockptr;
if( heapid->id == BIGLIST_ID ) {
FreeBigListNode( mem, TRUE );
} else if( heapid->id < NUM_HEAPS ) {
RCMemLayer0Free( blockptr, Heaps[ heapid->id ] );
} else {
RcFatalError( ERR_INTERNAL, INTERR_MEM_FREE_FAILED );
}
}
extern void RCMemLayer1ShutDown( void )
/*************************************/
{
BigMemList *curnode;
BigMemList *nextnode;
int i;
for( i = 0; i < NUM_HEAPS; i++ ) {
RCMemLayer0ShutDown( Heaps[i] );
}
curnode = BigList;
nextnode = BigList;
while( nextnode != NULL ) {
nextnode = curnode->next;
#ifdef RCMEM_DEBUG
RcFprintf( stderr, NULL,
"Unfreed Memory Detected (0x%x bytes at 0x%x)\n",
curnode->size, (char *)curnode + sizeof( BigMemList ) );
#endif
free( curnode );
curnode = nextnode;
}
}
extern void *RCMemLayer1Realloc( void *mem, size_t size )
/*******************************************************/
{
char *blockptr;
BigMemList *newbigptr;
void *newnode;
HeapId *heapid;
HeapId *idptr;
BigMemList *reallocptr;
unsigned long reallocsize;
unsigned short headersize;
#ifdef RCMEM_DEBUG
DebugMemInfo *debugmem;
#endif
if( mem == NULL ) { // emulate realloc() behaviour
return( RCMemLayer1Malloc( size ) );
}
blockptr = (char *)mem - sizeof( HeapId );
heapid = (HeapId *)blockptr;
if( heapid->id == BIGLIST_ID ) {
reallocptr = (BigMemList *)( (char *)heapid - sizeof( BigMemList ) );
if( reallocptr->size < size ) {
FreeBigListNode( mem, FALSE );
headersize = sizeof( BigMemList ) + sizeof( HeapId );
reallocsize = size + headersize;
#ifdef RCMEM_DEBUG
reallocsize++;
#endif
newnode = realloc( reallocptr, reallocsize );
if( newnode == NULL ) {
RcFatalError( ERR_OUT_OF_MEMORY );
}
newbigptr = (BigMemList *)newnode;
newbigptr->next = BigList;
newbigptr->size = size;
idptr = (HeapId *)( (char *)newbigptr + sizeof( BigMemList ) );
idptr->id = BIGLIST_ID;
BigList = newbigptr;
#ifdef RCMEM_DEBUG
*((char *)newbigptr + headersize + size ) = RCMEM_ENDBYTE;
#endif
return( (char *)newbigptr + headersize );
}
} else if( heapid->id < NUM_HEAPS ) {
if( size + sizeof( HeapId ) > HeapSizes[ heapid->id ] ) {
newnode = RCMemLayer1Malloc( size );
memcpy( newnode, mem, HeapSizes[ heapid->id ] - sizeof( HeapId ) );
RCMemLayer1Free( mem );
return( newnode );
}
#ifdef RCMEM_DEBUG
else {
debugmem = (DebugMemInfo *)((char *)blockptr -
sizeof( DebugMemInfo ) );
debugmem->size = size + sizeof( HeapId );
*((char *)mem + size) = RCMEM_ENDBYTE;
}
#endif
} else {
RcFatalError( ERR_INTERNAL, INTERR_MEM_REALLOC_FAILED );
}
return( mem );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -