From 716fa446cd0d677bd0a71d131ccbf569cabada23 Mon Sep 17 00:00:00 2001 From: Krzysztof Chruscinski Date: Mon, 22 Aug 2022 14:27:20 +0200 Subject: [PATCH] tests: lib: spsc_pbuf: Improve stress test Improve stress tests to be more robust and demanding. Previous implementation did not reveal race condition. Signed-off-by: Krzysztof Chruscinski --- tests/lib/spsc_pbuf/src/main.c | 100 +++++++++++++++++++-------------- 1 file changed, 58 insertions(+), 42 deletions(-) diff --git a/tests/lib/spsc_pbuf/src/main.c b/tests/lib/spsc_pbuf/src/main.c index 1e39ba94954..e35ca0b1945 100644 --- a/tests/lib/spsc_pbuf/src/main.c +++ b/tests/lib/spsc_pbuf/src/main.c @@ -11,6 +11,7 @@ #define HDR_LEN sizeof(uint32_t) #define TLEN(len) ROUND_UP(HDR_LEN + len, sizeof(uint32_t)) +#define STRESS_TIMEOUT_MS ((CONFIG_SYS_CLOCK_TICKS_PER_SEC < 10000) ? 1000 : 15000) /* The buffer size itself would be 199 bytes. * 212 - sizeof(struct spsc_pbuf) - 1 = 199. @@ -415,6 +416,7 @@ struct stress_data { uint32_t capacity; uint32_t write_cnt; uint32_t read_cnt; + uint32_t wr_err; }; bool stress_read(void *user_data, uint32_t cnt, bool last, int prio) @@ -422,20 +424,22 @@ bool stress_read(void *user_data, uint32_t cnt, bool last, int prio) struct stress_data *ctx = (struct stress_data *)user_data; char buf[128]; int len; + int rpt = (sys_rand32_get() & 3) + 1; - len = spsc_pbuf_read(ctx->pbuf, buf, (uint16_t)sizeof(buf)); + for (int i = 0; i < rpt; i++) { + len = spsc_pbuf_read(ctx->pbuf, buf, (uint16_t)sizeof(buf)); + if (len == 0) { + return true; + } - if (len == 0) { - return true; + if (len < 0) { + zassert_true(false, "Unexpected error: %d, cnt:%d", len, ctx->read_cnt); + } + + check_buffer(buf, len, ctx->read_cnt); + ctx->read_cnt++; } - if (len < 0) { - zassert_true(false, "Unexpected error: %d, cnt:%d", len, ctx->read_cnt); - } - - check_buffer(buf, len, ctx->read_cnt); - ctx->read_cnt++; - return true; } @@ -444,36 +448,41 @@ bool stress_write(void *user_data, uint32_t cnt, bool last, int prio) struct stress_data *ctx = (struct stress_data *)user_data; char buf[128]; uint16_t len = 1 + (sys_rand32_get() % (ctx->capacity / 4)); + int rpt = (sys_rand32_get() & 1) + 1; zassert_true(len < sizeof(buf), "len:%d %d", len, ctx->capacity); - memset(buf, (uint8_t)ctx->write_cnt, len); - if (spsc_pbuf_write(ctx->pbuf, buf, len) == 0) { - ctx->write_cnt++; + for (int i = 0; i < rpt; i++) { + memset(buf, (uint8_t)ctx->write_cnt, len); + if (spsc_pbuf_write(ctx->pbuf, buf, len) == len) { + ctx->write_cnt++; + } else { + ctx->wr_err++; + } } return true; } - - ZTEST(test_spsc_pbuf, test_stress) { static uint8_t buffer[128] __aligned(MAX(Z_SPSC_PBUF_DCACHE_LINE, 4)); - static struct stress_data ctx; + static struct stress_data ctx = {}; uint32_t repeat = 0; - ctx.write_cnt = 0; - ctx.read_cnt = 0; ctx.pbuf = spsc_pbuf_init(buffer, sizeof(buffer), 0); ctx.capacity = spsc_pbuf_capacity(ctx.pbuf); - ztress_set_timeout(K_MSEC(5000)); - ZTRESS_EXECUTE(ZTRESS_THREAD(stress_read, &ctx, repeat, 0, Z_TIMEOUT_TICKS(4)), - ZTRESS_THREAD(stress_write, &ctx, repeat, 1000, Z_TIMEOUT_TICKS(4))); + ztress_set_timeout(K_MSEC(STRESS_TIMEOUT_MS)); + TC_PRINT("Reading from an interrupt, writing from a thread\n"); + ZTRESS_EXECUTE(ZTRESS_TIMER(stress_read, &ctx, repeat, Z_TIMEOUT_TICKS(4)), + ZTRESS_THREAD(stress_write, &ctx, repeat, 2000, Z_TIMEOUT_TICKS(4))); + TC_PRINT("Writes:%d failures: %d\n", ctx.write_cnt, ctx.wr_err); - ZTRESS_EXECUTE(ZTRESS_THREAD(stress_write, &ctx, repeat, 0, Z_TIMEOUT_TICKS(4)), + TC_PRINT("Writing from an interrupt, reading from a thread\n"); + ZTRESS_EXECUTE(ZTRESS_TIMER(stress_write, &ctx, repeat, Z_TIMEOUT_TICKS(4)), ZTRESS_THREAD(stress_read, &ctx, repeat, 1000, Z_TIMEOUT_TICKS(4))); + TC_PRINT("Writes:%d failures: %d\n", ctx.write_cnt, ctx.wr_err); } bool stress_claim_free(void *user_data, uint32_t cnt, bool last, int prio) @@ -481,40 +490,47 @@ bool stress_claim_free(void *user_data, uint32_t cnt, bool last, int prio) struct stress_data *ctx = (struct stress_data *)user_data; char *buf; uint16_t len; + int rpt = sys_rand32_get() % 0x3; - len = spsc_pbuf_claim(ctx->pbuf, &buf); + for (int i = 0; i < rpt; i++) { + len = spsc_pbuf_claim(ctx->pbuf, &buf); - if (len == 0) { - return true; + if (len == 0) { + return true; + } + + check_buffer(buf, len, ctx->read_cnt); + + spsc_pbuf_free(ctx->pbuf, len); + + ctx->read_cnt++; } - check_buffer(buf, len, ctx->read_cnt); - - spsc_pbuf_free(ctx->pbuf, len); - - ctx->read_cnt++; - return true; } bool stress_alloc_commit(void *user_data, uint32_t cnt, bool last, int prio) { struct stress_data *ctx = (struct stress_data *)user_data; - uint16_t len = 1 + (sys_rand32_get() % (ctx->capacity / 4)); + uint32_t rnd = sys_rand32_get(); + uint16_t len = 1 + (rnd % (ctx->capacity / 4)); + int rpt = rnd % 0x3; char *buf; int err; - err = spsc_pbuf_alloc(ctx->pbuf, len, &buf); - zassert_true(err >= 0, NULL); - if (err != len) { - return true; + for (int i = 0; i < rpt; i++) { + err = spsc_pbuf_alloc(ctx->pbuf, len, &buf); + zassert_true(err >= 0, NULL); + if (err != len) { + return true; + } + + memset(buf, (uint8_t)ctx->write_cnt, len); + + spsc_pbuf_commit(ctx->pbuf, len); + ctx->write_cnt++; } - memset(buf, (uint8_t)ctx->write_cnt, len); - - spsc_pbuf_commit(ctx->pbuf, len); - ctx->write_cnt++; - return true; } @@ -529,7 +545,7 @@ ZTEST(test_spsc_pbuf, test_stress_0cpy) ctx.pbuf = spsc_pbuf_init(buffer, sizeof(buffer), 0); ctx.capacity = spsc_pbuf_capacity(ctx.pbuf); - ztress_set_timeout(K_MSEC(5000)); + ztress_set_timeout(K_MSEC(STRESS_TIMEOUT_MS)); ZTRESS_EXECUTE(ZTRESS_THREAD(stress_claim_free, &ctx, repeat, 0, Z_TIMEOUT_TICKS(4)), ZTRESS_THREAD(stress_alloc_commit, &ctx, repeat, 1000, Z_TIMEOUT_TICKS(4)));