Skip to content

Commit 084b722

Browse files
author
Arto Kinnunen
committed
Squashed 'connectivity/libraries/nanostack-libservice/' changes from 67d7b93ec6..a526cc3f41
a526cc3f41 Merge pull request ARMmbed#97 from PelionIoT/sync_from_mbed_os 2f82569918 Add license notice to Arm copyrighted source files ad7631083a Merge pull request ARMmbed#96 from PelionIoT/heap_lite_stats 18b742b2c7 Heap stat's enabled allways by default. 9b4cbaf101 Added extended block list to dynamic memory tracker (ARMmbed#95) 8ff6d31abb Added dynamic memory tracker and hooks to dynmem library (ARMmbed#93) cf2b133082 Merge pull request ARMmbed#92 from LDong-Arm/add_present_flag 9eb6f2dde7 Add config to generate macro MBED_CONF_NANOSTACK_LIBSERVICE_PRESENT git-subtree-dir: connectivity/libraries/nanostack-libservice git-subtree-split: a526cc3f41bfd0ec6a78e6998b8f8dcc1bd2afc9
1 parent 70e2f11 commit 084b722

File tree

12 files changed

+743
-44
lines changed

12 files changed

+743
-44
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ source/libip6string/ip6tos.c \
55
source/libip6string/stoip6.c \
66
source/libList/ns_list.c \
77
source/nsdynmemLIB/nsdynmemLIB.c \
8+
source/nsdynmemtracker/nsdynmem_tracker_lib.c \
89
source/nvmHelper/ns_nvm_helper.c \
910

1011
LIB := libservice.a

mbed-client-libservice/nsdynmemLIB.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ extern "C" {
3737
typedef size_t ns_mem_block_size_t; //external interface unsigned heap block size type
3838
typedef size_t ns_mem_heap_size_t; //total heap size type.
3939

40+
// Can be used to enable tracking of dynamic memory allocations
41+
#include "nsdynmem_tracker.h"
42+
4043
/*!
4144
* \enum heap_fail_t
4245
* \brief Dynamically heap system failure call back event types.
@@ -64,7 +67,6 @@ typedef struct mem_stat_t {
6467
uint32_t heap_alloc_fail_cnt; /**< Counter for Heap allocation fail. */
6568
} mem_stat_t;
6669

67-
6870
typedef struct ns_mem_book ns_mem_book_t;
6971

7072
/**
@@ -99,7 +101,9 @@ extern int ns_dyn_mem_region_add(void *region_ptr, ns_mem_heap_size_t region_siz
99101
* \return 0, Free OK
100102
* \return <0, Free Fail
101103
*/
104+
#if NSDYNMEM_TRACKER_ENABLED!=1
102105
extern void ns_dyn_mem_free(void *heap_ptr);
106+
#endif
103107

104108
/**
105109
* \brief Allocate temporary data.
@@ -111,7 +115,9 @@ extern void ns_dyn_mem_free(void *heap_ptr);
111115
* \return 0, Allocate Fail
112116
* \return >0, Pointer to allocated data sector.
113117
*/
118+
#if NSDYNMEM_TRACKER_ENABLED!=1
114119
extern void *ns_dyn_mem_temporary_alloc(ns_mem_block_size_t alloc_size);
120+
#endif
115121

116122
/**
117123
* \brief Allocate long period data.
@@ -123,7 +129,9 @@ extern void *ns_dyn_mem_temporary_alloc(ns_mem_block_size_t alloc_size);
123129
* \return 0, Allocate Fail
124130
* \return >0, Pointer to allocated data sector.
125131
*/
132+
#if NSDYNMEM_TRACKER_ENABLED!=1
126133
extern void *ns_dyn_mem_alloc(ns_mem_block_size_t alloc_size);
134+
#endif
127135

