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 + -
显示快捷键?