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:  Near heap expansion routines.
  28. *
  29. ****************************************************************************/
  30.  
  31.  
  32. //#include "dll.h"        // needs to be first
  33. #include "variety.h"
  34. #include <stddef.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.  
  42. #if defined(__SMALL_DATA__)
  43.  
  44. _WCRTLINK void *_expand( void *stg, size_t amount )
  45. {
  46.     return( _nexpand( stg, amount ) );
  47. }
  48.  
  49. #endif
  50.  
  51. #if defined(__AXP__) || defined(__PPC__)
  52.     #define _SEGMENT int
  53. #else
  54.     #define _SEGMENT __segment
  55. #endif
  56.  
  57. int __HeapManager_expand( _SEGMENT seg,
  58.                           unsigned offset,
  59.                           size_t req_size,
  60.                           size_t *growth_size )
  61. {
  62.     #if defined(M_I86)
  63.         typedef struct freelistp __based(seg) *fptr;
  64.         typedef char __based(void) *cptr;
  65.  
  66.         struct miniheapblkp __based(seg) *hblk;
  67.     #else
  68.         typedef struct freelistp _WCNEAR *fptr;
  69.         typedef char _WCNEAR *cptr;
  70.  
  71.         mheapptr hblk;
  72.     #endif
  73.     fptr        p1;
  74.     fptr        p2;
  75.     fptr        pnext;
  76.     fptr        pprev;
  77.     size_t      new_size;
  78.     size_t      old_size;
  79.     size_t      free_size;
  80.  
  81.     /* round (new_size + tag) to multiple of pointer size */
  82.     new_size = (req_size + TAG_SIZE + ROUND_SIZE) & ~ROUND_SIZE;
  83.     if( new_size < req_size ) new_size = ~0; //go for max
  84.     if( new_size < FRL_SIZE ) {
  85.         new_size = FRL_SIZE;
  86.     }
  87.     p1 = (fptr) ((cptr)offset - TAG_SIZE);
  88.     old_size = p1->len & ~1;
  89.     if( new_size > old_size ) {
  90.         /* enlarging the current allocation */
  91.         p2 = (fptr) ((cptr)p1 + old_size);
  92.         *growth_size = new_size - old_size;
  93.         for(;;) {
  94.             free_size = p2->len;
  95.             if( p2->len == END_TAG ) {
  96.                 return( __HM_TRYGROW );
  97.             } else if( free_size & 1 ) { /* next piece is allocated */
  98.                 break;
  99.             } else {
  100.                 pnext = p2->next;
  101.                 pprev = p2->prev;
  102.  
  103.                 if( seg == _DGroup() ) { // near heap
  104.                     for( hblk = __nheapbeg; hblk->next; hblk = hblk->next ) {
  105.                         if( (fptr)hblk <= (fptr)offset &&
  106.                             (fptr)((PTR)hblk+hblk->len) > (fptr)offset ) break;
  107.                     }
  108.                 }
  109.                 #if defined(M_I86)
  110.                     else {      // Based heap
  111.                         hblk = 0;
  112.                     }
  113.                 #endif
  114.  
  115.                 if( hblk->rover == p2 ) { /* 09-feb-91 */
  116.                     hblk->rover = p2->prev;
  117.                 }
  118.                 if( free_size < *growth_size  ||
  119.                     free_size - *growth_size < FRL_SIZE ) {
  120.                     /* unlink small free block */
  121.                     pprev->next = pnext;
  122.                     pnext->prev = pprev;
  123.                     p1->len += free_size;
  124.                     hblk->numfree--;
  125.                     if( free_size >= *growth_size ) {
  126.                         return( __HM_SUCCESS );
  127.                     }
  128.                     *growth_size -= free_size;
  129.                     p2 = (fptr) ((cptr)p2 + free_size);
  130.                 } else {
  131.                     p2 = (fptr) ((cptr)p2 + *growth_size);
  132.                     p2->len = free_size - *growth_size;
  133.                     p2->prev = pprev;
  134.                     p2->next = pnext;
  135.                     pprev->next = p2;
  136.                     pnext->prev = p2;
  137.                     p1->len += *growth_size;
  138.                     return( __HM_SUCCESS );
  139.                 }
  140.             }
  141.         }
  142.         /* no suitable free blocks behind, have to move block */
  143.         return( __HM_FAIL );
  144.     } else {
  145.         /* shrinking the current allocation */
  146.         if( old_size - new_size >= FRL_SIZE ) {
  147.             /* block big enough to split */
  148.             p1->len = new_size | 1;
  149.             p1 = (fptr) ((cptr)p1 + new_size);
  150.             p1->len = (old_size - new_size) | 1;
  151.             if( seg == _DGroup() ) { // near heap
  152.                 for( hblk = __nheapbeg; hblk->next; hblk = hblk->next ) {
  153.                     if( (fptr)hblk <= (fptr)offset &&
  154.                         (fptr)((PTR)hblk+hblk->len) > (fptr)offset ) break;
  155.                 }
  156.             }
  157.             #if defined(M_I86)
  158.                 else    // Based heap
  159.                     hblk = 0;
  160.             #endif
  161.             /* _bfree will decrement 'numalloc' 08-jul-91 */
  162.             hblk->numalloc++;
  163.             #if defined(M_I86)
  164.                 _bfree( seg, (cptr)p1 + TAG_SIZE );
  165.                 /* free the top portion */
  166.             #else
  167.                 _nfree( (cptr)p1 + TAG_SIZE );
  168.             #endif
  169.         }
  170.     }
  171.     return( __HM_SUCCESS );
  172. }
  173.  
  174.  
  175. _WCRTLINK void _WCNEAR *_nexpand( void _WCNEAR *stg, size_t req_size )
  176.     {
  177.         struct {
  178.             unsigned expanded : 1;
  179.         } flags;
  180.         int retval;
  181.         size_t growth_size;
  182.  
  183.         flags.expanded = 0;
  184.         _AccessNHeap();
  185.         for( ;; ) {
  186.             retval = __HeapManager_expand( _DGroup(),
  187.                                            (unsigned) stg,
  188.                                            req_size,
  189.                                            &growth_size );
  190.             if( retval == __HM_SUCCESS ) {
  191.                 _ReleaseNHeap();
  192.                 return( stg );
  193.             }
  194.             if( retval == __HM_FAIL || !__IsCtsNHeap() ) break;
  195.             if( retval == __HM_TRYGROW ) {
  196.                 if( flags.expanded ) break;
  197.                 if( __ExpandDGROUP( growth_size ) == 0 ) {
  198.                     break;
  199.                 }
  200.                 flags.expanded = 1;
  201.             }
  202.         }
  203.         _ReleaseNHeap();
  204.         return( NULL );
  205.     }
  206.