Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /****************************************************************************
  2. *
  3. *                            Open Watcom Project
  4. *
  5. *    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
  6. *
  7. *  ========================================================================
  8. *
  9. *    This file contains Original Code and/or Modifications of Original
  10. *    Code as defined in and that are subject to the Sybase Open Watcom
  11. *    Public License version 1.0 (the 'License'). You may not use this file
  12. *    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
  13. *    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
  14. *    provided with the Original Code and Modifications, and is also
  15. *    available at www.sybase.com/developer/opensource.
  16. *
  17. *    The Original Code and all software distributed under the License are
  18. *    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  19. *    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
  20. *    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
  21. *    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
  22. *    NON-INFRINGEMENT. Please see the License for the specific language
  23. *    governing rights and limitations under the License.
  24. *
  25. *  ========================================================================
  26. *
  27. * Description:  Implementation of near _heapmin() and _nheapmin().
  28. *
  29. ****************************************************************************/
  30.  
  31.  
  32. //#include "dll.h"        // needs to be first
  33. #include "variety.h"
  34. #include <stddef.h>
  35. #include <stdlib.h>
  36. #include <malloc.h>
  37. #include "heap.h"
  38. #include "heapacc.h"
  39. #if defined(__DOS_EXT__)
  40. // #include "extender.h"
  41. #endif
  42. #if defined(__WINDOWS_286__) || defined(__NT__)
  43. int _stdcall UserFree(void* p);  
  44. // #include "windows.h"
  45. #endif
  46. #if defined(__OS2__)
  47. // #include <wos2.h>
  48. #endif
  49. #if defined(__WINDOWS_386__)
  50. // extern int __pascal DPMIFree(unsigned long);   // windows extender function
  51. #endif
  52. #if defined(__CALL21__)
  53. // #include "tinyio.h"
  54. #endif
  55.  
  56. #if defined(__SMALL_DATA__)
  57.  
  58. _WCRTLINK int _heapshrink( void )
  59. {
  60.     return( _nheapshrink() );
  61. }
  62.  
  63. _WCRTLINK int _heapmin( void )
  64. {
  65.     return( _nheapshrink() );
  66. }
  67.  
  68. #endif
  69.  
  70. _WCRTLINK int _nheapmin( void )
  71. {
  72.     return( _nheapshrink() );
  73. }
  74.  
  75. #if defined(__WARP__)        || \
  76.     defined(__WINDOWS_286__) || \
  77.     defined(__WINDOWS_386__) || \
  78.     defined(__NT__)          || \
  79.     defined(__CALL21__)
  80. static int __ReturnMemToSystem( mheapptr mhp )
  81. {
  82.         mheapptr pnext;
  83.  
  84.         pnext = mhp->next;
  85. #if defined(__WARP__)
  86.         if( DosFreeMem( (PBYTE)mhp ) ) return( -1 );
  87. #elif defined(__NT__)
  88.         //if( LocalFree( (HLOCAL)mhp ) != NULL ) return( -1 );
  89. //        if (!VirtualFree(mhp, 0, MEM_RELEASE))
  90. //            return -1;
  91.         if(!UserFree(mhp))
  92.           return -1;
  93.              
  94. #elif defined(__WINDOWS_386__)
  95.         if( DPMIFree( (unsigned long)mhp ) != 0 ) return( -1 );
  96. #elif defined(__WINDOWS_286__)
  97.         if( LocalFree( (HLOCAL)mhp ) != NULL ) return( -1 );
  98. #elif defined(__CALL21__)
  99.         // No way to free storage under OSI
  100.         if( mhp ) return( -1 );
  101. #endif
  102.         if( __MiniHeapRover == mhp ) {  // Update rovers
  103.             if( pnext ) {
  104.                 __MiniHeapRover = pnext;
  105.             } else {
  106.                 __MiniHeapRover = __nheapbeg;
  107.                 __LargestSizeB4MiniHeapRover = 0;
  108.             }
  109.         }
  110.         if( __MiniHeapFreeRover == mhp ) {
  111.             __MiniHeapFreeRover = 0;
  112.         }
  113.         return( 0 ); // success
  114. }
  115.  
  116. static void __ReleaseMiniHeap( mheapptr mhp )
  117. {
  118.     mheapptr pprev;
  119.     mheapptr pnext;
  120.  
  121.     pprev = mhp->prev;
  122.     pnext = mhp->next;
  123.     if( __ReturnMemToSystem( mhp ) == 0 ) {
  124.         if( pprev == NULL ) {
  125.             __nheapbeg = pnext;
  126.         } else {
  127.             pprev->next = pnext;
  128.         }
  129.         if( pnext != NULL )  pnext->prev = pprev;
  130.     } //else: do not unlink if the memory cannot be freed successfully
  131. }
  132.  
  133. #endif
  134.  
  135. _WCRTLINK int _nheapshrink( void )
  136. {
  137.     mheapptr mhp;
  138. #if !defined(__WARP__)        && \
  139.     !defined(__WINDOWS_286__) && \
  140.     !defined(__WINDOWS_386__) && \
  141.     !defined(__NT__)          && \
  142.     !defined(__CALL21__)
  143.     // Shrink by adjusting _curbrk
  144.  
  145.     frlptr last_free;
  146.     frlptr end_tag;
  147.     unsigned new_brk;
  148.  
  149.     _AccessNHeap();
  150.     #if defined(__DOS_EXT__)
  151.     if( !_IsRationalZeroBase() && !_IsCodeBuilder() ) {
  152.     #endif
  153.         if( __nheapbeg == NULL ) {
  154.             _ReleaseNHeap();
  155.             return( 0 ); // No near heap, can't shrink
  156.         }
  157.         /* Goto the end of miniheaplist (if there's more than 1 blk) */
  158.         for( mhp = __nheapbeg; mhp->next; mhp = mhp->next );
  159.         /* check that last free block is at end of heap */
  160.         last_free = mhp->freehead.prev;
  161.         end_tag = (frlptr) ( (PTR)last_free + last_free->len );
  162.         if( end_tag->len != END_TAG ) {
  163.             _ReleaseNHeap();
  164.             return( 0 );
  165.         }
  166.         if( end_tag != (frlptr) ((PTR)mhp + mhp->len ) ) {
  167.             _ReleaseNHeap();
  168.             return( 0 );
  169.         }
  170.         #if defined(__DOS_EXT__)
  171.         // only shrink if we can shave off at least 4k
  172.         if( last_free->len < 0x1000 ) {
  173.             _ReleaseNHeap();
  174.             return( 0 );
  175.         }
  176.         #else
  177.         if( last_free->len <= sizeof( frl ) ) {
  178.             _ReleaseNHeap();
  179.             return( 0 );
  180.         }
  181.         #endif
  182.         /* make sure there hasn't been an external change in _curbrk */
  183.         if( sbrk( 0 ) != &(end_tag->prev) ) {
  184.             _ReleaseNHeap();
  185.             return( 0 );
  186.         }
  187.         /* calculate adjustment factor */
  188.         if( mhp->len-last_free->len > sizeof( struct miniheapblkp ) ) {
  189.             // this miniheapblk is still being used
  190.             #if defined(__DOS_EXT__)
  191.                 frlptr new_last_free;
  192.                 new_last_free = (frlptr)((((unsigned)last_free + 0xfff) & ~0xfff) - TAG_SIZE);
  193.                 if( new_last_free == last_free ) {
  194.             #endif
  195.                     // remove entire entry
  196.                     mhp->len -= last_free->len;
  197.                     --mhp->numfree;
  198.                     // Relink the freelist entries, and update the rover
  199.                     mhp->freehead.prev = last_free->prev;
  200.                     last_free->prev->next = &mhp->freehead;
  201.                     if( mhp->rover == last_free ) mhp->rover = last_free->prev;
  202.             #if defined(__DOS_EXT__)
  203.                 } else {
  204.                     // just shrink the last free entry
  205.                     mhp->len -= last_free->len;
  206.                     last_free->len = (PTR)new_last_free - (PTR)last_free;
  207.                     mhp->len += last_free->len;
  208.                     last_free = new_last_free;
  209.                 }
  210.             #endif
  211.             last_free->len = END_TAG;
  212.             new_brk = (unsigned) ((PTR)last_free + TAG_SIZE );
  213.         } else {
  214.             // we can remove this miniheapblk
  215.             if( mhp->prev ) { // Not the first miniheapblk
  216.                 mhp->prev->next = NULL;
  217.                 new_brk = (unsigned)mhp;//->prev + (unsigned)mhp->prev->len;
  218.             } else { // Is the first miniheapblk
  219.                 new_brk = (unsigned)__nheapbeg;
  220.                 __nheapbeg = NULL;
  221.             }
  222.             // Update rover info
  223.             if( __MiniHeapRover == mhp ) {
  224.                 __MiniHeapRover = __nheapbeg;
  225.                 __LargestSizeB4MiniHeapRover = 0;
  226.             }
  227.         }
  228.  
  229.         if( __brk( new_brk ) == (void _WCNEAR *) -1 ) {
  230.             _ReleaseNHeap();
  231.             return( -1 );
  232.         }
  233.         _ReleaseNHeap();
  234.         return( 0 );
  235.     #if defined(__DOS_EXT__)
  236.     }
  237.     __FreeDPMIBlocks(); // For RSI/zero-base and Intel CB
  238.     _ReleaseNHeap();
  239.     return( 0 );
  240.     #endif
  241. #else
  242.     // Shrink by releasing mini-heaps
  243.     {
  244.         mheapptr pnext;
  245.  
  246.         _AccessNHeap();
  247.         for( mhp = __nheapbeg; mhp; mhp = pnext ) {
  248.             pnext = mhp->next;
  249.             if( mhp->len - sizeof(struct miniheapblkp) ==
  250.                 (mhp->freehead.prev)->len ) __ReleaseMiniHeap( mhp );
  251.         }
  252.         _ReleaseNHeap();
  253.         return( 0 );
  254.     }
  255. #endif
  256. }
  257.