Ticket #746: pr746a.diff

File pr746a.diff, 35.0 KB (added by osv2, on 12/03/06 at 13:31:13)

pr746a.diff

  • ada/rtems.adb

    ? ChangeLog.hold
    RCS file: /usr1/CVS/rtems/cpukit/ada/rtems.adb,v
    retrieving revision 1.17
    diff -u -r1.17 rtems.adb
     
    15051505         Segment,
    15061506         Size_Base'Unchecked_Access
    15071507      );
    1508       Size := SIZE_Base;
     1508      Size := Size_Base;
    15091509
    15101510   end Region_Get_Segment_Size;
    15111511 
     1512   procedure Region_Resize_Segment (
     1513      ID         : in     RTEMS.ID;
     1514      Segment    : in     RTEMS.Address;
     1515      Size       : in     RTEMS.Unsigned32;
     1516      Old_Size   :    out RTEMS.Unsigned32;
     1517      Result     :    out RTEMS.Status_Codes
     1518   ) is
     1519      function Region_Resize_Segment_Base (
     1520         ID       : RTEMS.ID;
     1521         Segment  : RTEMS.Address;
     1522         Size     : RTEMS.Unsigned32;
     1523         Old_Size : access RTEMS.Unsigned32
     1524      )  return RTEMS.Status_Codes;
     1525      pragma Import (C, Region_Resize_Segment_Base,
     1526         "rtems_region_get_segment_size");
     1527      Old_Size_Base : aliased RTEMS.Unsigned32;
     1528   begin
     1529 
     1530      Result := Region_Resize_Segment_Base (
     1531         ID,
     1532         Segment,
     1533         Size,
     1534         Size_Base'Unchecked_Access
     1535      );
     1536      Old_Size := Old_Size_Base;
     1537
     1538   end Region_Resize_Segment;
     1539
    15121540   procedure Region_Return_Segment (
    15131541      ID      : in     RTEMS.ID;
    15141542      Segment : in     RTEMS.Address;
  • ada/rtems.ads

    RCS file: /usr1/CVS/rtems/cpukit/ada/rtems.ads,v
    retrieving revision 1.22
    diff -u -r1.22 rtems.ads
     
    12991299      Result     :    out RTEMS.Status_Codes
    13001300   );
    13011301
     1302   procedure Region_Resize_Segment (
     1303      ID         : in     RTEMS.ID;
     1304      Segment    : in     RTEMS.Address;
     1305      Old_Size   : in     RTEMS.Unsigned32;
     1306      Size       :    out RTEMS.Unsigned32;
     1307      Result     :    out RTEMS.Status_Codes
     1308   );
     1309
    13021310   procedure Region_Return_Segment (
    13031311      ID      : in     RTEMS.ID;
    13041312      Segment : in     RTEMS.Address;
  • libcsupport/src/malloc.c

    RCS file: /usr1/CVS/rtems/cpukit/libcsupport/src/malloc.c,v
    retrieving revision 1.41
    diff -u -r1.41 malloc.c
     
    308308  }
    309309
    310310  /*
    311    * Continue with calloc().
     311   * Continue with realloc().
    312312   */
    313313  if ( !ptr )
    314314    return malloc( size );
     
    318318    return (void *) 0;
    319319  }
    320320
     321  status =
     322    rtems_region_resize_segment( RTEMS_Malloc_Heap, ptr, size, &old_size );
     323
     324  if( status == RTEMS_SUCCESSFUL ) {
     325    return ptr;
     326  }
     327  else if ( status != RTEMS_UNSATISFIED ) {
     328    errno = EINVAL;
     329    return (void *) 0;
     330  }
     331
    321332  new_area = malloc( size );
    322333
    323334  MSBUMP(malloc_calls, -1);   /* subtract off the malloc */
  • rtems/Makefile.am

    RCS file: /usr1/CVS/rtems/cpukit/rtems/Makefile.am,v
    retrieving revision 1.26
    diff -u -r1.26 Makefile.am
     
    105105REGION_C_FILES = src/region.c src/regioncreate.c src/regiondelete.c \
    106106    src/regionextend.c src/regiongetsegment.c src/regiongetsegmentsize.c \
    107107    src/regionident.c src/regionreturnsegment.c src/regiongetinfo.c \
    108     src/regiongetfreeinfo.c
     108    src/regiongetfreeinfo.c src/regionresizesegment.c \
     109    src/regionprocessqueue.c
    109110
    110111PARTITION_C_FILES = src/part.c src/partcreate.c src/partdelete.c \
    111112    src/partgetbuffer.c src/partident.c src/partreturnbuffer.c
  • rtems/include/rtems/rtems/region.h

    RCS file: /usr1/CVS/rtems/cpukit/rtems/include/rtems/rtems/region.h,v
    retrieving revision 1.19
    diff -u -r1.19 region.h
     
    232232  void       *segment
    233233);
    234234
     235/*
     236 *  rtems_region_resize_segment
     237 *
     238 *  DESCRIPTION:
     239 *
     240 *  This routine implements the rtems_region_resize_segment directive.  It
     241 *  tries to resize segment in the region associated with 'id' to the new size
     242 *  'size' in place. The first 'size' or old size bytes of the segment
     243 *  (whatever is less) are guaranteed to remain unmodified. The segment must
     244 *  have been previously allocated from the same region.  If resizing the
     245 *  segment results in enough memory being available to satisfy the
     246 *  rtems_region_get_segment of the first blocked task, then that task and as
     247 *  many subsequent tasks as possible will be unblocked with their requests
     248 *  satisfied.
     249 *  Returns:
     250 *    RTEMS_SUCCESSFUL  - operation successful
     251 *    RTEMS_UNSATISFIED - the segment can't be resized in place
     252 *    any other code    - failure.
     253 *  On RTEMS_SUCCESSFUL or RTEMS_UNSATISFIED exit it returns into the
     254 *  'old_size' the old size in bytes of the user memory area of the specified
     255 *  segment.
     256 */
     257
     258rtems_status_code rtems_region_resize_segment(
     259  Objects_Id  id,
     260  void       *segment,
     261  size_t      size,
     262  size_t     *old_size
     263);
     264
    235265#ifndef __RTEMS_APPLICATION__
    236266#include <rtems/rtems/region.inl>
     267extern void _Region_Process_queue(Region_Control *the_region);
    237268#endif
    238269#if defined(RTEMS_MULTIPROCESSING)
    239270#include <rtems/rtems/regionmp.h>
  • new file rtems/src/regionprocessqueue.c

    RCS file: rtems/src/regionprocessqueue.c
    diff -N rtems/src/regionprocessqueue.c
    - +  
     1/*
     2 *  Region Manager
     3 *
     4 *
     5 *  COPYRIGHT (c) 1989-1999.
     6 *  On-Line Applications Research Corporation (OAR).
     7 *
     8 *  The license and distribution terms for this file may be
     9 *  found in the file LICENSE in this distribution or at
     10 *  http://www.rtems.com/license/LICENSE.
     11 *
     12 *  $Id: $
     13 */
     14
     15#include <rtems/system.h>
     16#include <rtems/rtems/status.h>
     17#include <rtems/rtems/support.h>
     18#include <rtems/score/object.h>
     19#include <rtems/rtems/options.h>
     20#include <rtems/rtems/region.h>
     21#include <rtems/score/states.h>
     22#include <rtems/score/thread.h>
     23#include <rtems/score/apimutex.h>
     24
     25/*PAGE
     26 *
     27 *  _Region_Process_queue
     28 *
     29 *  If enough memory is available to satisfy the rtems_region_get_segment of
     30 *  the first blocked task, then that task and as many subsequent tasks as
     31 *  possible will be unblocked with their requests satisfied.
     32 *
     33 *  Input parameters:
     34 *    the_region - the region
     35 *
     36 *  Output parameters:
     37 *    none
     38 */
     39
     40void _Region_Process_queue(
     41  Region_Control *the_region
     42)
     43{
     44  Thread_Control *the_thread;
     45  void           *the_segment;
     46  /*
     47   *  Switch from using the memory allocation mutex to using a
     48   *  dispatching disabled critical section.  We have to do this
     49   *  because this thread may unblock one or more threads that were
     50   *  waiting on memory. 
     51   *
     52   *  NOTE: Be sure to disable dispatching before unlocking the mutex
     53   *        since we do not want to open a window where a context
     54   *        switch could occur.
     55   */
     56  _Thread_Disable_dispatch();
     57  _RTEMS_Unlock_allocator();
     58
     59  /*
     60   *  NOTE: The following loop is O(n) where n is the number of
     61   *        threads whose memory request is satisfied.
     62   */
     63  for ( ; ; ) {
     64    the_thread = _Thread_queue_First( &the_region->Wait_queue );
     65
     66    if ( the_thread == NULL )
     67      break;
     68
     69    the_segment = (void **) _Region_Allocate_segment(
     70      the_region,
     71      the_thread->Wait.count
     72    );
     73
     74    if ( the_segment == NULL )
     75      break;
     76
     77    *(void **)the_thread->Wait.return_argument = the_segment;
     78    the_region->number_of_used_blocks += 1;
     79    _Thread_queue_Extract( &the_region->Wait_queue, the_thread );
     80    the_thread->Wait.return_code = RTEMS_SUCCESSFUL;
     81  }
     82  _Thread_Enable_dispatch();
     83}
  • new file rtems/src/regionresizesegment.c

    RCS file: rtems/src/regionresizesegment.c
    diff -N rtems/src/regionresizesegment.c
    - +  
     1/*
     2 *  Region Manager
     3 *
     4 *
     5 *  COPYRIGHT (c) 1989-1999.
     6 *  On-Line Applications Research Corporation (OAR).
     7 *
     8 *  The license and distribution terms for this file may be
     9 *  found in the file LICENSE in this distribution or at
     10 *  http://www.rtems.com/license/LICENSE.
     11 *
     12 *  $Id: $
     13 */
     14
     15#if HAVE_CONFIG_H
     16#include "config.h"
     17#endif
     18
     19#include <rtems/system.h>
     20#include <rtems/rtems/status.h>
     21#include <rtems/rtems/support.h>
     22#include <rtems/score/object.h>
     23#include <rtems/rtems/options.h>
     24#include <rtems/rtems/region.h>
     25#include <rtems/score/states.h>
     26#include <rtems/score/thread.h>
     27#include <rtems/score/apimutex.h>
     28
     29/*PAGE
     30 *
     31 *  rtems_region_resize_segment
     32 *
     33 *  This directive will try to resize segment to the new size 'size'
     34 *  "in place".
     35 *
     36 *  Input parameters:
     37 *    id      - region id
     38 *    segment - pointer to segment address
     39 *    size    - new required size
     40 *
     41 *  Output parameters:
     42 *    RTEMS_SUCCESSFUL - if successful
     43 *    error code       - if unsuccessful
     44 */
     45
     46rtems_status_code rtems_region_resize_segment(
     47  Objects_Id  id,
     48  void       *segment,
     49  size_t      size,
     50  size_t     *old_size
     51)
     52{
     53  register Region_Control *the_region;
     54  Objects_Locations        location;
     55  Heap_Resize_status       status;
     56  uint32_t                 avail_size;
     57  uint32_t                 osize;
     58
     59  if ( !old_size )
     60    return RTEMS_INVALID_ADDRESS;
     61
     62  _RTEMS_Lock_allocator();
     63  the_region = _Region_Get( id, &location );
     64  switch ( location ) {
     65
     66    case OBJECTS_REMOTE:        /* this error cannot be returned */
     67      _RTEMS_Unlock_allocator();
     68      return RTEMS_INTERNAL_ERROR;
     69
     70    case OBJECTS_ERROR:
     71      _RTEMS_Unlock_allocator();
     72      return RTEMS_INVALID_ID;
     73
     74    case OBJECTS_LOCAL:
     75
     76      _Region_Debug_Walk( the_region, 7 );
     77
     78      status = _Heap_Resize_block(
     79        &the_region->Memory,
     80        segment,
     81        (uint32_t) size,
     82        &osize,
     83        &avail_size
     84      );
     85      *old_size = (uint32_t) osize;
     86
     87      _Region_Debug_Walk( the_region, 8 );
     88
     89      if( status == HEAP_RESIZE_SUCCESSFUL && avail_size > 0 )
     90        _Region_Process_queue( the_region ); /* unlocks allocator internally */
     91      else
     92        _RTEMS_Unlock_allocator();
     93
     94      return
     95        (status == HEAP_RESIZE_SUCCESSFUL) ?  RTEMS_SUCCESSFUL :
     96        (status == HEAP_RESIZE_UNSATISFIED) ? RTEMS_UNSATISFIED :
     97        RTEMS_INVALID_ADDRESS;
     98  }
     99
     100  return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
     101}
  • rtems/src/regionreturnsegment.c

    RCS file: /usr1/CVS/rtems/cpukit/rtems/src/regionreturnsegment.c,v
    retrieving revision 1.11
    diff -u -r1.11 regionreturnsegment.c
     
    5555)
    5656{
    5757  register Region_Control *the_region;
    58   Thread_Control          *the_thread;
    5958  Objects_Locations        location;
    60   void                   **the_segment;
    6159#ifdef RTEMS_REGION_FREE_SHRED_PATTERN
    6260  uint32_t                 size;
    6361#endif
     
    8179
    8280#ifdef RTEMS_REGION_FREE_SHRED_PATTERN
    8381      if ( _Heap_Size_of_user_area( &the_region->Memory, segment, &size ) ) {
    84         memset(segment, (RTEMS_REGION_FREE_SHRED_PATTERN & 0xFF), size);
     82        memset( segment, (RTEMS_REGION_FREE_SHRED_PATTERN & 0xFF), size );
    8583      } else {
    8684        _RTEMS_Unlock_allocator();
    8785        return RTEMS_INVALID_ADDRESS;
     
    9997
    10098      the_region->number_of_used_blocks -= 1;
    10199
    102       /*
    103        *  Switch from using the memory allocation mutex to using a
    104        *  dispatching disabled critical section.  We have to do this
    105        *  because this thread may unblock one or more threads that were
    106        *  waiting on memory.
    107        *
    108        *  NOTE: The following loop is O(n) where n is the number of
    109        *        threads whose memory request is satisfied.
    110        */
    111       _RTEMS_Unlock_allocator();
    112       _Thread_Disable_dispatch();
    113 
    114       for ( ; ; ) {
    115         the_thread = _Thread_queue_First( &the_region->Wait_queue );
    116 
    117         if ( the_thread == NULL )
    118            break;
    119 
    120         the_segment = (void **) _Region_Allocate_segment(
    121            the_region,
    122            the_thread->Wait.count
    123         );
    124 
    125         if ( the_segment == NULL )
    126            break;
    127 
    128         *(void **)the_thread->Wait.return_argument = the_segment;
    129         the_region->number_of_used_blocks += 1;
    130         _Thread_queue_Extract( &the_region->Wait_queue, the_thread );
    131         the_thread->Wait.return_code = RTEMS_SUCCESSFUL;
    132       }
    133       _Thread_Enable_dispatch();
     100      _Region_Process_queue(the_region); /* unlocks allocator internally */
    134101
    135102      return RTEMS_SUCCESSFUL;
    136103  }
  • score/Makefile.am

    RCS file: /usr1/CVS/rtems/cpukit/score/Makefile.am,v
    retrieving revision 1.27
    diff -u -r1.27 Makefile.am
     
    9898
    9999HEAP_C_FILES = src/heap.c src/heapallocate.c src/heapextend.c src/heapfree.c \
    100100    src/heapsizeofuserarea.c src/heapwalk.c src/heapgetinfo.c \
    101     src/heapgetfreeinfo.c src/heapallocatealigned.c
     101    src/heapgetfreeinfo.c src/heapallocatealigned.c \
     102    src/heapresizeblock.c
    102103
    103104OBJECT_C_FILES = src/object.c src/objectallocate.c \
    104105    src/objectallocatebyindex.c src/objectclearname.c \
  • score/include/rtems/score/heap.h

    RCS file: /usr1/CVS/rtems/cpukit/score/include/rtems/score/heap.h,v
    retrieving revision 1.23
    diff -u -r1.23 heap.h
     
    165165  uint32_t searches;
    166166  /** total number of suceessful calls to free */
    167167  uint32_t frees;
     168  /** total number of successful resizes */
     169  uint32_t resizes;
    168170} Heap_Statistics;
    169171
    170172/**
     
    190192} Heap_Control;
    191193
    192194/**
    193  *  Status codes for heap_extend
     195 *  Status codes for _Heap_Extend
    194196 */
    195197
    196198typedef enum {
     
    200202} Heap_Extend_status;
    201203
    202204/**
     205 *  Status codes for _Heap_Resize_block
     206 */
     207
     208typedef enum {
     209  HEAP_RESIZE_SUCCESSFUL,
     210  HEAP_RESIZE_UNSATISFIED,
     211  HEAP_RESIZE_FATAL_ERROR
     212} Heap_Resize_status;
     213
     214/**
    203215 *  Status codes for _Heap_Get_information
    204216 */
    205217
     
    326338  size_t              *size
    327339);
    328340
     341/*
     342 *  This function tries to resize in place the block that is pointed to by the
     343 *  @a starting_address to the new @a size.
     344 *
     345 *  @param the_heap (in) is the heap to operate upon
     346 *  @param starting_address (in) is the starting address of the user block
     347 *         to be resized
     348 *  @param size (in) is the new size
     349 *  @param old_mem_size (in) points to a user area to return the size of the
     350 *         user memory area of the block before resizing.
     351 *  @param avail_mem_size (in) points to a user area to return the size of
     352 *         the user memory area of the free block that has been enlarged or
     353 *         created due to resizing, 0 if none.
     354 *  @return HEAP_RESIZE_SUCCESSFUL if successfully able to resize the block,
     355 *          HEAP_RESIZE_UNSATISFIED if the block can't be resized in place,
     356 *          HEAP_RESIZE_FATAL_ERROR if failure
     357 *  @return *old_mem_size filled in with the size of the user memory area of
     358 *          the block before resizing.
     359 *  @return *avail_mem_size filled in with the size of the user memory area
     360 *          of the free block that has been enlarged or created due to
     361 *          resizing, 0 if none.
     362 */
     363Heap_Resize_status _Heap_Resize_block(
     364  Heap_Control *the_heap,
     365  void         *starting_address,
     366  uint32_t     size,
     367  uint32_t     *old_mem_size,
     368  uint32_t     *avail_mem_size
     369);
     370
    329371/**
    330372 *  This routine returns the block of memory which begins
    331373 *  at @a starting_address to @a the_heap.  Any coalescing which is
     
    404446  uint32_t page_size,
    405447  uint32_t min_size);
    406448
    407 extern Heap_Block* _Heap_Block_allocate(
     449extern uint32_t _Heap_Block_allocate(
    408450  Heap_Control* the_heap,
    409451  Heap_Block* the_block,
    410452  uint32_t alloc_size);
  • score/src/heap.c

    RCS file: /usr1/CVS/rtems/cpukit/score/src/heap.c,v
    retrieving revision 1.22
    diff -u -r1.22 heap.c
     
    4444 *            |  unused space due to alignment |
    4545 *            |       size < page_size         |
    4646 *         0  +--------------------------------+ <- first block
    47  *            |  prev_size = 1 (arbitrary)     |
     47 *            |  prev_size = page_size         |
    4848 *         4  +--------------------------------+
    4949 *            |  size = size0              | 1 |
    5050 *         8  +---------------------+----------+ <- aligned on page_size
     
    5959 *     size0  +--------------------------------+ <- last dummy block
    6060 *            |  prev_size = size0             |
    6161 *        +4  +--------------------------------+
    62  *            |  size = 0 (arbitrary)      | 0 | <- prev block is free
     62 *            |  size = page_size          | 0 | <- prev block is free
    6363 *        +8  +--------------------------------+ <- aligned on page_size
    6464 *            |  unused space due to alignment |
    6565 *            |       size < page_size         |
     
    7474 *            +--------------------------------+ <- begin = starting_address
    7575 *            |  unused space due to alignment |
    7676 *            |       size < page_size         |
    77  *         0  +--------------------------------+ <- first block
    78  *            |  prev_size = 1 (arbitrary)     |
     77 *         0  +--------------------------------+ <- used block
     78 *            |  prev_size = page_size         |
    7979 *         4  +--------------------------------+
    80  *            |  size = S = size0 - BSIZE  | 1 |
    81  *         8  +---------------------+----------+ <- aligned on page_size
    82  *            |  next = HEAP_TAIL   |          |
    83  *        12  +---------------------+          |
    84  *            |  prev = HEAP_HEAD   |  memory  |
    85  *            +---------------------+          |
    86  *            |                     available  |
    87  *            |                                |
    88  *            |                for allocation  |
    89  *            |                                |
    90  *         S  +--------------------------------+ <- used block
    91  *            |  prev_size = size0 - BSIZE     |
    92  *        +4  +--------------------------------+
    93  *            |  size = BSIZE              | 0 | <- prev block is free
    94  *        +8  +--------------------------------+ <- aligned on page_size
     80 *            |  size = BSIZE              | 1 | <- prev block is used
     81 *         8  +--------------------------------+ <- aligned on page_size
    9582 *            |              .                 | Pointer returned to the user
    96  *            |              .                 | is (S+8) for _Heap_Allocate()
     83 *            |              .                 | is 8 for _Heap_Allocate()
    9784 *            |              .                 | and is in range
    98  * S + 8 +    |         user-accessible        | [S+8,S+8+page_size) for
    99  *   page_size+- - -                      - - -+ _Heap_Allocate_aligned()
     85 * 8 +        |         user-accessible        | [8,8+page_size) for
     86 *  page_size +- - -                      - - -+ _Heap_Allocate_aligned()
    10087 *            |             area               |
    10188 *            |              .                 |
    102  * S + BSIZE  +- - - - -     .        - - - - -+ <- last dummy block
     89 *     BSIZE  +- - - - -     .        - - - - -+ <- free block
    10390 *            |              .                 |
    104  *        +4  +--------------------------------+
    105  *            |  size = 0 (arbitrary)      | 1 | <- prev block is used
    106  *        +8  +--------------------------------+ <- aligned on page_size
     91 * BSIZE  +4  +--------------------------------+
     92 *            |  size = S = size0 - BSIZE  | 1 | <- prev block is used
     93 * BSIZE  +8  +-------------------+------------+ <- aligned on page_size
     94 *            |  next = HEAP_TAIL |            |
     95 * BSIZE +12  +-------------------+            |
     96 *            |  prev = HEAP_HEAD |     memory |
     97 *            +-------------------+            |
     98 *            |                   .  available |
     99 *            |                   .            |
     100 *            |                   .        for |
     101 *            |                   .            |
     102 * BSIZE +S+0 +-------------------+ allocation + <- last dummy block
     103 *            |  prev_size = S    |            |
     104 *       +S+4 +-------------------+------------+
     105 *            |  size = page_size          | 0 | <- prev block is free
     106 *       +S+8 +--------------------------------+ <- aligned on page_size
    107107 *            |  unused space due to alignment |
    108108 *            |       size < page_size         |
    109109 *            +--------------------------------+ <- end = begin + size
     
    160160
    161161  the_block = (Heap_Block *) aligned_start;
    162162
    163   the_block->prev_size = HEAP_PREV_USED;
     163  the_block->prev_size = page_size;
    164164  the_block->size = the_size | HEAP_PREV_USED;
    165165  the_block->next = _Heap_Tail( the_heap );
    166166  the_block->prev = _Heap_Head( the_heap );
     
    175175  the_block = _Heap_Block_at( the_block, the_size );
    176176  the_heap->final = the_block;       /* Permanent final block of the heap */
    177177  the_block->prev_size = the_size;   /* Previous block is free */
    178   the_block->size = 0;  /* This is the only block with size=0  */
     178  the_block->size = page_size;
    179179
    180180  stats->size = size;
    181181  stats->free_size = the_size;
     
    187187  stats->allocs = 0;
    188188  stats->searches = 0;
    189189  stats->frees = 0;
     190  stats->resizes = 0;
    190191  stats->instance = instance++;
    191192
    192193  return ( the_size - HEAP_BLOCK_USED_OVERHEAD );
     
    213214  uint32_t block_size = size + HEAP_BLOCK_USED_OVERHEAD;
    214215  _Heap_Align_up(&block_size, page_size);
    215216  if(block_size < min_size) block_size = min_size;
     217  /* 'block_size' becomes <= 'size' if and only if overflow occured. */
    216218  return (block_size > size) ? block_size : 0;
    217219}
    218220
    219221/*
    220222 * Allocate block of size 'alloc_size' from 'the_block' belonging to
    221  * 'the_heap'. Either split 'the_block' or allocate it entirely.
    222  * Return the block allocated.
     223 * 'the_heap'. Split 'the_block' if possible, otherwise allocate it entirely.
     224 * When split, make the lower part used, and leave the upper part free.
     225 * Return the size of allocated block.
    223226 */
    224 Heap_Block* _Heap_Block_allocate(
     227unsigned32 _Heap_Block_allocate(
    225228  Heap_Control* the_heap,
    226229  Heap_Block* the_block,
    227230  uint32_t alloc_size)
     
    233236  _HAssert(_Heap_Is_aligned(block_size, the_heap->page_size));
    234237  _HAssert(_Heap_Is_aligned(alloc_size, the_heap->page_size));
    235238  _HAssert(alloc_size <= block_size);
     239  _HAssert(_Heap_Is_prev_used(the_block));
    236240
    237241  if(the_rest >= the_heap->min_block_size) {
    238     /* Split the block so that lower part is still free, and upper part
    239        becomes used. */
    240     the_block->size = the_rest | HEAP_PREV_USED;
    241     the_block = _Heap_Block_at(the_block, the_rest);
    242     the_block->prev_size = the_rest;
    243     the_block->size = alloc_size;
     242    /* Split the block so that upper part is still free, and lower part
     243       becomes used. This is slightly less optimal than leaving lower part
     244       free as it requires replacing block in the free blocks list, but it
     245       makes it possible to reuse this code in the _Heap_Resize_block(). */
     246    Heap_Block *next_block = _Heap_Block_at(the_block, alloc_size);
     247    _Heap_Block_replace(the_block, next_block);
     248    the_block->size = alloc_size | HEAP_PREV_USED;
     249    next_block->size = the_rest | HEAP_PREV_USED;
     250    _Heap_Block_at(next_block, the_rest)->prev_size = the_rest;
    244251  }
    245252  else {
    246253    /* Don't split the block as remainder is either zero or too small to be
     
    248255       block and remove the block from the list of free blocks. */
    249256    _Heap_Block_remove(the_block);
    250257    alloc_size = block_size;
     258    _Heap_Block_at(the_block, alloc_size)->size |= HEAP_PREV_USED;
    251259    stats->free_blocks -= 1;
    252260  }
    253   /* Mark the block as used (in the next block). */
    254   _Heap_Block_at(the_block, alloc_size)->size |= HEAP_PREV_USED;
    255261  /* Update statistics */
    256262  stats->free_size -= alloc_size;
    257263  if(stats->min_free_size > stats->free_size)
    258264    stats->min_free_size = stats->free_size;
    259265  stats->used_blocks += 1;
    260   return the_block;
     266  return alloc_size;
    261267}
  • score/src/heapallocate.c

    RCS file: /usr1/CVS/rtems/cpukit/score/src/heapallocate.c,v
    retrieving revision 1.9
    diff -u -r1.9 heapallocate.c
     
    6262    /* Don't bother to mask out the HEAP_PREV_USED bit as it won't change the
    6363       result of the comparison. */
    6464    if(the_block->size >= the_size) {
    65       the_block = _Heap_Block_allocate(the_heap, the_block, the_size );
     65      (void)_Heap_Block_allocate(the_heap, the_block, the_size );
    6666
    6767      ptr = _Heap_User_area(the_block);
    6868
  • score/src/heapallocatealigned.c

    RCS file: /usr1/CVS/rtems/cpukit/score/src/heapallocatealigned.c,v
    retrieving revision 1.2
    diff -u -r1.2 heapallocatealigned.c
     
    172172
    173173          _HAssert(_Heap_Is_aligned_ptr((void*)aligned_user_addr, alignment));
    174174
    175           the_block =
    176             _Heap_Block_allocate(the_heap, the_block, alloc_size);
     175          (void)_Heap_Block_allocate(the_heap, the_block, alloc_size);
    177176
    178177          stats->searches += search_count + 1;
    179178          stats->allocs += 1;
  • score/src/heapfree.c

    RCS file: /usr1/CVS/rtems/cpukit/score/src/heapfree.c,v
    retrieving revision 1.7
    diff -u -r1.7 heapfree.c
     
    5151
    5252  if ( !_Heap_Is_block_in( the_heap, the_block ) ) {
    5353    _HAssert(starting_address == NULL);
     54    _HAssert(FALSE);
    5455    return( FALSE );
    5556  }
    5657
    5758  the_size = _Heap_Block_size( the_block );
    5859  next_block = _Heap_Block_at( the_block, the_size );
    5960
    60   if ( !_Heap_Is_prev_used( next_block ) ) {
     61  if ( !_Heap_Is_block_in( the_heap, next_block ) ) {
    6162    _HAssert(FALSE);
    6263    return( FALSE );
    6364  }
    6465
    65   if ( !_Heap_Is_block_in( the_heap, next_block ) ) {
     66  if ( !_Heap_Is_prev_used( next_block ) ) {
    6667    _HAssert(FALSE);
    6768    return( FALSE );
    6869  }
  • new file score/src/heapresizeblock.c

    RCS file: score/src/heapresizeblock.c
    diff -N score/src/heapresizeblock.c
    - +  
     1/*
     2 *  Heap Handler
     3 *
     4 *  COPYRIGHT (c) 1989-1999.
     5 *  On-Line Applications Research Corporation (OAR).
     6 *
     7 *  The license and distribution terms for this file may be
     8 *  found in the file LICENSE in this distribution or at
     9 *  http://www.rtems.com/license/LICENSE.
     10 *
     11 *  $Id: $
     12 */
     13
     14
     15#include <rtems/system.h>
     16#include <rtems/score/sysstate.h>
     17#include <rtems/score/heap.h>
     18
     19/*
     20 *  _Heap_Resize_block
     21 *
     22 *  DESCRIPTION:
     23 *
     24 *  This routine tries to resize in place the block that is pointed to by the
     25 *  'starting_address' to the new 'size'.
     26 *
     27 *  Input parameters:
     28 *    the_heap         - pointer to heap header
     29 *    starting_address - starting address of the memory block
     30 *    size             - new size
     31 *
     32 *  Output parameters:
     33 *    'old_mem_size'   - the size of the user memory area of the block before
     34 *                       resizing.
     35 *    'avail_mem_size' - the size of the user memory area of the free block
     36 *                       that has been enlarged or created due to resizing,
     37 *                       0 if none.
     38 *    Returns
     39 *      HEAP_RESIZE_SUCCESSFUL  - if success
     40 *      HEAP_RESIZE_UNSATISFIED - if the block can't be resized in place
     41 *      HEAP_RESIZE_FATAL_ERROR - if failure
     42 */
     43
     44Heap_Resize_status _Heap_Resize_block(
     45  Heap_Control *the_heap,
     46  void         *starting_address,
     47  uint32_t      size,
     48  uint32_t     *old_mem_size,
     49  uint32_t     *avail_mem_size
     50)
     51{
     52  Heap_Block *the_block;
     53  Heap_Block *next_block;
     54  uint32_t   next_block_size;
     55  boolean    next_is_used;
     56  Heap_Block *next_next_block;
     57  uint32_t   old_block_size;
     58  uint32_t   old_user_size;
     59  uint32_t   prev_used_flag;
     60  Heap_Statistics *const stats = &the_heap->stats;
     61  uint32_t const min_block_size = the_heap->min_block_size;
     62  uint32_t const page_size = the_heap->page_size;
     63
     64  *old_mem_size = 0;
     65  *avail_mem_size = 0;
     66
     67  _Heap_Start_of_block(the_heap, starting_address, &the_block);
     68  _HAssert(_Heap_Is_block_in(the_heap, the_block));
     69  if (!_Heap_Is_block_in(the_heap, the_block))
     70    return HEAP_RESIZE_FATAL_ERROR;
     71
     72  prev_used_flag = the_block->size & HEAP_PREV_USED;
     73  old_block_size = _Heap_Block_size(the_block);
     74  next_block = _Heap_Block_at(the_block, old_block_size);
     75
     76  _HAssert(_Heap_Is_block_in(the_heap, next_block));
     77  _HAssert(_Heap_Is_prev_used(next_block));
     78  if ( !_Heap_Is_block_in(the_heap, next_block) ||
     79       !_Heap_Is_prev_used(next_block))
     80    return HEAP_RESIZE_FATAL_ERROR;
     81
     82  next_block_size = _Heap_Block_size(next_block);
     83  next_next_block = _Heap_Block_at(next_block, next_block_size);
     84  next_is_used    = (next_block == the_heap->final) ||
     85                     _Heap_Is_prev_used(next_next_block);
     86
     87  /* See _Heap_Size_of_user_area() source for explanations */
     88  old_user_size = _Addresses_Subtract(next_block, starting_address)
     89    + HEAP_BLOCK_HEADER_OFFSET;
     90
     91  *old_mem_size = old_user_size;
     92
     93  if (size > old_user_size) {
     94    /* Need to extend the block: allocate part of the next block and then
     95       merge 'the_block' and allocated block together. */
     96    if (next_is_used)    /* Next block is in use, -- no way to extend */
     97      return HEAP_RESIZE_UNSATISFIED;
     98    else {
     99      uint32_t add_block_size = size - old_user_size;
     100      _Heap_Align_up(&add_block_size, page_size);
     101      if (add_block_size < min_block_size)
     102        add_block_size = min_block_size;
     103      if (add_block_size > next_block_size)
     104        return HEAP_RESIZE_UNSATISFIED; /* Next block is too small or none. */
     105      add_block_size =
     106        _Heap_Block_allocate(the_heap, next_block, add_block_size);
     107      /* Merge two subsequent blocks */
     108      the_block->size = (old_block_size + add_block_size) | prev_used_flag;
     109      --stats->used_blocks;
     110    }
     111  } else {
     112
     113    /* Calculate how much memory we could free */
     114    uint32_t free_block_size = old_user_size - size;
     115    _Heap_Align_down(&free_block_size, page_size);
     116
     117    if (free_block_size > 0) {
     118
     119      /* To free some memory the block should be shortened so that it can
     120         can hold 'size' user bytes and still remain not shorter than
     121         'min_block_size'. */
     122
     123      uint32_t new_block_size = old_block_size - free_block_size;
     124
     125      if (new_block_size < min_block_size) {
     126        uint32_t delta = min_block_size - new_block_size;
     127        _HAssert(free_block_size >= delta);
     128        free_block_size -= delta;
     129        if (free_block_size == 0) {
     130          ++stats->resizes;
     131          return HEAP_RESIZE_SUCCESSFUL;
     132        }
     133        new_block_size += delta;
     134      }
     135
     136      _HAssert(new_block_size >= min_block_size);
     137      _HAssert(new_block_size + free_block_size == old_block_size);
     138      _HAssert(_Heap_Is_aligned(new_block_size, page_size));
     139      _HAssert(_Heap_Is_aligned(free_block_size, page_size));
     140
     141      if (!next_is_used) {
     142        /* Extend the next block to the low addresses by 'free_block_size' */
     143        Heap_Block *const new_next_block =
     144          _Heap_Block_at(the_block, new_block_size);
     145        uint32_t const new_next_block_size =
     146          next_block_size + free_block_size;
     147        _HAssert(_Heap_Is_block_in(the_heap, next_next_block));
     148        the_block->size = new_block_size | prev_used_flag;
     149        new_next_block->size = new_next_block_size | HEAP_PREV_USED;
     150        next_next_block->prev_size = new_next_block_size;
     151        _Heap_Block_replace(next_block, new_next_block);
     152        the_heap->stats.free_size += free_block_size;
     153        *avail_mem_size = new_next_block_size - HEAP_BLOCK_USED_OVERHEAD;
     154
     155      } else if (free_block_size >= min_block_size) {
     156        /* Split the block into 2 used  parts, then free the second one. */
     157        the_block->size = new_block_size | prev_used_flag;
     158        next_block = _Heap_Block_at(the_block, new_block_size);
     159        next_block->size = free_block_size | HEAP_PREV_USED;
     160        ++stats->used_blocks; /* We have created used block */
     161        --stats->frees;       /* Don't count next call in stats */
     162        _Heap_Free(the_heap, _Heap_User_area(next_block));
     163        *avail_mem_size = free_block_size - HEAP_BLOCK_USED_OVERHEAD;
     164      }
     165    }
     166  }
     167
     168  ++stats->resizes;
     169  return HEAP_RESIZE_SUCCESSFUL;
     170}
  • score/src/heapsizeofuserarea.c

    RCS file: /usr1/CVS/rtems/cpukit/score/src/heapsizeofuserarea.c,v
    retrieving revision 1.9
    diff -u -r1.9 heapsizeofuserarea.c
     
    5555
    5656  _Heap_Start_of_block( the_heap, starting_address, &the_block );
    5757
     58  _HAssert(_Heap_Is_block_in( the_heap, the_block ));
    5859  if ( !_Heap_Is_block_in( the_heap, the_block ) )
    5960    return( FALSE );
    6061
    6162  the_size   = _Heap_Block_size( the_block );
    6263  next_block = _Heap_Block_at( the_block, the_size );
    6364
     65  _HAssert(_Heap_Is_block_in( the_heap, next_block ));
     66  _HAssert(_Heap_Is_prev_used( next_block ));
    6467  if (
    6568    !_Heap_Is_block_in( the_heap, next_block ) ||
    6669    !_Heap_Is_prev_used( next_block )
  • score/src/heapwalk.c

    RCS file: /usr1/CVS/rtems/cpukit/score/src/heapwalk.c,v
    retrieving revision 1.6
    diff -u -r1.6 heapwalk.c
     
    8787    error = 1;
    8888  }
    8989
    90   if (the_block->prev_size != HEAP_PREV_USED) {
    91     printf("PASS: %d !prev_size of 1st block isn't HEAP_PREV_USED\n", source);
     90  if (the_block->prev_size != the_heap->page_size) {
     91    printf("PASS: %d !prev_size of 1st block isn't page_size\n", source);
    9292    error = 1;
    9393  }
    9494
     
    162162    error = 1;
    163163  }
    164164
    165   if (_Heap_Block_size(the_block) != 0) {
    166     printf("PASS: %d !last block's size isn't 0\n", source);
     165  if (_Heap_Block_size(the_block) != the_heap->page_size) {
     166    printf("PASS: %d !last block's size isn't page_size\n", source);
    167167    error = 1;
    168168  }
    169169