11/*
2- * Copyright (c) 2014-2018 ARM Limited. All rights reserved.
2+ * Copyright (c) 2014-2019 ARM Limited. All rights reserved.
33 * SPDX-License-Identifier: Apache-2.0
44 * Licensed under the Apache License, Version 2.0 (the License); you may
55 * not use this file except in compliance with the License.
@@ -33,10 +33,13 @@ typedef struct {
3333
3434typedef int ns_mem_word_size_t ; // internal signed heap block size type
3535
36+ // Amount of memory regions
37+ #define REGION_COUNT 3
38+
3639/* struct for book keeping variables */
3740struct ns_mem_book {
38- ns_mem_word_size_t * heap_main ;
39- ns_mem_word_size_t * heap_main_end ;
41+ ns_mem_word_size_t * heap_main [ REGION_COUNT ] ;
42+ ns_mem_word_size_t * heap_main_end [ REGION_COUNT ] ;
4043 mem_stat_t * mem_stat_info_ptr ;
4144 void (* heap_failure_callback )(heap_fail_t );
4245 NS_LIST_HEAD (hole_t , link ) holes_list ;
@@ -68,14 +71,49 @@ static void heap_failure(ns_mem_book_t *book, heap_fail_t reason)
6871 }
6972}
7073
71- #endif
74+ static int ns_dyn_mem_region_find (ns_mem_book_t * book , ns_mem_word_size_t * block_ptr , ns_mem_word_size_t size )
75+ {
76+ int index ;
77+ for (index = 0 ; index < REGION_COUNT ; index ++ ) {
78+ if (book -> heap_main [index ] != 0 ) {
79+ if ((block_ptr >= book -> heap_main [index ]) &&
80+ (block_ptr < book -> heap_main_end [index ]) &&
81+ ((block_ptr + size ) < book -> heap_main_end [index ])) {
82+ return index ;
83+ }
84+ }
85+ }
86+
87+ return -1 ;
88+ }
89+
90+ static int ns_dyn_mem_region_save (ns_mem_book_t * book , ns_mem_word_size_t * region_start_ptr , ns_mem_word_size_t region_size )
91+ {
92+ for (int i = 1 ; i < REGION_COUNT ; i ++ ) {
93+ if (book -> heap_main [i ] == 0 ) {
94+ book -> heap_main [i ] = region_start_ptr ;
95+ book -> heap_main_end [i ] = book -> heap_main [i ] + region_size ;
96+ return 0 ;
97+ }
98+ }
99+
100+ return -1 ;
101+ }
102+
103+
104+ #endif //STANDARD_MALLOC
72105
73106void ns_dyn_mem_init (void * heap , ns_mem_heap_size_t h_size ,
74107 void (* passed_fptr )(heap_fail_t ), mem_stat_t * info_ptr )
75108{
76109 default_book = ns_mem_init (heap , h_size , passed_fptr , info_ptr );
77110}
78111
112+ int ns_dyn_mem_region_add (void * region_ptr , ns_mem_heap_size_t region_size )
113+ {
114+ return ns_mem_region_add (default_book , region_ptr , region_size );
115+ }
116+
79117const mem_stat_t * ns_dyn_mem_get_mem_stat (void )
80118{
81119#ifndef STANDARD_MALLOC
@@ -85,7 +123,6 @@ const mem_stat_t *ns_dyn_mem_get_mem_stat(void)
85123#endif
86124}
87125
88-
89126ns_mem_book_t * ns_mem_init (void * heap , ns_mem_heap_size_t h_size ,
90127 void (* passed_fptr )(heap_fail_t ),
91128 mem_stat_t * info_ptr )
@@ -107,19 +144,23 @@ ns_mem_book_t *ns_mem_init(void *heap, ns_mem_heap_size_t h_size,
107144 if (temp_int ) {
108145 h_size -= (sizeof (ns_mem_word_size_t ) - temp_int );
109146 }
147+
110148 book = heap ;
111- book -> heap_main = (ns_mem_word_size_t * ) & (book [1 ]); // SET Heap Pointer
149+ memset (book -> heap_main , 0 , REGION_COUNT * sizeof (ns_mem_word_size_t * ));
150+ memset (book -> heap_main_end , 0 , REGION_COUNT * sizeof (ns_mem_word_size_t * ));
151+
152+ book -> heap_main [0 ] = (ns_mem_word_size_t * ) & (book [1 ]); // SET Heap Pointer
112153 book -> heap_size = h_size - sizeof (ns_mem_book_t ); //Set Heap Size
113154 temp_int = (book -> heap_size / sizeof (ns_mem_word_size_t ));
114155 temp_int -= 2 ;
115- ptr = book -> heap_main ;
156+ ptr = book -> heap_main [ 0 ] ;
116157 * ptr = - (temp_int );
117158 ptr += (temp_int + 1 );
118159 * ptr = - (temp_int );
119- book -> heap_main_end = ptr ;
160+ book -> heap_main_end [ 0 ] = ptr ;
120161
121162 ns_list_init (& book -> holes_list );
122- ns_list_add_to_start (& book -> holes_list , hole_from_block_start (book -> heap_main ));
163+ ns_list_add_to_start (& book -> holes_list , hole_from_block_start (book -> heap_main [ 0 ] ));
123164
124165 book -> mem_stat_info_ptr = info_ptr ;
125166 //RESET Memory by Hea Len
@@ -135,6 +176,81 @@ ns_mem_book_t *ns_mem_init(void *heap, ns_mem_heap_size_t h_size,
135176 return book ;
136177}
137178
179+ int ns_mem_region_add (ns_mem_book_t * book , void * region_ptr , ns_mem_heap_size_t region_size )
180+ {
181+ #ifndef STANDARD_MALLOC
182+ if (!book || !region_ptr || region_size < 3 * sizeof (ns_mem_word_size_t )) {
183+ return -1 ;
184+ }
185+
186+ ns_mem_word_size_t * block_ptr ;
187+ ns_mem_word_size_t temp_int ;
188+
189+ /* Do memory alignment */
190+ temp_int = ((uintptr_t )region_ptr % sizeof (ns_mem_word_size_t ));
191+ if (temp_int ) {
192+ region_ptr = (uint8_t * ) region_ptr + (sizeof (ns_mem_word_size_t ) - temp_int );
193+ region_size -= (sizeof (ns_mem_word_size_t ) - temp_int );
194+ }
195+
196+ /* Make correction for total length */
197+ temp_int = (region_size % sizeof (ns_mem_word_size_t ));
198+ if (temp_int ) {
199+ region_size -= (sizeof (ns_mem_word_size_t ) - temp_int );
200+ }
201+
202+ // Create hole from new heap memory
203+ temp_int = (region_size / sizeof (ns_mem_word_size_t ));
204+ temp_int -= 2 ;
205+ block_ptr = region_ptr ;
206+ * block_ptr = - (temp_int );
207+ block_ptr += (temp_int + 1 ); // now block_ptr points to end of block
208+ * block_ptr = - (temp_int );
209+
210+ // find place for the new hole from the holes list
211+ hole_t * hole_to_add = hole_from_block_start (region_ptr );
212+ hole_t * previous_hole = NULL ;
213+ ns_list_foreach (hole_t , hole_in_list_ptr , & book -> holes_list ) {
214+ if (hole_in_list_ptr < hole_to_add ) {
215+ previous_hole = hole_in_list_ptr ;
216+ } else if (hole_in_list_ptr == hole_to_add ) {
217+ // trying to add memory block that is already in the list!
218+ return -2 ;
219+ }
220+ }
221+
222+ // save region
223+ if (ns_dyn_mem_region_save (book , region_ptr , (region_size / (sizeof (ns_mem_word_size_t ))) - 1 ) != 0 ) {
224+ return -3 ;
225+ }
226+
227+ // Add new hole to the list
228+ if (previous_hole ) {
229+ ns_list_add_after (& book -> holes_list , previous_hole , hole_to_add );
230+ } else {
231+ ns_list_add_to_start (& book -> holes_list , hole_to_add );
232+ }
233+
234+ // adjust total heap size with new hole
235+ book -> heap_size += region_size ;
236+
237+ if (book -> mem_stat_info_ptr ) {
238+ book -> mem_stat_info_ptr -> heap_sector_size = book -> heap_size ;
239+ }
240+
241+ // adjust temporary allocation limits to match new heap
242+ book -> temporary_alloc_heap_limit = book -> heap_size / 100 * (100 - TEMPORARY_ALLOC_FREE_HEAP_THRESHOLD );
243+
244+ return 0 ;
245+ #else
246+ (void ) book ;
247+ (void ) region_ptr ;
248+ (void ) region_size ;
249+
250+ return -1 ;
251+ #endif
252+ }
253+
138254const mem_stat_t * ns_mem_get_mem_stat (ns_mem_book_t * heap )
139255{
140256#ifndef STANDARD_MALLOC
@@ -211,7 +327,7 @@ static void dev_stat_update(mem_stat_t *mem_stat_info_ptr, mem_stat_update_t typ
211327
212328static ns_mem_word_size_t convert_allocation_size (ns_mem_book_t * book , ns_mem_block_size_t requested_bytes )
213329{
214- if (book -> heap_main == 0 ) {
330+ if (book -> heap_main [ 0 ] == 0 ) {
215331 heap_failure (book , NS_DYN_MEM_HEAP_SECTOR_UNITIALIZED );
216332 } else if (requested_bytes < 1 ) {
217333 heap_failure (book , NS_DYN_MEM_ALLOCATE_SIZE_NOT_VALID );
@@ -329,7 +445,6 @@ static void *ns_mem_internal_alloc(ns_mem_book_t *book, const ns_mem_block_size_
329445 if (block_ptr ) {
330446 //Update Allocate OK
331447 dev_stat_update (book -> mem_stat_info_ptr , DEV_HEAP_ALLOC_OK , (data_size + 2 ) * sizeof (ns_mem_word_size_t ));
332-
333448 } else {
334449 //Update Allocate Fail, second parameter is used for stats
335450 dev_stat_update (book -> mem_stat_info_ptr , DEV_HEAP_ALLOC_FAIL , 0 );
@@ -381,12 +496,25 @@ static void ns_mem_free_and_merge_with_adjacent_blocks(ns_mem_book_t *book, ns_m
381496 hole_t * existing_end = NULL ;
382497 ns_mem_word_size_t * start = cur_block ;
383498 ns_mem_word_size_t * end = cur_block + data_size + 1 ;
499+ ns_mem_word_size_t * region_start ;
500+ ns_mem_word_size_t * region_end ;
501+
502+ int region_index = ns_dyn_mem_region_find (book , cur_block , data_size );
503+ if (region_index >= 0 ) {
504+ region_start = book -> heap_main [region_index ];
505+ region_end = book -> heap_main_end [region_index ];
506+ } else {
507+ heap_failure (book , NS_DYN_MEM_HEAP_SECTOR_CORRUPTED );
508+ // can't find region for the block, return
509+ return ;
510+ }
511+
384512 //invalidate current block
385513 * start = - data_size ;
386514 * end = - data_size ;
387515 ns_mem_word_size_t merged_data_size = data_size ;
388516
389- if (start != book -> heap_main ) {
517+ if (start != region_start ) {
390518 if (* (start - 1 ) < 0 ) {
391519 ns_mem_word_size_t * block_end = start - 1 ;
392520 ns_mem_word_size_t block_size = 1 + (- * block_end ) + 1 ;
@@ -401,7 +529,7 @@ static void ns_mem_free_and_merge_with_adjacent_blocks(ns_mem_book_t *book, ns_m
401529 }
402530 }
403531
404- if (end != book -> heap_main_end ) {
532+ if (end != region_end ) {
405533 if (* (end + 1 ) < 0 ) {
406534 ns_mem_word_size_t * block_start = end + 1 ;
407535 ns_mem_word_size_t block_size = 1 + (- * block_start ) + 1 ;
@@ -457,6 +585,16 @@ static void ns_mem_free_and_merge_with_adjacent_blocks(ns_mem_book_t *book, ns_m
457585}
458586#endif
459587
588+ static bool pointer_address_validate (ns_mem_book_t * book , ns_mem_word_size_t * ptr , ns_mem_word_size_t size )
589+ {
590+
591+ if (ns_dyn_mem_region_find (book , ptr , size ) >= 0 ) {
592+ return true;
593+ }
594+
595+ return false;
596+ }
597+
460598void ns_mem_free (ns_mem_book_t * book , void * block )
461599{
462600#ifndef STANDARD_MALLOC
@@ -472,9 +610,7 @@ void ns_mem_free(ns_mem_book_t *book, void *block)
472610 ptr -- ;
473611 //Read Current Size
474612 size = * ptr ;
475- if (ptr < book -> heap_main || ptr >= book -> heap_main_end ) {
476- heap_failure (book , NS_DYN_MEM_POINTER_NOT_VALID );
477- } else if ((ptr + size ) >= book -> heap_main_end ) {
613+ if (!pointer_address_validate (book , ptr , size )) {
478614 heap_failure (book , NS_DYN_MEM_POINTER_NOT_VALID );
479615 } else if (size < 0 ) {
480616 heap_failure (book , NS_DYN_MEM_DOUBLE_FREE );
@@ -489,6 +625,7 @@ void ns_mem_free(ns_mem_book_t *book, void *block)
489625 }
490626 }
491627 }
628+
492629 platform_exit_critical ();
493630#else
494631 platform_enter_critical ();
0 commit comments