2024-04-22 00:09:51 +08:00

147 lines
3.4 KiB
C

#include "vmem.h"
#include "vstring.h"
/**< Memory pool */
static uint8_t mem_pool_base[VMEM_POOL_SIZE] = {0};
/**< Memory management table */
static uint16_t mem_map_base[VMEM_MTABLE_SIZE] = {0};
/**< Memory table size */
static const uint32_t mem_table_size = VMEM_MTABLE_SIZE;
/**< Memory chunking size */
static const uint32_t mem_block_size = VMEM_BLOCK_SIZE;
/**< Memory pool size */
static const uint32_t mem_pool_size = VMEM_POOL_SIZE;
uint8_t vmem_used(void)
{
uint32_t used = 0;
uint32_t i;
for (i = 0; i < mem_table_size; i++)
{
if(mem_map_base[i])used++;
}
return (used*100)/(mem_table_size);
}
/**
* \brief memory allocation function for internal calls
* \param[in] size: memory size to allocate (in bytes)
* \return memory offset address or 0xFFFFFFFF failed
*/
static uint32_t memory_alloc(uint32_t size)
{
signed long offset=0;
uint32_t nmemb; /* Number of memory blocks required */
uint32_t cmemb = 0; /* Number of contiguous empty memory blocks */
uint32_t i;
/* No allocation required */
if (size == 0) return 0xFFFFFFFF;
/* Obtain the number of contiguous memory blocks that need to be allocated */
nmemb = size / mem_block_size;
/* Round up to obtain enough memory block space */
if (size % mem_block_size) nmemb++;
/* Search the entire memory control area */
for (offset = mem_table_size - 1; offset >= 0; offset--)
{
/* Continuously increasing the number of empty memory blocks */
if (!mem_map_base[offset]) cmemb++;
/* Zeroing Continuous Memory Blocks */
else cmemb = 0;
/* Found consecutive nmemb empty memory blocks */
if (cmemb == nmemb)
{
/* Mark memory block is not empty */
for (i = 0; i < nmemb; i++)
{
mem_map_base[offset + i] = nmemb;
}
/* Return offset address */
return (offset * mem_block_size);
}
}
return 0xFFFFFFFF;
}
/**
* \brief memory free function for internal calls
* \param[in] offset: memory address offset
* \return 0 success or others fail
*/
static uint8_t memory_free(uint32_t offset)
{
int index, nmemb, i;
/* Offset within memory pool */
if (offset < mem_pool_size)
{
index = offset / mem_block_size; /* Offset memory block number */
nmemb = mem_map_base[index]; /* Number of memory blocks */
/* Memory Block Zeroing */
for (i = 0; i < nmemb; i++)
{
mem_map_base[index + i] = 0;
}
return 0;
}
/* Offset not within memory pool */
else return 2;
}
void v_free(void *ptr)
{
uint32_t offset;
if (ptr == NULL) return;
offset = (uint32_t)ptr - (uint32_t)mem_pool_base;
memory_free(offset);
}
void *v_malloc(size_t size)
{
uint32_t offset;
offset = memory_alloc(size);
if (offset == 0xFFFFFFFF) return NULL;
return (void *)((uint32_t)mem_pool_base + offset);
}
void *v_realloc(void *ptr, size_t size)
{
uint32_t offset;
offset = memory_alloc(size);
if (offset == 0xFFFFFFFF) return NULL;
/* Copy old memory content to new memory */
v_memcpy((void *)((uint32_t)mem_pool_base + offset), ptr, size);
/* Release old memory */
v_free(ptr);
return (void *)((uint32_t)mem_pool_base + offset);
}
void *v_calloc(size_t size)
{
void *ptr;
ptr = v_malloc(size);
if (ptr) v_memset(ptr, 0, size);
return ptr;
}