memmgr.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 614 行 · 第 1/2 页

C
614
字号
        MEMORYSTATUS    info;

        GlobalMemoryStatus( &info );
        memory_available = info.dwAvailVirtual;
        if( size_requested != 0 ) {
            MemorySize = size_requested;
        } else {
            MemorySize = memory_available;
        }
    }
    #elif defined( __OS2__ ) || defined( __OSI__ )
        if( size_requested != 0 ) {
            MemorySize = size_requested;
        } else {
            MemorySize = _16M;
        }
        memory_available = _16M;
    #elif defined( __QNX__ )
    {
        struct _osinfo  data;

        qnx_osinfo( 0, &data );
        memory_available = (unsigned long)data.freememk * 1024;
        if( size_requested != 0 ) {
            if( memory_available < size_requested ) {
                NotEnoughMem();
            }
            MemorySize = size_requested;
        } else {
            MemorySize = memory_available;
        }
    }
    #elif defined( __LINUX__ )
        if( size_requested != 0 ) {
            MemorySize = size_requested;
        } else {
            MemorySize = _16M;
        }
        memory_available = _16M;
    #endif
    if( max_size_queried || size_queried ) {
        myitoa( (int)(memory_available/_1K), CopyStr( (char *)"Maximum WCGMEMORY=", (char *)buff ) );
        write( 1, buff, Length( buff ) );
        write( 1, "\r\n", 2 );
    }
}

static  void    MemInit( void )
/*****************************/
{
    if( !Initialized ) {
        int i;

        for( i = 0; i <= MAX_CLASS; ++i ) {
            _FreeList[i]   = NULL;
            _ClassSizes[i] = 1 << ( MIN_SIZE + i );
        }

        Initialized = 1;
        AllocSize   = 0;
        _Blks       = NULL;
#if !defined( __QNX__ )
        CalcMemSize();
#endif
    }
}


static int SizeToClass( tag amount )
/**********************************/
{
    int mem_class;

    if( amount >= MAX_ALLOC ) {
        return( MAX_CLASS );
    }
    if( amount <= ( 1 << MIN_SIZE ) ) {
        return( 0 );
    }
    --amount;
    amount >>= MIN_SIZE;
    mem_class = 0;
    for( ;; ) {
        ++mem_class;
        amount >>= 1;
        if( amount == 0 )
            break;
    }
    return( mem_class );
}


static tag ClassToSize( int mem_class )
/*************************************/
{
    return( _ClassSizes[mem_class] );
}


static pointer  GetFromFrl( tag amount, int frl_class )
/*****************************************************/
{
    frl     *free;

    free = _FreeList[ frl_class ];
    if( free != NULL ) {
        assert( !( free->length & ALLOCATED ) );
        free->length |= ALLOCATED;
        _FreeList[ frl_class ] = free->link;
        return( free );
    }
    return( NULL );
}


static pointer  GetFromBlk( tag amount )
/**************************************/
{
    mem_blk     *block;
    tag         *alloc;

    block = _Blks;
    while( block && (block->free < amount) )
        block = block->next;

    if( block ) {
        alloc = (tag*)((char*)block + block->size - block->free);
        assert( *alloc == 0 );
        *alloc = amount | ALLOCATED;
        block->free -= amount;
        return( ++alloc );
    }
    if( MemFromSys( 0 ) == NULL)    // Grab one empty block
        return( NULL );
    return( GetFromBlk( amount ) ); // We know this will now succeed
}


extern pointer  MemAlloc( tag amount )
/************************************/
{
    char        *chunk;
    int         mem_class;

    if( !Initialized )
        MemInit();
    if( amount == 0 )
        return( NULL );
    amount = ( amount + TAG_SIZE + (WORD_SIZE-1) ) & ~(WORD_SIZE-1);
    if( amount > MAX_ALLOC ) {
        return( (pointer)MemFromSys( amount ) );
    }

    if( amount < MIN_ALLOC )
        amount = MIN_ALLOC;

    mem_class = SizeToClass( amount );
    chunk = GetFromFrl( amount, mem_class );
    if( chunk != NULL )
        return( chunk + TAG_SIZE );

    return( GetFromBlk( ClassToSize( mem_class ) ) );
}


