/* * Copyright (c) 2023, Meta * * SPDX-License-Identifier: Apache-2.0 */ #include "_main.h" /* update interval for printing stats */ #if CONFIG_TEST_DURATION_S >= 60 #define UPDATE_INTERVAL_S 10 #elif CONFIG_TEST_DURATION_S >= 30 #define UPDATE_INTERVAL_S 5 #else #define UPDATE_INTERVAL_S 1 #endif enum th_id { WRITER, READER, }; typedef int (*eventfd_op_t)(int fd); static size_t count[2]; static struct k_thread th[2]; static const char *msg[2] = { [READER] = "reads", [WRITER] = "writes", }; static int read_op(int fd); static int write_op(int fd); static const eventfd_op_t op[2] = { [READER] = read_op, [WRITER] = write_op, }; static K_THREAD_STACK_ARRAY_DEFINE(th_stack, 2, CONFIG_TEST_STACK_SIZE); static int read_op(int fd) { eventfd_t value; return eventfd_read(fd, &value); } static int write_op(int fd) { return eventfd_write(fd, 1); } static void th_fun(void *arg1, void *arg2, void *arg3) { int ret; uint64_t now; uint64_t end; uint64_t report; enum th_id id = POINTER_TO_UINT(arg1); struct eventfd_fixture *fixture = arg2; const uint64_t report_ms = UPDATE_INTERVAL_S * MSEC_PER_SEC; const uint64_t end_ms = CONFIG_TEST_DURATION_S * MSEC_PER_SEC; for (now = k_uptime_get(), end = now + end_ms, report = now + report_ms; now < end; now = k_uptime_get()) { ret = op[id](fixture->fd); if (IS_ENABLED(CONFIG_TEST_EXTRA_ASSERTIONS)) { zassert_true(ret == 0 || (ret == -1 && errno == EAGAIN), "ret: %d errno: %d", ret, errno); } count[id] += (ret == 0); if (!IS_ENABLED(CONFIG_TEST_EXTRA_QUIET)) { if (now >= report) { printk("%zu %s\n", count[id], msg[id]); report += report_ms; } } Z_SPIN_DELAY(10); } printk("avg: %zu %s/s\n", (size_t)((count[id] * MSEC_PER_SEC) / end_ms), msg[id]); } ZTEST_F(eventfd, test_stress) { enum th_id i; enum th_id begin = MIN(READER, WRITER); enum th_id end = MAX(READER, WRITER) + 1; printk("BOARD: %s\n", CONFIG_BOARD); printk("TEST_DURATION_S: %u\n", CONFIG_TEST_DURATION_S); printk("UPDATE_INTERVAL_S: %u\n", UPDATE_INTERVAL_S); reopen(&fixture->fd, 0, EFD_NONBLOCK | EFD_SEMAPHORE); for (i = begin; i < end; ++i) { k_thread_create(&th[i], th_stack[i], K_THREAD_STACK_SIZEOF(th_stack[0]), th_fun, UINT_TO_POINTER(i), fixture, NULL, K_LOWEST_APPLICATION_THREAD_PRIO, 0, K_NO_WAIT); } for (i = begin; i < end; ++i) { zassert_ok(k_thread_join(&th[i], K_FOREVER)); } zassert_true(count[READER] > 0, "read count is zero"); zassert_true(count[WRITER] > 0, "write count is zero"); zassert_true(count[WRITER] >= count[READER], "read count (%zu) > write count (%zu)", count[READER], count[WRITER]); }