2016-05-22 01:54:29 +00:00
|
|
|
#include "k_def.h"
|
|
|
|
#include "bit_ops.h"
|
2016-05-17 19:03:18 +00:00
|
|
|
|
2016-05-24 07:10:32 +00:00
|
|
|
typedef union
|
|
|
|
{
|
2016-05-17 19:03:18 +00:00
|
|
|
uint32_t size;
|
|
|
|
uint32_t flags;
|
2016-05-24 07:10:32 +00:00
|
|
|
} _salloc_header;
|
2016-05-17 19:03:18 +00:00
|
|
|
|
|
|
|
#define ALLOC_FLAG_NUM 2
|
|
|
|
#define ALLOC_HEADER_FLAG_FREE 0
|
|
|
|
#define ALLOC_HEADER_FLAG_LAST 1
|
|
|
|
|
2016-05-24 07:10:32 +00:00
|
|
|
static void _set_salloc_header_size(_salloc_header *header, uint32_t size)
|
2016-05-17 19:03:18 +00:00
|
|
|
{
|
|
|
|
// align the integer, ignoring overflowed bits
|
|
|
|
size <<= ALLOC_FLAG_NUM;
|
|
|
|
|
|
|
|
// clear ALLOC_FLAG_NUM-th to 31-th bits
|
|
|
|
header->size &= ~bit_field_mask_32(ALLOC_FLAG_NUM, 31);
|
|
|
|
// set bits
|
|
|
|
header->size |= size;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-05-24 07:10:32 +00:00
|
|
|
static uint32_t _read_salloc_header_size(_salloc_header *header)
|
2016-05-17 19:03:18 +00:00
|
|
|
{
|
|
|
|
return header->size >> ALLOC_FLAG_NUM;
|
|
|
|
}
|
|
|
|
|
2016-05-24 07:10:32 +00:00
|
|
|
static uint32_t _read_salloc_header_flag(_salloc_header *header, uint32_t bit)
|
2016-05-17 19:03:18 +00:00
|
|
|
{
|
|
|
|
return (header->flags & bit_mask_32(bit)) == 0 ? 0 : 1;
|
|
|
|
}
|
|
|
|
|
2016-05-24 07:10:32 +00:00
|
|
|
static void _set_salloc_header_flag(_salloc_header *header, uint32_t bit, uint32_t value)
|
2016-05-17 19:03:18 +00:00
|
|
|
{
|
|
|
|
value &= bit_mask_32(0);
|
2016-05-24 07:10:32 +00:00
|
|
|
if (value == 1)
|
2016-05-17 19:03:18 +00:00
|
|
|
{
|
|
|
|
header->flags |= bit_mask_32(bit);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
header->flags &= ~bit_mask_32(bit);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-05-24 07:10:32 +00:00
|
|
|
static void _salloc_join(void *base)
|
2016-05-17 19:03:18 +00:00
|
|
|
{
|
2016-05-24 07:10:32 +00:00
|
|
|
if (base != NULL)
|
2016-05-17 19:03:18 +00:00
|
|
|
{
|
2016-05-24 07:10:32 +00:00
|
|
|
char *c_ptr = (char *) base;
|
|
|
|
while (1)
|
2016-05-17 19:03:18 +00:00
|
|
|
{
|
2016-05-24 07:10:32 +00:00
|
|
|
uint32_t c_blk_free = _read_salloc_header_flag((_salloc_header *) c_ptr, ALLOC_HEADER_FLAG_FREE);
|
|
|
|
uint32_t c_blk_last = _read_salloc_header_flag((_salloc_header *) c_ptr, ALLOC_HEADER_FLAG_LAST);
|
|
|
|
uint32_t c_blk_size = _read_salloc_header_size((_salloc_header *) c_ptr);
|
|
|
|
char *n_ptr = c_blk_last == 1 ? NULL : c_ptr + c_blk_size;
|
|
|
|
if (n_ptr != NULL && c_blk_free == 1)
|
2016-05-17 19:03:18 +00:00
|
|
|
{
|
|
|
|
// if this is not the last block and the prev block is free
|
2016-05-24 07:10:32 +00:00
|
|
|
uint32_t n_blk_free = _read_salloc_header_flag((_salloc_header *) n_ptr, ALLOC_HEADER_FLAG_FREE);
|
|
|
|
uint32_t n_blk_last = _read_salloc_header_flag((_salloc_header *) n_ptr, ALLOC_HEADER_FLAG_LAST);
|
|
|
|
uint32_t n_blk_size = _read_salloc_header_size((_salloc_header *) n_ptr);
|
2016-05-17 19:03:18 +00:00
|
|
|
|
|
|
|
if (n_blk_free == 1)
|
|
|
|
{
|
|
|
|
// logically gone
|
2016-05-24 07:10:32 +00:00
|
|
|
_set_salloc_header_size((_salloc_header *) c_ptr, n_blk_size + c_blk_size);
|
|
|
|
_set_salloc_header_flag((_salloc_header *) c_ptr, ALLOC_HEADER_FLAG_LAST, n_blk_last);
|
2016-05-17 19:03:18 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// update the c_ptr
|
2016-05-24 07:10:32 +00:00
|
|
|
if (c_blk_last == 0)
|
2016-05-17 19:03:18 +00:00
|
|
|
{
|
|
|
|
c_ptr += c_blk_size;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-24 07:10:32 +00:00
|
|
|
bool SAPI salloc_assert(void *base, uint32_t blk_size[], bool blk_free[], uint32_t size)
|
|
|
|
{
|
|
|
|
if (base == NULL || blk_free == NULL || blk_size == NULL)
|
|
|
|
return NULL;
|
|
|
|
uint32_t i = 0;
|
|
|
|
char *c_ptr = (char *) base;
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
uint32_t cur_blk_free = _read_salloc_header_flag((_salloc_header *) c_ptr, ALLOC_HEADER_FLAG_FREE);
|
|
|
|
uint32_t cur_blk_last = _read_salloc_header_flag((_salloc_header *) c_ptr, ALLOC_HEADER_FLAG_LAST);
|
|
|
|
uint32_t cur_blk_size = _read_salloc_header_size((_salloc_header *) c_ptr);
|
|
|
|
if (cur_blk_free != blk_free[i] || cur_blk_size != blk_size[i])
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
c_ptr += cur_blk_size;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
if (cur_blk_last == 1)
|
|
|
|
{
|
|
|
|
return i == size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-05-17 19:03:18 +00:00
|
|
|
|
2016-05-24 07:10:32 +00:00
|
|
|
void SAPI salloc_init(void *base, uint32_t size)
|
2016-05-17 19:03:18 +00:00
|
|
|
{
|
2016-05-24 07:10:32 +00:00
|
|
|
if (base != NULL && size >= sizeof(_salloc_header))
|
2016-05-17 19:03:18 +00:00
|
|
|
{
|
2016-05-24 07:10:32 +00:00
|
|
|
_salloc_header *ptr = (_salloc_header *) base;
|
|
|
|
_set_salloc_header_size(ptr, size);
|
|
|
|
_set_salloc_header_flag(ptr, ALLOC_HEADER_FLAG_FREE, 1);
|
|
|
|
_set_salloc_header_flag(ptr, ALLOC_HEADER_FLAG_LAST, 1);
|
2016-05-17 19:03:18 +00:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-05-24 07:10:32 +00:00
|
|
|
void *SAPI salloc(void *base, uint32_t size)
|
2016-05-17 19:03:18 +00:00
|
|
|
{
|
2016-05-24 07:10:32 +00:00
|
|
|
void *result = NULL;
|
|
|
|
if (base != NULL && size != 0)
|
2016-05-17 19:03:18 +00:00
|
|
|
{
|
2016-05-24 07:10:32 +00:00
|
|
|
uint32_t total_size = size + sizeof(_salloc_header);
|
|
|
|
char *c_ptr = (char *) base;
|
|
|
|
while (1)
|
2016-05-17 19:03:18 +00:00
|
|
|
{
|
2016-05-24 07:10:32 +00:00
|
|
|
uint32_t cur_blk_free = _read_salloc_header_flag((_salloc_header *) c_ptr, ALLOC_HEADER_FLAG_FREE);
|
|
|
|
uint32_t cur_blk_size = _read_salloc_header_size((_salloc_header *) c_ptr);
|
|
|
|
uint32_t cur_blk_last = _read_salloc_header_flag((_salloc_header *) c_ptr, ALLOC_HEADER_FLAG_LAST);
|
|
|
|
if (cur_blk_free == 0 || cur_blk_size < total_size)
|
2016-05-17 19:03:18 +00:00
|
|
|
{
|
|
|
|
//if cur block not a free block
|
|
|
|
//or the current block size is less than the size we want
|
2016-05-24 07:10:32 +00:00
|
|
|
if (cur_blk_last == 1)
|
2016-05-17 19:03:18 +00:00
|
|
|
//if last one, break and fail.
|
|
|
|
break;
|
|
|
|
else
|
|
|
|
c_ptr += cur_blk_size;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// we have a free block with enough size
|
2016-05-24 07:10:32 +00:00
|
|
|
if (total_size == cur_blk_size ||
|
|
|
|
cur_blk_size - total_size < sizeof(_salloc_header))
|
2016-05-17 19:03:18 +00:00
|
|
|
{
|
2016-05-24 07:10:32 +00:00
|
|
|
// since the space left is not enough for salloc_header
|
2016-05-17 19:03:18 +00:00
|
|
|
// we alloc the whole block
|
2016-05-24 07:10:32 +00:00
|
|
|
_set_salloc_header_flag((_salloc_header *) c_ptr, ALLOC_HEADER_FLAG_FREE, 0);
|
2016-05-17 19:03:18 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// we split the block here
|
|
|
|
// set properties for the first block
|
2016-05-24 07:10:32 +00:00
|
|
|
_set_salloc_header_size((_salloc_header *) c_ptr, total_size);
|
|
|
|
_set_salloc_header_flag((_salloc_header *) c_ptr, ALLOC_HEADER_FLAG_LAST, 0);
|
|
|
|
_set_salloc_header_flag((_salloc_header *) c_ptr, ALLOC_HEADER_FLAG_FREE, 0);
|
2016-05-17 19:03:18 +00:00
|
|
|
|
|
|
|
// set properties for the second block
|
2016-05-24 07:10:32 +00:00
|
|
|
_set_salloc_header_size((_salloc_header *) (c_ptr + total_size), cur_blk_size - total_size);
|
|
|
|
_set_salloc_header_flag((_salloc_header *) (c_ptr + total_size), ALLOC_HEADER_FLAG_LAST,
|
|
|
|
cur_blk_last);
|
|
|
|
_set_salloc_header_flag((_salloc_header *) (c_ptr + total_size), ALLOC_HEADER_FLAG_FREE, 1);
|
2016-05-17 19:03:18 +00:00
|
|
|
}
|
|
|
|
// return the pointer, skip the alloc header
|
2016-05-24 07:10:32 +00:00
|
|
|
result = c_ptr + sizeof(_salloc_header);
|
2016-05-17 19:03:18 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2016-05-24 07:10:32 +00:00
|
|
|
void SAPI sfree(void *base, void *ptr)
|
2016-05-17 19:03:18 +00:00
|
|
|
{
|
2016-05-24 07:10:32 +00:00
|
|
|
if (base != NULL && ptr != NULL)
|
2016-05-17 19:03:18 +00:00
|
|
|
{
|
2016-05-24 07:10:32 +00:00
|
|
|
char *c_ptr = (char *) base;
|
|
|
|
while (1)
|
2016-05-17 19:03:18 +00:00
|
|
|
{
|
2016-05-24 07:10:32 +00:00
|
|
|
uint32_t cur_blk_free = _read_salloc_header_flag((_salloc_header *) c_ptr, ALLOC_HEADER_FLAG_FREE);
|
|
|
|
uint32_t cur_blk_last = _read_salloc_header_flag((_salloc_header *) c_ptr, ALLOC_HEADER_FLAG_LAST);
|
|
|
|
uint32_t cur_blk_size = _read_salloc_header_size((_salloc_header *) c_ptr);
|
|
|
|
if (cur_blk_free == 0 && ptr == c_ptr + sizeof(_salloc_header))
|
2016-05-17 19:03:18 +00:00
|
|
|
{
|
|
|
|
// we found the block, mark it as free
|
2016-05-24 07:10:32 +00:00
|
|
|
_set_salloc_header_flag((_salloc_header *) c_ptr, ALLOC_HEADER_FLAG_FREE, 1);
|
2016-05-17 19:03:18 +00:00
|
|
|
// merge blocks
|
2016-05-24 07:10:32 +00:00
|
|
|
_salloc_join(base);
|
2016-05-17 19:03:18 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-05-24 07:10:32 +00:00
|
|
|
if (cur_blk_last == 1)
|
2016-05-17 19:03:18 +00:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
c_ptr += cur_blk_size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|