128136
/**
129137
* \brief Get pointer to the current mem_stat_t set via ns_dyn_mem_init.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright (c) 2020 ARM Limited. All rights reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
* Licensed under the Apache License, Version 2.0 (the License); you may
5+
* not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/**
18+
* \file nsdynmem_tracker.h
19+
* \brief Dynamical Memory Tracker definitions to override the default NS dynamic memory functionality
20+
* Provides tracking and tracing of dynamic memory blocks
21+
*/
22+
23+
#ifndef NSDYNMEM_TRACKER_H_
24+
#define NSDYNMEM_TRACKER_H_
25+
#ifdef __cplusplus
26+
extern "C" {
27+
#endif
28+
29+
#if NSDYNMEM_TRACKER_ENABLED==1
30+
31+
#define ns_dyn_mem_free(block) ns_dyn_mem_tracker_dyn_mem_free(block, __func__, __LINE__)
32+
#define ns_dyn_mem_temporary_alloc(alloc_size) ns_dyn_mem_tracker_dyn_mem_temporary_alloc(alloc_size, __func__, __LINE__)
33+
#define ns_dyn_mem_alloc(alloc_size) ns_dyn_mem_tracker_dyn_mem_alloc(alloc_size, __func__, __LINE__)
34+
35+
void *ns_dyn_mem_tracker_dyn_mem_alloc(ns_mem_heap_size_t alloc_size, const char *function, uint32_t line);
36+
void *ns_dyn_mem_tracker_dyn_mem_temporary_alloc(ns_mem_heap_size_t alloc_size, const char *function, uint32_t line);
37+
void ns_dyn_mem_tracker_dyn_mem_free(void *block, const char *function, uint32_t line);
38+
39+
#endif
40+
41+
#ifdef __cplusplus
42+
}
43+
#endif
44+
#endif /* NSDYNMEM_TRACKER_H_ */
45+
46+
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* Copyright (c) 2020 ARM Limited. All rights reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
* Licensed under the Apache License, Version 2.0 (the License); you may
5+
* not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
18+
/**
19+
* \file nsdynmem_tracker_lib.h
20+
* \brief Dynamical Memory Tracker library API
21+
* Provides tracking and tracing of dynamic memory blocks
22+
*/
23+
24+
#ifndef NSDYNMEM_TRACKER_LIB_H_
25+
#define NSDYNMEM_TRACKER_LIB_H_
26+
#ifdef __cplusplus
27+
extern "C" {
28+
#endif
29+
30+
#if NSDYNMEM_TRACKER_ENABLED==1
31+
32+
// Memory block structure with caller information
33+
typedef struct ns_dyn_mem_tracker_lib_mem_blocks_s {
34+
void *block; /**< Allocated memory block */
35+
void *caller_addr; /**< Caller address */
36+
uint32_t size; /**< Allocation size */
37+
uint32_t total_size; /**< Total allocation size for all allocations */
38+
uint32_t lifetime; /**< Memory block lifetime in steps (e.g. seconds) */
39+
uint32_t ref_count; /**< Reference count */
40+
const char *function; /**< Caller function */
41+
uint16_t line; /**< Caller line in module */
42+
bool permanent : 1; /**< Permanent memory block */
43+
bool permanent_printed : 1; /**< Permanent memory block printed */
44+
} ns_dyn_mem_tracker_lib_mem_blocks_t;
45+
46+
// Extended memory block structure that is used if same caller allocates multiple memory blocks
47+
typedef struct ns_dyn_mem_tracker_lib_mem_blocks_ext_s {
48+
void *block; /**< Allocated memory block */
49+
void *caller_addr; /**< Caller address */
50+
uint32_t size; /**< Allocation size */
51+
} ns_dyn_mem_tracker_lib_mem_blocks_ext_t;
52+
53+
// Allocator information structure
54+
typedef struct ns_dyn_mem_tracker_lib_allocators_s {
55+
void *caller_addr; /**< Caller address */
56+
uint32_t alloc_count; /**< Number of allocations */
57+
uint32_t total_memory; /**< Total memory used by allocations */
58+
uint32_t min_lifetime; /**< Shortest lifetime among the allocations */
59+
const char *function; /**< Function name string */
60+
uint16_t line; /**< Module line */
61+
} ns_dyn_mem_tracker_lib_allocators_t;
62+
63+
// Memory block array allocator / array size increase allocator
64+
typedef ns_dyn_mem_tracker_lib_mem_blocks_t *ns_dyn_mem_tracker_lib_alloc_mem_blocks(ns_dyn_mem_tracker_lib_mem_blocks_t *blocks, uint16_t *mem_blocks_count);
65+
// Extended memory block array allocator / array size increase allocator
66+
typedef ns_dyn_mem_tracker_lib_mem_blocks_ext_t *ns_dyn_mem_tracker_lib_alloc_mem_blocks_ext(ns_dyn_mem_tracker_lib_mem_blocks_ext_t *blocks, uint32_t *mem_blocks_count);
67+
// Extended memory block array index hash function to get memory block (allocation/search start) index from block address
68+
typedef uint32_t ns_dyn_mem_tracker_lib_mem_block_index_hash(void *block, uint32_t ext_mem_blocks_count);
69+
70+
typedef struct ns_dyn_mem_tracker_lib_conf_s {
71+
ns_dyn_mem_tracker_lib_mem_blocks_t *mem_blocks; /**< Memory blocks array, if NULL calls allocator on init */
72+
ns_dyn_mem_tracker_lib_mem_blocks_ext_t *ext_mem_blocks; /**< Extended memory blocks array, if NULL calls allocator on init */
73+
ns_dyn_mem_tracker_lib_allocators_t *top_allocators; /**< Top allocators array */
74+
ns_dyn_mem_tracker_lib_allocators_t *permanent_allocators; /**< Permanent allocators */
75+
ns_dyn_mem_tracker_lib_allocators_t *to_permanent_allocators; /**< To permanent allocators */
76+
ns_dyn_mem_tracker_lib_allocators_t *max_snap_shot_allocators; /**< Snap shot of maximum memory used by allocators */
77+
ns_dyn_mem_tracker_lib_alloc_mem_blocks *alloc_mem_blocks; /**< Memory block array allocator / array size increase allocator */
78+
ns_dyn_mem_tracker_lib_alloc_mem_blocks_ext *ext_alloc_mem_blocks; /**< Extended memory block array allocator / array size increase allocator */
79+
ns_dyn_mem_tracker_lib_mem_block_index_hash *block_index_hash; /**< Hash function to get memory block index from block address */
80+
uint32_t allocated_memory; /**< Currently allocated memory */
81+
uint16_t mem_blocks_count; /**< Number of entries in memory blocks array */
82+
uint32_t ext_mem_blocks_count; /**< Number of entries in extended memory blocks array */
83+
uint16_t last_mem_block_index; /**< Last memory block in memory blocks array */
84+
uint16_t top_allocators_count; /**< Top allocators array count */
85+
uint16_t permanent_allocators_count; /**< Permanent allocators array count */
86+
uint16_t to_permanent_allocators_count; /**< To permanent allocators array count */
87+
uint16_t max_snap_shot_allocators_count; /**< Snap shot of maximum memory used by allocators array count */
88+
uint16_t to_permanent_steps_count; /**< How many steps before moving block to permanent allocators list */
89+
} ns_dyn_mem_tracker_lib_conf_t;
90+
91+
int8_t ns_dyn_mem_tracker_lib_alloc(ns_dyn_mem_tracker_lib_conf_t *conf, void *caller_addr, const char *function, uint32_t line, void *block, uint32_t alloc_size);
92+
int8_t ns_dyn_mem_tracker_lib_free(ns_dyn_mem_tracker_lib_conf_t *conf, void *caller_addr, const char *function, uint32_t line, void *block);
93+
void ns_dyn_mem_tracker_lib_step(ns_dyn_mem_tracker_lib_conf_t *conf);
94+
int8_t ns_dyn_mem_tracker_lib_allocator_lists_update(ns_dyn_mem_tracker_lib_conf_t *conf);
95+
void ns_dyn_mem_tracker_lib_max_snap_shot_update(ns_dyn_mem_tracker_lib_conf_t *conf);
96+
97+
#endif
98+
99+
#ifdef __cplusplus
100+
}
101+
#endif
102+
#endif /* NSDYNMEM_TRACKER_LIB_H_ */
103+
104+

