123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323 |
- /*
- * Copyright (c) 2006-2019, 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"
- #define TEST_SLAB_SIZE 1024 * 1024
- 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 slab_alloc_context
- {
- rt_list_t node;
- rt_size_t size;
- rt_uint8_t magic;
- };
- struct slab_alloc_head
- {
- rt_list_t list;
- rt_size_t count;
- rt_tick_t start;
- rt_tick_t end;
- rt_tick_t interval;
- };
- #define SLAB_RANG_ALLOC_BLK_MIN 2
- #define SLAB_RANG_ALLOC_BLK_MAX 5
- #define SLAB_RANG_ALLOC_TEST_TIME 5
- static void slab_alloc_test(void)
- {
- struct slab_alloc_head head;
- rt_uint8_t *buf;
- rt_slab_t heap;
- rt_size_t size;
- struct slab_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(SLAB_RANG_ALLOC_TEST_TIME * 1000);
- head.interval = (head.end - head.start) / 20;
- buf = rt_malloc(TEST_SLAB_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_SLAB_SIZE);
- heap = rt_slab_init("slab_tc", buf, TEST_SLAB_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("#");
- }
- // %60 probability to perform alloc operation
- if (rand() % 10 >= 4)
- {
- size = rand() % SLAB_RANG_ALLOC_BLK_MAX + SLAB_RANG_ALLOC_BLK_MIN;
- size *= sizeof(struct slab_alloc_context);
- ctx = rt_slab_alloc(heap, 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 slab_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_slab_free(heap, 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 slab_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_slab_free(heap, ctx);
- head.count --;
- }
- }
- }
- while (!rt_list_isempty(&head.list))
- {
- ctx = rt_list_first_entry(&head.list, struct slab_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_slab_free(heap, ctx);
- head.count --;
- }
- uassert_int_equal(head.count, 0);
- // slab heap deinit
- rt_slab_detach(heap);
- /* release test resources */
- rt_free(buf);
- }
- #define SLAB_RANG_REALLOC_BLK_MIN 0
- #define SLAB_RANG_REALLOC_BLK_MAX 5
- #define SLAB_RANG_REALLOC_TEST_TIME 5
- struct slab_realloc_context
- {
- rt_size_t size;
- rt_uint8_t magic;
- };
- struct slab_realloc_head
- {
- struct slab_realloc_context **ctx_tab;
- rt_size_t count;
- rt_tick_t start;
- rt_tick_t end;
- rt_tick_t interval;
- };
- static void slab_realloc_test(void)
- {
- struct slab_realloc_head head;
- rt_uint8_t *buf;
- rt_slab_t heap;
- rt_size_t size, idx;
- struct slab_realloc_context *ctx;
- int res;
- size = RT_ALIGN(sizeof(struct slab_realloc_context), RT_ALIGN_SIZE) + RT_ALIGN_SIZE;
- size = TEST_SLAB_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(SLAB_RANG_ALLOC_TEST_TIME * 1000);
- head.interval = (head.end - head.start) / 20;
- buf = rt_malloc(TEST_SLAB_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_SLAB_SIZE);
- heap = rt_slab_init("slab_tc", buf, TEST_SLAB_SIZE);
- /* init ctx tab */
- size = head.count * sizeof(struct slab_realloc_context *);
- head.ctx_tab = rt_slab_alloc(heap, 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() % SLAB_RANG_ALLOC_BLK_MAX + SLAB_RANG_ALLOC_BLK_MIN;
- size *= sizeof(struct slab_realloc_context);
- idx = rand() % head.count;
- ctx = rt_slab_realloc(heap, 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_slab_realloc(heap, ctx, 0);
- head.ctx_tab[idx] = RT_NULL;
- }
- }
- }
- continue;
- }
- /* check slab */
- 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 slab */
- 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 slab
- 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_slab_realloc(heap, ctx, 0);
- head.ctx_tab[idx] = RT_NULL;
- }
- // slab heap deinit
- rt_slab_detach(heap);
- /* 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(slab_alloc_test);
- UTEST_UNIT_RUN(slab_realloc_test);
- }
- UTEST_TC_EXPORT(testcase, "testcases.kernel.slab_tc", utest_tc_init, utest_tc_cleanup, 20);
|