589 lines
19 KiB
C
589 lines
19 KiB
C
|
/*
|
||
|
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||
|
*
|
||
|
* SPDX-License-Identifier: Apache-2.0
|
||
|
*
|
||
|
* Change Logs:
|
||
|
* Date Author Notes
|
||
|
* 2021-10-14 tyx the first version
|
||
|
*/
|
||
|
|
||
|
#include <rtthread.h>
|
||
|
#include <stdlib.h>
|
||
|
#include "utest.h"
|
||
|
|
||
|
struct rt_small_mem_item
|
||
|
{
|
||
|
rt_ubase_t pool_ptr; /**< small memory object addr */
|
||
|
#ifdef ARCH_CPU_64BIT
|
||
|
rt_uint32_t resv;
|
||
|
#endif /* ARCH_CPU_64BIT */
|
||
|
rt_size_t next; /**< next free item */
|
||
|
rt_size_t prev; /**< prev free item */
|
||
|
#ifdef RT_USING_MEMTRACE
|
||
|
#ifdef ARCH_CPU_64BIT
|
||
|
rt_uint8_t thread[8]; /**< thread name */
|
||
|
#else
|
||
|
rt_uint8_t thread[4]; /**< thread name */
|
||
|
#endif /* ARCH_CPU_64BIT */
|
||
|
#endif /* RT_USING_MEMTRACE */
|
||
|
};
|
||
|
|
||
|
struct rt_small_mem
|
||
|
{
|
||
|
struct rt_memory parent; /**< inherit from rt_memory */
|
||
|
rt_uint8_t *heap_ptr; /**< pointer to the heap */
|
||
|
struct rt_small_mem_item *heap_end;
|
||
|
struct rt_small_mem_item *lfree;
|
||
|
rt_size_t mem_size_aligned; /**< aligned memory size */
|
||
|
};
|
||
|
|
||
|
#define MEM_SIZE(_heap, _mem) \
|
||
|
(((struct rt_small_mem_item *)(_mem))->next - ((rt_ubase_t)(_mem) - \
|
||
|
(rt_ubase_t)((_heap)->heap_ptr)) - RT_ALIGN(sizeof(struct rt_small_mem_item), RT_ALIGN_SIZE))
|
||
|
|
||
|
#define TEST_MEM_SIZE 1024
|
||
|
|
||
|
static rt_size_t max_block(struct rt_small_mem *heap)
|
||
|
{
|
||
|
struct rt_small_mem_item *mem;
|
||
|
rt_size_t max = 0, size;
|
||
|
|
||
|
for (mem = (struct rt_small_mem_item *)heap->heap_ptr;
|
||
|
mem != heap->heap_end;
|
||
|
mem = (struct rt_small_mem_item *)&heap->heap_ptr[mem->next])
|
||
|
{
|
||
|
if (((rt_ubase_t)mem->pool_ptr & 0x1) == 0)
|
||
|
{
|
||
|
size = MEM_SIZE(heap, mem);
|
||
|
if (size > max)
|
||
|
{
|
||
|
max = size;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return max;
|
||
|
}
|
||
|
|
||
|
static int _mem_cmp(void *ptr, rt_uint8_t v, rt_size_t size)
|
||
|
{
|
||
|
while (size-- != 0)
|
||
|
{
|
||
|
if (*(rt_uint8_t *)ptr != v)
|
||
|
return *(rt_uint8_t *)ptr - v;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
struct mem_test_context
|
||
|
{
|
||
|
void *ptr;
|
||
|
rt_size_t size;
|
||
|
rt_uint8_t magic;
|
||
|
};
|
||
|
|
||
|
static void mem_functional_test(void)
|
||
|
{
|
||
|
rt_size_t total_size;
|
||
|
rt_uint8_t *buf;
|
||
|
struct rt_small_mem *heap;
|
||
|
rt_uint8_t magic = __LINE__;
|
||
|
|
||
|
/* Prepare test memory */
|
||
|
buf = rt_malloc(TEST_MEM_SIZE);
|
||
|
uassert_not_null(buf);
|
||
|
uassert_int_equal(RT_ALIGN((rt_ubase_t)buf, RT_ALIGN_SIZE), (rt_ubase_t)buf);
|
||
|
rt_memset(buf, 0xAA, TEST_MEM_SIZE);
|
||
|
/* small heap init */
|
||
|
heap = (struct rt_small_mem *)rt_smem_init("mem_tc", buf, TEST_MEM_SIZE);
|
||
|
/* get total size */
|
||
|
total_size = max_block(heap);
|
||
|
uassert_int_not_equal(total_size, 0);
|
||
|
/*
|
||
|
* Allocate all memory at a time and test whether
|
||
|
* the memory allocation release function is effective
|
||
|
*/
|
||
|
{
|
||
|
struct mem_test_context ctx;
|
||
|
ctx.magic = magic++;
|
||
|
ctx.size = max_block(heap);
|
||
|
ctx.ptr = rt_smem_alloc(&heap->parent, ctx.size);
|
||
|
uassert_not_null(ctx.ptr);
|
||
|
rt_memset(ctx.ptr, ctx.magic, ctx.size);
|
||
|
uassert_int_equal(_mem_cmp(ctx.ptr, ctx.magic, ctx.size), 0);
|
||
|
rt_smem_free(ctx.ptr);
|
||
|
uassert_int_equal(max_block(heap), total_size);
|
||
|
}
|
||
|
/*
|
||
|
* Apply for memory release sequentially and
|
||
|
* test whether memory block merging is effective
|
||
|
*/
|
||
|
{
|
||
|
rt_size_t i, max_free = 0;
|
||
|
struct mem_test_context ctx[3];
|
||
|
/* alloc mem */
|
||
|
for (i = 0; i < sizeof(ctx) / sizeof(ctx[0]); i++)
|
||
|
{
|
||
|
ctx[i].magic = magic++;
|
||
|
ctx[i].size = max_block(heap) / (sizeof(ctx) / sizeof(ctx[0]) - i);
|
||
|
ctx[i].ptr = rt_smem_alloc(&heap->parent, ctx[i].size);
|
||
|
uassert_not_null(ctx[i].ptr);
|
||
|
rt_memset(ctx[i].ptr, ctx[i].magic, ctx[i].size);
|
||
|
}
|
||
|
/* All memory has been applied. The remaining memory should be 0 */
|
||
|
uassert_int_equal(max_block(heap), 0);
|
||
|
/* Verify that the memory data is correct */
|
||
|
for (i = 0; i < sizeof(ctx) / sizeof(ctx[0]); i++)
|
||
|
{
|
||
|
uassert_int_equal(_mem_cmp(ctx[i].ptr, ctx[i].magic, ctx[i].size), 0);
|
||
|
}
|
||
|
/* Sequential memory release */
|
||
|
for (i = 0; i < sizeof(ctx) / sizeof(ctx[0]); i++)
|
||
|
{
|
||
|
uassert_int_equal(_mem_cmp(ctx[i].ptr, ctx[i].magic, ctx[i].size), 0);
|
||
|
rt_smem_free(ctx[i].ptr);
|
||
|
max_free += ctx[i].size;
|
||
|
uassert_true(max_block(heap) >= max_free);
|
||
|
}
|
||
|
/* Check whether the memory is fully merged */
|
||
|
uassert_int_equal(max_block(heap), total_size);
|
||
|
}
|
||
|
/*
|
||
|
* Apply for memory release at an interval to
|
||
|
* test whether memory block merging is effective
|
||
|
*/
|
||
|
{
|
||
|
rt_size_t i, max_free = 0;
|
||
|
struct mem_test_context ctx[3];
|
||
|
/* alloc mem */
|
||
|
for (i = 0; i < sizeof(ctx) / sizeof(ctx[0]); i++)
|
||
|
{
|
||
|
ctx[i].magic = magic++;
|
||
|
ctx[i].size = max_block(heap) / (sizeof(ctx) / sizeof(ctx[0]) - i);
|
||
|
ctx[i].ptr = rt_smem_alloc(&heap->parent, ctx[i].size);
|
||
|
uassert_not_null(ctx[i].ptr);
|
||
|
rt_memset(ctx[i].ptr, ctx[i].magic, ctx[i].size);
|
||
|
}
|
||
|
/* All memory has been applied. The remaining memory should be 0 */
|
||
|
uassert_int_equal(max_block(heap), 0);
|
||
|
/* Verify that the memory data is correct */
|
||
|
for (i = 0; i < sizeof(ctx) / sizeof(ctx[0]); i++)
|
||
|
{
|
||
|
uassert_int_equal(_mem_cmp(ctx[i].ptr, ctx[i].magic, ctx[i].size), 0);
|
||
|
}
|
||
|
/* Release even address */
|
||
|
for (i = 0; i < sizeof(ctx) / sizeof(ctx[0]); i++)
|
||
|
{
|
||
|
if (i % 2 == 0)
|
||
|
{
|
||
|
uassert_int_equal(_mem_cmp(ctx[i].ptr, ctx[i].magic, ctx[i].size), 0);
|
||
|
rt_smem_free(ctx[i].ptr);
|
||
|
uassert_true(max_block(heap) >= ctx[0].size);
|
||
|
}
|
||
|
}
|
||
|
/* Release odd addresses and merge memory blocks */
|
||
|
for (i = 0; i < sizeof(ctx) / sizeof(ctx[0]); i++)
|
||
|
{
|
||
|
if (i % 2 != 0)
|
||
|
{
|
||
|
uassert_int_equal(_mem_cmp(ctx[i].ptr, ctx[i].magic, ctx[i].size), 0);
|
||
|
rt_smem_free(ctx[i].ptr);
|
||
|
max_free += ctx[i - 1].size + ctx[i + 1].size;
|
||
|
uassert_true(max_block(heap) >= max_free);
|
||
|
}
|
||
|
}
|
||
|
/* Check whether the memory is fully merged */
|
||
|
uassert_int_equal(max_block(heap), total_size);
|
||
|
}
|
||
|
/* mem realloc test,Small - > Large */
|
||
|
{
|
||
|
/* Request a piece of memory for subsequent reallocation operations */
|
||
|
struct mem_test_context ctx[3];
|
||
|
ctx[0].magic = magic++;
|
||
|
ctx[0].size = max_block(heap) / 3;
|
||
|
ctx[0].ptr = rt_smem_alloc(&heap->parent, ctx[0].size);
|
||
|
uassert_not_null(ctx[0].ptr);
|
||
|
rt_memset(ctx[0].ptr, ctx[0].magic, ctx[0].size);
|
||
|
/* Apply for a small piece of memory and split the continuous memory */
|
||
|
ctx[1].magic = magic++;
|
||
|
ctx[1].size = RT_ALIGN_SIZE;
|
||
|
ctx[1].ptr = rt_smem_alloc(&heap->parent, ctx[1].size);
|
||
|
uassert_not_null(ctx[1].ptr);
|
||
|
rt_memset(ctx[1].ptr, ctx[1].magic, ctx[1].size);
|
||
|
/* Check whether the maximum memory block is larger than the first piece of memory */
|
||
|
uassert_true(max_block(heap) > ctx[0].size);
|
||
|
/* Reallocate the first piece of memory */
|
||
|
ctx[2].magic = magic++;
|
||
|
ctx[2].size = max_block(heap);
|
||
|
ctx[2].ptr = rt_smem_realloc(&heap->parent, ctx[0].ptr, ctx[2].size);
|
||
|
uassert_not_null(ctx[2].ptr);
|
||
|
uassert_int_not_equal(ctx[0].ptr, ctx[2].ptr);
|
||
|
uassert_int_equal(_mem_cmp(ctx[2].ptr, ctx[0].magic, ctx[0].size), 0);
|
||
|
rt_memset(ctx[2].ptr, ctx[2].magic, ctx[2].size);
|
||
|
/* Free the second piece of memory */
|
||
|
uassert_int_equal(_mem_cmp(ctx[1].ptr, ctx[1].magic, ctx[1].size), 0);
|
||
|
rt_smem_free(ctx[1].ptr);
|
||
|
/* Free reallocated memory */
|
||
|
uassert_int_equal(_mem_cmp(ctx[2].ptr, ctx[2].magic, ctx[2].size), 0);
|
||
|
rt_smem_free(ctx[2].ptr);
|
||
|
/* Check memory integrity */
|
||
|
uassert_int_equal(max_block(heap), total_size);
|
||
|
}
|
||
|
/* mem realloc test,Large - > Small */
|
||
|
{
|
||
|
rt_size_t max_free;
|
||
|
struct mem_test_context ctx;
|
||
|
/* alloc a piece of memory */
|
||
|
ctx.magic = magic++;
|
||
|
ctx.size = max_block(heap) / 2;
|
||
|
ctx.ptr = rt_smem_alloc(&heap->parent, ctx.size);
|
||
|
uassert_not_null(ctx.ptr);
|
||
|
rt_memset(ctx.ptr, ctx.magic, ctx.size);
|
||
|
uassert_int_equal(_mem_cmp(ctx.ptr, ctx.magic, ctx.size), 0);
|
||
|
/* Get remaining memory */
|
||
|
max_free = max_block(heap);
|
||
|
/* Change memory size */
|
||
|
ctx.size = ctx.size / 2;
|
||
|
uassert_int_equal((rt_ubase_t)rt_smem_realloc(&heap->parent, ctx.ptr, ctx.size), (rt_ubase_t)ctx.ptr);
|
||
|
/* Get remaining size */
|
||
|
uassert_true(max_block(heap) > max_free);
|
||
|
/* Free memory */
|
||
|
uassert_int_equal(_mem_cmp(ctx.ptr, ctx.magic, ctx.size), 0);
|
||
|
rt_smem_free(ctx.ptr);
|
||
|
/* Check memory integrity */
|
||
|
uassert_int_equal(max_block(heap), total_size);
|
||
|
}
|
||
|
/* mem realloc test,equal */
|
||
|
{
|
||
|
rt_size_t max_free;
|
||
|
struct mem_test_context ctx;
|
||
|
/* alloc a piece of memory */
|
||
|
ctx.magic = magic++;
|
||
|
ctx.size = max_block(heap) / 2;
|
||
|
ctx.ptr = rt_smem_alloc(&heap->parent, ctx.size);
|
||
|
uassert_not_null(ctx.ptr);
|
||
|
rt_memset(ctx.ptr, ctx.magic, ctx.size);
|
||
|
uassert_int_equal(_mem_cmp(ctx.ptr, ctx.magic, ctx.size), 0);
|
||
|
/* Get remaining memory */
|
||
|
max_free = max_block(heap);
|
||
|
/* Do not change memory size */
|
||
|
uassert_int_equal((rt_ubase_t)rt_smem_realloc(&heap->parent, ctx.ptr, ctx.size), (rt_ubase_t)ctx.ptr);
|
||
|
/* Get remaining size */
|
||
|
uassert_true(max_block(heap) == max_free);
|
||
|
/* Free memory */
|
||
|
uassert_int_equal(_mem_cmp(ctx.ptr, ctx.magic, ctx.size), 0);
|
||
|
rt_smem_free(ctx.ptr);
|
||
|
/* Check memory integrity */
|
||
|
uassert_int_equal(max_block(heap), total_size);
|
||
|
}
|
||
|
/* small heap deinit */
|
||
|
rt_smem_detach(&heap->parent);
|
||
|
/* release test resources */
|
||
|
rt_free(buf);
|
||
|
}
|
||
|
|
||
|
struct mem_alloc_context
|
||
|
{
|
||
|
rt_list_t node;
|
||
|
rt_size_t size;
|
||
|
rt_uint8_t magic;
|
||
|
};
|
||
|
|
||
|
struct mem_alloc_head
|
||
|
{
|
||
|
rt_list_t list;
|
||
|
rt_size_t count;
|
||
|
rt_tick_t start;
|
||
|
rt_tick_t end;
|
||
|
rt_tick_t interval;
|
||
|
};
|
||
|
|
||
|
#define MEM_RANG_ALLOC_BLK_MIN 2
|
||
|
#define MEM_RANG_ALLOC_BLK_MAX 5
|
||
|
#define MEM_RANG_ALLOC_TEST_TIME 5
|
||
|
|
||
|
static void mem_alloc_test(void)
|
||
|
{
|
||
|
struct mem_alloc_head head;
|
||
|
rt_uint8_t *buf;
|
||
|
struct rt_small_mem *heap;
|
||
|
rt_size_t total_size, size;
|
||
|
struct mem_alloc_context *ctx;
|
||
|
|
||
|
/* init */
|
||
|
rt_list_init(&head.list);
|
||
|
head.count = 0;
|
||
|
head.start = rt_tick_get();
|
||
|
head.end = rt_tick_get() + rt_tick_from_millisecond(MEM_RANG_ALLOC_TEST_TIME * 1000);
|
||
|
head.interval = (head.end - head.start) / 20;
|
||
|
buf = rt_malloc(TEST_MEM_SIZE);
|
||
|
uassert_not_null(buf);
|
||
|
uassert_int_equal(RT_ALIGN((rt_ubase_t)buf, RT_ALIGN_SIZE), (rt_ubase_t)buf);
|
||
|
rt_memset(buf, 0xAA, TEST_MEM_SIZE);
|
||
|
heap = (struct rt_small_mem *)rt_smem_init("mem_tc", buf, TEST_MEM_SIZE);
|
||
|
total_size = max_block(heap);
|
||
|
uassert_int_not_equal(total_size, 0);
|
||
|
/* test run */
|
||
|
while (head.end - head.start < RT_TICK_MAX / 2)
|
||
|
{
|
||
|
if (rt_tick_get() - head.start >= head.interval)
|
||
|
{
|
||
|
head.start = rt_tick_get();
|
||
|
rt_kprintf("#");
|
||
|
}
|
||
|
/* %60 probability to perform alloc operation */
|
||
|
if (rand() % 10 >= 4)
|
||
|
{
|
||
|
size = rand() % MEM_RANG_ALLOC_BLK_MAX + MEM_RANG_ALLOC_BLK_MIN;
|
||
|
size *= sizeof(struct mem_alloc_context);
|
||
|
ctx = rt_smem_alloc(&heap->parent, size);
|
||
|
if (ctx == RT_NULL)
|
||
|
{
|
||
|
if (head.count == 0)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
size = head.count / 2;
|
||
|
while (size != head.count)
|
||
|
{
|
||
|
ctx = rt_list_first_entry(&head.list, struct mem_alloc_context, node);
|
||
|
rt_list_remove(&ctx->node);
|
||
|
if (ctx->size > sizeof(*ctx))
|
||
|
{
|
||
|
if (_mem_cmp(&ctx[1], ctx->magic, ctx->size - sizeof(*ctx)) != 0)
|
||
|
{
|
||
|
uassert_true(0);
|
||
|
}
|
||
|
}
|
||
|
rt_memset(ctx, 0xAA, ctx->size);
|
||
|
rt_smem_free(ctx);
|
||
|
head.count --;
|
||
|
}
|
||
|
continue;
|
||
|
}
|
||
|
if (RT_ALIGN((rt_ubase_t)ctx, RT_ALIGN_SIZE) != (rt_ubase_t)ctx)
|
||
|
{
|
||
|
uassert_int_equal(RT_ALIGN((rt_ubase_t)ctx, RT_ALIGN_SIZE), (rt_ubase_t)ctx);
|
||
|
}
|
||
|
rt_memset(ctx, 0, size);
|
||
|
rt_list_init(&ctx->node);
|
||
|
ctx->size = size;
|
||
|
ctx->magic = rand() & 0xff;
|
||
|
if (ctx->size > sizeof(*ctx))
|
||
|
{
|
||
|
rt_memset(&ctx[1], ctx->magic, ctx->size - sizeof(*ctx));
|
||
|
}
|
||
|
rt_list_insert_after(&head.list, &ctx->node);
|
||
|
head.count += 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (!rt_list_isempty(&head.list))
|
||
|
{
|
||
|
ctx = rt_list_first_entry(&head.list, struct mem_alloc_context, node);
|
||
|
rt_list_remove(&ctx->node);
|
||
|
if (ctx->size > sizeof(*ctx))
|
||
|
{
|
||
|
if (_mem_cmp(&ctx[1], ctx->magic, ctx->size - sizeof(*ctx)) != 0)
|
||
|
{
|
||
|
uassert_true(0);
|
||
|
}
|
||
|
}
|
||
|
rt_memset(ctx, 0xAA, ctx->size);
|
||
|
rt_smem_free(ctx);
|
||
|
head.count --;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
while (!rt_list_isempty(&head.list))
|
||
|
{
|
||
|
ctx = rt_list_first_entry(&head.list, struct mem_alloc_context, node);
|
||
|
rt_list_remove(&ctx->node);
|
||
|
if (ctx->size > sizeof(*ctx))
|
||
|
{
|
||
|
if (_mem_cmp(&ctx[1], ctx->magic, ctx->size - sizeof(*ctx)) != 0)
|
||
|
{
|
||
|
uassert_true(0);
|
||
|
}
|
||
|
}
|
||
|
rt_memset(ctx, 0xAA, ctx->size);
|
||
|
rt_smem_free(ctx);
|
||
|
head.count --;
|
||
|
}
|
||
|
uassert_int_equal(head.count, 0);
|
||
|
uassert_int_equal(max_block(heap), total_size);
|
||
|
/* small heap deinit */
|
||
|
rt_smem_detach(&heap->parent);
|
||
|
/* release test resources */
|
||
|
rt_free(buf);
|
||
|
}
|
||
|
|
||
|
#define MEM_RANG_REALLOC_BLK_MIN 0
|
||
|
#define MEM_RANG_REALLOC_BLK_MAX 5
|
||
|
#define MEM_RANG_REALLOC_TEST_TIME 5
|
||
|
|
||
|
struct mem_realloc_context
|
||
|
{
|
||
|
rt_size_t size;
|
||
|
rt_uint8_t magic;
|
||
|
};
|
||
|
|
||
|
struct mem_realloc_head
|
||
|
{
|
||
|
struct mem_realloc_context **ctx_tab;
|
||
|
rt_size_t count;
|
||
|
rt_tick_t start;
|
||
|
rt_tick_t end;
|
||
|
rt_tick_t interval;
|
||
|
};
|
||
|
|
||
|
static void mem_realloc_test(void)
|
||
|
{
|
||
|
struct mem_realloc_head head;
|
||
|
rt_uint8_t *buf;
|
||
|
struct rt_small_mem *heap;
|
||
|
rt_size_t total_size, size, idx;
|
||
|
struct mem_realloc_context *ctx;
|
||
|
int res;
|
||
|
|
||
|
size = RT_ALIGN(sizeof(struct mem_realloc_context), RT_ALIGN_SIZE) + RT_ALIGN_SIZE;
|
||
|
size = TEST_MEM_SIZE / size;
|
||
|
/* init */
|
||
|
head.ctx_tab = RT_NULL;
|
||
|
head.count = size;
|
||
|
head.start = rt_tick_get();
|
||
|
head.end = rt_tick_get() + rt_tick_from_millisecond(MEM_RANG_ALLOC_TEST_TIME * 1000);
|
||
|
head.interval = (head.end - head.start) / 20;
|
||
|
buf = rt_malloc(TEST_MEM_SIZE);
|
||
|
uassert_not_null(buf);
|
||
|
uassert_int_equal(RT_ALIGN((rt_ubase_t)buf, RT_ALIGN_SIZE), (rt_ubase_t)buf);
|
||
|
rt_memset(buf, 0xAA, TEST_MEM_SIZE);
|
||
|
heap = (struct rt_small_mem *)rt_smem_init("mem_tc", buf, TEST_MEM_SIZE);
|
||
|
total_size = max_block(heap);
|
||
|
uassert_int_not_equal(total_size, 0);
|
||
|
/* init ctx tab */
|
||
|
size = head.count * sizeof(struct mem_realloc_context *);
|
||
|
head.ctx_tab = rt_smem_alloc(&heap->parent, size);
|
||
|
uassert_not_null(head.ctx_tab);
|
||
|
rt_memset(head.ctx_tab, 0, size);
|
||
|
/* test run */
|
||
|
while (head.end - head.start < RT_TICK_MAX / 2)
|
||
|
{
|
||
|
if (rt_tick_get() - head.start >= head.interval)
|
||
|
{
|
||
|
head.start = rt_tick_get();
|
||
|
rt_kprintf("#");
|
||
|
}
|
||
|
size = rand() % MEM_RANG_ALLOC_BLK_MAX + MEM_RANG_ALLOC_BLK_MIN;
|
||
|
size *= sizeof(struct mem_realloc_context);
|
||
|
idx = rand() % head.count;
|
||
|
ctx = rt_smem_realloc(&heap->parent, head.ctx_tab[idx], size);
|
||
|
if (ctx == RT_NULL)
|
||
|
{
|
||
|
if (size == 0)
|
||
|
{
|
||
|
if (head.ctx_tab[idx])
|
||
|
{
|
||
|
head.ctx_tab[idx] = RT_NULL;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (idx = 0; idx < head.count; idx++)
|
||
|
{
|
||
|
ctx = head.ctx_tab[idx];
|
||
|
if (rand() % 2 && ctx)
|
||
|
{
|
||
|
if (ctx->size > sizeof(*ctx))
|
||
|
{
|
||
|
res = _mem_cmp(&ctx[1], ctx->magic, ctx->size - sizeof(*ctx));
|
||
|
if (res != 0)
|
||
|
{
|
||
|
uassert_int_equal(res, 0);
|
||
|
}
|
||
|
}
|
||
|
rt_memset(ctx, 0xAA, ctx->size);
|
||
|
rt_smem_realloc(&heap->parent, ctx, 0);
|
||
|
head.ctx_tab[idx] = RT_NULL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
continue;
|
||
|
}
|
||
|
/* check mem */
|
||
|
if (head.ctx_tab[idx] != RT_NULL)
|
||
|
{
|
||
|
res = 0;
|
||
|
if (ctx->size < size)
|
||
|
{
|
||
|
if (ctx->size > sizeof(*ctx))
|
||
|
{
|
||
|
res = _mem_cmp(&ctx[1], ctx->magic, ctx->size - sizeof(*ctx));
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (size > sizeof(*ctx))
|
||
|
{
|
||
|
res = _mem_cmp(&ctx[1], ctx->magic, size - sizeof(*ctx));
|
||
|
}
|
||
|
}
|
||
|
if (res != 0)
|
||
|
{
|
||
|
uassert_int_equal(res, 0);
|
||
|
}
|
||
|
}
|
||
|
/* init mem */
|
||
|
ctx->magic = rand() & 0xff;
|
||
|
ctx->size = size;
|
||
|
if (ctx->size > sizeof(*ctx))
|
||
|
{
|
||
|
rt_memset(&ctx[1], ctx->magic, ctx->size - sizeof(*ctx));
|
||
|
}
|
||
|
head.ctx_tab[idx] = ctx;
|
||
|
}
|
||
|
/* free all mem */
|
||
|
for (idx = 0; idx < head.count; idx++)
|
||
|
{
|
||
|
ctx = head.ctx_tab[idx];
|
||
|
if (ctx == RT_NULL)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
if (ctx->size > sizeof(*ctx))
|
||
|
{
|
||
|
res = _mem_cmp(&ctx[1], ctx->magic, ctx->size - sizeof(*ctx));
|
||
|
if (res != 0)
|
||
|
{
|
||
|
uassert_int_equal(res, 0);
|
||
|
}
|
||
|
}
|
||
|
rt_memset(ctx, 0xAA, ctx->size);
|
||
|
rt_smem_realloc(&heap->parent, ctx, 0);
|
||
|
head.ctx_tab[idx] = RT_NULL;
|
||
|
}
|
||
|
uassert_int_not_equal(max_block(heap), total_size);
|
||
|
/* small heap deinit */
|
||
|
rt_smem_detach(&heap->parent);
|
||
|
/* release test resources */
|
||
|
rt_free(buf);
|
||
|
}
|
||
|
|
||
|
static rt_err_t utest_tc_init(void)
|
||
|
{
|
||
|
return RT_EOK;
|
||
|
}
|
||
|
|
||
|
static rt_err_t utest_tc_cleanup(void)
|
||
|
{
|
||
|
return RT_EOK;
|
||
|
}
|
||
|
|
||
|
static void testcase(void)
|
||
|
{
|
||
|
UTEST_UNIT_RUN(mem_functional_test);
|
||
|
UTEST_UNIT_RUN(mem_alloc_test);
|
||
|
UTEST_UNIT_RUN(mem_realloc_test);
|
||
|
}
|
||
|
UTEST_TC_EXPORT(testcase, "testcases.kernel.mem_tc", utest_tc_init, utest_tc_cleanup, 20);
|