mirror of
https://gitee.com/Lamdonn/varch.git
synced 2025-12-06 08:46:42 +08:00
159 lines
4.1 KiB
C
159 lines
4.1 KiB
C
/*********************************************************************************************************
|
|
* ------------------------------------------------------------------------------------------------------
|
|
* file description
|
|
* ------------------------------------------------------------------------------------------------------
|
|
* \file vmem.c
|
|
* \unit vmem
|
|
* \brief Simple implementation of memory pool
|
|
* \author Lamdonn
|
|
* \version v1.0.0
|
|
* \license GPL-2.0
|
|
* \copyright Copyright (C) 2023 Lamdonn.
|
|
********************************************************************************************************/
|
|
#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;
|
|
}
|