1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2019 Intel Corporation
10 #include <rte_debug.h>
11 #include <rte_memzone.h>
12 #include <rte_atomic.h>
13 #include <rte_timer.h>
14 #include <rte_cycles.h>
15 #include <rte_mempool.h>
16 #include <rte_random.h>
21 #define NUM_TIMERS (1 << 20) /* ~1M timers */
22 #define NUM_LCORES_NEEDED 3
23 #define TEST_INFO_MZ_NAME "test_timer_info_mz"
24 #define MSECPERSEC 1E3
26 #define launch_proc(ARGV) \
27 process_dup(ARGV, sizeof(ARGV)/(sizeof(ARGV[0])), __func__)
30 unsigned int mstr_lcore;
31 unsigned int mgr_lcore;
32 unsigned int sec_lcore;
33 uint32_t timer_data_id;
34 volatile int expected_count;
35 volatile int expired_count;
36 struct rte_mempool *tim_mempool;
37 struct rte_timer *expired_timers[NUM_TIMERS];
38 int expired_timers_idx;
39 volatile int exit_flag;
43 timer_secondary_spawn_wait(unsigned int lcore)
46 #ifdef RTE_EXEC_ENV_LINUXAPP
47 char tmp[PATH_MAX] = {0};
48 char prefix[PATH_MAX] = {0};
50 get_current_prefix(tmp, sizeof(tmp));
52 snprintf(prefix, sizeof(prefix), "--file-prefix=%s", tmp);
54 const char *prefix = "";
56 char const *argv[] = {
59 "--proc-type=secondary",
63 snprintf(coremask, sizeof(coremask), "%x", (1 << lcore));
65 return launch_proc(argv);
69 handle_expired_timer(struct rte_timer *tim)
71 struct test_info *test_info = tim->arg;
73 test_info->expired_count++;
74 test_info->expired_timers[test_info->expired_timers_idx++] = tim;
78 timer_manage_loop(void *arg)
81 uint64_t tick_cycles = TICK_MSECS * rte_get_timer_hz() / MSECPERSEC;
82 uint64_t prev_tsc = 0, cur_tsc, diff_tsc;
83 struct test_info *test_info = arg;
85 while (!test_info->exit_flag) {
86 cur_tsc = rte_rdtsc();
87 diff_tsc = cur_tsc - prev_tsc;
89 if (diff_tsc > tick_cycles) {
90 /* Scan timer list for expired timers */
91 rte_timer_alt_manage(test_info->timer_data_id,
94 handle_expired_timer);
96 /* Return expired timer objects back to mempool */
97 rte_mempool_put_bulk(test_info->tim_mempool,
98 (void **)test_info->expired_timers,
99 test_info->expired_timers_idx);
101 test_info->expired_timers_idx = 0;
113 test_timer_secondary(void)
115 int proc_type = rte_eal_process_type();
116 const struct rte_memzone *mz;
117 struct test_info *test_info;
120 if (proc_type == RTE_PROC_PRIMARY) {
121 if (rte_lcore_count() < NUM_LCORES_NEEDED) {
122 printf("Not enough cores for test_timer_secondary, expecting at least %u\n",
127 mz = rte_memzone_reserve(TEST_INFO_MZ_NAME, sizeof(*test_info),
129 test_info = mz->addr;
130 TEST_ASSERT_NOT_NULL(test_info, "Couldn't allocate memory for "
133 test_info->tim_mempool = rte_mempool_create("test_timer_mp",
134 NUM_TIMERS, sizeof(struct rte_timer), 0, 0,
135 NULL, NULL, NULL, NULL, rte_socket_id(), 0);
137 ret = rte_timer_data_alloc(&test_info->timer_data_id);
138 TEST_ASSERT_SUCCESS(ret, "Failed to allocate timer data "
141 unsigned int *mstr_lcorep = &test_info->mstr_lcore;
142 unsigned int *mgr_lcorep = &test_info->mgr_lcore;
143 unsigned int *sec_lcorep = &test_info->sec_lcore;
145 *mstr_lcorep = rte_get_master_lcore();
146 *mgr_lcorep = rte_get_next_lcore(*mstr_lcorep, 1, 1);
147 *sec_lcorep = rte_get_next_lcore(*mgr_lcorep, 1, 1);
149 ret = rte_eal_remote_launch(timer_manage_loop,
152 TEST_ASSERT_SUCCESS(ret, "Failed to launch timer manage loop");
154 ret = timer_secondary_spawn_wait(*sec_lcorep);
155 TEST_ASSERT_SUCCESS(ret, "Secondary process execution failed");
159 test_info->exit_flag = 1;
160 rte_eal_wait_lcore(*mgr_lcorep);
162 #ifdef RTE_LIBRTE_TIMER_DEBUG
163 rte_timer_alt_dump_stats(test_info->timer_data_id, stdout);
166 return test_info->expected_count == test_info->expired_count ?
167 TEST_SUCCESS : TEST_FAILED;
169 } else if (proc_type == RTE_PROC_SECONDARY) {
170 uint64_t ticks, timeout_ms;
171 struct rte_timer *tim;
174 mz = rte_memzone_lookup(TEST_INFO_MZ_NAME);
175 test_info = mz->addr;
176 TEST_ASSERT_NOT_NULL(test_info, "Couldn't lookup memzone for "
179 for (i = 0; i < NUM_TIMERS; i++) {
180 rte_mempool_get(test_info->tim_mempool, (void **)&tim);
184 /* generate timeouts between 10 and 160 ms */
185 timeout_ms = ((rte_rand() & 0xF) + 1) * 10;
186 ticks = timeout_ms * rte_get_timer_hz() / MSECPERSEC;
188 ret = rte_timer_alt_reset(test_info->timer_data_id,
190 test_info->mgr_lcore, NULL,
195 test_info->expected_count++;
197 /* randomly leave timer running or stop it */
201 ret = rte_timer_alt_stop(test_info->timer_data_id,
204 test_info->expected_count--;
205 rte_mempool_put(test_info->tim_mempool,
217 REGISTER_TEST_COMMAND(timer_secondary_autotest, test_timer_secondary);