mirror of
https://github.com/MaJerle/lwmem.git
synced 2025-01-13 21:42:53 +08:00
simple implementation for grow-only malloc (minimalistic)
This commit is contained in:
parent
254ea2855f
commit
7e45fe460c
@ -10,6 +10,7 @@ else()
|
|||||||
target_sources(${PROJECT_NAME} PUBLIC
|
target_sources(${PROJECT_NAME} PUBLIC
|
||||||
${CMAKE_CURRENT_LIST_DIR}/dev/main.cpp
|
${CMAKE_CURRENT_LIST_DIR}/dev/main.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/tests/lwmem_test.c
|
${CMAKE_CURRENT_LIST_DIR}/tests/lwmem_test.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/tests/lwmem_test_simple.c
|
||||||
|
|
||||||
# win32 port
|
# win32 port
|
||||||
${CMAKE_CURRENT_LIST_DIR}/lwmem/src/system/lwmem_sys_win32.c
|
${CMAKE_CURRENT_LIST_DIR}/lwmem/src/system/lwmem_sys_win32.c
|
||||||
|
@ -41,9 +41,10 @@
|
|||||||
* Open "include/lwmem/lwmem_opt.h" and
|
* Open "include/lwmem/lwmem_opt.h" and
|
||||||
* copy & replace here settings you want to change values
|
* copy & replace here settings you want to change values
|
||||||
*/
|
*/
|
||||||
#define LWMEM_CFG_OS 1
|
#define LWMEM_CFG_OS 1
|
||||||
#define LWMEM_CFG_OS_MUTEX_HANDLE HANDLE
|
#define LWMEM_CFG_OS_MUTEX_HANDLE HANDLE
|
||||||
#define LWMEM_CFG_ENABLE_STATS 0
|
#define LWMEM_CFG_ENABLE_STATS 0
|
||||||
#define LWMEM_CFG_CLEAN_MEMORY 1
|
#define LWMEM_CFG_CLEAN_MEMORY 1
|
||||||
|
#define LWMEM_CFG_SUPPORT_REALLOC_AND_FREE 1
|
||||||
|
|
||||||
#endif /* LWMEM_HDR_OPTS_H */
|
#endif /* LWMEM_HDR_OPTS_H */
|
||||||
|
11
dev/main.cpp
11
dev/main.cpp
@ -5,20 +5,29 @@
|
|||||||
#include "lwmem/lwmem.hpp"
|
#include "lwmem/lwmem.hpp"
|
||||||
|
|
||||||
extern "C" void lwmem_test_run(void);
|
extern "C" void lwmem_test_run(void);
|
||||||
|
extern "C" void lwmem_test_simple_run(void);
|
||||||
extern "C" void lwmem_test_memory_structure(void);
|
extern "C" void lwmem_test_memory_structure(void);
|
||||||
|
|
||||||
/* Setup manager */
|
/* Setup manager */
|
||||||
Lwmem::LwmemLight<1024> manager;
|
static Lwmem::LwmemLight<1024> manager;
|
||||||
|
|
||||||
int
|
int
|
||||||
main(void) {
|
main(void) {
|
||||||
|
#if LWMEM_CFG_SUPPORT_REALLOC_AND_FREE
|
||||||
lwmem_test_memory_structure();
|
lwmem_test_memory_structure();
|
||||||
//lwmem_test_run();
|
//lwmem_test_run();
|
||||||
|
#else
|
||||||
|
lwmem_test_simple_run();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 1
|
||||||
/* Test C++ code */
|
/* Test C++ code */
|
||||||
void* ret = manager.malloc(123);
|
void* ret = manager.malloc(123);
|
||||||
std::cout << ret << std::endl;
|
std::cout << ret << std::endl;
|
||||||
|
#if LWMEM_CFG_SUPPORT_REALLOC_AND_FREE
|
||||||
manager.free(ret);
|
manager.free(ret);
|
||||||
|
#endif /* LWMEM_CFG_SUPPORT_REALLOC_AND_FREE */
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
#define ASSERT(x) do { \
|
#define ASSERT(x) \
|
||||||
if (!(x)) { \
|
do { \
|
||||||
printf("Assert failed with condition (" # x ")\r\n"); \
|
if (!(x)) { \
|
||||||
} else {\
|
printf("Assert failed with condition (" #x ")\r\n"); \
|
||||||
printf("Assert passed with condition (" # x ")\r\n"); \
|
} else { \
|
||||||
}\
|
printf("Assert passed with condition (" #x ")\r\n"); \
|
||||||
} while (0)
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
/* For debug purposes */
|
/* For debug purposes */
|
||||||
lwmem_region_t* regions_used;
|
lwmem_region_t* regions_used;
|
||||||
size_t regions_count = 1; /* Use only 1 region for debug purposes of non-free areas */
|
size_t regions_count = 1; /* Use only 1 region for debug purposes of non-free areas */
|
||||||
|
|
||||||
int
|
int
|
||||||
main(void) {
|
main(void) {
|
||||||
uint8_t* ptr1, *ptr2, *ptr3, *ptr4;
|
uint8_t *ptr1, *ptr2, *ptr3, *ptr4;
|
||||||
uint8_t* rptr1, *rptr2, *rptr3, *rptr4;
|
uint8_t *rptr1, *rptr2, *rptr3, *rptr4;
|
||||||
|
|
||||||
/* Create regions for debug purpose */
|
/* Create regions for debug purpose */
|
||||||
if (!lwmem_debug_create_regions(®ions_used, regions_count, 128)) {
|
if (!lwmem_debug_create_regions(®ions_used, regions_count, 128)) {
|
||||||
@ -31,11 +32,11 @@ main(void) {
|
|||||||
ptr2 = lwmem_malloc(4);
|
ptr2 = lwmem_malloc(4);
|
||||||
ptr3 = lwmem_malloc(4);
|
ptr3 = lwmem_malloc(4);
|
||||||
ptr4 = lwmem_malloc(16);
|
ptr4 = lwmem_malloc(16);
|
||||||
lwmem_free(ptr1); /* Free but keep value for future comparison */
|
lwmem_free(ptr1); /* Free but keep value for future comparison */
|
||||||
lwmem_free(ptr3); /* Free but keep value for future comparison */
|
lwmem_free(ptr3); /* Free but keep value for future comparison */
|
||||||
lwmem_debug_print(1, 1);
|
lwmem_debug_print(1, 1);
|
||||||
printf("Debug above is effectively state 3\r\n");
|
printf("Debug above is effectively state 3\r\n");
|
||||||
lwmem_debug_save_state(); /* Every restore operations rewinds here */
|
lwmem_debug_save_state(); /* Every restore operations rewinds here */
|
||||||
|
|
||||||
/* We always try to reallocate pointer ptr2 */
|
/* We always try to reallocate pointer ptr2 */
|
||||||
|
|
||||||
@ -53,7 +54,7 @@ main(void) {
|
|||||||
printf("State 3b\r\n");
|
printf("State 3b\r\n");
|
||||||
rptr2 = lwmem_realloc(ptr2, 20);
|
rptr2 = lwmem_realloc(ptr2, 20);
|
||||||
lwmem_debug_print(1, 1);
|
lwmem_debug_print(1, 1);
|
||||||
ASSERT(rptr2 == ptr2);
|
ASSERT(rptr2 == ptr1);
|
||||||
|
|
||||||
/* Create 3c case */
|
/* Create 3c case */
|
||||||
printf("\r\n------------------------------------------------------------------------\r\n");
|
printf("\r\n------------------------------------------------------------------------\r\n");
|
||||||
|
@ -52,7 +52,7 @@ State 3b
|
|||||||
| 4 | 0034A548 | 1 | 56 | 48 |Free block |
|
| 4 | 0034A548 | 1 | 56 | 48 |Free block |
|
||||||
| 5 | 0034A580 | 0 | 0 | 0 |End of region |
|
| 5 | 0034A580 | 0 | 0 | 0 |End of region |
|
||||||
|-------|----------|--------|------|------------------|----------------|
|
|-------|----------|--------|------|------------------|----------------|
|
||||||
Assert failed with condition (rptr2 == ptr2)
|
Assert passed with condition (rptr2 == ptr1)
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
-- > State restored to last saved!
|
-- > State restored to last saved!
|
||||||
|
@ -83,10 +83,16 @@ typedef struct {
|
|||||||
* \brief LwMEM main structure
|
* \brief LwMEM main structure
|
||||||
*/
|
*/
|
||||||
typedef struct lwmem {
|
typedef struct lwmem {
|
||||||
lwmem_block_t start_block; /*!< Holds beginning of memory allocation regions */
|
|
||||||
lwmem_block_t* end_block; /*!< Pointer to the last memory location in regions linked list */
|
|
||||||
size_t mem_available_bytes; /*!< Memory size available for allocation */
|
size_t mem_available_bytes; /*!< Memory size available for allocation */
|
||||||
size_t mem_regions_count; /*!< Number of regions used for allocation */
|
#if LWMEM_CFG_SUPPORT_REALLOC_AND_FREE
|
||||||
|
lwmem_block_t start_block; /*!< Holds beginning of memory allocation regions */
|
||||||
|
lwmem_block_t* end_block; /*!< Pointer to the last memory location in regions linked list */
|
||||||
|
size_t mem_regions_count; /*!< Number of regions used for allocation */
|
||||||
|
#else
|
||||||
|
uint8_t* mem_next_available_ptr; /*!< Pointer for next allocation */
|
||||||
|
uint8_t is_initialized; /*!< Set to `1` when initialized */
|
||||||
|
#endif
|
||||||
|
|
||||||
#if LWMEM_CFG_OS || __DOXYGEN__
|
#if LWMEM_CFG_OS || __DOXYGEN__
|
||||||
LWMEM_CFG_OS_MUTEX_HANDLE mutex; /*!< System mutex for OS */
|
LWMEM_CFG_OS_MUTEX_HANDLE mutex; /*!< System mutex for OS */
|
||||||
#endif /* LWMEM_CFG_OS || __DOXYGEN__ */
|
#endif /* LWMEM_CFG_OS || __DOXYGEN__ */
|
||||||
@ -112,7 +118,7 @@ void* lwmem_malloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, const size_t
|
|||||||
void* lwmem_calloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, const size_t nitems, const size_t size);
|
void* lwmem_calloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, const size_t nitems, const size_t size);
|
||||||
#if LWMEM_CFG_SUPPORT_REALLOC_AND_FREE || __DOXYGEN__
|
#if LWMEM_CFG_SUPPORT_REALLOC_AND_FREE || __DOXYGEN__
|
||||||
void* lwmem_realloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, void* const ptr, const size_t size);
|
void* lwmem_realloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, void* const ptr, const size_t size);
|
||||||
uint8_t lwmem_realloc_s_ex(lwmem_t* lwobj, const lwmem_region_t* region, void** const ptr, const size_t size);
|
int lwmem_realloc_s_ex(lwmem_t* lwobj, const lwmem_region_t* region, void** const ptr, const size_t size);
|
||||||
void lwmem_free_ex(lwmem_t* lwobj, void* const ptr);
|
void lwmem_free_ex(lwmem_t* lwobj, void* const ptr);
|
||||||
void lwmem_free_s_ex(lwmem_t* lwobj, void** const ptr);
|
void lwmem_free_s_ex(lwmem_t* lwobj, void** const ptr);
|
||||||
size_t lwmem_get_size_ex(lwmem_t* lwobj, void* ptr);
|
size_t lwmem_get_size_ex(lwmem_t* lwobj, void* ptr);
|
||||||
|
@ -169,6 +169,8 @@
|
|||||||
*/
|
*/
|
||||||
static lwmem_t lwmem_default;
|
static lwmem_t lwmem_default;
|
||||||
|
|
||||||
|
#if LWMEM_CFG_SUPPORT_REALLOC_AND_FREE
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Get region aligned start address and aligned size
|
* \brief Get region aligned start address and aligned size
|
||||||
* \param[in] region: Region to check for size and address
|
* \param[in] region: Region to check for size and address
|
||||||
@ -187,12 +189,6 @@ prv_get_region_addr_size(const lwmem_region_t* region, uint8_t** msa, size_t* ms
|
|||||||
*msa = NULL;
|
*msa = NULL;
|
||||||
*msz = 0;
|
*msz = 0;
|
||||||
|
|
||||||
/* Check region size and align it to config bits */
|
|
||||||
mem_size = region->size & ~LWMEM_ALIGN_BITS; /* Size does not include lower bits */
|
|
||||||
if (mem_size < (2 * LWMEM_BLOCK_MIN_SIZE)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Start address must be aligned to configuration
|
* Start address must be aligned to configuration
|
||||||
* Increase start address and decrease effective region size
|
* Increase start address and decrease effective region size
|
||||||
@ -442,8 +438,6 @@ prv_alloc(lwmem_t* const lwobj, const lwmem_region_t* region, const size_t size)
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LWMEM_CFG_SUPPORT_REALLOC_AND_FREE
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Free input pointer
|
* \brief Free input pointer
|
||||||
* \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance
|
* \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance
|
||||||
@ -582,8 +576,7 @@ prv_realloc(lwmem_t* const lwobj, const lwmem_region_t* region, void* const ptr,
|
|||||||
/* Input block points to address somewhere between "prev" and "prev->next" pointers */
|
/* Input block points to address somewhere between "prev" and "prev->next" pointers */
|
||||||
|
|
||||||
/* Check if "block" and next free "prev->next" create contiguous memory with size of at least new requested size */
|
/* Check if "block" and next free "prev->next" create contiguous memory with size of at least new requested size */
|
||||||
if ((LWMEM_TO_BYTE_PTR(block) + block_size)
|
if ((LWMEM_TO_BYTE_PTR(block) + block_size) == LWMEM_TO_BYTE_PTR(prev->next)
|
||||||
== LWMEM_TO_BYTE_PTR(prev->next) /* Blocks create contiguous block */
|
|
||||||
&& (block_size + prev->next->size) >= final_size) { /* Size is greater or equal to requested */
|
&& (block_size + prev->next->size) >= final_size) { /* Size is greater or equal to requested */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -593,8 +586,8 @@ prv_realloc(lwmem_t* const lwobj, const lwmem_region_t* region, void* const ptr,
|
|||||||
lwobj->mem_available_bytes -= prev->next->size; /* For now decrease effective available bytes */
|
lwobj->mem_available_bytes -= prev->next->size; /* For now decrease effective available bytes */
|
||||||
LWMEM_UPDATE_MIN_FREE(lwobj);
|
LWMEM_UPDATE_MIN_FREE(lwobj);
|
||||||
block->size = block_size + prev->next->size; /* Increase effective size of new block */
|
block->size = block_size + prev->next->size; /* Increase effective size of new block */
|
||||||
prev->next =
|
prev->next = prev->next->next; /* Set next to next's next,
|
||||||
prev->next->next; /* Set next to next's next, effectively remove expanded block from free list */
|
effectively remove expanded block from free list */
|
||||||
|
|
||||||
prv_split_too_big_block(lwobj, block, final_size); /* Split block if it is too big */
|
prv_split_too_big_block(lwobj, block, final_size); /* Split block if it is too big */
|
||||||
LWMEM_BLOCK_SET_ALLOC(block); /* Set block as allocated */
|
LWMEM_BLOCK_SET_ALLOC(block); /* Set block as allocated */
|
||||||
@ -624,10 +617,10 @@ prv_realloc(lwmem_t* const lwobj, const lwmem_region_t* region, void* const ptr,
|
|||||||
|
|
||||||
lwobj->mem_available_bytes -= prev->size; /* For now decrease effective available bytes */
|
lwobj->mem_available_bytes -= prev->size; /* For now decrease effective available bytes */
|
||||||
LWMEM_UPDATE_MIN_FREE(lwobj);
|
LWMEM_UPDATE_MIN_FREE(lwobj);
|
||||||
prev->size += block_size; /* Increase size of input block size */
|
prev->size += block_size; /* Increase size of input block size */
|
||||||
prevprev->next =
|
prevprev->next = prev->next; /* Remove prev from free list as it is now being used
|
||||||
prev->next; /* Remove prev from free list as it is now being used for allocation together with existing block */
|
for allocation together with existing block */
|
||||||
block = prev; /* Move block pointer to previous one */
|
block = prev; /* Move block pointer to previous one */
|
||||||
|
|
||||||
prv_split_too_big_block(lwobj, block, final_size); /* Split block if it is too big */
|
prv_split_too_big_block(lwobj, block, final_size); /* Split block if it is too big */
|
||||||
LWMEM_BLOCK_SET_ALLOC(block); /* Set block as allocated */
|
LWMEM_BLOCK_SET_ALLOC(block); /* Set block as allocated */
|
||||||
@ -698,79 +691,21 @@ prv_realloc(lwmem_t* const lwobj, const lwmem_region_t* region, void* const ptr,
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* LWMEM_CFG_SUPPORT_REALLOC_AND_FREE */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Initializes and assigns user regions for memory used by allocator algorithm
|
* \brief Assign the memory structure for advanced memory allocation system
|
||||||
* \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance
|
*
|
||||||
* \param[in] regions: Pointer to array of regions with address and respective size.
|
* \param lwobj
|
||||||
* Regions must be in increasing order (start address) and must not overlap in-between.
|
* \param regions
|
||||||
* Last region entry must have address `NULL` and size set to `0`
|
* \return size_t
|
||||||
* \code{.c}
|
|
||||||
//Example definition
|
|
||||||
lwmem_region_t regions[] = {
|
|
||||||
{ (void *)0x10000000, 0x1000 }, //Region starts at address 0x10000000 and is 0x1000 bytes long
|
|
||||||
{ (void *)0x20000000, 0x2000 }, //Region starts at address 0x20000000 and is 0x2000 bytes long
|
|
||||||
{ (void *)0x30000000, 0x3000 }, //Region starts at address 0x30000000 and is 0x3000 bytes long
|
|
||||||
{ NULL, 0 } //Array termination indicator
|
|
||||||
}
|
|
||||||
\endcode
|
|
||||||
* \return `0` on failure, number of final regions used for memory manager on success
|
|
||||||
* \note This function is not thread safe when used with operating system.
|
|
||||||
* It must be called only once to setup memory regions
|
|
||||||
*/
|
*/
|
||||||
size_t
|
static size_t
|
||||||
lwmem_assignmem_ex(lwmem_t* lwobj, const lwmem_region_t* regions) {
|
prv_assignmem(lwmem_t* lwobj, const lwmem_region_t* regions) {
|
||||||
uint8_t* mem_start_addr;
|
uint8_t* mem_start_addr = NULL;
|
||||||
size_t mem_size, len = 0;
|
size_t mem_size = 0;
|
||||||
lwmem_block_t *first_block, *prev_end_block;
|
lwmem_block_t *first_block = NULL, *prev_end_block = NULL;
|
||||||
|
|
||||||
lwobj = LWMEM_GET_LWOBJ(lwobj);
|
for (size_t idx = 0; regions->size > 0 && regions->start_addr != NULL; ++idx, ++regions) {
|
||||||
/* Check first things first */
|
/* Get region start address and size, stop on failure */
|
||||||
if (regions == NULL || lwobj->end_block != NULL /* Init function may only be called once per lwmem instance */
|
|
||||||
|| (((size_t)LWMEM_CFG_ALIGN_NUM) & (((size_t)LWMEM_CFG_ALIGN_NUM) - 1)) > 0) { /* Must be power of 2 */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check values entered by application */
|
|
||||||
mem_start_addr = (void*)0;
|
|
||||||
mem_size = 0;
|
|
||||||
for (size_t i = 0;; ++i) {
|
|
||||||
/*
|
|
||||||
* Check for valid entry or end of array descriptor
|
|
||||||
*
|
|
||||||
* Invalid entry is considered as "end-of-region" indicator
|
|
||||||
*/
|
|
||||||
if (regions[i].size == 0 && regions[i].start_addr == NULL) {
|
|
||||||
len = i;
|
|
||||||
if (len == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* New region(s) must be higher (in address space) than previous one */
|
|
||||||
if ((mem_start_addr + mem_size) > LWMEM_TO_BYTE_PTR(regions[i].start_addr)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Save new values for next round */
|
|
||||||
mem_start_addr = regions[i].start_addr;
|
|
||||||
mem_size = regions[i].size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Process further checks of valid inputs */
|
|
||||||
if (regions == NULL || len == 0
|
|
||||||
#if LWMEM_CFG_OS
|
|
||||||
|| lwmem_sys_mutex_isvalid(&(lwobj->mutex)) /* Check if mutex valid already = must not be */
|
|
||||||
|| !lwmem_sys_mutex_create(&(lwobj->mutex)) /* Final step = try to create mutex for new instance */
|
|
||||||
#endif /* LWMEM_CFG_OS */
|
|
||||||
) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < len; ++i, ++regions) {
|
|
||||||
/* Get region start address and size */
|
|
||||||
if (!prv_get_region_addr_size(regions, &mem_start_addr, &mem_size)) {
|
if (!prv_get_region_addr_size(regions, &mem_start_addr, &mem_size)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -831,6 +766,161 @@ lwmem_assignmem_ex(lwmem_t* lwobj, const lwmem_region_t* regions) {
|
|||||||
return lwobj->mem_regions_count; /* Return number of regions used by manager */
|
return lwobj->mem_regions_count; /* Return number of regions used by manager */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else /* LWMEM_CFG_SUPPORT_REALLOC_AND_FREE */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Assign the regions for simple algorithm
|
||||||
|
*
|
||||||
|
* At this point, regions check has been performed, so we assume
|
||||||
|
* everything is ready to proceed
|
||||||
|
*
|
||||||
|
* \param lwobj: LwMEM object
|
||||||
|
* \param regions: List of regions to assign
|
||||||
|
* \return Number of regions used
|
||||||
|
*/
|
||||||
|
static size_t
|
||||||
|
prv_assignmem_simple(lwmem_t* const lwobj, const lwmem_region_t* regions) {
|
||||||
|
uint8_t* mem_start_addr = regions[0].start_addr;
|
||||||
|
size_t mem_size = regions[0].size;
|
||||||
|
|
||||||
|
/* Adjust alignment data */
|
||||||
|
if (((size_t)mem_start_addr) & LWMEM_ALIGN_BITS) {
|
||||||
|
mem_start_addr += ((size_t)LWMEM_CFG_ALIGN_NUM) - ((size_t)mem_start_addr & LWMEM_ALIGN_BITS);
|
||||||
|
mem_size -= (size_t)(mem_start_addr - LWMEM_TO_BYTE_PTR(regions[0].start_addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Align mem to alignment*/
|
||||||
|
mem_size = mem_size & ~LWMEM_ALIGN_BITS;
|
||||||
|
|
||||||
|
/* Store the available information */
|
||||||
|
lwobj->mem_available_bytes = mem_size;
|
||||||
|
lwobj->mem_next_available_ptr = mem_start_addr;
|
||||||
|
lwobj->is_initialized = 1;
|
||||||
|
return 1; /* One region is being used only for now */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Simple allocation algorithm, that can only allocate memory,
|
||||||
|
* but it does not support free.
|
||||||
|
*
|
||||||
|
* It uses simple first-in-first-serve concept,
|
||||||
|
* where memory grows upward gradually, up until it reaches the end
|
||||||
|
* of memory area
|
||||||
|
*
|
||||||
|
* \param lwobj: LwMEM object
|
||||||
|
* \param region: Selected region. Not used in the current revision,
|
||||||
|
* but footprint remains the same if one day library will support it
|
||||||
|
* \param size: Requested allocation size
|
||||||
|
* \return `NULL` on failure, or pointer to allocated memory
|
||||||
|
*/
|
||||||
|
static void*
|
||||||
|
prv_alloc_simple(lwmem_t* const lwobj, const lwmem_region_t* region, const size_t size) {
|
||||||
|
void* retval = NULL;
|
||||||
|
const size_t alloc_size = LWMEM_ALIGN(size);
|
||||||
|
|
||||||
|
if (alloc_size <= lwobj->mem_available_bytes) {
|
||||||
|
retval = lwobj->mem_next_available_ptr;
|
||||||
|
|
||||||
|
/* Get ready for next iteration */
|
||||||
|
lwobj->mem_next_available_ptr += alloc_size;
|
||||||
|
lwobj->mem_available_bytes -= alloc_size;
|
||||||
|
}
|
||||||
|
(void)region;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LWMEM_CFG_SUPPORT_REALLOC_AND_FREE */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Initializes and assigns user regions for memory used by allocator algorithm
|
||||||
|
* \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance
|
||||||
|
* \param[in] regions: Pointer to array of regions with address and respective size.
|
||||||
|
* Regions must be in increasing order (start address) and must not overlap in-between.
|
||||||
|
* Last region entry must have address `NULL` and size set to `0`
|
||||||
|
* \code{.c}
|
||||||
|
//Example definition
|
||||||
|
lwmem_region_t regions[] = {
|
||||||
|
{ (void *)0x10000000, 0x1000 }, //Region starts at address 0x10000000 and is 0x1000 bytes long
|
||||||
|
{ (void *)0x20000000, 0x2000 }, //Region starts at address 0x20000000 and is 0x2000 bytes long
|
||||||
|
{ (void *)0x30000000, 0x3000 }, //Region starts at address 0x30000000 and is 0x3000 bytes long
|
||||||
|
{ NULL, 0 } //Array termination indicator
|
||||||
|
}
|
||||||
|
\endcode
|
||||||
|
* \return `0` on failure, number of final regions used for memory manager on success
|
||||||
|
* \note This function is not thread safe when used with operating system.
|
||||||
|
* It must be called only once to setup memory regions
|
||||||
|
*/
|
||||||
|
size_t
|
||||||
|
lwmem_assignmem_ex(lwmem_t* lwobj, const lwmem_region_t* regions) {
|
||||||
|
uint8_t* mem_start_addr = NULL;
|
||||||
|
size_t mem_size = 0, len = 0;
|
||||||
|
|
||||||
|
lwobj = LWMEM_GET_LWOBJ(lwobj);
|
||||||
|
|
||||||
|
/* Check first things first */
|
||||||
|
if (regions == NULL || (((size_t)LWMEM_CFG_ALIGN_NUM) & (((size_t)LWMEM_CFG_ALIGN_NUM) - 1)) > 0
|
||||||
|
#if LWMEM_CFG_SUPPORT_REALLOC_AND_FREE
|
||||||
|
|| lwobj->end_block != NULL /* Init function may only be called once per lwmem instance */
|
||||||
|
#else
|
||||||
|
|| lwobj->is_initialized /* Already initialized? */
|
||||||
|
#endif /* LWMEM_CFG_SUPPORT_REALLOC_AND_FREE */
|
||||||
|
) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check values entered by application */
|
||||||
|
mem_start_addr = (void*)0;
|
||||||
|
mem_size = 0;
|
||||||
|
for (size_t idx = 0;; ++idx) {
|
||||||
|
/*
|
||||||
|
* Check for valid entry or end of array descriptor
|
||||||
|
* Invalid entry is considered as "end-of-region" indicator
|
||||||
|
*/
|
||||||
|
if (regions[idx].size == 0 && regions[idx].start_addr == NULL) {
|
||||||
|
len = idx;
|
||||||
|
if (len == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !LWMEM_CFG_SUPPORT_REALLOC_AND_FREE
|
||||||
|
/*
|
||||||
|
* In case of simple allocation algorithm, we (for now!) only allow one region.
|
||||||
|
* Return zero value if user passed more than one region in a sequence.
|
||||||
|
*/
|
||||||
|
else if (idx > 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* LWMEM_CFG_SUPPORT_REALLOC_AND_FREE */
|
||||||
|
|
||||||
|
/* New region(s) must be higher (in address space) than previous one */
|
||||||
|
if ((mem_start_addr + mem_size) > LWMEM_TO_BYTE_PTR(regions[idx].start_addr)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save new values for next round */
|
||||||
|
mem_start_addr = regions[idx].start_addr;
|
||||||
|
mem_size = regions[idx].size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Final init and check before initializing the regions */
|
||||||
|
if (len == 0
|
||||||
|
#if LWMEM_CFG_OS
|
||||||
|
|| lwmem_sys_mutex_isvalid(&(lwobj->mutex)) /* Check if mutex valid already = must not be */
|
||||||
|
|| !lwmem_sys_mutex_create(&(lwobj->mutex)) /* Final step = try to create mutex for new instance */
|
||||||
|
#endif /* LWMEM_CFG_OS */
|
||||||
|
) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LWMEM_CFG_SUPPORT_REALLOC_AND_FREE
|
||||||
|
return prv_assignmem(lwobj, regions);
|
||||||
|
#else /* LWMEM_CFG_SUPPORT_REALLOC_AND_FREE */
|
||||||
|
return prv_assignmem_simple(lwobj, regions);
|
||||||
|
#endif /* LWMEM_CFG_SUPPORT_REALLOC_AND_FREE */
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Allocate memory of requested size in specific lwmem instance and optional region.
|
* \brief Allocate memory of requested size in specific lwmem instance and optional region.
|
||||||
* \note This is an extended malloc version function declaration to support advanced features
|
* \note This is an extended malloc version function declaration to support advanced features
|
||||||
@ -843,10 +933,16 @@ lwmem_assignmem_ex(lwmem_t* lwobj, const lwmem_region_t* regions) {
|
|||||||
*/
|
*/
|
||||||
void*
|
void*
|
||||||
lwmem_malloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, const size_t size) {
|
lwmem_malloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, const size_t size) {
|
||||||
void* ptr;
|
void* ptr = NULL;
|
||||||
|
|
||||||
lwobj = LWMEM_GET_LWOBJ(lwobj);
|
lwobj = LWMEM_GET_LWOBJ(lwobj);
|
||||||
|
|
||||||
LWMEM_PROTECT(lwobj);
|
LWMEM_PROTECT(lwobj);
|
||||||
|
#if LWMEM_CFG_SUPPORT_REALLOC_AND_FREE
|
||||||
ptr = prv_alloc(lwobj, region, size);
|
ptr = prv_alloc(lwobj, region, size);
|
||||||
|
#else /* LWMEM_CFG_SUPPORT_REALLOC_AND_FREE */
|
||||||
|
ptr = prv_alloc_simple(lwobj, region, size);
|
||||||
|
#endif /* LWMEM_CFG_SUPPORT_REALLOC_AND_FREE */
|
||||||
LWMEM_UNPROTECT(lwobj);
|
LWMEM_UNPROTECT(lwobj);
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
@ -856,7 +952,7 @@ lwmem_malloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, const size_t size)
|
|||||||
* in specific lwmem instance and region.
|
* in specific lwmem instance and region.
|
||||||
*
|
*
|
||||||
* It resets allocated block of memory to zero if allocation is successful
|
* It resets allocated block of memory to zero if allocation is successful
|
||||||
|
*
|
||||||
* \note This is an extended calloc version function declaration to support advanced features
|
* \note This is an extended calloc version function declaration to support advanced features
|
||||||
* \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance
|
* \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance
|
||||||
* \param[in] region: Optional region instance within LwMEM instance to force allocation from.
|
* \param[in] region: Optional region instance within LwMEM instance to force allocation from.
|
||||||
@ -868,16 +964,22 @@ lwmem_malloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, const size_t size)
|
|||||||
*/
|
*/
|
||||||
void*
|
void*
|
||||||
lwmem_calloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, const size_t nitems, const size_t size) {
|
lwmem_calloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, const size_t nitems, const size_t size) {
|
||||||
void* ptr;
|
void* ptr = NULL;
|
||||||
const size_t s = size * nitems;
|
const size_t alloc_size = size * nitems;
|
||||||
|
|
||||||
lwobj = LWMEM_GET_LWOBJ(lwobj);
|
lwobj = LWMEM_GET_LWOBJ(lwobj);
|
||||||
|
|
||||||
LWMEM_PROTECT(lwobj);
|
LWMEM_PROTECT(lwobj);
|
||||||
ptr = prv_alloc(lwobj, region, s);
|
#if LWMEM_CFG_SUPPORT_REALLOC_AND_FREE
|
||||||
if (ptr != NULL) {
|
ptr = prv_alloc(lwobj, region, alloc_size);
|
||||||
LWMEM_MEMSET(ptr, 0x00, s);
|
#else /* LWMEM_CFG_SUPPORT_REALLOC_AND_FREE */
|
||||||
}
|
ptr = prv_alloc_simple(lwobj, region, alloc_size);
|
||||||
|
#endif /* LWMEM_CFG_SUPPORT_REALLOC_AND_FREE */
|
||||||
LWMEM_UNPROTECT(lwobj);
|
LWMEM_UNPROTECT(lwobj);
|
||||||
|
|
||||||
|
if (ptr != NULL) {
|
||||||
|
LWMEM_MEMSET(ptr, 0x00, alloc_size);
|
||||||
|
}
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -943,7 +1045,7 @@ lwmem_realloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, void* const ptr,
|
|||||||
* \return `1` if successfully reallocated, `0` otherwise
|
* \return `1` if successfully reallocated, `0` otherwise
|
||||||
* \note This function is thread safe when \ref LWMEM_CFG_OS is enabled
|
* \note This function is thread safe when \ref LWMEM_CFG_OS is enabled
|
||||||
*/
|
*/
|
||||||
uint8_t
|
int
|
||||||
lwmem_realloc_s_ex(lwmem_t* lwobj, const lwmem_region_t* region, void** const ptr, const size_t size) {
|
lwmem_realloc_s_ex(lwmem_t* lwobj, const lwmem_region_t* region, void** const ptr, const size_t size) {
|
||||||
void* new_ptr;
|
void* new_ptr;
|
||||||
|
|
||||||
|
@ -1,70 +1,75 @@
|
|||||||
#include "lwmem/lwmem.h"
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include "lwmem/lwmem.h"
|
||||||
|
|
||||||
|
#if LWMEM_CFG_SUPPORT_REALLOC_AND_FREE
|
||||||
|
|
||||||
/* Assert check */
|
/* Assert check */
|
||||||
#define ASSERT(x) do { \
|
#define ASSERT(x) \
|
||||||
if (!(x)) { \
|
do { \
|
||||||
printf("Assert on line %d failed with condition (" # x ")\r\n", (int)__LINE__); \
|
if (!(x)) { \
|
||||||
} else {\
|
printf("Assert on line %d failed with condition (" #x ")\r\n", (int)__LINE__); \
|
||||||
printf("Assert on line %d passed with condition (" # x ")\r\n", (int)__LINE__); \
|
} else { \
|
||||||
}\
|
printf("Assert on line %d passed with condition (" #x ")\r\n", (int)__LINE__); \
|
||||||
} while (0)
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
/********************************************/
|
/********************************************/
|
||||||
/* Test case helpers */
|
/* Test case helpers */
|
||||||
#define UINT_PTR_CAST(x) ((uintptr_t)(x))
|
#define UINT_PTR_CAST(x) ((uintptr_t)(x))
|
||||||
#define IS_ALLOC_IN_REGION(ptr, region) ASSERT( \
|
#define IS_ALLOC_IN_REGION(ptr, region) \
|
||||||
UINT_PTR_CAST(ptr) >= UINT_PTR_CAST((region)->start_addr) \
|
ASSERT(UINT_PTR_CAST(ptr) >= UINT_PTR_CAST((region)->start_addr) \
|
||||||
&& UINT_PTR_CAST(ptr) < (UINT_PTR_CAST((region)->start_addr) + (region)->size) \
|
&& UINT_PTR_CAST(ptr) < (UINT_PTR_CAST((region)->start_addr) + (region)->size))
|
||||||
)
|
|
||||||
|
|
||||||
/********************************************/
|
/********************************************/
|
||||||
/* Configuration for default lwmem instance */
|
/* Configuration for default lwmem instance */
|
||||||
|
|
||||||
/* Region memory declaration */
|
/* Region memory declaration */
|
||||||
uint8_t lw_mem1[1024], lw_mem2[256], lw_mem3[128];
|
static struct {
|
||||||
|
uint8_t m1[128];
|
||||||
|
uint8_t m2[256];
|
||||||
|
uint8_t m3[1024];
|
||||||
|
} lw_mem;
|
||||||
|
|
||||||
/* Regions descriptor */
|
/* Regions descriptor */
|
||||||
lwmem_region_t
|
static lwmem_region_t lw_regions[] = {
|
||||||
lw_regions[] = {
|
{lw_mem.m1, sizeof(lw_mem.m1)},
|
||||||
{ lw_mem3, sizeof(lw_mem3) },
|
{lw_mem.m2, sizeof(lw_mem.m2)},
|
||||||
{ lw_mem2, sizeof(lw_mem2) },
|
{lw_mem.m3, sizeof(lw_mem.m3)},
|
||||||
{ lw_mem1, sizeof(lw_mem1) },
|
{NULL, 0},
|
||||||
{ NULL, 0 }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/********************************************/
|
/********************************************/
|
||||||
/********************************************/
|
/********************************************/
|
||||||
/* Configuration for custom lwmem instance */
|
/* Configuration for custom lwmem instance */
|
||||||
/* LwMEM instance */
|
/* LwMEM instance */
|
||||||
lwmem_t lw_c;
|
static lwmem_t lw_c;
|
||||||
|
|
||||||
/* Region memory declaration */
|
static struct {
|
||||||
uint8_t lw_c_mem1[1024], lw_c_mem2[256], lw_c_mem3[128];
|
uint8_t m1[128];
|
||||||
|
uint8_t m2[256];
|
||||||
|
uint8_t m3[1024];
|
||||||
|
} lw_mem_c;
|
||||||
|
|
||||||
/* Regions descriptor */
|
/* Regions descriptor */
|
||||||
lwmem_region_t
|
static lwmem_region_t lw_c_regions[] = {
|
||||||
lw_c_regions[] = {
|
{lw_mem_c.m1, sizeof(lw_mem_c.m1)},
|
||||||
{ lw_c_mem3, sizeof(lw_c_mem3) },
|
{lw_mem_c.m2, sizeof(lw_mem_c.m2)},
|
||||||
{ lw_c_mem2, sizeof(lw_c_mem2) },
|
{lw_mem_c.m3, sizeof(lw_mem_c.m3)},
|
||||||
{ lw_c_mem1, sizeof(lw_c_mem1) },
|
{NULL, 0},
|
||||||
{ NULL, 0 }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/********************************************/
|
/********************************************/
|
||||||
|
|
||||||
void
|
void
|
||||||
lwmem_test_run(void) {
|
lwmem_test_run(void) {
|
||||||
void* ptr_1, * ptr_2, * ptr_3;
|
void *ptr_1 = NULL, *ptr_2 = NULL, *ptr_3 = NULL;
|
||||||
void* ptr_c_1, * ptr_c_2, * ptr_c_3;
|
void *ptr_c_1 = NULL, *ptr_c_2 = NULL, *ptr_c_3 = NULL;
|
||||||
|
|
||||||
/* Initialize default lwmem instance */
|
/* Initialize default lwmem instance */
|
||||||
/* Use one of 2 possible function calls: */
|
/* Use one of 2 possible function calls: */
|
||||||
lwmem_assignmem(lw_regions);
|
lwmem_assignmem(lw_regions);
|
||||||
//lwmem_assignmem_ex(NULL, lw_regions);
|
//lwmem_assignmem_ex(NULL, lw_regions);
|
||||||
|
|
||||||
/* Initialize another, custom instance */
|
|
||||||
lwmem_assignmem_ex(&lw_c, lw_c_regions);
|
|
||||||
|
|
||||||
/* Regions initialized... */
|
/* Regions initialized... */
|
||||||
|
|
||||||
/********************************************/
|
/********************************************/
|
||||||
@ -73,15 +78,18 @@ lwmem_test_run(void) {
|
|||||||
|
|
||||||
/* Allocation of 64 bytes must in in first region */
|
/* Allocation of 64 bytes must in in first region */
|
||||||
ptr_1 = lwmem_malloc(64);
|
ptr_1 = lwmem_malloc(64);
|
||||||
|
ASSERT(ptr_1 != NULL);
|
||||||
IS_ALLOC_IN_REGION(ptr_1, &lw_regions[0]);
|
IS_ALLOC_IN_REGION(ptr_1, &lw_regions[0]);
|
||||||
|
|
||||||
/* Allocation of 256 bytes can only be in 3rd region */
|
/* Allocation of 256 bytes can only be in 3rd region */
|
||||||
ptr_2 = lwmem_malloc(256);
|
ptr_2 = lwmem_malloc(256);
|
||||||
|
ASSERT(ptr_2 != NULL);
|
||||||
IS_ALLOC_IN_REGION(ptr_2, &lw_regions[2]);
|
IS_ALLOC_IN_REGION(ptr_2, &lw_regions[2]);
|
||||||
|
|
||||||
/* Allocation of 128 bytes can be in second or third region (depends on memory availability),
|
/* Allocation of 128 bytes can be in second or third region (depends on memory availability),
|
||||||
but in case of these tests it can be (and should be) in second region */
|
but in case of these tests it can be (and should be) in second region */
|
||||||
ptr_3 = lwmem_malloc(128);
|
ptr_3 = lwmem_malloc(128);
|
||||||
|
ASSERT(ptr_3 != NULL);
|
||||||
IS_ALLOC_IN_REGION(ptr_3, &lw_regions[1]);
|
IS_ALLOC_IN_REGION(ptr_3, &lw_regions[1]);
|
||||||
|
|
||||||
/* Free all pointers to default state */
|
/* Free all pointers to default state */
|
||||||
@ -92,10 +100,12 @@ lwmem_test_run(void) {
|
|||||||
/* Force allocation region to be used */
|
/* Force allocation region to be used */
|
||||||
/* Allocation of 16-bytes forced to 2nd region */
|
/* Allocation of 16-bytes forced to 2nd region */
|
||||||
ptr_1 = lwmem_malloc_ex(NULL, &lw_regions[1], 16);
|
ptr_1 = lwmem_malloc_ex(NULL, &lw_regions[1], 16);
|
||||||
|
ASSERT(ptr_1 != NULL);
|
||||||
IS_ALLOC_IN_REGION(ptr_1, &lw_regions[1]);
|
IS_ALLOC_IN_REGION(ptr_1, &lw_regions[1]);
|
||||||
|
|
||||||
/* Allocate ptr 2 in any region of default lwmem, the first available must be 1st region */
|
/* Allocate ptr 2 in any region of default lwmem, the first available must be 1st region */
|
||||||
ptr_2 = lwmem_malloc_ex(NULL, NULL, 16);
|
ptr_2 = lwmem_malloc_ex(NULL, NULL, 16);
|
||||||
|
ASSERT(ptr_2 != NULL);
|
||||||
IS_ALLOC_IN_REGION(ptr_2, &lw_regions[0]);
|
IS_ALLOC_IN_REGION(ptr_2, &lw_regions[0]);
|
||||||
|
|
||||||
/* Free pointers */
|
/* Free pointers */
|
||||||
@ -106,33 +116,41 @@ lwmem_test_run(void) {
|
|||||||
/* Run tests on custom region */
|
/* Run tests on custom region */
|
||||||
/********************************************/
|
/********************************************/
|
||||||
|
|
||||||
|
/* Initialize another, custom instance */
|
||||||
|
lwmem_assignmem_ex(&lw_c, lw_c_regions);
|
||||||
|
|
||||||
/* Allocation of 64 bytes must in in first region */
|
/* Allocation of 64 bytes must in in first region */
|
||||||
ptr_c_1 = lwmem_malloc_ex(&lw_c, NULL, 64);
|
ptr_c_1 = lwmem_malloc_ex(&lw_c, NULL, 64);
|
||||||
|
ASSERT(ptr_c_1 != NULL);
|
||||||
IS_ALLOC_IN_REGION(ptr_c_1, &lw_c_regions[0]);
|
IS_ALLOC_IN_REGION(ptr_c_1, &lw_c_regions[0]);
|
||||||
|
|
||||||
/* Allocation of 256 bytes can only be in 3rd region */
|
/* Allocation of 256 bytes can only be in 3rd region */
|
||||||
ptr_c_2 = lwmem_malloc_ex(&lw_c, NULL, 256);
|
ptr_c_2 = lwmem_malloc_ex(&lw_c, NULL, 256);
|
||||||
|
ASSERT(ptr_c_2 != NULL);
|
||||||
IS_ALLOC_IN_REGION(ptr_c_2, &lw_c_regions[2]);
|
IS_ALLOC_IN_REGION(ptr_c_2, &lw_c_regions[2]);
|
||||||
|
|
||||||
/* Allocation of 128 bytes can be in second or third region (depends on memory availability),
|
/* Allocation of 128 bytes can be in second or third region (depends on memory availability),
|
||||||
but in case of these tests it can be (and should be) in second region */
|
but in case of these tests it can be (and should be) in second region */
|
||||||
ptr_c_3 = lwmem_malloc_ex(&lw_c, NULL, 128);
|
ptr_c_3 = lwmem_malloc_ex(&lw_c, NULL, 128);
|
||||||
|
ASSERT(ptr_c_3 != NULL);
|
||||||
IS_ALLOC_IN_REGION(ptr_c_3, &lw_c_regions[1]);
|
IS_ALLOC_IN_REGION(ptr_c_3, &lw_c_regions[1]);
|
||||||
|
|
||||||
/* Free all pointers to default state */
|
/* Free all pointers to default state */
|
||||||
lwmem_free(ptr_c_1);
|
lwmem_free(ptr_c_1);
|
||||||
lwmem_free(ptr_c_2);
|
lwmem_free(ptr_c_2);
|
||||||
lwmem_free(ptr_c_3);
|
lwmem_free(ptr_c_3);
|
||||||
|
|
||||||
|
printf("Done\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For debug purposes */
|
/* For debug purposes */
|
||||||
lwmem_region_t* regions_used;
|
static lwmem_region_t* regions_used;
|
||||||
size_t regions_count = 4; /* Use only 1 region for debug purposes of non-free areas */
|
static size_t regions_count = 4; /* Use only 1 region for debug purposes of non-free areas */
|
||||||
|
|
||||||
void
|
void
|
||||||
lwmem_test_memory_structure(void) {
|
lwmem_test_memory_structure(void) {
|
||||||
uint8_t* ptr1, *ptr2, *ptr3, *ptr4;
|
uint8_t *ptr1, *ptr2, *ptr3, *ptr4;
|
||||||
uint8_t* rptr1, *rptr2, *rptr3, *rptr4;
|
uint8_t *rptr1, *rptr2, *rptr3, *rptr4;
|
||||||
size_t used_regions;
|
size_t used_regions;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -156,16 +174,20 @@ lwmem_test_memory_structure(void) {
|
|||||||
|
|
||||||
/* Test case 1, allocate 3 blocks, each of different size */
|
/* Test case 1, allocate 3 blocks, each of different size */
|
||||||
/* We know that sizeof internal metadata block is 8 bytes on win32 */
|
/* We know that sizeof internal metadata block is 8 bytes on win32 */
|
||||||
printf("\r\n\r\nAllocating 4 pointers and freeing first and third..\r\n");
|
printf("\r\n------------------------------------------------------------------------\r\n");
|
||||||
|
printf("Allocating 4 pointers\r\n\r\n");
|
||||||
ptr1 = lwmem_malloc(8);
|
ptr1 = lwmem_malloc(8);
|
||||||
ptr2 = lwmem_malloc(4);
|
ptr2 = lwmem_malloc(4);
|
||||||
ptr3 = lwmem_malloc(4);
|
ptr3 = lwmem_malloc(4);
|
||||||
ptr4 = lwmem_malloc(16);
|
ptr4 = lwmem_malloc(16);
|
||||||
lwmem_free(ptr1); /* Free but keep value for future comparison */
|
lwmem_debug_print(1, 1);
|
||||||
lwmem_free(ptr3); /* Free but keep value for future comparison */
|
printf("\r\n------------------------------------------------------------------------\r\n");
|
||||||
|
printf("Freeing first and third pointers\r\n\r\n");
|
||||||
|
lwmem_free(ptr1); /* Free but keep value for future comparison */
|
||||||
|
lwmem_free(ptr3); /* Free but keep value for future comparison */
|
||||||
lwmem_debug_print(1, 1);
|
lwmem_debug_print(1, 1);
|
||||||
printf("Debug above is effectively state 3\r\n");
|
printf("Debug above is effectively state 3\r\n");
|
||||||
lwmem_debug_save_state(); /* Every restore operations rewinds here */
|
lwmem_debug_save_state(); /* Every restore operations rewinds here */
|
||||||
|
|
||||||
/* We always try to reallocate pointer ptr2 */
|
/* We always try to reallocate pointer ptr2 */
|
||||||
|
|
||||||
@ -183,7 +205,7 @@ lwmem_test_memory_structure(void) {
|
|||||||
printf("State 3b\r\n");
|
printf("State 3b\r\n");
|
||||||
rptr2 = lwmem_realloc(ptr2, 20);
|
rptr2 = lwmem_realloc(ptr2, 20);
|
||||||
lwmem_debug_print(1, 1);
|
lwmem_debug_print(1, 1);
|
||||||
ASSERT(rptr2 == ptr2);
|
ASSERT(rptr2 == ptr1);
|
||||||
|
|
||||||
/* Create 3c case */
|
/* Create 3c case */
|
||||||
printf("\r\n------------------------------------------------------------------------\r\n");
|
printf("\r\n------------------------------------------------------------------------\r\n");
|
||||||
@ -200,4 +222,11 @@ lwmem_test_memory_structure(void) {
|
|||||||
rptr4 = lwmem_realloc(ptr2, 36);
|
rptr4 = lwmem_realloc(ptr2, 36);
|
||||||
lwmem_debug_print(1, 1);
|
lwmem_debug_print(1, 1);
|
||||||
ASSERT(rptr4 != ptr1 && rptr4 != ptr2 && rptr4 != ptr3 && rptr4 != ptr4);
|
ASSERT(rptr4 != ptr1 && rptr4 != ptr2 && rptr4 != ptr3 && rptr4 != ptr4);
|
||||||
}
|
|
||||||
|
printf("ptr1: %08X\r\nptr2: %08X\r\nptr3: %08X\r\nptr4: %08X\r\n", (unsigned)ptr1, (unsigned)ptr2, (unsigned)ptr3,
|
||||||
|
(unsigned)ptr4);
|
||||||
|
printf("r_ptr1: %08X\r\nr_ptr2: %08X\r\nr_ptr3: %08X\r\nr_ptr4: %08X\r\n", (unsigned)rptr1, (unsigned)rptr2,
|
||||||
|
(unsigned)rptr3, (unsigned)rptr4);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LWMEM_CFG_SUPPORT_REALLOC_AND_FREE */
|
68
tests/lwmem_test_simple.c
Normal file
68
tests/lwmem_test_simple.c
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include "lwmem/lwmem.h"
|
||||||
|
|
||||||
|
#if !LWMEM_CFG_SUPPORT_REALLOC_AND_FREE
|
||||||
|
|
||||||
|
/* Assert check */
|
||||||
|
#define ASSERT(x) \
|
||||||
|
do { \
|
||||||
|
if (!(x)) { \
|
||||||
|
printf("Assert on line %d failed with condition (" #x ")\r\n", (int)__LINE__); \
|
||||||
|
} else { \
|
||||||
|
printf("Assert on line %d passed with condition (" #x ")\r\n", (int)__LINE__); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/********************************************/
|
||||||
|
/* Configuration for default lwmem instance */
|
||||||
|
|
||||||
|
/* Region memory declaration */
|
||||||
|
static uint8_t lw_mem1[1024], lw_mem2[256], lw_mem3[128];
|
||||||
|
|
||||||
|
/* Regions descriptor */
|
||||||
|
static lwmem_region_t lw_regions_too_many[] = {
|
||||||
|
{lw_mem3, sizeof(lw_mem3)},
|
||||||
|
{lw_mem2, sizeof(lw_mem2)},
|
||||||
|
{lw_mem1, sizeof(lw_mem1)},
|
||||||
|
{NULL, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
/********************************************/
|
||||||
|
/********************************************/
|
||||||
|
/* Region memory declaration */
|
||||||
|
/* Use uint32 for alignment reasons */
|
||||||
|
static uint32_t lw_c_mem1[64 / 4];
|
||||||
|
|
||||||
|
/* Regions descriptor */
|
||||||
|
static lwmem_region_t lw_c_regions[] = {
|
||||||
|
{lw_c_mem1, sizeof(lw_c_mem1)},
|
||||||
|
{NULL, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
/********************************************/
|
||||||
|
|
||||||
|
void
|
||||||
|
lwmem_test_simple_run(void) {
|
||||||
|
size_t retval;
|
||||||
|
void* ptr;
|
||||||
|
|
||||||
|
/* Should fail -> too many regions */
|
||||||
|
retval = lwmem_assignmem(lw_regions_too_many);
|
||||||
|
ASSERT(retval == 0);
|
||||||
|
|
||||||
|
/* Should fly now */
|
||||||
|
retval = lwmem_assignmem(lw_c_regions);
|
||||||
|
ASSERT(retval != 0);
|
||||||
|
|
||||||
|
/* We have 64 bytes from now on */
|
||||||
|
|
||||||
|
/* Try to allocate memory */
|
||||||
|
ptr = lwmem_malloc(32);
|
||||||
|
ASSERT(ptr != NULL);
|
||||||
|
ptr = lwmem_malloc(32);
|
||||||
|
ASSERT(ptr != NULL);
|
||||||
|
ptr = lwmem_malloc(4);
|
||||||
|
ASSERT(ptr == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !LWMEM_CFG_SUPPORT_REALLOC_AND_FREE */
|
Loading…
x
Reference in New Issue
Block a user