summaryrefslogtreecommitdiffstats
path: root/cpukit/score/include/rtems/score/heap.h
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2005-05-20 19:15:41 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2005-05-20 19:15:41 +0000
commit80f2885b70bca394c002241c119a0fca7add2a42 (patch)
tree59dfc9a04bbf39cd637826ade7fc51e2a5c8a37f /cpukit/score/include/rtems/score/heap.h
parent2005-05-20 Joel Sherrill <joel@OARcorp.com> (diff)
downloadrtems-80f2885b70bca394c002241c119a0fca7add2a42.tar.bz2
2005-05-14 Sergei Organov <osv@topconrd.ru>
PR 746/rtems Optimize realloc(). The problem is that realloc() can neither grow nor shrink efficiently the current memory region without support from underlying heap/region modules. The patch introduces one new routine for each of heap and region modules, _Heap_Resize_block(), and rtems_region_resize_segment(), respectively, and uses the latter to optimize realloc(). The implementation of _Heap_Resize_block() lead to changing of the heap allocation strategy: now the heap manager, when splits larger free block into used and new free parts, makes the first part of the block used, not the last one as it was before. Due to this new strategy, _Heap_Resize_block() never needs to change the user pointer. Caveat: unlike previous heap implementation, first few bytes of the contents of the memory allocated from the heap are now almost never all zero. This can trigger bugs in client code that have not been visible before this patch. * libcsupport/src/malloc.c (realloc): try to resize segment in place using new rtems_region_resize_segment() routine before falling back to the malloc()/free() method. * score/src/heap.c: (_Heap_Initialize): change initial heap layout to reflect new allocation strategy of using of the lower part of a previously free block when splitting it for the purpose of allocation. (_Heap_Block_allocate): when split, make the lower part used, and leave the upper part free. Return type changed from Heap_Block* to uint32_t. * score/include/rtems/score/heap.h: (Heap_Statistics): added 'resizes' field. (Heap_Resize_status): new enum. (_Heap_Resize_block): new routine. (_Heap_Block_allocate): return type changed from Heap_Block* to uint32_t. * score/src/heapwalk.c: reflect new heap layout in checks. * score/src/heapsizeofuserarea.c: more assertions added. * score/src/heapresizeblock.c: new file. (_Heap_Resize_block): new routine. * score/src/heapfree.c: reverse the checks _Heap_Is_block_in() and _Heap_Is_prev_used() on entry to be in this order. * score/src/heapallocate.c, score/src/heapallocatealigned.c: ignore return value of _Heap_Block_allocate(). * score/Makefile.am (HEAP_C_FILES): added src/heapresizeblock.c. * rtems/include/rtems/rtems/region.h: (rtems_region_resize_segment): new interface routine. (_Region_Process_queue): new internal routine called from rtems_region_resize_segment() and rtems_region_return_segment(). * rtems/src/regionreturnsegment.c: move queue management code into the new internal routine _Region_Process_queue() and call it. * rtems/src/regionresizesegment.c: new file. (rtems_region_resize_segment): new interface routine. * rtems/src/regionprocessqueue.c: new file. (_Region_Process_queue): new internal routine containing queue management code factored out from 'regionreturnsegment.c'. * rtems/Makefile.am (REGION_C_FILES): Added src/regionresizesegment.c, and src/regionprocessqueue.c. * ada/rtems.adb, ada/rtems.ads: Added Region_Resize_Segment.
Diffstat (limited to '')
-rw-r--r--cpukit/score/include/rtems/score/heap.h46
1 files changed, 44 insertions, 2 deletions
diff --git a/cpukit/score/include/rtems/score/heap.h b/cpukit/score/include/rtems/score/heap.h
index da0aea361d..4ec7396854 100644
--- a/cpukit/score/include/rtems/score/heap.h
+++ b/cpukit/score/include/rtems/score/heap.h
@@ -165,6 +165,8 @@ typedef struct Heap_Statistics_tag {
uint32_t searches;
/** total number of suceessful calls to free */
uint32_t frees;
+ /** total number of successful resizes */
+ uint32_t resizes;
} Heap_Statistics;
/**
@@ -190,7 +192,7 @@ typedef struct {
} Heap_Control;
/**
- * Status codes for heap_extend
+ * Status codes for _Heap_Extend
*/
typedef enum {
@@ -200,6 +202,16 @@ typedef enum {
} Heap_Extend_status;
/**
+ * Status codes for _Heap_Resize_block
+ */
+
+typedef enum {
+ HEAP_RESIZE_SUCCESSFUL,
+ HEAP_RESIZE_UNSATISFIED,
+ HEAP_RESIZE_FATAL_ERROR
+} Heap_Resize_status;
+
+/**
* Status codes for _Heap_Get_information
*/
@@ -326,6 +338,36 @@ boolean _Heap_Size_of_user_area(
size_t *size
);
+/*
+ * This function tries to resize in place the block that is pointed to by the
+ * @a starting_address to the new @a size.
+ *
+ * @param the_heap (in) is the heap to operate upon
+ * @param starting_address (in) is the starting address of the user block
+ * to be resized
+ * @param size (in) is the new size
+ * @param old_mem_size (in) points to a user area to return the size of the
+ * user memory area of the block before resizing.
+ * @param avail_mem_size (in) points to a user area to return the size of
+ * the user memory area of the free block that has been enlarged or
+ * created due to resizing, 0 if none.
+ * @return HEAP_RESIZE_SUCCESSFUL if successfully able to resize the block,
+ * HEAP_RESIZE_UNSATISFIED if the block can't be resized in place,
+ * HEAP_RESIZE_FATAL_ERROR if failure
+ * @return *old_mem_size filled in with the size of the user memory area of
+ * the block before resizing.
+ * @return *avail_mem_size filled in with the size of the user memory area
+ * of the free block that has been enlarged or created due to
+ * resizing, 0 if none.
+ */
+Heap_Resize_status _Heap_Resize_block(
+ Heap_Control *the_heap,
+ void *starting_address,
+ uint32_t size,
+ uint32_t *old_mem_size,
+ uint32_t *avail_mem_size
+);
+
/**
* This routine returns the block of memory which begins
* at @a starting_address to @a the_heap. Any coalescing which is
@@ -404,7 +446,7 @@ extern uint32_t _Heap_Calc_block_size(
uint32_t page_size,
uint32_t min_size);
-extern Heap_Block* _Heap_Block_allocate(
+extern uint32_t _Heap_Block_allocate(
Heap_Control* the_heap,
Heap_Block* the_block,
uint32_t alloc_size);