mbed_lib.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
11
{
2-
"name": "nanostack-libservice"
2+
"name": "nanostack-libservice",
3+
"macros": ["NSDYNMEM_TRACKER_ENABLED=MBED_CONF_NANOSTACK_LIBSERVICE_NSDYNMEM_TRACKER_ENABLED"],
4+
"config": {
5+
"present": 1,
6+
"nsdynmem-tracker-enabled": {
7+
"help": "Use to enable dynamic memory tracker",
8+
"value": 0
9+
}
10+
}
311
}

source/nsdynmemLIB/nsdynmemLIB.c

Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
#include <stdint.h>
1717
#include <string.h>
18+
#undef NSDYNMEM_TRACKER_ENABLED
1819
#include "nsdynmemLIB.h"
1920
#include "platform/arm_hal_interrupt.h"
2021
#include <stdlib.h>
@@ -47,6 +48,7 @@ struct ns_mem_book {
4748
ns_mem_heap_size_t temporary_alloc_heap_limit; /* Amount of reserved heap temporary alloc can't exceed */
4849
};
4950

51+
static mem_stat_t default_stats;
5052
static ns_mem_book_t *default_book; // heap pointer for original "ns_" API use
5153

5254
// size of a hole_t in our word units
@@ -162,12 +164,14 @@ ns_mem_book_t *ns_mem_init(void *heap, ns_mem_heap_size_t h_size,
162164
ns_list_init(&book->holes_list);
163165
ns_list_add_to_start(&book->holes_list, hole_from_block_start(book->heap_main[0]));
164166

165-
book->mem_stat_info_ptr = info_ptr;
166-
//RESET Memory by Hea Len
167167
if (info_ptr) {
168-
memset(book->mem_stat_info_ptr, 0, sizeof(mem_stat_t));
169-
book->mem_stat_info_ptr->heap_sector_size = book->heap_size;
168+
book->mem_stat_info_ptr = info_ptr;
169+
} else {
170+
book->mem_stat_info_ptr = &default_stats;
170171
}
172+
//RESET Memory by Heap Len
173+
memset(book->mem_stat_info_ptr, 0, sizeof(mem_stat_t));
174+
book->mem_stat_info_ptr->heap_sector_size = book->heap_size;
171175
book->temporary_alloc_heap_limit = book->heap_size / 100 * (100 - TEMPORARY_ALLOC_FREE_HEAP_THRESHOLD);
172176
#endif
173177
//There really is no support to standard malloc in this library anymore
@@ -234,9 +238,7 @@ int ns_mem_region_add(ns_mem_book_t *book, void *region_ptr, ns_mem_heap_size_t
234238
// adjust total heap size with new hole
235239
book->heap_size += region_size;
236240

237-
if (book->mem_stat_info_ptr) {
238-
book->mem_stat_info_ptr->heap_sector_size = book->heap_size;
239-
}
241+
book->mem_stat_info_ptr->heap_sector_size = book->heap_size;
240242

241243
// adjust temporary allocation limits to match new heap
242244
book->temporary_alloc_heap_limit = book->heap_size / 100 * (100 - TEMPORARY_ALLOC_FREE_HEAP_THRESHOLD);
@@ -265,8 +267,8 @@ int ns_mem_set_temporary_alloc_free_heap_threshold(ns_mem_book_t *book, uint8_t
265267
#ifndef STANDARD_MALLOC
266268
ns_mem_heap_size_t heap_limit = 0;
267269

268-
if (!book || !book->mem_stat_info_ptr) {
269-
// no book or mem_stats
270+
if (!book) {
271+
// no book
270272
return -1;
271273
}
272274

@@ -304,25 +306,25 @@ extern int ns_dyn_mem_set_temporary_alloc_free_heap_threshold(uint8_t free_heap_
304306
#ifndef STANDARD_MALLOC
305307
static void dev_stat_update(mem_stat_t *mem_stat_info_ptr, mem_stat_update_t type, ns_mem_block_size_t size)
306308
{
307-
if (mem_stat_info_ptr) {
308-
switch (type) {
309-
case DEV_HEAP_ALLOC_OK:
310-
mem_stat_info_ptr->heap_sector_alloc_cnt++;
311-
mem_stat_info_ptr->heap_sector_allocated_bytes += size;
312-
if (mem_stat_info_ptr->heap_sector_allocated_bytes_max < mem_stat_info_ptr->heap_sector_allocated_bytes) {
313-
mem_stat_info_ptr->heap_sector_allocated_bytes_max = mem_stat_info_ptr->heap_sector_allocated_bytes;
314-
}
315-
mem_stat_info_ptr->heap_alloc_total_bytes += size;
316-
break;
317-
case DEV_HEAP_ALLOC_FAIL:
318-
mem_stat_info_ptr->heap_alloc_fail_cnt++;
319-
break;
320-
case DEV_HEAP_FREE:
321-
mem_stat_info_ptr->heap_sector_alloc_cnt--;
322-
mem_stat_info_ptr->heap_sector_allocated_bytes -= size;
323-
break;
324-
}
309+
310+
switch (type) {
311+
case DEV_HEAP_ALLOC_OK:
312+
mem_stat_info_ptr->heap_sector_alloc_cnt++;
313+
mem_stat_info_ptr->heap_sector_allocated_bytes += size;
314+
if (mem_stat_info_ptr->heap_sector_allocated_bytes_max < mem_stat_info_ptr->heap_sector_allocated_bytes) {
315+
mem_stat_info_ptr->heap_sector_allocated_bytes_max = mem_stat_info_ptr->heap_sector_allocated_bytes;
316+
}
317+
mem_stat_info_ptr->heap_alloc_total_bytes += size;
318+
break;
319+
case DEV_HEAP_ALLOC_FAIL:
320+
mem_stat_info_ptr->heap_alloc_fail_cnt++;
321+
break;
322+
case DEV_HEAP_FREE:
323+
mem_stat_info_ptr->heap_sector_alloc_cnt--;
324+
mem_stat_info_ptr->heap_sector_allocated_bytes -= size;
325+
break;
325326
}
327+
326328
}
327329

328330
static ns_mem_word_size_t convert_allocation_size(ns_mem_book_t *book, ns_mem_block_size_t requested_bytes)
@@ -363,7 +365,7 @@ static void *ns_mem_internal_alloc(ns_mem_book_t *book, const ns_mem_block_size_
363365
return NULL;
364366
}
365367

366-
if (book->mem_stat_info_ptr && direction == 1) {
368+
if (direction == 1) {
367369
if (book->mem_stat_info_ptr->heap_sector_allocated_bytes > book->temporary_alloc_heap_limit) {
368370
/* Not enough heap for temporary memory allocation */
369371
dev_stat_update(book->mem_stat_info_ptr, DEV_HEAP_ALLOC_FAIL, 0);
@@ -441,14 +443,14 @@ static void *ns_mem_internal_alloc(ns_mem_book_t *book, const ns_mem_block_size_
441443
block_ptr[1 + data_size] = data_size;
442444

443445
done:
444-
if (book->mem_stat_info_ptr) {
445-
if (block_ptr) {
446-
//Update Allocate OK
447-
dev_stat_update(book->mem_stat_info_ptr, DEV_HEAP_ALLOC_OK, (data_size + 2) * sizeof(ns_mem_word_size_t));
448-
} else {
449-
//Update Allocate Fail, second parameter is used for stats
450-
dev_stat_update(book->mem_stat_info_ptr, DEV_HEAP_ALLOC_FAIL, 0);
451-
}
446+
447+
448+
if (block_ptr) {
449+
//Update Allocate OK
450+
dev_stat_update(book->mem_stat_info_ptr, DEV_HEAP_ALLOC_OK, (data_size + 2) * sizeof(ns_mem_word_size_t));
451+
} else {
452+
//Update Allocate Fail, second parameter is used for stats
453+
dev_stat_update(book->mem_stat_info_ptr, DEV_HEAP_ALLOC_FAIL, 0);
452454
}
453455
platform_exit_critical();
454456

@@ -619,10 +621,8 @@ void ns_mem_free(ns_mem_book_t *book, void *block)
619621
heap_failure(book, NS_DYN_MEM_HEAP_SECTOR_CORRUPTED);
620622
} else {
621623
ns_mem_free_and_merge_with_adjacent_blocks(book, ptr, size);
622-
if (book->mem_stat_info_ptr) {
623-
//Update Free Counter
624-
dev_stat_update(book->mem_stat_info_ptr, DEV_HEAP_FREE, (size + 2) * sizeof(ns_mem_word_size_t));
625-
}
624+
//Update Free Counter
625+
dev_stat_update(book->mem_stat_info_ptr, DEV_HEAP_FREE, (size + 2) * sizeof(ns_mem_word_size_t));
626626
}
627627
}
628628

0 commit comments

Comments
 (0)