mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #10971 from artokin/nanostack_libservice_update
Nanostack: sync libservice with changes in master copypull/11020/head
commit
faf7f79e03
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2018 ARM Limited. All rights reserved.
|
||||
* Copyright (c) 2014-2019 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
|
@ -71,11 +71,25 @@ typedef struct ns_mem_book ns_mem_book_t;
|
|||
* \brief Init and set Dynamical heap pointer and length.
|
||||
*
|
||||
* \param heap_ptr Pointer to dynamically heap buffer
|
||||
* \param heap_size size of the heap buffer
|
||||
* \param h_size size of the heap buffer
|
||||
* \param passed_fptr pointer to heap error callback function
|
||||
* \param info_ptr Pointer to mem_stat_t for memory statistics. Can be NULL.
|
||||
*
|
||||
* \return None
|
||||
*/
|
||||
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);
|
||||
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);
|
||||
|
||||
/**
|
||||
* \brief Add memory region to initialized heap.
|
||||
*
|
||||
* This method adds memory region to already initialized heap.
|
||||
* Method will reset temporary heap threshold to the default value.
|
||||
*
|
||||
* \param region_ptr Pointer to memory region to be added
|
||||
* \param region_size size of the region buffer
|
||||
* \return 0 on success, <0 in case of errors.
|
||||
*/
|
||||
extern int ns_dyn_mem_region_add(void *region_ptr, ns_mem_heap_size_t region_size);
|
||||
|
||||
/**
|
||||
* \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
|
|||
* \return <0, Free Fail
|
||||
*/
|
||||
extern void ns_dyn_mem_free(void *heap_ptr);
|
||||
|
||||
/**
|
||||
* \brief Allocate temporary data.
|
||||
*
|
||||
|
@ -97,6 +112,7 @@ extern void ns_dyn_mem_free(void *heap_ptr);
|
|||
* \return >0, Pointer to allocated data sector.
|
||||
*/
|
||||
extern void *ns_dyn_mem_temporary_alloc(ns_mem_block_size_t alloc_size);
|
||||
|
||||
/**
|
||||
* \brief Allocate long period data.
|
||||
*
|
||||
|
@ -118,7 +134,7 @@ extern void *ns_dyn_mem_alloc(ns_mem_block_size_t alloc_size);
|
|||
* Note: the caller may not modify the returned structure.
|
||||
*
|
||||
* \return NULL, no mem_stat_t was given on initialization
|
||||
* \return !=0, Pointer to mem_stat_t.
|
||||
* \return Pointer to mem_stat_t or NULL.
|
||||
*/
|
||||
extern const mem_stat_t *ns_dyn_mem_get_mem_stat(void);
|
||||
|
||||
|
@ -139,11 +155,27 @@ extern int ns_dyn_mem_set_temporary_alloc_free_heap_threshold(uint8_t free_heap_
|
|||
/**
|
||||
* \brief Init and set Dynamical heap pointer and length.
|
||||
*
|
||||
* \param heap_ptr Pointer to dynamically heap buffer
|
||||
* \param heap_size size of the heap buffer
|
||||
* \return !=0, Pointer to ns_mem_book_t.
|
||||
* \param heap_ptr Pointer to dynamically heap buffer.
|
||||
* \param h_size size of the heap buffer.
|
||||
* \param passed_fptr pointer to heap error callback function.
|
||||
* \param info_ptr Pointer to mem_stat_t for memory statistics. Can be NULL.
|
||||
* \return Pointer to ns_mem_book_t.
|
||||
*/
|
||||
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);
|
||||
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);
|
||||
|
||||
/**
|
||||
* \brief Add memory region to initialized heap.
|
||||
*
|
||||
* This method adds memory region to already initialized heap.
|
||||
* Method will reset temporary heap threshold to the default value.
|
||||
*
|
||||
* \param book Address of book keeping structure.
|
||||
* \param region_ptr Pointer to memory region buffer.
|
||||
* \param region_size size of the memory region to add
|
||||
*
|
||||
* \return 0 on success, <0 in case of errors.
|
||||
*/
|
||||
extern int ns_mem_region_add(ns_mem_book_t *book, void *region_ptr, ns_mem_heap_size_t region_size);
|
||||
|
||||
/**
|
||||
* \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 (*
|
|||
* \return <0, Free Fail
|
||||
*/
|
||||
extern void ns_mem_free(ns_mem_book_t *book, void *heap_ptr);
|
||||
|
||||
/**
|
||||
* \brief Allocate temporary data.
|
||||
*
|
||||
|
@ -167,6 +200,7 @@ extern void ns_mem_free(ns_mem_book_t *book, void *heap_ptr);
|
|||
* \return >0, Pointer to allocated data sector.
|
||||
*/
|
||||
extern void *ns_mem_temporary_alloc(ns_mem_book_t *book, ns_mem_block_size_t alloc_size);
|
||||
|
||||
/**
|
||||
* \brief Allocate long period data.
|
||||
*
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2018 ARM Limited. All rights reserved.
|
||||
* Copyright (c) 2014-2019 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
|
@ -33,10 +33,13 @@ typedef struct {
|
|||
|
||||
typedef int ns_mem_word_size_t; // internal signed heap block size type
|
||||
|
||||
// Amount of memory regions
|
||||
#define REGION_COUNT 3
|
||||
|
||||
/* struct for book keeping variables */
|
||||
struct ns_mem_book {
|
||||
ns_mem_word_size_t *heap_main;
|
||||
ns_mem_word_size_t *heap_main_end;
|
||||
ns_mem_word_size_t *heap_main[REGION_COUNT];
|
||||
ns_mem_word_size_t *heap_main_end[REGION_COUNT];
|
||||
mem_stat_t *mem_stat_info_ptr;
|
||||
void (*heap_failure_callback)(heap_fail_t);
|
||||
NS_LIST_HEAD(hole_t, link) holes_list;
|
||||
|
@ -68,7 +71,37 @@ static void heap_failure(ns_mem_book_t *book, heap_fail_t reason)
|
|||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
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)
|
||||
{
|
||||
int index;
|
||||
for (index = 0; index < REGION_COUNT; index++) {
|
||||
if (book->heap_main[index] != 0) {
|
||||
if ((block_ptr >= book->heap_main[index]) &&
|
||||
(block_ptr < book->heap_main_end[index]) &&
|
||||
((block_ptr + size) < book->heap_main_end[index])) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
for (int i = 1; i < REGION_COUNT; i++) {
|
||||
if (book->heap_main[i] == 0) {
|
||||
book->heap_main[i] = region_start_ptr;
|
||||
book->heap_main_end[i] = book->heap_main[i] + region_size;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#endif //STANDARD_MALLOC
|
||||
|
||||
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)
|
||||
|
@ -76,6 +109,11 @@ void ns_dyn_mem_init(void *heap, ns_mem_heap_size_t h_size,
|
|||
default_book = ns_mem_init(heap, h_size, passed_fptr, info_ptr);
|
||||
}
|
||||
|
||||
int ns_dyn_mem_region_add(void *region_ptr, ns_mem_heap_size_t region_size)
|
||||
{
|
||||
return ns_mem_region_add(default_book, region_ptr, region_size);
|
||||
}
|
||||
|
||||
const mem_stat_t *ns_dyn_mem_get_mem_stat(void)
|
||||
{
|
||||
#ifndef STANDARD_MALLOC
|
||||
|
@ -85,7 +123,6 @@ const mem_stat_t *ns_dyn_mem_get_mem_stat(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
|
@ -107,19 +144,23 @@ ns_mem_book_t *ns_mem_init(void *heap, ns_mem_heap_size_t h_size,
|
|||
if (temp_int) {
|
||||
h_size -= (sizeof(ns_mem_word_size_t) - temp_int);
|
||||
}
|
||||
|
||||
book = heap;
|
||||
book->heap_main = (ns_mem_word_size_t *) & (book[1]); // SET Heap Pointer
|
||||
memset(book->heap_main, 0, REGION_COUNT * sizeof(ns_mem_word_size_t *));
|
||||
memset(book->heap_main_end, 0, REGION_COUNT * sizeof(ns_mem_word_size_t *));
|
||||
|
||||
book->heap_main[0] = (ns_mem_word_size_t *) & (book[1]); // SET Heap Pointer
|
||||
book->heap_size = h_size - sizeof(ns_mem_book_t); //Set Heap Size
|
||||
temp_int = (book->heap_size / sizeof(ns_mem_word_size_t));
|
||||
temp_int -= 2;
|
||||
ptr = book->heap_main;
|
||||
ptr = book->heap_main[0];
|
||||
*ptr = -(temp_int);
|
||||
ptr += (temp_int + 1);
|
||||
*ptr = -(temp_int);
|
||||
book->heap_main_end = ptr;
|
||||
book->heap_main_end[0] = ptr;
|
||||
|
||||
ns_list_init(&book->holes_list);
|
||||
ns_list_add_to_start(&book->holes_list, hole_from_block_start(book->heap_main));
|
||||
ns_list_add_to_start(&book->holes_list, hole_from_block_start(book->heap_main[0]));
|
||||
|
||||
book->mem_stat_info_ptr = info_ptr;
|
||||
//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,
|
|||
return book;
|
||||
}
|
||||
|
||||
int ns_mem_region_add(ns_mem_book_t *book, void *region_ptr, ns_mem_heap_size_t region_size)
|
||||
{
|
||||
#ifndef STANDARD_MALLOC
|
||||
if (!book || !region_ptr || region_size < 3 * sizeof(ns_mem_word_size_t)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ns_mem_word_size_t *block_ptr;
|
||||
ns_mem_word_size_t temp_int;
|
||||
|
||||
/* Do memory alignment */
|
||||
temp_int = ((uintptr_t)region_ptr % sizeof(ns_mem_word_size_t));
|
||||
if (temp_int) {
|
||||
region_ptr = (uint8_t *) region_ptr + (sizeof(ns_mem_word_size_t) - temp_int);
|
||||
region_size -= (sizeof(ns_mem_word_size_t) - temp_int);
|
||||
}
|
||||
|
||||
/* Make correction for total length */
|
||||
temp_int = (region_size % sizeof(ns_mem_word_size_t));
|
||||
if (temp_int) {
|
||||
region_size -= (sizeof(ns_mem_word_size_t) - temp_int);
|
||||
}
|
||||
|
||||
// Create hole from new heap memory
|
||||
temp_int = (region_size / sizeof(ns_mem_word_size_t));
|
||||
temp_int -= 2;
|
||||
block_ptr = region_ptr;
|
||||
*block_ptr = -(temp_int);
|
||||
block_ptr += (temp_int + 1); // now block_ptr points to end of block
|
||||
*block_ptr = -(temp_int);
|
||||
|
||||
// find place for the new hole from the holes list
|
||||
hole_t *hole_to_add = hole_from_block_start(region_ptr);
|
||||
hole_t *previous_hole = NULL;
|
||||
ns_list_foreach(hole_t, hole_in_list_ptr, &book->holes_list) {
|
||||
if (hole_in_list_ptr < hole_to_add) {
|
||||
previous_hole = hole_in_list_ptr;
|
||||
} else if (hole_in_list_ptr == hole_to_add) {
|
||||
// trying to add memory block that is already in the list!
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
// save region
|
||||
if (ns_dyn_mem_region_save(book, region_ptr, (region_size / (sizeof(ns_mem_word_size_t))) - 1) != 0) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
// Add new hole to the list
|
||||
if (previous_hole) {
|
||||
ns_list_add_after(&book->holes_list, previous_hole, hole_to_add);
|
||||
} else {
|
||||
ns_list_add_to_start(&book->holes_list, hole_to_add);
|
||||
}
|
||||
|
||||
// adjust total heap size with new hole
|
||||
book->heap_size += region_size;
|
||||
|
||||
if (book->mem_stat_info_ptr) {
|
||||
book->mem_stat_info_ptr->heap_sector_size = book->heap_size;
|
||||
}
|
||||
|
||||
// adjust temporary allocation limits to match new heap
|
||||
book->temporary_alloc_heap_limit = book->heap_size / 100 * (100 - TEMPORARY_ALLOC_FREE_HEAP_THRESHOLD);
|
||||
|
||||
return 0;
|
||||
#else
|
||||
(void) book;
|
||||
(void) region_ptr;
|
||||
(void) region_size;
|
||||
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
const mem_stat_t *ns_mem_get_mem_stat(ns_mem_book_t *heap)
|
||||
{
|
||||
#ifndef STANDARD_MALLOC
|
||||
|
@ -211,7 +327,7 @@ static void dev_stat_update(mem_stat_t *mem_stat_info_ptr, mem_stat_update_t typ
|
|||
|
||||
static ns_mem_word_size_t convert_allocation_size(ns_mem_book_t *book, ns_mem_block_size_t requested_bytes)
|
||||
{
|
||||
if (book->heap_main == 0) {
|
||||
if (book->heap_main[0] == 0) {
|
||||
heap_failure(book, NS_DYN_MEM_HEAP_SECTOR_UNITIALIZED);
|
||||
} else if (requested_bytes < 1) {
|
||||
heap_failure(book, NS_DYN_MEM_ALLOCATE_SIZE_NOT_VALID);
|
||||
|
@ -329,7 +445,6 @@ done:
|
|||
if (block_ptr) {
|
||||
//Update Allocate OK
|
||||
dev_stat_update(book->mem_stat_info_ptr, DEV_HEAP_ALLOC_OK, (data_size + 2) * sizeof(ns_mem_word_size_t));
|
||||
|
||||
} else {
|
||||
//Update Allocate Fail, second parameter is used for stats
|
||||
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
|
|||
hole_t *existing_end = NULL;
|
||||
ns_mem_word_size_t *start = cur_block;
|
||||
ns_mem_word_size_t *end = cur_block + data_size + 1;
|
||||
ns_mem_word_size_t *region_start;
|
||||
ns_mem_word_size_t *region_end;
|
||||
|
||||
int region_index = ns_dyn_mem_region_find(book, cur_block, data_size);
|
||||
if (region_index >= 0) {
|
||||
region_start = book->heap_main[region_index];
|
||||
region_end = book->heap_main_end[region_index];
|
||||
} else {
|
||||
heap_failure(book, NS_DYN_MEM_HEAP_SECTOR_CORRUPTED);
|
||||
// can't find region for the block, return
|
||||
return;
|
||||
}
|
||||
|
||||
//invalidate current block
|
||||
*start = -data_size;
|
||||
*end = -data_size;
|
||||
ns_mem_word_size_t merged_data_size = data_size;
|
||||
|
||||
if (start != book->heap_main) {
|
||||
if (start != region_start) {
|
||||
if (*(start - 1) < 0) {
|
||||
ns_mem_word_size_t *block_end = start - 1;
|
||||
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
|
|||
}
|
||||
}
|
||||
|
||||
if (end != book->heap_main_end) {
|
||||
if (end != region_end) {
|
||||
if (*(end + 1) < 0) {
|
||||
ns_mem_word_size_t *block_start = end + 1;
|
||||
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
|
|||
}
|
||||
#endif
|
||||
|
||||
static bool pointer_address_validate(ns_mem_book_t *book, ns_mem_word_size_t *ptr, ns_mem_word_size_t size)
|
||||
{
|
||||
|
||||
if (ns_dyn_mem_region_find(book, ptr, size) >= 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ns_mem_free(ns_mem_book_t *book, void *block)
|
||||
{
|
||||
#ifndef STANDARD_MALLOC
|
||||
|
@ -472,9 +610,7 @@ void ns_mem_free(ns_mem_book_t *book, void *block)
|
|||
ptr --;
|
||||
//Read Current Size
|
||||
size = *ptr;
|
||||
if (ptr < book->heap_main || ptr >= book->heap_main_end) {
|
||||
heap_failure(book, NS_DYN_MEM_POINTER_NOT_VALID);
|
||||
} else if ((ptr + size) >= book->heap_main_end) {
|
||||
if (!pointer_address_validate(book, ptr, size)) {
|
||||
heap_failure(book, NS_DYN_MEM_POINTER_NOT_VALID);
|
||||
} else if (size < 0) {
|
||||
heap_failure(book, NS_DYN_MEM_DOUBLE_FREE);
|
||||
|
@ -489,6 +625,7 @@ void ns_mem_free(ns_mem_book_t *book, void *block)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
platform_exit_critical();
|
||||
#else
|
||||
platform_enter_critical();
|
||||
|
|
|
@ -17,8 +17,17 @@
|
|||
#include "nsdynmemLIB.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "error_callback.h"
|
||||
|
||||
// hardcoded amount of regions, keep in sync with nsdynmemlib "REGION_COUNT"
|
||||
#define NS_MEM_REGION_CNT (3)
|
||||
// size of nsdynmemlib book keeping data ns_mem_book_t
|
||||
#define NS_MEM_BOOK_SIZE (64 + (NS_MEM_REGION_CNT-1)*2*sizeof(ns_mem_heap_size_t))
|
||||
#define NS_MEM_BOOK_SIZE_WITH_HOLE (NS_MEM_BOOK_SIZE + 2*sizeof(ns_mem_heap_size_t))
|
||||
|
||||
int ret_val;
|
||||
|
||||
TEST_GROUP(dynmem)
|
||||
{
|
||||
void setup() {
|
||||
|
@ -37,7 +46,7 @@ TEST(dynmem, init)
|
|||
mem_stat_t info;
|
||||
reset_heap_error();
|
||||
ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
|
||||
CHECK(info.heap_sector_size >= (size - 72));
|
||||
CHECK(info.heap_sector_size == (size - NS_MEM_BOOK_SIZE));
|
||||
CHECK(!heap_have_failed());
|
||||
CHECK(ns_dyn_mem_get_mem_stat() == &info);
|
||||
free(heap);
|
||||
|
@ -50,7 +59,7 @@ TEST(dynmem, different_sizes)
|
|||
mem_stat_t info;
|
||||
uint8_t *heap = (uint8_t *)malloc(size);
|
||||
ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
|
||||
CHECK(info.heap_sector_size >= (size - 72));
|
||||
CHECK(info.heap_sector_size >= (size - NS_MEM_BOOK_SIZE_WITH_HOLE));
|
||||
CHECK(!heap_have_failed());
|
||||
CHECK(ns_dyn_mem_alloc(10));
|
||||
free(heap);
|
||||
|
@ -69,12 +78,196 @@ TEST(dynmem, diff_alignment)
|
|||
ptr++;
|
||||
size--;
|
||||
ns_dyn_mem_init(ptr, size, &heap_fail_callback, &info);
|
||||
CHECK(info.heap_sector_size >= (size - 72));
|
||||
CHECK(info.heap_sector_size >= (size - NS_MEM_BOOK_SIZE_WITH_HOLE));
|
||||
CHECK(!heap_have_failed());
|
||||
}
|
||||
free(heap);
|
||||
}
|
||||
|
||||
TEST(dynmem, heap_add_region_api)
|
||||
{
|
||||
#if (NS_MEM_REGION_CNT > 1)
|
||||
uint16_t size = 1000;
|
||||
uint8_t *heap = (uint8_t *)malloc(size);
|
||||
uint8_t *heap2add = (uint8_t *)malloc(size);
|
||||
uint8_t *heap2add2 = (uint8_t *)malloc(size);
|
||||
|
||||
mem_stat_t info;
|
||||
|
||||
reset_heap_error();
|
||||
ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
|
||||
CHECK(info.heap_sector_size == (size - NS_MEM_BOOK_SIZE))
|
||||
|
||||
// param error, return <0
|
||||
ret_val = ns_dyn_mem_region_add(NULL, size);
|
||||
CHECK(0 != ret_val);
|
||||
|
||||
// param error, return <0
|
||||
ret_val = ns_dyn_mem_region_add(heap2add, 0);
|
||||
CHECK(0 != ret_val);
|
||||
|
||||
// param error, return <0
|
||||
ret_val = ns_dyn_mem_region_add(heap2add, 8);
|
||||
CHECK(0 != ret_val);
|
||||
|
||||
// All OK - success, 1 reserved for bookkeeping
|
||||
ret_val = ns_dyn_mem_region_add(heap2add, size);
|
||||
CHECK(0 == ret_val);
|
||||
|
||||
CHECK(!heap_have_failed());
|
||||
CHECK(ns_dyn_mem_get_mem_stat() == &info);
|
||||
CHECK(info.heap_sector_size == (2 * size - NS_MEM_BOOK_SIZE))
|
||||
|
||||
// All OK - add more memory again success
|
||||
ret_val = ns_dyn_mem_region_add(heap2add2, size);
|
||||
CHECK(0 == ret_val);
|
||||
CHECK(info.heap_sector_size == (3 * size - NS_MEM_BOOK_SIZE))
|
||||
|
||||
free(heap);
|
||||
free(heap2add);
|
||||
free(heap2add2);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(dynmem, heap_add_region)
|
||||
{
|
||||
#if (NS_MEM_REGION_CNT > 1 && NS_MEM_REGION_CNT < 4)
|
||||
uint16_t size = 200;
|
||||
uint8_t *heap = (uint8_t *)malloc(size);
|
||||
uint8_t *heap_add1 = (uint8_t *)malloc(size);
|
||||
uint8_t *heap_add2 = (uint8_t *)malloc(size);
|
||||
uint8_t *heap_add3 = (uint8_t *)malloc(size);
|
||||
void *p[size * 4];
|
||||
|
||||
mem_stat_t info;
|
||||
|
||||
reset_heap_error();
|
||||
ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
|
||||
CHECK(info.heap_sector_size == (size - NS_MEM_BOOK_SIZE))
|
||||
|
||||
ret_val = ns_dyn_mem_region_add(heap_add1, size);
|
||||
CHECK(0 == ret_val);
|
||||
|
||||
// region already added, therefore fails
|
||||
ret_val = ns_dyn_mem_region_add(heap_add1, size);
|
||||
CHECK(0 != ret_val);
|
||||
|
||||
ret_val = ns_dyn_mem_region_add(heap_add3, size);
|
||||
CHECK(0 == ret_val);
|
||||
|
||||
// There is room for 2 additional regions , therfore fails
|
||||
ret_val = ns_dyn_mem_region_add(heap_add2, size);
|
||||
CHECK(0 != ret_val);
|
||||
|
||||
CHECK(info.heap_sector_size == (3 * size - NS_MEM_BOOK_SIZE))
|
||||
|
||||
CHECK(!heap_have_failed());
|
||||
int block_size = 10;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < size * 3; i++) {
|
||||
p[i] = ns_dyn_mem_alloc(block_size);
|
||||
if (p[i]) {
|
||||
memset(p[i], 0xb0, block_size);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
CHECK(!heap_have_failed());
|
||||
CHECK(info.heap_alloc_fail_cnt == 1);
|
||||
CHECK(info.heap_sector_alloc_cnt == i);
|
||||
CHECK(info.heap_sector_allocated_bytes == info.heap_sector_allocated_bytes_max);
|
||||
|
||||
for (; i >= 0; i--) {
|
||||
ns_dyn_mem_free(p[i]);
|
||||
}
|
||||
CHECK(!heap_have_failed());
|
||||
CHECK(info.heap_sector_alloc_cnt == 0);
|
||||
|
||||
free(heap);
|
||||
free(heap_add1);
|
||||
free(heap_add2);
|
||||
free(heap_add3);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(dynmem, heap_add_region_randomized)
|
||||
{
|
||||
/**
|
||||
* Test:
|
||||
* - multiple regions
|
||||
* - regions are not from continous
|
||||
* - all memory allocated from heap
|
||||
* - blocks are deallocated in random order
|
||||
*/
|
||||
#if (NS_MEM_REGION_CNT > 1)
|
||||
uint32_t size = 200000;
|
||||
uint8_t *heap_ptr[NS_MEM_REGION_CNT]; // heap memory regions
|
||||
void *ptrs[size * NS_MEM_REGION_CNT / 4] = {0}; // allocated memory pointers
|
||||
mem_stat_t info;
|
||||
uint8_t *gap_between_regions = NULL;
|
||||
|
||||
for (int cnt = 0; cnt < NS_MEM_REGION_CNT; cnt++) {
|
||||
heap_ptr[cnt] = (uint8_t *)malloc(size);
|
||||
if (gap_between_regions) {
|
||||
free(gap_between_regions);
|
||||
}
|
||||
gap_between_regions = (uint8_t *)malloc(size / 3);
|
||||
}
|
||||
free(gap_between_regions);
|
||||
|
||||
reset_heap_error();
|
||||
ns_dyn_mem_init(heap_ptr[0], size, &heap_fail_callback, &info);
|
||||
CHECK(info.heap_sector_size == (size - NS_MEM_BOOK_SIZE))
|
||||
|
||||
for (int cnt = NS_MEM_REGION_CNT - 1; cnt > 0; cnt--) {
|
||||
ret_val = ns_dyn_mem_region_add(heap_ptr[cnt], size);
|
||||
CHECK(0 == ret_val);
|
||||
}
|
||||
|
||||
CHECK(info.heap_sector_size == (NS_MEM_REGION_CNT * size - NS_MEM_BOOK_SIZE))
|
||||
|
||||
CHECK(!heap_have_failed());
|
||||
|
||||
srand(time(NULL));
|
||||
int block_size;
|
||||
int i;
|
||||
for (i = 0; i < size * NS_MEM_REGION_CNT; i++) {
|
||||
// allocate huge amount of small blocks until allocation fails
|
||||
block_size = (rand() % 4) + 1;
|
||||
ptrs[i] = ns_dyn_mem_alloc(block_size);
|
||||
if (ptrs[i]) {
|
||||
memset(ptrs[i], 0xb0, block_size);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
CHECK(!heap_have_failed());
|
||||
CHECK(info.heap_alloc_fail_cnt == 1);
|
||||
CHECK(info.heap_sector_alloc_cnt == i);
|
||||
CHECK(info.heap_sector_allocated_bytes == info.heap_sector_allocated_bytes_max);
|
||||
|
||||
// free allocated memmory blocks in random order
|
||||
int block_id;
|
||||
do {
|
||||
block_id = (rand() % i);
|
||||
if (ptrs[block_id] != NULL) {
|
||||
ns_dyn_mem_free(ptrs[block_id]);
|
||||
ptrs[block_id] = NULL;
|
||||
}
|
||||
} while (info.heap_sector_alloc_cnt != 0);
|
||||
|
||||
|
||||
CHECK(!heap_have_failed());
|
||||
CHECK(info.heap_sector_alloc_cnt == 0);
|
||||
CHECK(info.heap_sector_allocated_bytes == 0);
|
||||
|
||||
for (int cnt = 0; cnt < NS_MEM_REGION_CNT; cnt++) {
|
||||
free(heap_ptr[cnt]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(dynmem, ns_dyn_mem_alloc)
|
||||
{
|
||||
uint16_t size = 1000;
|
||||
|
@ -90,7 +283,10 @@ TEST(dynmem, ns_dyn_mem_alloc)
|
|||
int i;
|
||||
for (i = 0; i < size; i++) {
|
||||
p[i] = ns_dyn_mem_alloc(block);
|
||||
if (!p[i]) {
|
||||
|
||||
if (p[i]) {
|
||||
memset(p[i], 0xb0, block);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -152,17 +348,17 @@ TEST(dynmem, ns_dyn_mem_temporary_alloc_with_heap_threshold)
|
|||
CHECK(!heap_have_failed());
|
||||
|
||||
// test1: temporary alloc will fail if there is less than 5% heap free
|
||||
p1 = ns_dyn_mem_temporary_alloc((size - 72) * 0.96);
|
||||
p1 = ns_dyn_mem_temporary_alloc((size - NS_MEM_BOOK_SIZE_WITH_HOLE) * 0.96);
|
||||
CHECK(!heap_have_failed());
|
||||
CHECK(p1);
|
||||
p2 = ns_dyn_mem_temporary_alloc((size - 72) * 0.02);
|
||||
p2 = ns_dyn_mem_temporary_alloc((size - NS_MEM_BOOK_SIZE_WITH_HOLE) * 0.02);
|
||||
CHECK(p2 == NULL);
|
||||
CHECK(!heap_have_failed());
|
||||
CHECK(info.heap_alloc_fail_cnt == 1);
|
||||
|
||||
// Test2, disable threshold feature and try p2 allocation again
|
||||
ns_dyn_mem_set_temporary_alloc_free_heap_threshold(0, 0);
|
||||
p2 = ns_dyn_mem_temporary_alloc((size - 72) * 0.02);
|
||||
p2 = ns_dyn_mem_temporary_alloc((size - NS_MEM_BOOK_SIZE_WITH_HOLE) * 0.02);
|
||||
CHECK(!heap_have_failed());
|
||||
CHECK(p2);
|
||||
ns_dyn_mem_free(p1);
|
||||
|
@ -172,9 +368,9 @@ TEST(dynmem, ns_dyn_mem_temporary_alloc_with_heap_threshold)
|
|||
|
||||
// Test3, enable feature by free heap percentage
|
||||
ns_dyn_mem_set_temporary_alloc_free_heap_threshold(40, 0);
|
||||
p1 = ns_dyn_mem_temporary_alloc((size - 72) * 0.65);
|
||||
p1 = ns_dyn_mem_temporary_alloc((size - NS_MEM_BOOK_SIZE_WITH_HOLE) * 0.65);
|
||||
CHECK(p1);
|
||||
p2 = ns_dyn_mem_temporary_alloc((size - 72) * 0.10);
|
||||
p2 = ns_dyn_mem_temporary_alloc((size - NS_MEM_BOOK_SIZE_WITH_HOLE) * 0.10);
|
||||
CHECK(p2 == NULL);
|
||||
ns_dyn_mem_free(p1);
|
||||
CHECK(!heap_have_failed());
|
||||
|
@ -183,7 +379,7 @@ TEST(dynmem, ns_dyn_mem_temporary_alloc_with_heap_threshold)
|
|||
|
||||
// Test4, enable feature by free heap amount
|
||||
ns_dyn_mem_set_temporary_alloc_free_heap_threshold(0, 200);
|
||||
p1 = ns_dyn_mem_temporary_alloc(size - 72 - 100 /*828 bytes */);
|
||||
p1 = ns_dyn_mem_temporary_alloc(size - NS_MEM_BOOK_SIZE_WITH_HOLE - 100);
|
||||
CHECK(p1);
|
||||
p2 = ns_dyn_mem_temporary_alloc(1);
|
||||
CHECK(p2 == NULL);
|
||||
|
@ -216,7 +412,7 @@ TEST(dynmem, ns_dyn_mem_temporary_alloc_with_heap_threshold)
|
|||
|
||||
TEST(dynmem, test_both_allocs_with_hole_usage)
|
||||
{
|
||||
uint16_t size = 112;
|
||||
uint16_t size = NS_MEM_BOOK_SIZE_WITH_HOLE + 15 + 5;
|
||||
mem_stat_t info;
|
||||
void *p[size];
|
||||
uint8_t *heap = (uint8_t *)malloc(size);
|
||||
|
@ -322,7 +518,7 @@ TEST(dynmem, corrupted_memory)
|
|||
|
||||
TEST(dynmem, no_big_enough_sector)
|
||||
{
|
||||
uint16_t size = 112;
|
||||
uint16_t size = NS_MEM_BOOK_SIZE_WITH_HOLE + (5 * 8);
|
||||
mem_stat_t info;
|
||||
uint8_t *heap = (uint8_t *)malloc(size);
|
||||
uint8_t *ptr = heap;
|
||||
|
@ -354,7 +550,7 @@ TEST(dynmem, diff_sizes)
|
|||
ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
|
||||
CHECK(!heap_have_failed());
|
||||
int i;
|
||||
for (i = 1; i < (size - 72); i++) {
|
||||
for (i = 1; i < (size - NS_MEM_BOOK_SIZE_WITH_HOLE); i++) {
|
||||
p = ns_dyn_mem_temporary_alloc(i);
|
||||
CHECK(p);
|
||||
ns_dyn_mem_free(p);
|
||||
|
@ -495,7 +691,7 @@ TEST(dynmem, not_negative_stats)
|
|||
|
||||
TEST(dynmem, test_invalid_pointer_freed)
|
||||
{
|
||||
uint16_t size = 92;
|
||||
uint16_t size = 1000;
|
||||
uint8_t *heap = (uint8_t *)malloc(size);
|
||||
CHECK(NULL != heap);
|
||||
reset_heap_error();
|
||||
|
|
Loading…
Reference in New Issue