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 ); }
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 ); }
_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 }