/
phprus
/
github_dpdk
Обзор
Документация
Войти
/
phprus
/
github_dpdk
Код
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
app/test/test_timer_secondary.c
239 строк
6 KB
Bruce Richardson
test: fix failing tests on FreeBSD
29 апр 2026, 17:54
29 апр 2026, 17:54
f927605
Код
Авторство
О чём код?
/* SPDX-License-Identifier: BSD-3-Clause * Copyright(c) 2019 Intel Corporation */ #include <stdio.h> #include <string.h> #include <rte_eal.h> #include <rte_lcore.h> #include <rte_debug.h> #include <rte_memzone.h> #include <rte_timer.h> #include <rte_cycles.h> #include <rte_mempool.h> #include <rte_pause.h> #include <rte_random.h> #include <rte_stdatomic.h> #include "test.h" #ifndef RTE_EXEC_ENV_LINUX int test_timer_secondary(void) { printf("timer_secondary only supported on Linux, skipping test\n"); return TEST_SKIPPED; } #else #include "process.h" #define NUM_TIMERS_MAX (1 << 20) /* ~1M timers */ #define NUM_TIMERS_MIN (1 << 14) /* 16K minimum */ #define NUM_LCORES_NEEDED 3 #define TEST_INFO_MZ_NAME "test_timer_info_mz" #define MSECPERSEC 1E3 #define launch_proc(ARGV) process_dup(ARGV, RTE_DIM(ARGV), __func__) struct test_info { unsigned int main_lcore; unsigned int mgr_lcore; unsigned int sec_lcore; unsigned int num_timers; uint32_t timer_data_id; RTE_ATOMIC(unsigned int) expected_count; RTE_ATOMIC(unsigned int) expired_count; struct rte_mempool *tim_mempool; struct rte_timer *expired_timers[NUM_TIMERS_MAX]; int expired_timers_idx; RTE_ATOMIC(int) exit_flag; }; static int timer_secondary_spawn_wait(unsigned int lcore) { char core_str[10]; const char *prefix; prefix = file_prefix_arg(); if (prefix == NULL) return -1; char const *argv[] = { prgname, "-l", core_str, "--proc-type=secondary", prefix }; snprintf(core_str, sizeof(core_str), "%u", lcore); return launch_proc(argv); } static void handle_expired_timer(struct rte_timer *tim) { struct test_info *test_info = tim->arg; rte_atomic_fetch_add_explicit(&test_info->expired_count, 1, rte_memory_order_relaxed); test_info->expired_timers[test_info->expired_timers_idx++] = tim; } static int timer_manage_loop(void *arg) { #define TICK_MSECS 1 uint64_t tick_cycles = TICK_MSECS * rte_get_timer_hz() / MSECPERSEC; uint64_t prev_tsc = 0, cur_tsc, diff_tsc; struct test_info *test_info = arg; while (!rte_atomic_load_explicit(&test_info->exit_flag, rte_memory_order_acquire)) { cur_tsc = rte_rdtsc(); diff_tsc = cur_tsc - prev_tsc; if (diff_tsc > tick_cycles) { /* Scan timer list for expired timers */ rte_timer_alt_manage(test_info->timer_data_id, NULL, 0, handle_expired_timer); /* Return expired timer objects back to mempool */ rte_mempool_put_bulk(test_info->tim_mempool, (void **)test_info->expired_timers, test_info->expired_timers_idx); test_info->expired_timers_idx = 0; prev_tsc = cur_tsc; } rte_pause(); } return 0; } int test_timer_secondary(void) { int proc_type = rte_eal_process_type(); const struct rte_memzone *mz; struct test_info *test_info; int ret; if (proc_type == RTE_PROC_PRIMARY) { if (rte_lcore_count() < NUM_LCORES_NEEDED) { printf("Not enough cores for test_timer_secondary, expecting at least %u\n", NUM_LCORES_NEEDED); return TEST_SKIPPED; } mz = rte_memzone_reserve(TEST_INFO_MZ_NAME, sizeof(*test_info), SOCKET_ID_ANY, 0); TEST_ASSERT_NOT_NULL(mz, "Couldn't allocate memory for " "test data"); test_info = mz->addr; test_info->num_timers = test_scale_iterations(NUM_TIMERS_MAX, NUM_TIMERS_MIN); test_info->tim_mempool = rte_mempool_create("test_timer_mp", test_info->num_timers, sizeof(struct rte_timer), 0, 0, NULL, NULL, NULL, NULL, rte_socket_id(), 0); ret = rte_timer_data_alloc(&test_info->timer_data_id); TEST_ASSERT_SUCCESS(ret, "Failed to allocate timer data " "instance"); unsigned int *main_lcorep = &test_info->main_lcore; unsigned int *mgr_lcorep = &test_info->mgr_lcore; unsigned int *sec_lcorep = &test_info->sec_lcore; *main_lcorep = rte_get_main_lcore(); *mgr_lcorep = rte_get_next_lcore(*main_lcorep, 1, 1); *sec_lcorep = rte_get_next_lcore(*mgr_lcorep, 1, 1); ret = rte_eal_remote_launch(timer_manage_loop, (void *)test_info, *mgr_lcorep); TEST_ASSERT_SUCCESS(ret, "Failed to launch timer manage loop"); ret = timer_secondary_spawn_wait(*sec_lcorep); /* must set exit flag even on error case, so check ret later */ rte_delay_ms(500); rte_atomic_store_explicit(&test_info->exit_flag, 1, rte_memory_order_release); TEST_ASSERT_SUCCESS(ret, "Secondary process execution failed"); rte_eal_wait_lcore(*mgr_lcorep); #ifdef RTE_LIBRTE_TIMER_DEBUG rte_timer_alt_dump_stats(test_info->timer_data_id, stdout); #endif return rte_atomic_load_explicit(&test_info->expected_count, rte_memory_order_relaxed) == rte_atomic_load_explicit(&test_info->expired_count, rte_memory_order_relaxed) ? TEST_SUCCESS : TEST_FAILED; } else if (proc_type == RTE_PROC_SECONDARY) { uint64_t ticks, timeout_ms; struct rte_timer *tim; unsigned int i; mz = rte_memzone_lookup(TEST_INFO_MZ_NAME); TEST_ASSERT_NOT_NULL(mz, "Couldn't lookup memzone for " "test info"); test_info = mz->addr; for (i = 0; i < test_info->num_timers; i++) { ret = rte_mempool_get(test_info->tim_mempool, (void **)&tim); TEST_ASSERT_SUCCESS(ret, "Couldn't get timer from mempool"); rte_timer_init(tim); /* generate timeouts between 10 and 80 ms */ timeout_ms = ((rte_rand() & 0x7) + 1) * 10; ticks = timeout_ms * rte_get_timer_hz() / MSECPERSEC; ret = rte_timer_alt_reset(test_info->timer_data_id, tim, ticks, SINGLE, test_info->mgr_lcore, NULL, test_info); if (ret < 0) return TEST_FAILED; rte_atomic_fetch_add_explicit(&test_info->expected_count, 1, rte_memory_order_relaxed); /* randomly leave timer running or stop it */ if (rte_rand() & 1) continue; ret = rte_timer_alt_stop(test_info->timer_data_id, tim); if (ret == 0) { rte_atomic_fetch_sub_explicit(&test_info->expected_count, 1, rte_memory_order_relaxed); rte_mempool_put(test_info->tim_mempool, (void *)tim); } } return TEST_SUCCESS; } return TEST_FAILED; } #endif /* !RTE_EXEC_ENV_WINDOWS */ REGISTER_FAST_TEST(timer_secondary_autotest, NOHUGE_SKIP, ASAN_SKIP, test_timer_secondary);