carve.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 968 行 · 第 1/2 页
C
968 行
/****************************************************************************
*
* 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: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#if 0
#include "plusplus.h"
#include "errdefns.h"
#include "stats.h"
#include "memmgr.h"
#include "ring.h"
#include "pcheader.h"
#include "pragdefn.h"
#include "carve.h"
#else
#include header
#ifdef header2
# include header2
#endif
#include "ringcarv.h"
#endif
#if ( defined(__COMPACT__) || defined(__LARGE__) )
#error code will not work with segmented pointers
#endif
#ifndef TRUE
# define TRUE 1
# define FALSE 0
#endif
struct blk {
blk_t *next;
char data[1];
};
struct free_t {
free_t *next_free;
};
// assumes '->free_list' is non-NULL
#define _REMOVE_FROM_FREE( pcv, p ) \
{ \
free_t *head = pcv->free_list; \
pcv->free_list = head->next_free; \
p = head; \
DbgZapVerify( p, pcv->elm_size ); \
}
#define _ADD_TO_FREE( fl, p ) \
{ \
free_t *node = (free_t *) (p); \
node->next_free = (fl); \
(fl) = node; \
}
#ifndef NDEBUG
boolean restoreFromZapped( cv_t *cv )
{
size_t elm_size;
free_t *free_list;
free_t *curr_zapped;
free_t *next_zapped;
// we now check to make sure freed carve blocks have not been modified
// but during PCH writing, we intentionally modify a free block to
// distinguish them from allocated blocks thus we have to keep them
// out of the free list until we can re-zap them
elm_size = cv->elm_size;
free_list = cv->free_list;
curr_zapped = cv->zapped_free_list;
if( curr_zapped != NULL ) {
cv->zapped_free_list = NULL;
do {
next_zapped = curr_zapped->next_free;
DbgZapFreed( curr_zapped, elm_size );
_ADD_TO_FREE( free_list, curr_zapped );
curr_zapped = next_zapped;
} while( curr_zapped != NULL );
cv->free_list = free_list;
return( TRUE );
}
return( FALSE );
}
#else
#define restoreFromZapped( x )
#endif
static void newBlk( cv_t *cv )
{
size_t elm_size;
char *top_elm;
char *bottom_elm;
char *free_elm;
blk_t *newblk;
free_t *free_list;
DbgStmt( if( restoreFromZapped( cv ) ) return; );
elm_size = cv->elm_size;
free_list = cv->free_list;
newblk = _MemoryAllocate( sizeof( blk_t ) - 1 + cv->blk_top );
newblk->next = cv->blk_list;
cv->blk_list = newblk;
cv->blk_count++;
bottom_elm = newblk->data;
top_elm = bottom_elm + cv->blk_top;
free_elm = bottom_elm;
do {
/* free_list must be maintained as the reverse of CarveWalkAll ordering */
DbgZapFreed( free_elm, elm_size );
_ADD_TO_FREE( free_list, free_elm );
free_elm += elm_size;
} while( free_elm != top_elm );
cv->free_list = free_list;
}
carve_t CarveCreate( size_t elm_size, size_t elm_count )
/******************************************************/
{
cv_t *cv;
elm_size = ( elm_size + (sizeof(int)-1) ) & ~(sizeof(int)-1);
if( elm_size < sizeof( free_t ) ) {
elm_size = sizeof( free_t );
}
cv = _MemoryAllocate( sizeof( *cv ) );
cv->elm_size = elm_size;
cv->elm_count = elm_count;
cv->blk_top = elm_count * elm_size;
cv->blk_count = 0;
cv->blk_list = NULL;
cv->free_list = NULL;
cv->blk_map = NULL;
DbgStmt( cv->zapped_free_list = NULL );
DbgAssert( cv->elm_size != 0 );
DbgVerify( cv->blk_top < 0x10000, "carve: size * #/block > 64k" );
return( cv );
}
void CarveDestroy( carve_t cv )
/*****************************/
{
blk_t *cur;
blk_t *next;
if( cv != NULL ) {
cur = cv->blk_list;
while( cur != NULL ) {
next = cur->next;
_MemoryFree( cur );
cur = next;
}
DbgAssert( cv->blk_map == NULL );
_MemoryFree( cv );
}
}
void *CarveAlloc( carve_t cv )
/****************************/
{
void *p;
if( cv->free_list == NULL ) {
newBlk( cv );
}
_REMOVE_FROM_FREE( cv, p );
DbgZapAlloc( p, cv->elm_size );
return p;
}
#if 0
void *CarveZeroAlloc( carve_t cv )
/********************************/
{
void *v;
unsigned *p;
if( cv->free_list == NULL ) {
newBlk( cv );
}
_REMOVE_FROM_FREE( cv, v );
p = v;
DbgAssert( ( cv->elm_size / sizeof(*p) ) <= 8 );
switch( cv->elm_size / sizeof(*p) ) {
case 8:
p[7] = 0;
case 7:
p[6] = 0;
case 6:
p[5] = 0;
case 5:
p[4] = 0;
case 4:
p[3] = 0;
case 3:
p[2] = 0;
case 2:
p[1] = 0;
case 1:
p[0] = 0;
}
return p;
}
#endif
#ifndef NDEBUG
#define TOO_MANY_TO_WALK 512
static blk_t *withinABlock( carve_t cv, void *elm )
{
blk_t *block;
char *compare;
char *start;
for( block = cv->blk_list; block != NULL; block = block->next ) {
start = block->data;
compare = start + cv->blk_top;
if( elm < start || elm > compare ) {
continue;
}
return( block );
}
return( NULL );
}
void CarveDebugFree( carve_t cv, void *elm )
{
free_t *check;
blk_t *block;
char *compare;
char *start;
size_t esize;
int i;
boolean do_search;
/* make sure object hasn't been freed before */
restoreFromZapped( cv );
esize = cv->elm_size;
if(( cv->elm_count * cv->blk_count ) > TOO_MANY_TO_WALK ) {
// there are lots of blocks to search so we weaken the check for speed
do_search = FALSE;
check = elm;
for( i = 0; i < 4; ++i ) {
if( DbgZapQuery( check, esize ) != 0 ) {
// would pass check to return as a free block!
do_search = TRUE;
break;
}
if( ! withinABlock( cv, check->next_free ) ) {
break;
}
check = check->next_free;
}
} else {
do_search = TRUE;
}
if( do_search ) {
for( check = cv->free_list; check != NULL; check = check->next_free ) {
if( elm == (void *) check ) {
_FatalAbort( "carve: freed object was previously freed" );
}
}
}
/* make sure object is from this carve allocator */
for( block = cv->blk_list; block != NULL; block = block->next ) {
start = block->data;
compare = start + cv->blk_top;
if( elm < start || elm > compare ) {
continue;
}
for(;;) {
if( compare == start ) break;
compare -= esize;
if( elm == compare ) break;
}
if( elm == compare ) break;
}
if( block == NULL ) {
_FatalAbort( "carve: freed object was never allocated" );
}
DbgZapFreed( elm, cv->elm_size );
}
#else
#define CarveDebugFree( cv, elm )
#endif
void CarveFree( carve_t cv, void *elm )
/*************************************/
{
if( elm == NULL ) {
return;
}
CarveDebugFree( cv, elm );
_ADD_TO_FREE( cv->free_list, elm );
}
#ifndef NDEBUG
void CarveVerifyAllGone( carve_t cv, char const *node_name )
/**********************************************************/
{
free_t *check;
blk_t *block;
char *compare;
boolean some_unfreed;
#ifdef ERR_RET
if( ERR_RET ) {
return;
}
#endif
restoreFromZapped( cv );
some_unfreed = FALSE;
for( block = cv->blk_list; block != NULL; block = block->next ) {
compare = block->data + cv->blk_top;
do {
compare -= cv->elm_size;
/* verify every block has been freed */
for( check = cv->free_list; check != NULL; check = check->next_free ) {
if( compare == (void *) check ) break;
}
if( check == NULL ) {
if( ! some_unfreed ) {
printf( "%s nodes unfreed:", node_name );
some_unfreed = TRUE;
}
printf( " %p", compare );
}
} while( compare != block->data );
}
if( some_unfreed ) {
putchar( '\n' );
#ifdef ERR_SET
ERR_SET;
#endif
}
}
#endif
#ifdef CARVEPCH
//!!!!!!!!!!!!!
//!!!!!!!!!!!!! THE FOLLOWING IS LIKELY C++ DEPENDENT.
//!!!!!!!!!!!!!
//!!!!!!!!!!!!! I'VE NOT ABSTRACTED THE DEPENDENCIES.
//!!!!!!!!!!!!!
//!!!!!!!!!!!!! JIM WELCH
//!!!!!!!!!!!!!
void *CarveGetIndex( carve_t cv, void *e )
/****************************************/
{
char *elm = e;
char *start;
char *top;
blk_t *block;
unsigned block_index;
if( elm == NULL ) {
return( (void *) CARVE_NULL_INDEX );
}
block_index = cv->blk_count + 1;
for( block = cv->blk_list; block != NULL; block = block->next ) {
--block_index;
start = block->data;
if( elm >= start ) {
top = start + cv->blk_top;
if( elm < top ) {
DbgAssert( (( elm - start ) % cv->elm_size ) == 0 );
return( (void *) MK_INDEX( block_index, elm - start ) );
}
}
}
_FatalAbort( "unable to find carve memory block" );
return( (void *) CARVE_ERROR_INDEX );
}
carve_t CarveRestart( carve_t cv )
/********************************/
{
blk_t *block;
blk_t *next;
char *free_elm;
char *stop;
size_t esize;
free_t *free_list;
#ifdef DUMP_MEMORY
if( !PragDbgToggle.dump_memory ) {
carve_t old_cv = cv;
restoreFromZapped( old_cv );
old_cv->free_list = (void *)-1;
for( block = old_cv->blk_list; block != NULL; block = next ) {
next = block->next;
DbgZapMem( block->data, -1, old_cv->blk_top );
_MemoryDeferredFree( block );
}
old_cv->blk_list = (void *) -1;
cv = CarveCreate( old_cv->elm_size, old_cv->elm_count );
_MemoryFree( old_cv );
}
#endif
block = cv->blk_list;
cv->blk_list = NULL;
free_list = NULL;
esize = cv->elm_size;
for( ; block != NULL; block = next ) {
next = block->next;
block->next = cv->blk_list;
cv->blk_list = block;
free_elm = block->data;
stop = free_elm + cv->blk_top;
do {
/* free_list must be maintained as the reverse of CarveWalkAll ordering */
DbgZapMem( free_elm, 0x1d, esize );
_ADD_TO_FREE( free_list, free_elm );
free_elm += esize;
} while( free_elm != stop );
}
cv->free_list = free_list;
return( cv );
}
void *CarveMapIndex( carve_t cv, void *aindex )
/*********************************************/
{
unsigned index = (unsigned) aindex;
blk_t *block;
blk_t **block_map;
unsigned block_index;
unsigned block_offset;
unsigned block_count;
/* given an index; find and allocate the carve element */
if( index == CARVE_NULL_INDEX ) {
return( NULL );
}
block_index = GET_BLOCK( index );
block_offset = GET_OFFSET( index );
block_map = cv->blk_map;
if( block_map != NULL ) {
block = block_map[ block_index - 1 ];
return( &(block->data[ block_offset ]) );
}
block_count = cv->blk_count;
for(;;) {
/* make sure that there are enough carve blocks */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?