Exemple #1
0
_WCRTLINK void _WCNEAR *_nexpand( void _WCNEAR *stg, size_t req_size )
    {
        struct {
            unsigned expanded : 1;
        } flags;
        int retval;
        size_t growth_size;

        flags.expanded = 0;
        _AccessNHeap();
        for( ;; ) {
            retval = __HeapManager_expand( _DGroup(),
                                           (unsigned) stg,
                                           req_size,
                                           &growth_size );
            if( retval == __HM_SUCCESS ) {
                _ReleaseNHeap();
                return( stg );
            }
            if( retval == __HM_FAIL || !__IsCtsNHeap() ) break;
            if( retval == __HM_TRYGROW ) {
                if( flags.expanded ) break;
                if( __ExpandDGROUP( growth_size ) == 0 ) {
                    break;
                }
                flags.expanded = 1;
            }
        }
        _ReleaseNHeap();
        return( NULL );
    }
Exemple #2
0
int __ExpandDGROUP( unsigned amount )
{
#if defined(__WINDOWS__) || defined(__WARP__) || defined(__NT__) \
  || defined(__CALL21__) || defined(__RDOS__)
    // first try to free any available storage
    _nheapshrink();
    return( __CreateNewNHeap( amount ) );
#else
    mheapptr    p1;
    frlptr      flp;
    unsigned    brk_value;
    tag         *last_tag;
    unsigned    new_brk_value;
    void        _WCNEAR *brk_ret;

  #if defined(__DOS_EXT__)
    if( !__IsCtsNHeap() ) {
        return( __CreateNewNHeap( amount ) );   // Won't slice either
    }
    // Rational non-zero based system should go through.
  #endif
    if( !__heap_enabled )
        return( 0 );
    if( _curbrk == ~1u )
        return( 0 );
    if( __AdjustAmount( &amount ) == 0 )
        return( 0 );
  #if defined(__DOS_EXT__)
    if( _IsPharLap() && !_IsFlashTek() ) {
        _curbrk = SegmentLimit();
    }
  #endif
    new_brk_value = amount + _curbrk;
    if( new_brk_value < _curbrk ) {
        new_brk_value = ~1u;
    }
    brk_ret = __brk( new_brk_value );
    if( brk_ret == (void _WCNEAR *)-1 ) {
        return( 0 );
    }
    brk_value = (unsigned)brk_ret;
    if( brk_value >  /*0xfff8*/ ~7u ) {
        return( 0 );
    }
    if( new_brk_value <= brk_value ) {
        return( 0 );
    }
    amount = new_brk_value - brk_value;
    if( amount - TAG_SIZE > amount ) {
        return( 0 );
    } else {
        amount -= TAG_SIZE;
    }
    for( p1 = __nheapbeg; p1 != NULL; p1 = p1->next ) {
        if( p1->next == NULL )
            break;
        if( (unsigned)p1 <= brk_value && ((unsigned)p1) + p1->len + TAG_SIZE >= brk_value ) {
            break;
        }
    }
    if( (p1 != NULL) && ((brk_value - TAG_SIZE) == (unsigned)( (PTR)p1 + p1->len) ) ) {
        /* we are extending the previous heap block (slicing) */
        /* nb. account for the end-of-heap tag */
        brk_value -= TAG_SIZE;
        amount += TAG_SIZE;
        flp = (frlptr) brk_value;
        /* adjust current entry in heap list */
        p1->len += amount;
        /* fix up end of heap links */
        last_tag = (tag *) ( (PTR)flp + amount );
        last_tag[0] = END_TAG;
    } else {
        if( amount < sizeof( miniheapblkp ) + sizeof( frl ) ) {
        /*  there isn't enough for a heap block (struct miniheapblkp) and
            one free block (frl) */
            return( 0 );
        }
        // Initializing the near heap if __nheapbeg == NULL,
        // otherwise, a new mini-heap is getting linked up
        p1 = (mheapptr)brk_value;
        p1->len = amount;
        flp = __LinkUpNewMHeap( p1 );
        amount = flp->len;
    }
    /* build a block for _nfree() */
    SET_MEMBLK_SIZE_USED( flp, amount );
    ++p1->numalloc;                         /* 28-dec-90 */
    p1->largest_blk = ~0;    /* set to largest value to be safe */
    _nfree( (PTR)flp + TAG_SIZE );
    return( 1 );
#endif
}
Exemple #3
0
static int __AdjustAmount( unsigned *amount )
{
    unsigned old_amount = *amount;
    unsigned amt;
#if !( defined(__WINDOWS__) || defined(__WARP__) || defined(__NT__) )
    unsigned last_free_amt;
#endif

    amt = old_amount;
    amt = __ROUND_UP_SIZE( amt + TAG_SIZE, ROUND_SIZE );
    if( amt < old_amount ) {
        return( 0 );
    }
#if !( defined(__WINDOWS__) || defined(__WARP__) || defined(__NT__) )
  #if defined(__DOS_EXT__)
    if( !__IsCtsNHeap() ) {
        // Allocating extra to identify the dpmi block
        amt += sizeof( dpmi_hdr );
    } else {
  #endif
        last_free_amt = __LastFree();   /* adjust for last free block */
        if( last_free_amt >= amt ) {
            amt = 0;
        } else {
            amt -= last_free_amt;
        }
  #if defined(__DOS_EXT__)
    }
  #endif
#endif
    /* amount is even here */
    /*
      extra amounts        (22-feb-91 AFS)

       (1) adding a new heap needs:
           frl                    free block req'd for _nmalloc request
                                  (frl is the MINIMUM because the block
                                  may be freed)
           tag                    end of miniheap descriptor
           struct miniheapblkp    start of miniheap descriptor
       (2) extending heap needs:
           tag               free block req'd for _nmalloc request
    */
    *amount = amt;
    amt += ( (TAG_SIZE) + sizeof( frl ) + sizeof( miniheapblkp ) );
    if( amt < *amount )
        return( 0 );            // Report request too large
    if( amt < _amblksiz ) {
        /*
          _amblksiz may not be even so round down to an even number
          nb. pathological case: where _amblksiz == 0xffff, we don't
                                 want the usual round up to even
        */
        amt = __ROUND_DOWN_SIZE( _amblksiz, 2 );
    }
#if defined(__WINDOWS_386__) || defined(__WARP__) || defined(__NT__) \
  || defined(__CALL21__) || defined(__DOS_EXT__) || defined(__RDOS__)
    /* make sure amount is a multiple of 4k/64k */
    *amount = amt;
    amt = __ROUND_UP_SIZE( amt, BLKSIZE_ALIGN );
    if( amt < *amount )
        return( 0 );
#endif
    *amount = amt;
    return( *amount != 0 );
}