void _WCNEAR *__brk( unsigned brk_value ) { unsigned old_brk_value; unsigned seg_size; __segment segment; if( brk_value < _STACKTOP ) { _RWD_errno = ENOMEM; return( (void _WCNEAR *)-1 ); } seg_size = ( brk_value + 0x0f ) >> 4; if( seg_size == 0 ) { seg_size = 0x1000; } /* try setting the block of memory */ _AccessNHeap(); segment = _DGroup(); if( qnx_segment_realloc( segment,((unsigned long)seg_size) << 4) == -1 ) { _RWD_errno = ENOMEM; _ReleaseNHeap(); return( (void _WCNEAR *)-1 ); } old_brk_value = _curbrk; /* return old value of _curbrk */ _curbrk = brk_value; /* set new break value */ _ReleaseNHeap(); return( (void _WCNEAR *)old_brk_value ); }
_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 ); }
_WCRTLINK void_nptr __brk( unsigned brk_value ) { unsigned old_brk_value; unsigned sys_brk_value; /* try setting the block of memory */ _AccessNHeap(); sys_brk_value = sys_brk( brk_value ); if( sys_brk_value == -1 ) { _RWD_errno = ENOMEM; _ReleaseNHeap(); return( (void_nptr)-1 ); } if( _curbrk == 0 ) { _curbrk = sys_brk_value; brk_value = sys_brk_value; } old_brk_value = _curbrk; /* return old value of _curbrk */ _curbrk = brk_value; /* set new break value */ _ReleaseNHeap(); return( (void_nptr)old_brk_value ); }
_WCRTLINK int _nheapchk( void ) { struct _heapinfo hi; int heap_status; size_t free_size; _AccessNHeap(); heap_status = checkFreeList( &free_size ); if( heap_status != _HEAPOK ) { _ReleaseNHeap(); return( heap_status ); } hi._pentry = NULL; for(;;) { heap_status = __NHeapWalk( &hi, __nheapbeg ); if( heap_status != _HEAPOK ) break; if( hi._useflag == _FREEENTRY ) { heap_status = checkFree( (frlptr) hi._pentry ); if( heap_status != _HEAPOK ) break; free_size -= hi._size; } } if( free_size != 0 ) { heap_status = _HEAPBADNODE; } else if( heap_status == _HEAPBADPTR ) { heap_status = _HEAPBADNODE; } else { if( heap_status == _HEAPEND ) { heap_status = _HEAPOK; } } _ReleaseNHeap(); return( heap_status ); }
_WCRTLINK int _use_os2_high_mem( int fUseHighMem ) { int prior; _AccessNHeap(); prior = _os2_use_obj_any; _os2_use_obj_any = fUseHighMem; _ReleaseNHeap(); return( prior ); }
_WCRTLINK int _nheapwalk( struct _heapinfo *entry ) { int heap_status; _AccessNHeap(); heap_status = __NHeapWalk( entry, __nheapbeg ); _ReleaseNHeap(); return( heap_status ); }
_WCRTLINK void *_os2hmalloc( size_t amount ) { int prior; void _WCNEAR *ptr; _AccessNHeap(); prior = _use_os2_high_mem( 1 ); ptr = _nmalloc( amount ); _use_os2_high_mem(prior); _ReleaseNHeap(); return( ptr ); }
_WCRTLINK void _nheapgrow( void ) { #if defined( __WINDOWS_286__ ) || !defined( _M_I86 ) _nfree( _nmalloc( 1 ) ); /* get something into the heap */ #else unsigned max_paras; unsigned curr_paras; unsigned diff_paras; unsigned expand; _AccessNHeap(); /* calculate # pages which always has extra slack space (ie. 0x10) */ curr_paras = (( _curbrk + 0x10 ) & ~0x0f ) >> 4; if( curr_paras == 0 ) { /* we're already at 64k */ _ReleaseNHeap(); return; } #if defined(__QNX__) if( qnx_segment_realloc( _DGroup(), 65536L ) == -1 ) { _ReleaseNHeap(); return; } max_paras = PARAS_IN_64K; #elif defined(__OS2__) if( DosReallocSeg( 0, _DGroup() ) ) { _ReleaseNHeap(); return; } max_paras = PARAS_IN_64K; #else if( _RWD_osmode != DOS_MODE ) { /* 23-apr-91 */ max_paras = PARAS_IN_64K; } else { max_paras = TinyMaxSet( _RWD_psp ); /* subtract off code size */ max_paras -= _DGroup() - _RWD_psp; if( max_paras > PARAS_IN_64K ) { max_paras = PARAS_IN_64K; } } #endif if( max_paras <= curr_paras ) { /* '<' -> something is wrong, '==' -> can't change size */ _ReleaseNHeap(); return; } diff_paras = max_paras - curr_paras; expand = (( diff_paras + 1 ) << 4 ) - ( _curbrk & 0x0f ); expand += __LastFree(); /* compensate for _expand's adjustment */ _ReleaseNHeap(); _nfree( _nmalloc( expand - ( sizeof( size_t ) + sizeof(frl) ) ) ); #endif }
void __FreeAllHeaps( void ) { mheapptr mhp; mheapptr pnext; // Free all the mini heaps back to OS _AccessNHeap(); for( mhp = __nheapbeg; mhp; mhp = pnext ) { pnext = mhp->next; __ReleaseMiniHeap( mhp ); } _ReleaseNHeap(); }
_WCRTLINK size_t _memmax( void ) /* return size of largest free piece from near heap */ { size_t maxlen, size; frlptr pnext; mheapptr mhp; maxlen = 0; _AccessNHeap(); for( mhp = __nheapbeg; mhp != NULL; mhp = mhp->next ) { pnext = mhp->freehead.next; while( pnext != (frlptr) &mhp->freehead ) { size = ((pnext->len - TAG_SIZE) & ~ROUND_SIZE); if( size > maxlen ) maxlen = size; pnext = pnext->next; } } _ReleaseNHeap(); return( maxlen ); }
_WCRTLINK void _WCNEAR *_nmalloc( size_t amt ) { unsigned largest; unsigned size; unsigned ptr; unsigned char expanded; mheapptr miniheap_ptr; # if defined(__WARP__) int use_obj_any; # endif // __WARP__ if( (amt == 0) || (amt > -sizeof(struct heapblk)) ) { return( (void _WCNEAR *)NULL ); } // Try to determine which miniheap to begin allocating from. // first, round up the amount size = (amt + TAG_SIZE + ROUND_SIZE) & ~ROUND_SIZE; if( size < FRL_SIZE ) { size = FRL_SIZE; } _AccessNHeap(); ptr = 0; expanded = 0; for(;;) { # if defined(__WARP__) // Need to update each pass in case 1st DosAllocMem determines OBJ_ANY not supported use_obj_any = _os2_obj_any_supported && _os2_use_obj_any; # endif // Figure out where to start looking for free blocks if( size > __LargestSizeB4MiniHeapRover ) { miniheap_ptr = __MiniHeapRover; if( miniheap_ptr == NULL ) { __LargestSizeB4MiniHeapRover = 0; // force to be updated miniheap_ptr = __nheapbeg; } } else { __LargestSizeB4MiniHeapRover = 0; // force to be updated miniheap_ptr = __nheapbeg; } // Search for free block for(;;) { if( miniheap_ptr == NULL ) { break; // Expand heap and retry maybe } __MiniHeapRover = miniheap_ptr; largest = miniheap_ptr->largest_blk; # if defined(__WARP__) if( use_obj_any == ( miniheap_ptr->used_obj_any != 0 ) ) { # endif // __WARP__ if( largest >= amt ) { ptr = __MemAllocator( amt, _DGroup(), (unsigned)miniheap_ptr ); if( ptr != 0 ) { goto lbl_release_heap; } } # if defined(__WARP__) } # endif // __WARP__ if( largest > __LargestSizeB4MiniHeapRover ) { __LargestSizeB4MiniHeapRover = largest; } miniheap_ptr = miniheap_ptr->next; } /* forever */ // OS/2 only - if not block of requested type, will allocate one and find in 2nd pass // Try to expand heap and retry if( expanded || !__ExpandDGROUP( amt ) ) { if( !__nmemneed( amt ) ) { break; // give up } expanded = 0; } else { expanded = 1; } } /* forever */ lbl_release_heap: _ReleaseNHeap(); return( (void _WCNEAR *)ptr ); }
_WCRTLINK void _nfree( void _WCNEAR *stg ) { mheapptr p1,p2; if( !stg ) return; _AccessNHeap(); do { // first try some likely locations p1 = __MiniHeapFreeRover; if( p1 ) { if( (PTR)p1 <= (PTR)stg && (PTR)p1+p1->len > (PTR)stg ) { break; } p2 = p1; p1 = p1->prev; if( p1 ) { if( (PTR)p1 <= (PTR)stg && (PTR)p1+p1->len > (PTR)stg ) { break; } } p1 = p2->next; if( p1 ) { if( (PTR)p1 <= (PTR)stg && (PTR)p1+p1->len > (PTR)stg ) { break; } } } p1 = __MiniHeapRover; if( p1 ) { if( (PTR)p1 <= (PTR)stg && (PTR)p1+p1->len > (PTR)stg ) { break; } p2 = p1; p1 = p1->prev; if( p1 ) { if( (PTR)p1 <= (PTR)stg && (PTR)p1+p1->len > (PTR)stg ) { break; } } p1 = p2->next; if( p1 ) { if( (PTR)p1 <= (PTR)stg && (PTR)p1+p1->len > (PTR)stg ) { break; } } } // not found near rover, so search the list for( p1 = __nheapbeg; p1; p1 = p1->next ) { if( (PTR)p1 <= (PTR)stg && (PTR)p1+p1->len > (PTR)stg ) { // break twice! goto found_it; } } // this pointer is not in the heap _ReleaseNHeap(); return; } while( 0 ); found_it: // we found the miniheap, free the storage __MemFree( (unsigned)stg, _DGroup(), (unsigned) p1 ); __MiniHeapFreeRover = p1; if( p1 < __MiniHeapRover ) { if( p1->largest_blk > __LargestSizeB4MiniHeapRover ) { __LargestSizeB4MiniHeapRover = p1->largest_blk; } } _ReleaseNHeap(); }
_WCRTLINK void _nfree( void_nptr cstg ) { heapblk_nptr heap; heapblk_nptr heap2; if( cstg == NULL ) return; _AccessNHeap(); do { // first try some likely locations heap = __MiniHeapFreeRover; if( heap != NULL ) { if( IS_IN_HEAP( cstg, heap ) ) { break; } heap2 = heap; heap = heap->prev.nptr; if( heap != NULL ) { if( IS_IN_HEAP( cstg, heap ) ) { break; } } heap = heap2->next.nptr; if( heap != NULL ) { if( IS_IN_HEAP( cstg, heap ) ) { break; } } } heap = __MiniHeapRover; if( heap != NULL ) { if( IS_IN_HEAP( cstg, heap ) ) { break; } heap2 = heap; heap = heap->prev.nptr; if( heap != NULL ) { if( IS_IN_HEAP( cstg, heap ) ) { break; } } heap = heap2->next.nptr; if( heap != NULL ) { if( IS_IN_HEAP( cstg, heap ) ) { break; } } } // not found near rover, so search the list for( heap = __nheapbeg; heap != NULL; heap = heap->next.nptr ) { if( IS_IN_HEAP( cstg, heap ) ) { // break twice! goto found_it; } } // this pointer is not in the heap _ReleaseNHeap(); return; } while( 0 ); found_it: // we found the miniheap, free the storage #ifdef _M_I86 __MemFree( cstg, _DGroup(), heap ); #else __MemFree( cstg, heap ); #endif __MiniHeapFreeRover = heap; if( heap < __MiniHeapRover ) { if( __LargestSizeB4MiniHeapRover < heap->largest_blk ) { __LargestSizeB4MiniHeapRover = heap->largest_blk; } } _ReleaseNHeap(); }
_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 }