Subversion Repositories Kolibri OS

Rev

Rev 553 | Blame | Compare with Previous | 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 "variety.h"
  33. #include <stddef.h>
  34. #include <stdlib.h>
  35. #include <malloc.h>
  36. #include "heap.h"
  37. #include "heapacc.h"
  38. #if defined(__DOS_EXT__)
  39. // #include "extender.h"
  40. #endif
  41. #if defined(__WINDOWS_286__) || defined(__NT__)
  42.  #include "kolibri.h"
  43. #endif
  44. #if defined(__OS2__)
  45. // #include <wos2.h>
  46. #endif
  47. #if defined(__WINDOWS_386__)
  48. // extern int __pascal DPMIFree(unsigned long);   // windows extender function
  49. #endif
  50. #if defined(__CALL21__)
  51. // #include "tinyio.h"
  52. #endif
  53.  
  54. #if defined(__SMALL_DATA__)
  55.  
  56. _WCRTLINK int _heapshrink( void )
  57. {
  58.     return( _nheapshrink() );
  59. }
  60.  
  61. _WCRTLINK int _heapmin( void )
  62. {
  63.     return( _nheapshrink() );
  64. }
  65.  
  66. #endif
  67.  
  68. _WCRTLINK int _nheapmin( void )
  69. {
  70.     return( _nheapshrink() );
  71. }
  72.  
  73. #if defined(__WARP__)        || \
  74.     defined(__WINDOWS_286__) || \
  75.     defined(__WINDOWS_386__) || \
  76.     defined(__NT__)          || \
  77.     defined(__CALL21__)
  78.  
  79. static void __ReleaseMiniHeap( mheapptr mhp )
  80. {
  81.     mheapptr pprev;
  82.     mheapptr pnext;
  83.  
  84.     pprev = mhp->prev;
  85.     pnext = mhp->next;
  86.     if( user_free( mhp ) == 1 ) {
  87.         if( pprev == NULL ) {
  88.             __nheapbeg = pnext;
  89.         } else {
  90.             pprev->next = pnext;
  91.         }
  92.         if( pnext != NULL )  pnext->prev = pprev;
  93.     } //else: do not unlink if the memory cannot be freed successfully
  94. }
  95.  
  96. #endif
  97.  
  98. _WCRTLINK int _nheapshrink( void )
  99. {
  100.     mheapptr mhp;
  101. #if !defined(__WARP__)        && \
  102.     !defined(__WINDOWS_286__) && \
  103.     !defined(__WINDOWS_386__) && \
  104.     !defined(__NT__)          && \
  105.     !defined(__CALL21__)
  106.     // Shrink by adjusting _curbrk
  107.  
  108.     frlptr last_free;
  109.     frlptr end_tag;
  110.     unsigned new_brk;
  111.  
  112.     _AccessNHeap();
  113.     #if defined(__DOS_EXT__)
  114.     if( !_IsRationalZeroBase() && !_IsCodeBuilder() ) {
  115.     #endif
  116.         if( __nheapbeg == NULL ) {
  117.             _ReleaseNHeap();
  118.             return( 0 ); // No near heap, can't shrink
  119.         }
  120.         /* Goto the end of miniheaplist (if there's more than 1 blk) */
  121.         for( mhp = __nheapbeg; mhp->next; mhp = mhp->next );
  122.         /* check that last free block is at end of heap */
  123.         last_free = mhp->freehead.prev;
  124.         end_tag = (frlptr) ( (PTR)last_free + last_free->len );
  125.         if( end_tag->len != END_TAG ) {
  126.             _ReleaseNHeap();
  127.             return( 0 );
  128.         }
  129.         if( end_tag != (frlptr) ((PTR)mhp + mhp->len ) ) {
  130.             _ReleaseNHeap();
  131.             return( 0 );
  132.         }
  133.         #if defined(__DOS_EXT__)
  134.         // only shrink if we can shave off at least 4k
  135.         if( last_free->len < 0x1000 ) {
  136.             _ReleaseNHeap();
  137.             return( 0 );
  138.         }
  139.         #else
  140.         if( last_free->len <= sizeof( frl ) ) {
  141.             _ReleaseNHeap();
  142.             return( 0 );
  143.         }
  144.         #endif
  145.         /* make sure there hasn't been an external change in _curbrk */
  146.         if( sbrk( 0 ) != &(end_tag->prev) ) {
  147.             _ReleaseNHeap();
  148.             return( 0 );
  149.         }
  150.         /* calculate adjustment factor */
  151.         if( mhp->len-last_free->len > sizeof( struct miniheapblkp ) ) {
  152.             // this miniheapblk is still being used
  153.             #if defined(__DOS_EXT__)
  154.                 frlptr new_last_free;
  155.                 new_last_free = (frlptr)((((unsigned)last_free + 0xfff) & ~0xfff) - TAG_SIZE);
  156.                 if( new_last_free == last_free ) {
  157.             #endif
  158.                     // remove entire entry
  159.                     mhp->len -= last_free->len;
  160.                     --mhp->numfree;
  161.                     // Relink the freelist entries, and update the rover
  162.                     mhp->freehead.prev = last_free->prev;
  163.                     last_free->prev->next = &mhp->freehead;
  164.                     if( mhp->rover == last_free ) mhp->rover = last_free->prev;
  165.             #if defined(__DOS_EXT__)
  166.                 } else {
  167.                     // just shrink the last free entry
  168.                     mhp->len -= last_free->len;
  169.                     last_free->len = (PTR)new_last_free - (PTR)last_free;
  170.                     mhp->len += last_free->len;
  171.                     last_free = new_last_free;
  172.                 }
  173.             #endif
  174.             last_free->len = END_TAG;
  175.             new_brk = (unsigned) ((PTR)last_free + TAG_SIZE );
  176.         } else {
  177.             // we can remove this miniheapblk
  178.             if( mhp->prev ) { // Not the first miniheapblk
  179.                 mhp->prev->next = NULL;
  180.                 new_brk = (unsigned)mhp;//->prev + (unsigned)mhp->prev->len;
  181.             } else { // Is the first miniheapblk
  182.                 new_brk = (unsigned)__nheapbeg;
  183.                 __nheapbeg = NULL;
  184.             }
  185.             // Update rover info
  186.             if( __MiniHeapRover == mhp ) {
  187.                 __MiniHeapRover = __nheapbeg;
  188.                 __LargestSizeB4MiniHeapRover = 0;
  189.             }
  190.         }
  191.  
  192.         if( __brk( new_brk ) == (void _WCNEAR *) -1 ) {
  193.             _ReleaseNHeap();
  194.             return( -1 );
  195.         }
  196.         _ReleaseNHeap();
  197.         return( 0 );
  198.     #if defined(__DOS_EXT__)
  199.     }
  200.     __FreeDPMIBlocks(); // For RSI/zero-base and Intel CB
  201.     _ReleaseNHeap();
  202.     return( 0 );
  203.     #endif
  204. #else
  205.     // Shrink by releasing mini-heaps
  206.     {
  207.         mheapptr pnext;
  208.  
  209.         _AccessNHeap();
  210.         for( mhp = __nheapbeg; mhp; mhp = pnext ) {
  211.             pnext = mhp->next;
  212.             if( mhp->len - sizeof(struct miniheapblkp) ==
  213.                 (mhp->freehead.prev)->len ) __ReleaseMiniHeap( mhp );
  214.         }
  215.         _ReleaseNHeap();
  216.         return( 0 );
  217.     }
  218. #endif
  219. }
  220.