summaryrefslogtreecommitdiffstats
path: root/c/src/exec/score/src/heapextend.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/exec/score/src/heapextend.c')
-rw-r--r--c/src/exec/score/src/heapextend.c113
1 files changed, 113 insertions, 0 deletions
diff --git a/c/src/exec/score/src/heapextend.c b/c/src/exec/score/src/heapextend.c
new file mode 100644
index 0000000000..38b74e66e2
--- /dev/null
+++ b/c/src/exec/score/src/heapextend.c
@@ -0,0 +1,113 @@
+/*
+ * Heap Handler
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+
+#include <rtems/system.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/heap.h>
+
+/*PAGE
+ *
+ * _Heap_Extend
+ *
+ * This routine grows the_heap memory area using the size bytes which
+ * begin at starting_address.
+ *
+ * Input parameters:
+ * the_heap - pointer to heap header.
+ * starting_address - pointer to the memory area.
+ * size - size in bytes of the memory block to allocate.
+ *
+ * Output parameters:
+ * *amount_extended - amount of memory added to the_heap
+ */
+
+Heap_Extend_status _Heap_Extend(
+ Heap_Control *the_heap,
+ void *starting_address,
+ unsigned32 size,
+ unsigned32 *amount_extended
+)
+{
+ Heap_Block *the_block;
+ unsigned32 *p;
+
+ /*
+ * The overhead was taken from the original heap memory.
+ */
+
+ Heap_Block *old_final;
+ Heap_Block *new_final;
+
+ /*
+ * There are five possibilities for the location of starting
+ * address:
+ *
+ * 1. non-contiguous lower address (NOT SUPPORTED)
+ * 2. contiguous lower address (NOT SUPPORTED)
+ * 3. in the heap (ERROR)
+ * 4. contiguous higher address (SUPPORTED)
+ * 5. non-contiguous higher address (NOT SUPPORTED)
+ *
+ * As noted, this code only supports (4).
+ */
+
+ if ( starting_address >= (void *) the_heap->start && /* case 3 */
+ starting_address <= (void *) the_heap->final
+ )
+ return HEAP_EXTEND_ERROR;
+
+ if ( starting_address < (void *) the_heap->start ) { /* cases 1 and 2 */
+
+ return HEAP_EXTEND_NOT_IMPLEMENTED; /* cases 1 and 2 */
+
+ } else { /* cases 4 and 5 */
+
+ the_block = (Heap_Block *)
+ _Addresses_Subtract_offset( starting_address, HEAP_OVERHEAD );
+ if ( the_block != the_heap->final )
+ return HEAP_EXTEND_NOT_IMPLEMENTED; /* case 5 */
+ }
+
+ /*
+ * Currently only case 4 should make it to this point.
+ * The basic trick is to make the extend area look like a used
+ * block and free it.
+ */
+
+ *amount_extended = size;
+
+ old_final = the_heap->final;
+ new_final = _Addresses_Add_offset( old_final, size );
+ /* SAME AS: _Addresses_Add_offset( starting_address, size-HEAP_OVERHEAD ); */
+
+ the_heap->final = new_final;
+
+ old_final->front_flag =
+ new_final->back_flag = _Heap_Build_flag( size, HEAP_BLOCK_USED );
+ new_final->front_flag = HEAP_DUMMY_FLAG;
+
+ /*
+ * Must pass in address of "user" area
+ * So add in the offset field.
+ */
+
+ p = (unsigned32 *) &old_final->next;
+ *p = sizeof(unsigned32);
+ p++;
+ _Heap_Free( the_heap, p );
+
+ return HEAP_EXTEND_SUCCESSFUL;
+}
+