extern void     MemFree( char *block )
/************************************/
{
    frl     *free;
    int     mem_class;
    tag     length;

    free   = (frl *)( block - TAG_SIZE );
    assert( free->length & ALLOCATED );
    free->length &= ~ALLOCATED;
    length = free->length;
    if( length > MAX_ALLOC ) {   // This was a full block
        blk_hdr     *header;
        mem_blk     *blk;

        header = (blk_hdr *)( block - sizeof( blk_hdr ) );
        blk    = header->block;
        blk->free += header->size + sizeof( blk_hdr );
        blk->size += header->size + sizeof( blk_hdr );
#ifndef NDEBUG
        // Must zero the memory for later checks in GetFromBlk
        memset( header, 0, length + sizeof( blk_hdr ) );
#endif
    } else {
        mem_class  = SizeToClass( length );
        free->link = _FreeList[ mem_class ];
        _FreeList[ mem_class ] = free;
    }
}

extern void     MemCoalesce( void )
/*********************************/
{
    return;
}


extern pointer_int      MemInUse( void )
/**************************************/
{
    if( !Initialized )
        MemInit();
    return( AllocSize );
}


extern pointer_int      MemSize( void )
/*************************************/
{
    switch( Initialized ) {
    case 0:
        MemInit();
#if defined( __QNX__ )
        /* fall through */
    case 1:
        CalcMemSize();
#endif
    }
    return( MemorySize );
}


static  char    *MemFromSys( tag amount )
/***************************************/
{
    char        *ptr;
    char        *chunk;
    blk_hdr     *allocated;
    mem_blk     *blk;
    unsigned    size;

    // round up size to multiple of 64K
    size = (amount + sizeof( mem_blk ) + sizeof( blk_hdr ) + (_64K - 1)) & - _64K;
#ifdef NDEBUG
    ptr = malloc( size );
#else
    ptr = calloc( 1, size );   // Need to clear memory for later assert() calls
#endif
    if( ptr != NULL ) {
        AllocSize += size;
#ifdef MEMORY_STATS
        if( AllocSize > PeakAlloc )
            PeakAlloc = AllocSize;
#endif
        blk = (void *)ptr;
        // If amount was zero, this block will be chopped up into
        // small chunks immediately. If nonzero, return pointer
        // to memory at the end of the block and use the rest for
        // small chunks. If the initial large allocation is freed,
        // it will also be reused for small blocks.
        blk->next = _Blks;
        _Blks = blk;
        blk->free = size - amount - sizeof( mem_blk );
        blk->size = size;
        if( amount ) {
            blk->size -= amount + sizeof( blk_hdr );
            blk->free -= sizeof( blk_hdr );
            allocated = (blk_hdr*)((char*)blk + sizeof( mem_blk ) + blk->free);
            allocated->block = blk;
            allocated->size  = amount | ALLOCATED;
            chunk = (char*)allocated + sizeof( blk_hdr );
        } else {
            chunk = (char*)blk + sizeof( mem_blk );
        }
        return( chunk );
    }
    return( NULL );
}


static  void MemToSys( mem_blk *what )
/************************************/
{
    free( what );
}


extern void MemFini( void )
/*************************/
{
    mem_blk *curr;
    mem_blk *next;

    curr = _Blks;
    while( curr != NULL ) {
        next = curr->next;
        MemToSys( curr );
        curr = next;
    }
#ifdef MEMORY_STATS
    {
        char    buff[80];

        myitoa( (int)(PeakAlloc/_1K), CopyStr( "Peak WCG memory usage (KB): ", buff ) );
        write( 1, buff, Length( buff ) );
        write( 1, "\r\n", 2 );
        PeakAlloc = 0;
    }
#endif
    Initialized = 0;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?