Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2019 Intel Corporation
3 : : */
4 : :
5 : : #include <stdio.h>
6 : : #include <string.h>
7 : :
8 : : #include <rte_eal.h>
9 : : #include <rte_lcore.h>
10 : : #include <rte_debug.h>
11 : : #include <rte_memzone.h>
12 : : #include <rte_timer.h>
13 : : #include <rte_cycles.h>
14 : : #include <rte_mempool.h>
15 : : #include <rte_random.h>
16 : :
17 : : #include "test.h"
18 : :
19 : : #ifdef RTE_EXEC_ENV_WINDOWS
20 : : int
21 : : test_timer_secondary(void)
22 : : {
23 : : printf("timer_secondary not supported on Windows, skipping test\n");
24 : : return TEST_SKIPPED;
25 : : }
26 : : #else
27 : :
28 : : #include "process.h"
29 : :
30 : : #define NUM_TIMERS (1 << 20) /* ~1M timers */
31 : : #define NUM_LCORES_NEEDED 3
32 : : #define TEST_INFO_MZ_NAME "test_timer_info_mz"
33 : : #define MSECPERSEC 1E3
34 : :
35 : : #define launch_proc(ARGV) process_dup(ARGV, RTE_DIM(ARGV), __func__)
36 : :
37 : : struct test_info {
38 : : unsigned int main_lcore;
39 : : unsigned int mgr_lcore;
40 : : unsigned int sec_lcore;
41 : : uint32_t timer_data_id;
42 : : volatile int expected_count;
43 : : volatile int expired_count;
44 : : struct rte_mempool *tim_mempool;
45 : : struct rte_timer *expired_timers[NUM_TIMERS];
46 : : int expired_timers_idx;
47 : : volatile int exit_flag;
48 : : };
49 : :
50 : : static int
51 : 0 : timer_secondary_spawn_wait(unsigned int lcore)
52 : : {
53 : : char coremask[10];
54 : : #ifdef RTE_EXEC_ENV_LINUXAPP
55 : 0 : char tmp[PATH_MAX] = {0};
56 : 0 : char prefix[PATH_MAX] = {0};
57 : :
58 : 0 : get_current_prefix(tmp, sizeof(tmp));
59 : :
60 : : snprintf(prefix, sizeof(prefix), "--file-prefix=%s", tmp);
61 : : #else
62 : : const char *prefix = "";
63 : : #endif
64 : 0 : char const *argv[] = {
65 : : prgname,
66 : : "-c", coremask,
67 : : "--proc-type=secondary",
68 : : prefix
69 : : };
70 : :
71 : 0 : snprintf(coremask, sizeof(coremask), "%x", (1 << lcore));
72 : :
73 : 0 : return launch_proc(argv);
74 : : }
75 : :
76 : : static void
77 : 0 : handle_expired_timer(struct rte_timer *tim)
78 : : {
79 : 0 : struct test_info *test_info = tim->arg;
80 : :
81 : 0 : test_info->expired_count++;
82 : 0 : test_info->expired_timers[test_info->expired_timers_idx++] = tim;
83 : 0 : }
84 : :
85 : : static int
86 : 0 : timer_manage_loop(void *arg)
87 : : {
88 : : #define TICK_MSECS 1
89 : 0 : uint64_t tick_cycles = TICK_MSECS * rte_get_timer_hz() / MSECPERSEC;
90 : : uint64_t prev_tsc = 0, cur_tsc, diff_tsc;
91 : : struct test_info *test_info = arg;
92 : :
93 [ # # ]: 0 : while (!test_info->exit_flag) {
94 : : cur_tsc = rte_rdtsc();
95 : 0 : diff_tsc = cur_tsc - prev_tsc;
96 : :
97 [ # # ]: 0 : if (diff_tsc > tick_cycles) {
98 : : /* Scan timer list for expired timers */
99 : 0 : rte_timer_alt_manage(test_info->timer_data_id,
100 : : NULL,
101 : : 0,
102 : : handle_expired_timer);
103 : :
104 : : /* Return expired timer objects back to mempool */
105 : 0 : rte_mempool_put_bulk(test_info->tim_mempool,
106 : 0 : (void **)test_info->expired_timers,
107 [ # # ]: 0 : test_info->expired_timers_idx);
108 : :
109 : 0 : test_info->expired_timers_idx = 0;
110 : :
111 : : prev_tsc = cur_tsc;
112 : : }
113 : :
114 : : rte_pause();
115 : : }
116 : :
117 : 0 : return 0;
118 : : }
119 : :
120 : : int
121 : 0 : test_timer_secondary(void)
122 : : {
123 : 0 : int proc_type = rte_eal_process_type();
124 : : const struct rte_memzone *mz;
125 : : struct test_info *test_info;
126 : : int ret;
127 : :
128 [ # # ]: 0 : if (proc_type == RTE_PROC_PRIMARY) {
129 [ # # ]: 0 : if (rte_lcore_count() < NUM_LCORES_NEEDED) {
130 : : printf("Not enough cores for test_timer_secondary, expecting at least %u\n",
131 : : NUM_LCORES_NEEDED);
132 : 0 : return TEST_SKIPPED;
133 : : }
134 : :
135 : 0 : mz = rte_memzone_reserve(TEST_INFO_MZ_NAME, sizeof(*test_info),
136 : : SOCKET_ID_ANY, 0);
137 [ # # ]: 0 : TEST_ASSERT_NOT_NULL(mz, "Couldn't allocate memory for "
138 : : "test data");
139 : 0 : test_info = mz->addr;
140 : :
141 : 0 : test_info->tim_mempool = rte_mempool_create("test_timer_mp",
142 : : NUM_TIMERS, sizeof(struct rte_timer), 0, 0,
143 : 0 : NULL, NULL, NULL, NULL, rte_socket_id(), 0);
144 : :
145 : 0 : ret = rte_timer_data_alloc(&test_info->timer_data_id);
146 [ # # ]: 0 : TEST_ASSERT_SUCCESS(ret, "Failed to allocate timer data "
147 : : "instance");
148 : :
149 : : unsigned int *main_lcorep = &test_info->main_lcore;
150 : : unsigned int *mgr_lcorep = &test_info->mgr_lcore;
151 : : unsigned int *sec_lcorep = &test_info->sec_lcore;
152 : :
153 : 0 : *main_lcorep = rte_get_main_lcore();
154 : 0 : *mgr_lcorep = rte_get_next_lcore(*main_lcorep, 1, 1);
155 : 0 : *sec_lcorep = rte_get_next_lcore(*mgr_lcorep, 1, 1);
156 : :
157 : 0 : ret = rte_eal_remote_launch(timer_manage_loop,
158 : : (void *)test_info,
159 : : *mgr_lcorep);
160 [ # # ]: 0 : TEST_ASSERT_SUCCESS(ret, "Failed to launch timer manage loop");
161 : :
162 : 0 : ret = timer_secondary_spawn_wait(*sec_lcorep);
163 [ # # ]: 0 : TEST_ASSERT_SUCCESS(ret, "Secondary process execution failed");
164 : :
165 : : rte_delay_ms(2000);
166 : :
167 : 0 : test_info->exit_flag = 1;
168 : 0 : rte_eal_wait_lcore(*mgr_lcorep);
169 : :
170 : : #ifdef RTE_LIBRTE_TIMER_DEBUG
171 : : rte_timer_alt_dump_stats(test_info->timer_data_id, stdout);
172 : : #endif
173 : :
174 : 0 : return test_info->expected_count == test_info->expired_count ?
175 [ # # ]: 0 : TEST_SUCCESS : TEST_FAILED;
176 : :
177 [ # # ]: 0 : } else if (proc_type == RTE_PROC_SECONDARY) {
178 : : uint64_t ticks, timeout_ms;
179 : : struct rte_timer *tim;
180 : : int i;
181 : :
182 : 0 : mz = rte_memzone_lookup(TEST_INFO_MZ_NAME);
183 [ # # ]: 0 : TEST_ASSERT_NOT_NULL(mz, "Couldn't lookup memzone for "
184 : : "test info");
185 : 0 : test_info = mz->addr;
186 : :
187 [ # # ]: 0 : for (i = 0; i < NUM_TIMERS; i++) {
188 [ # # ]: 0 : rte_mempool_get(test_info->tim_mempool, (void **)&tim);
189 : :
190 : 0 : rte_timer_init(tim);
191 : :
192 : : /* generate timeouts between 10 and 160 ms */
193 : 0 : timeout_ms = ((rte_rand() & 0xF) + 1) * 10;
194 : 0 : ticks = timeout_ms * rte_get_timer_hz() / MSECPERSEC;
195 : :
196 : 0 : ret = rte_timer_alt_reset(test_info->timer_data_id,
197 : : tim, ticks, SINGLE,
198 : : test_info->mgr_lcore, NULL,
199 : : test_info);
200 [ # # ]: 0 : if (ret < 0)
201 : : return TEST_FAILED;
202 : :
203 : 0 : test_info->expected_count++;
204 : :
205 : : /* randomly leave timer running or stop it */
206 [ # # ]: 0 : if (rte_rand() & 1)
207 : 0 : continue;
208 : :
209 : 0 : ret = rte_timer_alt_stop(test_info->timer_data_id,
210 : : tim);
211 [ # # ]: 0 : if (ret == 0) {
212 : 0 : test_info->expected_count--;
213 [ # # ]: 0 : rte_mempool_put(test_info->tim_mempool,
214 : : (void *)tim);
215 : : }
216 : :
217 : : }
218 : :
219 : : return TEST_SUCCESS;
220 : : }
221 : :
222 : : return TEST_FAILED;
223 : : }
224 : :
225 : : #endif /* !RTE_EXEC_ENV_WINDOWS */
226 : :
227 : 252 : REGISTER_TEST_COMMAND(timer_secondary_autotest, test_timer_secondary);
|