Skip to content

Commit 8730005

Browse files
author
Arto Kinnunen
committed
Squashed 'features/frameworks/nanostack-libservice/' changes from dd98c37..9af7568
9af7568 Merge pull request #87 from ARMmbed/sync_with_mbedos 5c16e57 (via Mbed OS) ns_list: avoid UINT_FAST8_MAX 36b4ace nsdynmenlib API to add memory region to heap (#86) git-subtree-dir: features/frameworks/nanostack-libservice git-subtree-split: 9af756886f082ef8a26372fae5a337203395457f
1 parent d53d1df commit 8730005

File tree

4 files changed

+406
-39
lines changed

4 files changed

+406
-39
lines changed

mbed-client-libservice/ns_list.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ union \
148148
{ \
149149
ns_list_t slist; \
150150
NS_FUNNY_COMPARE_OK \
151-
NS_STATIC_ASSERT(link_offset <= UINT_FAST8_MAX, "link offset too large") \
151+
NS_STATIC_ASSERT(link_offset <= (ns_list_offset_t) -1, "link offset too large") \
152152
NS_FUNNY_COMPARE_RESTORE \
153153
char (*offset)[link_offset + 1]; \
154154
entry_type *type; \

mbed-client-libservice/nsdynmemLIB.h

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
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.
@@ -71,11 +71,25 @@ typedef struct ns_mem_book ns_mem_book_t;
7171
* \brief Init and set Dynamical heap pointer and length.
7272
*
7373
* \param heap_ptr Pointer to dynamically heap buffer
74-
* \param heap_size size of the heap buffer
74+
* \param h_size size of the heap buffer
75+
* \param passed_fptr pointer to heap error callback function
76+
* \param info_ptr Pointer to mem_stat_t for memory statistics. Can be NULL.
77+
*
7578
* \return None
7679
*/
77-
extern void ns_dyn_mem_init(void *heap, ns_mem_heap_size_t h_size, void (*passed_fptr)(heap_fail_t), mem_stat_t *info_ptr);
80+
extern void ns_dyn_mem_init(void *heap_ptr, ns_mem_heap_size_t h_size, void (*passed_fptr)(heap_fail_t), mem_stat_t *info_ptr);
7881

82+
/**
83+
* \brief Add memory region to initialized heap.
84+
*
85+
* This method adds memory region to already initialized heap.
86+
* Method will reset temporary heap threshold to the default value.
87+
*
88+
* \param region_ptr Pointer to memory region to be added
89+
* \param region_size size of the region buffer
90+
* \return 0 on success, <0 in case of errors.
91+
*/
92+
extern int ns_dyn_mem_region_add(void *region_ptr, ns_mem_heap_size_t region_size);
7993

8094
/**
8195
* \brief Free allocated memory.
@@ -86,6 +100,7 @@ extern void ns_dyn_mem_init(void *heap, ns_mem_heap_size_t h_size, void (*passed
86100
* \return <0, Free Fail
87101
*/
88102
extern void ns_dyn_mem_free(void *heap_ptr);
103+
89104
/**
90105
* \brief Allocate temporary data.
91106
*
@@ -97,6 +112,7 @@ extern void ns_dyn_mem_free(void *heap_ptr);
97112
* \return >0, Pointer to allocated data sector.
98113
*/
99114
extern void *ns_dyn_mem_temporary_alloc(ns_mem_block_size_t alloc_size);
115+
100116
/**
101117
* \brief Allocate long period data.
102118
*
@@ -118,7 +134,7 @@ extern void *ns_dyn_mem_alloc(ns_mem_block_size_t alloc_size);
118134
* Note: the caller may not modify the returned structure.
119135
*
120136
* \return NULL, no mem_stat_t was given on initialization
121-
* \return !=0, Pointer to mem_stat_t.
137+
* \return Pointer to mem_stat_t or NULL.
122138
*/
123139
extern const mem_stat_t *ns_dyn_mem_get_mem_stat(void);
124140

@@ -139,11 +155,27 @@ extern int ns_dyn_mem_set_temporary_alloc_free_heap_threshold(uint8_t free_heap_
139155
/**
140156
* \brief Init and set Dynamical heap pointer and length.
141157
*
142-
* \param heap_ptr Pointer to dynamically heap buffer
143-
* \param heap_size size of the heap buffer
144-
* \return !=0, Pointer to ns_mem_book_t.
158+
* \param heap_ptr Pointer to dynamically heap buffer.
159+
* \param h_size size of the heap buffer.
160+
* \param passed_fptr pointer to heap error callback function.
161+
* \param info_ptr Pointer to mem_stat_t for memory statistics. Can be NULL.
162+
* \return Pointer to ns_mem_book_t.
145163
*/
146-
extern ns_mem_book_t *ns_mem_init(void *heap, ns_mem_heap_size_t h_size, void (*passed_fptr)(heap_fail_t), mem_stat_t *info_ptr);
164+
extern ns_mem_book_t *ns_mem_init(void *heap_ptr, ns_mem_heap_size_t h_size, void (*passed_fptr)(heap_fail_t), mem_stat_t *info_ptr);
165+
166+
/**
167+
* \brief Add memory region to initialized heap.
168+
*
169+
* This method adds memory region to already initialized heap.
170+
* Method will reset temporary heap threshold to the default value.
171+
*
172+
* \param book Address of book keeping structure.
173+
* \param region_ptr Pointer to memory region buffer.
174+
* \param region_size size of the memory region to add
175+
*
176+
* \return 0 on success, <0 in case of errors.
177+
*/
178+
extern int ns_mem_region_add(ns_mem_book_t *book, void *region_ptr, ns_mem_heap_size_t region_size);
147179

148180
/**
149181
* \brief Free allocated memory.
@@ -155,6 +187,7 @@ extern ns_mem_book_t *ns_mem_init(void *heap, ns_mem_heap_size_t h_size, void (*
155187
* \return <0, Free Fail
156188
*/
157189
extern void ns_mem_free(ns_mem_book_t *book, void *heap_ptr);
190+
158191
/**
159192
* \brief Allocate temporary data.
160193
*
@@ -167,6 +200,7 @@ extern void ns_mem_free(ns_mem_book_t *book, void *heap_ptr);
167200
* \return >0, Pointer to allocated data sector.
168201
*/
169202
extern void *ns_mem_temporary_alloc(ns_mem_book_t *book, ns_mem_block_size_t alloc_size);
203+
170204
/**
171205
* \brief Allocate long period data.
172206
*

source/nsdynmemLIB/nsdynmemLIB.c

Lines changed: 153 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
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

3434
typedef 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 */
3740
struct 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

73106
void 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+
79117
const 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-
89126
ns_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+
138254
const 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

212328
static 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+
460598
void 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

Comments
 (0)