mirror of https://github.com/ARMmbed/mbed-os.git
Squashed 'features/frameworks/nanostack-libservice/' changes from ddd45db..2705b9b
2705b9b Add IPv4 string conversion utils 8978dac Add API to set temporary allocation heap limit (#70) 86fa01c Update max heap size to use size_t (#68) 9808289 nsdynmemlib: silence IAR warnings caused by gotos skipping variable init git-subtree-dir: features/frameworks/nanostack-libservice git-subtree-split: 2705b9b93877f18828106df80af5b8c1c441e713pull/7389/head^2
parent
d6732a1b96
commit
a184ff592b
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2018 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
#ifndef IP4STRING_H
|
||||||
|
#define IP4STRING_H
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "ns_types.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print binary IPv4 address to a string.
|
||||||
|
*
|
||||||
|
* String must contain enough room for full address, 16 bytes exact.
|
||||||
|
*
|
||||||
|
* \param ip4addr IPv4 address.
|
||||||
|
* \param p buffer to write string to.
|
||||||
|
* \return length of generated string excluding the terminating null character
|
||||||
|
*/
|
||||||
|
uint_fast8_t ip4tos(const void *ip4addr, char *p);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert numeric IPv4 address string to a binary.
|
||||||
|
*
|
||||||
|
* \param ip4addr IPv4 address in string format.
|
||||||
|
* \param len Length of IPv4 string, maximum of 16..
|
||||||
|
* \param dest buffer for address. MUST be 4 bytes.
|
||||||
|
* \return boolean set to true if conversion succeed, false if it didn't
|
||||||
|
*/
|
||||||
|
bool stoip4(const char *ip4addr, size_t len, void *dest);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2016 ARM Limited. All rights reserved.
|
* Copyright (c) 2014-2018 ARM Limited. All rights reserved.
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||||
* not use this file except in compliance with the License.
|
* not use this file except in compliance with the License.
|
||||||
|
@ -32,10 +32,10 @@ extern "C" {
|
||||||
#include "ns_types.h"
|
#include "ns_types.h"
|
||||||
|
|
||||||
// Added to maintain backward compatibility with older implementation of ns_dyn_mem APIs
|
// Added to maintain backward compatibility with older implementation of ns_dyn_mem APIs
|
||||||
#define NSDYNMEMLIB_API_VERSION 2
|
#define NSDYNMEMLIB_API_VERSION 3
|
||||||
|
|
||||||
typedef uint16_t ns_mem_block_size_t; //external interface unsigned heap block size type
|
typedef size_t ns_mem_block_size_t; //external interface unsigned heap block size type
|
||||||
typedef uint16_t ns_mem_heap_size_t; //total heap size type.
|
typedef size_t ns_mem_heap_size_t; //total heap size type.
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \enum heap_fail_t
|
* \enum heap_fail_t
|
||||||
|
@ -122,6 +122,20 @@ extern void *ns_dyn_mem_alloc(ns_mem_block_size_t alloc_size);
|
||||||
*/
|
*/
|
||||||
extern const mem_stat_t *ns_dyn_mem_get_mem_stat(void);
|
extern const mem_stat_t *ns_dyn_mem_get_mem_stat(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Set amount of free heap that must be available for temporary memory allocation to succeed.
|
||||||
|
*
|
||||||
|
* Temporary memory allocation will fail if system does not have defined amount of heap free.
|
||||||
|
*
|
||||||
|
* Note: the caller must set mem_stat_t structure in initialization.
|
||||||
|
*
|
||||||
|
* \param free_heap_percentage percentage of total heap that must be free for temporary memory allocation. Set free_heap_amount to 0 when this percentage value.
|
||||||
|
* \param free_heap_amount Amount of free heap that must be free for temporary memory allocation. This value takes preference over percentage parameter value.
|
||||||
|
*
|
||||||
|
* \return 0 on success, <0 otherwise
|
||||||
|
*/
|
||||||
|
extern int ns_dyn_mem_set_temporary_alloc_free_heap_threshold(uint8_t free_heap_percentage, ns_mem_heap_size_t free_heap_amount);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Init and set Dynamical heap pointer and length.
|
* \brief Init and set Dynamical heap pointer and length.
|
||||||
*
|
*
|
||||||
|
@ -181,8 +195,24 @@ extern void *ns_mem_alloc(ns_mem_book_t *book, ns_mem_block_size_t alloc_size);
|
||||||
*/
|
*/
|
||||||
extern const mem_stat_t *ns_mem_get_mem_stat(ns_mem_book_t *book);
|
extern const mem_stat_t *ns_mem_get_mem_stat(ns_mem_book_t *book);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Set amount of free heap that must be available for temporary memory allocation to succeed.
|
||||||
|
*
|
||||||
|
* Temporary memory allocation will fail if system does not have defined amount of heap free.
|
||||||
|
*
|
||||||
|
* Note: the caller must set mem_stat_t structure in initialization.
|
||||||
|
*
|
||||||
|
* \param book Address of book keeping structure
|
||||||
|
* \param free_heap_percentage percentage of total heap that must be free for temporary memory allocation. Set free_heap_amount to 0 when using percentage value.
|
||||||
|
* \param free_heap_amount Amount of free heap that must be free for temporary memory allocation. This value takes preference over the percentage parameter value.
|
||||||
|
*
|
||||||
|
* \return 0 on success, <0 otherwise
|
||||||
|
*/
|
||||||
|
extern int ns_mem_set_temporary_alloc_free_heap_threshold(ns_mem_book_t *book, uint8_t free_heap_percentage, ns_mem_heap_size_t free_heap_amount);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif /* NSDYNMEMLIB_H_ */
|
#endif /* NSDYNMEMLIB_H_ */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2018 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "common_functions.h"
|
||||||
|
#include "ip4string.h"
|
||||||
|
|
||||||
|
static void ipv4_itoa(char *string, uint8_t byte);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print binary IPv4 address to a string.
|
||||||
|
* String must contain enough room for full address, 16 bytes exact.
|
||||||
|
* \param addr IPv4 address.
|
||||||
|
* \p buffer to write string to.
|
||||||
|
*/
|
||||||
|
uint_fast8_t ip4tos(const void *ip4addr, char *p)
|
||||||
|
{
|
||||||
|
uint_fast8_t outputPos = 0;
|
||||||
|
const uint8_t *byteArray = ip4addr;
|
||||||
|
|
||||||
|
for (uint_fast8_t component = 0; component < 4; ++component) {
|
||||||
|
//Convert the byte to string
|
||||||
|
ipv4_itoa(&p[outputPos], byteArray[component]);
|
||||||
|
|
||||||
|
//Move outputPos to the end of the string
|
||||||
|
while (p[outputPos] != '\0') {
|
||||||
|
outputPos += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Append a dot if this is not the last digit
|
||||||
|
if (component < 3) {
|
||||||
|
p[outputPos++] = '.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return length of generated string, excluding the terminating null character
|
||||||
|
return outputPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ipv4_itoa(char *string, uint8_t byte)
|
||||||
|
{
|
||||||
|
char *baseString = string;
|
||||||
|
|
||||||
|
//Write the digits to the buffer from the least significant to the most
|
||||||
|
// This is the incorrect order but we will swap later
|
||||||
|
do {
|
||||||
|
*string++ = '0' + byte % 10;
|
||||||
|
byte /= 10;
|
||||||
|
} while(byte);
|
||||||
|
|
||||||
|
//We put the final \0, then go back one step on the last digit for the swap
|
||||||
|
*string-- = '\0';
|
||||||
|
|
||||||
|
//We now swap the digits
|
||||||
|
while (baseString < string) {
|
||||||
|
uint8_t tmp = *string;
|
||||||
|
*string-- = *baseString;
|
||||||
|
*baseString++ = tmp;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2018 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "common_functions.h"
|
||||||
|
#include "ip4string.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert numeric IPv4 address string to a binary.
|
||||||
|
* \param ip4addr IPv4 address in string format.
|
||||||
|
* \param len Length of IPv4 string, maximum of 16..
|
||||||
|
* \param dest buffer for address. MUST be 4 bytes.
|
||||||
|
* \return boolean set to true if conversion succeded, false if it didn't
|
||||||
|
*/
|
||||||
|
bool stoip4(const char *ip4addr, size_t len, void *dest)
|
||||||
|
{
|
||||||
|
uint8_t *addr = dest;
|
||||||
|
|
||||||
|
if (len > 16) { // Too long, not possible
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint_fast8_t stringLength = 0, byteCount = 0;
|
||||||
|
|
||||||
|
//Iterate over each component of the IP. The exit condition is in the middle of the loop
|
||||||
|
while (true) {
|
||||||
|
|
||||||
|
//No valid character (IPv4 addresses don't have implicit 0, that is x.y..z being read as x.y.0.z)
|
||||||
|
if (stringLength == len || ip4addr[stringLength] < '0' || ip4addr[stringLength] > '9') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//For each component, we convert it to the raw value
|
||||||
|
uint_fast16_t byte = 0;
|
||||||
|
while (stringLength < len && ip4addr[stringLength] >= '0' && ip4addr[stringLength] <= '9') {
|
||||||
|
byte *= 10;
|
||||||
|
byte += ip4addr[stringLength++] - '0';
|
||||||
|
|
||||||
|
//We go over the maximum value for an IPv4 component
|
||||||
|
if (byte > 0xff) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Append the component
|
||||||
|
addr[byteCount++] = (uint8_t) byte;
|
||||||
|
|
||||||
|
//If we're at the end, we leave the loop. It's the only way to reach the `true` output
|
||||||
|
if (byteCount == 4) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//If the next character is invalid, we return false
|
||||||
|
if (stringLength == len || ip4addr[stringLength++] != '.') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return stringLength == len || ip4addr[stringLength] == '\0';
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2015 ARM Limited. All rights reserved.
|
* Copyright (c) 2014-2018 ARM Limited. All rights reserved.
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||||
* not use this file except in compliance with the License.
|
* not use this file except in compliance with the License.
|
||||||
|
@ -41,6 +41,7 @@ struct ns_mem_book {
|
||||||
void (*heap_failure_callback)(heap_fail_t);
|
void (*heap_failure_callback)(heap_fail_t);
|
||||||
NS_LIST_HEAD(hole_t, link) holes_list;
|
NS_LIST_HEAD(hole_t, link) holes_list;
|
||||||
ns_mem_heap_size_t heap_size;
|
ns_mem_heap_size_t heap_size;
|
||||||
|
ns_mem_heap_size_t temporary_alloc_heap_limit; /* Amount of reserved heap temporary alloc can't exceed */
|
||||||
};
|
};
|
||||||
|
|
||||||
static ns_mem_book_t *default_book; // heap pointer for original "ns_" API use
|
static ns_mem_book_t *default_book; // heap pointer for original "ns_" API use
|
||||||
|
@ -48,6 +49,8 @@ static ns_mem_book_t *default_book; // heap pointer for original "ns_" API use
|
||||||
// size of a hole_t in our word units
|
// size of a hole_t in our word units
|
||||||
#define HOLE_T_SIZE ((ns_mem_word_size_t) ((sizeof(hole_t) + sizeof(ns_mem_word_size_t) - 1) / sizeof(ns_mem_word_size_t)))
|
#define HOLE_T_SIZE ((ns_mem_word_size_t) ((sizeof(hole_t) + sizeof(ns_mem_word_size_t) - 1) / sizeof(ns_mem_word_size_t)))
|
||||||
|
|
||||||
|
#define TEMPORARY_ALLOC_FREE_HEAP_THRESHOLD 5 /* temporary allocations must leave 5% of the heap free */
|
||||||
|
|
||||||
static NS_INLINE hole_t *hole_from_block_start(ns_mem_word_size_t *start)
|
static NS_INLINE hole_t *hole_from_block_start(ns_mem_word_size_t *start)
|
||||||
{
|
{
|
||||||
return (hole_t *)(start + 1);
|
return (hole_t *)(start + 1);
|
||||||
|
@ -124,6 +127,7 @@ ns_mem_book_t *ns_mem_init(void *heap, ns_mem_heap_size_t h_size,
|
||||||
memset(book->mem_stat_info_ptr, 0, sizeof(mem_stat_t));
|
memset(book->mem_stat_info_ptr, 0, sizeof(mem_stat_t));
|
||||||
book->mem_stat_info_ptr->heap_sector_size = book->heap_size;
|
book->mem_stat_info_ptr->heap_sector_size = book->heap_size;
|
||||||
}
|
}
|
||||||
|
book->temporary_alloc_heap_limit = book->heap_size/100 * (100-TEMPORARY_ALLOC_FREE_HEAP_THRESHOLD);
|
||||||
#endif
|
#endif
|
||||||
//There really is no support to standard malloc in this library anymore
|
//There really is no support to standard malloc in this library anymore
|
||||||
book->heap_failure_callback = passed_fptr;
|
book->heap_failure_callback = passed_fptr;
|
||||||
|
@ -140,6 +144,47 @@ const mem_stat_t *ns_mem_get_mem_stat(ns_mem_book_t *heap)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ns_mem_set_temporary_alloc_free_heap_threshold(ns_mem_book_t *book, uint8_t free_heap_percentage, ns_mem_heap_size_t free_heap_amount)
|
||||||
|
{
|
||||||
|
#ifndef STANDARD_MALLOC
|
||||||
|
ns_mem_heap_size_t heap_limit = 0;
|
||||||
|
|
||||||
|
if (!book || !book->mem_stat_info_ptr) {
|
||||||
|
// no book or mem_stats
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (free_heap_amount && free_heap_amount < book->heap_size/2) {
|
||||||
|
heap_limit = book->heap_size - free_heap_amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!free_heap_amount && free_heap_percentage && free_heap_percentage < 50) {
|
||||||
|
heap_limit = book->heap_size/100 * (100 - free_heap_percentage);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (free_heap_amount == 0 && free_heap_percentage == 0) {
|
||||||
|
// feature disabled, allow whole heap to be reserved by temporary allo
|
||||||
|
heap_limit = book->heap_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (heap_limit == 0) {
|
||||||
|
// illegal heap parameters
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
book->temporary_alloc_heap_limit = heap_limit;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
return -3;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int ns_dyn_mem_set_temporary_alloc_free_heap_threshold(uint8_t free_heap_percentage, ns_mem_heap_size_t free_heap_amount)
|
||||||
|
{
|
||||||
|
return ns_mem_set_temporary_alloc_free_heap_threshold(default_book, free_heap_percentage, free_heap_amount);
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef STANDARD_MALLOC
|
#ifndef STANDARD_MALLOC
|
||||||
static void dev_stat_update(mem_stat_t *mem_stat_info_ptr, mem_stat_update_t type, ns_mem_block_size_t size)
|
static void dev_stat_update(mem_stat_t *mem_stat_info_ptr, mem_stat_update_t type, ns_mem_block_size_t size)
|
||||||
{
|
{
|
||||||
|
@ -179,8 +224,7 @@ static ns_mem_word_size_t convert_allocation_size(ns_mem_book_t *book, ns_mem_bl
|
||||||
// Checks that block length indicators are valid
|
// Checks that block length indicators are valid
|
||||||
// Block has format: Size of data area [1 word] | data area [abs(size) words]| Size of data area [1 word]
|
// Block has format: Size of data area [1 word] | data area [abs(size) words]| Size of data area [1 word]
|
||||||
// If Size is negative it means area is unallocated
|
// If Size is negative it means area is unallocated
|
||||||
// For direction, use 1 for direction up and -1 for down
|
static int8_t ns_mem_block_validate(ns_mem_word_size_t *block_start)
|
||||||
static int8_t ns_mem_block_validate(ns_mem_word_size_t *block_start, int direction)
|
|
||||||
{
|
{
|
||||||
int8_t ret_val = -1;
|
int8_t ret_val = -1;
|
||||||
ns_mem_word_size_t *end = block_start;
|
ns_mem_word_size_t *end = block_start;
|
||||||
|
@ -203,6 +247,14 @@ static void *ns_mem_internal_alloc(ns_mem_book_t *book, const ns_mem_block_size_
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (book->mem_stat_info_ptr && direction == 1) {
|
||||||
|
if (book->mem_stat_info_ptr->heap_sector_allocated_bytes > book->temporary_alloc_heap_limit) {
|
||||||
|
/* Not enough heap for temporary memory allocation */
|
||||||
|
dev_stat_update(book->mem_stat_info_ptr, DEV_HEAP_ALLOC_FAIL, 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ns_mem_word_size_t *block_ptr = NULL;
|
ns_mem_word_size_t *block_ptr = NULL;
|
||||||
|
|
||||||
platform_enter_critical();
|
platform_enter_critical();
|
||||||
|
@ -220,7 +272,7 @@ static void *ns_mem_internal_alloc(ns_mem_book_t *book, const ns_mem_block_size_
|
||||||
: ns_list_get_previous(&book->holes_list, cur_hole)
|
: ns_list_get_previous(&book->holes_list, cur_hole)
|
||||||
) {
|
) {
|
||||||
ns_mem_word_size_t *p = block_start_from_hole(cur_hole);
|
ns_mem_word_size_t *p = block_start_from_hole(cur_hole);
|
||||||
if (ns_mem_block_validate(p, direction) != 0 || *p >= 0) {
|
if (ns_mem_block_validate(p) != 0 || *p >= 0) {
|
||||||
//Validation failed, or this supposed hole has positive (allocated) size
|
//Validation failed, or this supposed hole has positive (allocated) size
|
||||||
heap_failure(book, NS_DYN_MEM_HEAP_SECTOR_CORRUPTED);
|
heap_failure(book, NS_DYN_MEM_HEAP_SECTOR_CORRUPTED);
|
||||||
break;
|
break;
|
||||||
|
@ -236,7 +288,9 @@ static void *ns_mem_internal_alloc(ns_mem_book_t *book, const ns_mem_block_size_
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
ns_mem_word_size_t block_data_size = -*block_ptr;
|
// Separate declaration from initialization to keep IAR happy as the gotos skip this block.
|
||||||
|
ns_mem_word_size_t block_data_size;
|
||||||
|
block_data_size = -*block_ptr;
|
||||||
if (block_data_size >= (data_size + 2 + HOLE_T_SIZE)) {
|
if (block_data_size >= (data_size + 2 + HOLE_T_SIZE)) {
|
||||||
ns_mem_word_size_t hole_size = block_data_size - data_size - 2;
|
ns_mem_word_size_t hole_size = block_data_size - data_size - 2;
|
||||||
ns_mem_word_size_t *hole_ptr;
|
ns_mem_word_size_t *hole_ptr;
|
||||||
|
@ -277,7 +331,7 @@ static void *ns_mem_internal_alloc(ns_mem_book_t *book, const ns_mem_block_size_
|
||||||
dev_stat_update(book->mem_stat_info_ptr, DEV_HEAP_ALLOC_OK, (data_size + 2) * sizeof(ns_mem_word_size_t));
|
dev_stat_update(book->mem_stat_info_ptr, DEV_HEAP_ALLOC_OK, (data_size + 2) * sizeof(ns_mem_word_size_t));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
//Update Allocate Fail, second parameter is not used for stats
|
//Update Allocate Fail, second parameter is used for stats
|
||||||
dev_stat_update(book->mem_stat_info_ptr, DEV_HEAP_ALLOC_FAIL, 0);
|
dev_stat_update(book->mem_stat_info_ptr, DEV_HEAP_ALLOC_FAIL, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -425,7 +479,7 @@ void ns_mem_free(ns_mem_book_t *book, void *block)
|
||||||
} else if (size < 0) {
|
} else if (size < 0) {
|
||||||
heap_failure(book, NS_DYN_MEM_DOUBLE_FREE);
|
heap_failure(book, NS_DYN_MEM_DOUBLE_FREE);
|
||||||
} else {
|
} else {
|
||||||
if (ns_mem_block_validate(ptr, 1) != 0) {
|
if (ns_mem_block_validate(ptr) != 0) {
|
||||||
heap_failure(book, NS_DYN_MEM_HEAP_SECTOR_CORRUPTED);
|
heap_failure(book, NS_DYN_MEM_HEAP_SECTOR_CORRUPTED);
|
||||||
} else {
|
} else {
|
||||||
ns_mem_free_and_merge_with_adjacent_blocks(book, ptr, size);
|
ns_mem_free_and_merge_with_adjacent_blocks(book, ptr, size);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
* Copyright (c) 2015-2018 ARM Limited. All rights reserved.
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||||
* not use this file except in compliance with the License.
|
* not use this file except in compliance with the License.
|
||||||
|
@ -37,7 +37,7 @@ TEST(dynmem, init)
|
||||||
mem_stat_t info;
|
mem_stat_t info;
|
||||||
reset_heap_error();
|
reset_heap_error();
|
||||||
ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
|
ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
|
||||||
CHECK(info.heap_sector_size >= (size-64));
|
CHECK(info.heap_sector_size >= (size-72));
|
||||||
CHECK(!heap_have_failed());
|
CHECK(!heap_have_failed());
|
||||||
CHECK(ns_dyn_mem_get_mem_stat() == &info);
|
CHECK(ns_dyn_mem_get_mem_stat() == &info);
|
||||||
free(heap);
|
free(heap);
|
||||||
|
@ -50,7 +50,7 @@ TEST(dynmem, different_sizes)
|
||||||
mem_stat_t info;
|
mem_stat_t info;
|
||||||
uint8_t *heap = (uint8_t*)malloc(size);
|
uint8_t *heap = (uint8_t*)malloc(size);
|
||||||
ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
|
ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
|
||||||
CHECK(info.heap_sector_size >= (size-64));
|
CHECK(info.heap_sector_size >= (size-72));
|
||||||
CHECK(!heap_have_failed());
|
CHECK(!heap_have_failed());
|
||||||
CHECK(ns_dyn_mem_alloc(10));
|
CHECK(ns_dyn_mem_alloc(10));
|
||||||
free(heap);
|
free(heap);
|
||||||
|
@ -68,7 +68,7 @@ TEST(dynmem, diff_alignment)
|
||||||
for (int i=0; i<16; i++) {
|
for (int i=0; i<16; i++) {
|
||||||
ptr++; size--;
|
ptr++; size--;
|
||||||
ns_dyn_mem_init(ptr, size, &heap_fail_callback, &info);
|
ns_dyn_mem_init(ptr, size, &heap_fail_callback, &info);
|
||||||
CHECK(info.heap_sector_size >= (size-64));
|
CHECK(info.heap_sector_size >= (size-72));
|
||||||
CHECK(!heap_have_failed());
|
CHECK(!heap_have_failed());
|
||||||
}
|
}
|
||||||
free(heap);
|
free(heap);
|
||||||
|
@ -136,6 +136,81 @@ TEST(dynmem, ns_dyn_mem_temporary_alloc)
|
||||||
free(heap);
|
free(heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(dynmem, ns_dyn_mem_temporary_alloc_with_heap_threshold)
|
||||||
|
{
|
||||||
|
uint16_t size = 1000;
|
||||||
|
mem_stat_t info;
|
||||||
|
void *p1, *p2;
|
||||||
|
int ret_val;
|
||||||
|
uint8_t *heap = (uint8_t*)malloc(size);
|
||||||
|
CHECK(NULL != heap);
|
||||||
|
reset_heap_error();
|
||||||
|
ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
|
||||||
|
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);
|
||||||
|
CHECK(!heap_have_failed());
|
||||||
|
CHECK(p1);
|
||||||
|
p2 = ns_dyn_mem_temporary_alloc((size-72)*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);
|
||||||
|
CHECK(!heap_have_failed());
|
||||||
|
CHECK(p2);
|
||||||
|
ns_dyn_mem_free(p1);
|
||||||
|
ns_dyn_mem_free(p2);
|
||||||
|
CHECK(info.heap_alloc_fail_cnt == 1);
|
||||||
|
CHECK(info.heap_sector_alloc_cnt == 0);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
CHECK(p1);
|
||||||
|
p2 = ns_dyn_mem_temporary_alloc((size-72)*0.10);
|
||||||
|
CHECK(p2==NULL);
|
||||||
|
ns_dyn_mem_free(p1);
|
||||||
|
CHECK(!heap_have_failed());
|
||||||
|
CHECK(info.heap_alloc_fail_cnt == 2);
|
||||||
|
CHECK(info.heap_sector_alloc_cnt == 0);
|
||||||
|
|
||||||
|
// 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 */);
|
||||||
|
CHECK(p1);
|
||||||
|
p2 = ns_dyn_mem_temporary_alloc(1);
|
||||||
|
CHECK(p2==NULL);
|
||||||
|
ns_dyn_mem_free(p1);
|
||||||
|
|
||||||
|
// Test5, illegal API parameters
|
||||||
|
ret_val = ns_dyn_mem_set_temporary_alloc_free_heap_threshold(0, size/2);
|
||||||
|
CHECK(ret_val==-2);
|
||||||
|
ret_val = ns_dyn_mem_set_temporary_alloc_free_heap_threshold(0, size*2);
|
||||||
|
CHECK(ret_val==-2);
|
||||||
|
ret_val = ns_dyn_mem_set_temporary_alloc_free_heap_threshold(51, 0);
|
||||||
|
CHECK(ret_val==-2);
|
||||||
|
ret_val = ns_dyn_mem_set_temporary_alloc_free_heap_threshold(255, 0);
|
||||||
|
CHECK(ret_val==-2);
|
||||||
|
|
||||||
|
CHECK(!heap_have_failed());
|
||||||
|
CHECK(info.heap_alloc_fail_cnt == 3);
|
||||||
|
CHECK(info.heap_sector_alloc_cnt == 0);
|
||||||
|
free(heap);
|
||||||
|
|
||||||
|
// Test6, feature is disabled if info is not set
|
||||||
|
heap = (uint8_t*)malloc(size);
|
||||||
|
CHECK(NULL != heap);
|
||||||
|
ns_dyn_mem_init(heap, size, &heap_fail_callback, NULL);
|
||||||
|
ret_val = ns_dyn_mem_set_temporary_alloc_free_heap_threshold(0, 0);
|
||||||
|
CHECK(ret_val==-1);
|
||||||
|
CHECK(!heap_have_failed());
|
||||||
|
free(heap);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(dynmem, test_both_allocs_with_hole_usage) {
|
TEST(dynmem, test_both_allocs_with_hole_usage) {
|
||||||
uint16_t size = 112;
|
uint16_t size = 112;
|
||||||
mem_stat_t info;
|
mem_stat_t info;
|
||||||
|
@ -273,7 +348,7 @@ TEST(dynmem, diff_sizes)
|
||||||
ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
|
ns_dyn_mem_init(heap, size, &heap_fail_callback, &info);
|
||||||
CHECK(!heap_have_failed());
|
CHECK(!heap_have_failed());
|
||||||
int i;
|
int i;
|
||||||
for (i=1; i<(size-64); i++) {
|
for (i=1; i<(size-72); i++) {
|
||||||
p = ns_dyn_mem_temporary_alloc(i);
|
p = ns_dyn_mem_temporary_alloc(i);
|
||||||
CHECK(p);
|
CHECK(p);
|
||||||
ns_dyn_mem_free(p);
|
ns_dyn_mem_free(p);
|
||||||
|
|
|
@ -1,5 +1,17 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
* Copyright (c) 2015 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define NS_LIST_FN extern
|
#define NS_LIST_FN extern
|
||||||
|
|
|
@ -1,6 +1,19 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2015 ARM Limited. All rights reserved.
|
* Copyright (c) 2016, 2018 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "nsdynmemLIB_stub.h"
|
#include "nsdynmemLIB_stub.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -12,11 +25,11 @@
|
||||||
|
|
||||||
nsdynmemlib_stub_data_t nsdynmemlib_stub;
|
nsdynmemlib_stub_data_t nsdynmemlib_stub;
|
||||||
|
|
||||||
void ns_dyn_mem_init(uint8_t *heap, uint16_t h_size, void (*passed_fptr)(heap_fail_t), mem_stat_t *info_ptr)
|
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)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void *ns_dyn_mem_alloc(int16_t alloc_size)
|
void *ns_dyn_mem_alloc(ns_mem_block_size_t alloc_size)
|
||||||
{
|
{
|
||||||
if (nsdynmemlib_stub.returnCounter > 0)
|
if (nsdynmemlib_stub.returnCounter > 0)
|
||||||
{
|
{
|
||||||
|
@ -29,7 +42,7 @@ void *ns_dyn_mem_alloc(int16_t alloc_size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void *ns_dyn_mem_temporary_alloc(int16_t alloc_size)
|
void *ns_dyn_mem_temporary_alloc(ns_mem_block_size_t alloc_size)
|
||||||
{
|
{
|
||||||
if (nsdynmemlib_stub.returnCounter > 0)
|
if (nsdynmemlib_stub.returnCounter > 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,17 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015 ARM Limited. All rights reserved.
|
* Copyright (c) 2016, 2018 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
#ifndef __NSDYNMEMLIB_STUB_H__
|
#ifndef __NSDYNMEMLIB_STUB_H__
|
||||||
#define __NSDYNMEMLIB_STUB_H__
|
#define __NSDYNMEMLIB_STUB_H__
|
||||||
|
|
|
@ -1,5 +1,17 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, ARM Limited, All Rights Reserved.
|
* Copyright (c) 2016 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ns_types.h"
|
#include "ns_types.h"
|
||||||
|
|
Loading…
Reference in New Issue