Esempio n. 1
0
void *__ReAllocDPMIBlock( frlptr p1, unsigned req_size )
{
    mheapptr            mhp;
    struct dpmi_hdr     *dpmi;
    struct dpmi_hdr     *prev_dpmi;
    unsigned            size;
    frlptr              flp, flp2;

    if( !__heap_enabled )
        return( 0 );
    __FreeDPMIBlocks();
    prev_dpmi = NULL;
    for( mhp = __nheapbeg; mhp; mhp = mhp->next ) {
        if( ((PTR)mhp + sizeof(struct miniheapblkp) == (PTR)p1)
          && (mhp->numalloc == 1) ) {
            // The mini-heap contains only this memblk
            __unlink( mhp );
            dpmi = ((struct dpmi_hdr *)mhp) - 1;
            if( dpmi->dos_seg_value != 0 )
                return( NULL );
            size = mhp->len + sizeof(struct dpmi_hdr) + TAG_SIZE;
            size += ( req_size - (p1->len-TAG_SIZE) );
            size += BLKSIZE_ALIGN_MASK;
            size &= ~BLKSIZE_ALIGN_MASK;
            prev_dpmi = dpmi;
            dpmi = TinyDPMIRealloc( dpmi, size );
            if( dpmi == NULL ) {
                dpmi = prev_dpmi;
                return( NULL );         // indicate resize failed
            }
            dpmi->dos_seg_value = 0;
            mhp = (mheapptr)( dpmi + 1 );
            mhp->len = size - sizeof(struct dpmi_hdr) - TAG_SIZE;
            flp = __LinkUpNewMHeap( mhp );
            mhp->numalloc = 1;

            // round up to even number
            req_size = (req_size + 1) & ~1;
            size = flp->len - req_size;
            if( size >= FRL_SIZE ) {    // Enough to spare a free block
                flp->len = req_size | 1;// adjust size and set allocated bit
                // Make up a free block at the end
                flp2 = (frlptr)((PTR)flp + req_size);
                flp2->len = size | 1;
                ++mhp->numalloc;
                mhp->largest_blk = 0;
                _nfree( (PTR)flp2 + TAG_SIZE );
            } else {
                flp->len |= 1; // set allocated bit
            }
            return( flp );
        }
    }
    return( NULL );
}
Esempio n. 2
0
static void *RationalAlloc( size_t size )
{
    dpmi_hdr        *dpmi;
    mheapptr        mhp;
    tiny_ret_t      save_DOS_block;
    tiny_ret_t      DOS_block;

    __FreeDPMIBlocks();
    /* size is a multiple of 4k */
    dpmi = TinyDPMIAlloc( size );
    if( dpmi != NULL ) {
        mhp = (mheapptr)( dpmi + 1 );
        mhp->len = size - sizeof( dpmi_hdr );
        dpmi->dos_seg_value = 0;        // indicate DPMI block
        return( (void *)mhp );
    }
    if( __minreal & 0xfff00000 ) {
        /* checks for users that want >1M real memory saved */
        __minreal = 0xfffff;
    }
    if( size > 0x00010000 ) {
        /* cannot allocate more than 64k from DOS real memory */
        return( NULL );
    }
    save_DOS_block = TinyAllocBlock( __ROUND_DOWN_SIZE_TO_PARA( __minreal ) | 1 );
    if( TINY_OK( save_DOS_block ) ) {
        DOS_block = TinyAllocBlock( __ROUND_DOWN_SIZE_TO_PARA( size ) );
        TinyFreeBlock( save_DOS_block );
        if( TINY_OK( DOS_block ) ) {
            dpmi = (dpmi_hdr *)TinyDPMIBase( DOS_block );
            dpmi->dos_seg_value = DOS_block;
            mhp = (mheapptr)( dpmi + 1 );
            mhp->len = size - sizeof( dpmi_hdr );
            return( (void *)mhp );
        }
    }
    return( NULL );
}
Esempio n. 3
0
_WCRTLINK int _nheapshrink( void )
{
    mheapptr mhp;
#if !defined(__WARP__)        && \
    !defined(__WINDOWS_286__) && \
    !defined(__WINDOWS_386__) && \
    !defined(__NT__)          && \
    !defined(__CALL21__)      && \
    !defined(__SNAP__)
    // Shrink by adjusting _curbrk

    frlptr last_free;
    frlptr end_tag;
    unsigned new_brk;

    _AccessNHeap();
    #if defined(__DOS_EXT__)
    if( !_IsRationalZeroBase() && !_IsCodeBuilder() ) {
    #endif
        if( __nheapbeg == NULL ) {
            _ReleaseNHeap();
            return( 0 ); // No near heap, can't shrink
        }
        /* Goto the end of miniheaplist (if there's more than 1 blk) */
        for( mhp = __nheapbeg; mhp->next; mhp = mhp->next );
        /* check that last free block is at end of heap */
        last_free = mhp->freehead.prev;
        end_tag = (frlptr) ( (PTR)last_free + last_free->len );
        if( end_tag->len != END_TAG ) {
            _ReleaseNHeap();
            return( 0 );
        }
        if( end_tag != (frlptr) ((PTR)mhp + mhp->len ) ) {
            _ReleaseNHeap();
            return( 0 );
        }
        #if defined(__DOS_EXT__)
        // only shrink if we can shave off at least 4k
        if( last_free->len < 0x1000 ) {
            _ReleaseNHeap();
            return( 0 );
        }
        #else
        if( last_free->len <= sizeof( frl ) ) {
            _ReleaseNHeap();
            return( 0 );
        }
        #endif
        /* make sure there hasn't been an external change in _curbrk */
        if( sbrk( 0 ) != &(end_tag->prev) ) {
            _ReleaseNHeap();
            return( 0 );
        }
        /* calculate adjustment factor */
        if( mhp->len-last_free->len > sizeof( struct miniheapblkp ) ) {
            // this miniheapblk is still being used
            #if defined(__DOS_EXT__)
                frlptr new_last_free;
                new_last_free = (frlptr)((((unsigned)last_free + 0xfff) & ~0xfff) - TAG_SIZE);
                if( new_last_free == last_free ) {
            #endif
                    // remove entire entry
                    mhp->len -= last_free->len;
                    --mhp->numfree;
                    // Relink the freelist entries, and update the rover
                    mhp->freehead.prev = last_free->prev;
                    last_free->prev->next = &mhp->freehead;
                    if( mhp->rover == last_free ) mhp->rover = last_free->prev;
            #if defined(__DOS_EXT__)
                } else {
                    // just shrink the last free entry
                    mhp->len -= last_free->len;
                    last_free->len = (PTR)new_last_free - (PTR)last_free;
                    mhp->len += last_free->len;
                    last_free = new_last_free;
                }
            #endif
            last_free->len = END_TAG;
            new_brk = (unsigned) ((PTR)last_free + TAG_SIZE );
        } else {
            // we can remove this miniheapblk
            if( mhp->prev ) { // Not the first miniheapblk
                mhp->prev->next = NULL;
                new_brk = (unsigned)mhp;//->prev + (unsigned)mhp->prev->len;
            } else { // Is the first miniheapblk
                new_brk = (unsigned)__nheapbeg;
                __nheapbeg = NULL;
            }
            // Update rover info
            if( __MiniHeapRover == mhp ) {
                __MiniHeapRover = __nheapbeg;
                __LargestSizeB4MiniHeapRover = 0;
            }
        }

        if( __brk( new_brk ) == (void _WCNEAR *) -1 ) {
            _ReleaseNHeap();
            return( -1 );
        }
        _ReleaseNHeap();
        return( 0 );
    #if defined(__DOS_EXT__)
    }
    __FreeDPMIBlocks(); // For RSI/zero-base and Intel CB
    _ReleaseNHeap();
    return( 0 );
    #endif
#else
    // Shrink by releasing mini-heaps
    {
        mheapptr pnext;

        _AccessNHeap();
        for( mhp = __nheapbeg; mhp; mhp = pnext ) {
            pnext = mhp->next;
            if( mhp->len - sizeof(struct miniheapblkp) ==
                (mhp->freehead.prev)->len ) __ReleaseMiniHeap( mhp );
        }
        _ReleaseNHeap();
        return( 0 );
    }
#endif
}