test/event: add asymmetric cases for crypto adapter
[dpdk.git] / app / test / test_timer_secondary.c
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 timer_secondary_spawn_wait(unsigned int lcore)
52 {
53         char coremask[10];
54 #ifdef RTE_EXEC_ENV_LINUXAPP
55         char tmp[PATH_MAX] = {0};
56         char prefix[PATH_MAX] = {0};
57
58         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         char const *argv[] = {
65                 prgname,
66                 "-c", coremask,
67                 "--proc-type=secondary",
68                 prefix
69         };
70
71         snprintf(coremask, sizeof(coremask), "%x", (1 << lcore));
72
73         return launch_proc(argv);
74 }
75
76 static void
77 handle_expired_timer(struct rte_timer *tim)
78 {
79         struct test_info *test_info = tim->arg;
80
81         test_info->expired_count++;
82         test_info->expired_timers[test_info->expired_timers_idx++] = tim;
83 }
84
85 static int
86 timer_manage_loop(void *arg)
87 {
88 #define TICK_MSECS 1
89         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         while (!test_info->exit_flag) {
94                 cur_tsc = rte_rdtsc();
95                 diff_tsc = cur_tsc - prev_tsc;
96
97                 if (diff_tsc > tick_cycles) {
98                         /* Scan timer list for expired timers */
99                         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                         rte_mempool_put_bulk(test_info->tim_mempool,
106                                              (void **)test_info->expired_timers,
107                                              test_info->expired_timers_idx);
108
109                         test_info->expired_timers_idx = 0;
110
111                         prev_tsc = cur_tsc;
112                 }
113
114                 rte_pause();
115         }
116
117         return 0;
118 }
119
120 int
121 test_timer_secondary(void)
122 {
123         int proc_type = rte_eal_process_type();
124         const struct rte_memzone *mz;
125         struct test_info *test_info;
126         int ret;
127
128         if (proc_type == RTE_PROC_PRIMARY) {
129                 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                         return TEST_SKIPPED;
133                 }
134
135                 mz = rte_memzone_reserve(TEST_INFO_MZ_NAME, sizeof(*test_info),
136                                          SOCKET_ID_ANY, 0);
137                 TEST_ASSERT_NOT_NULL(mz, "Couldn't allocate memory for "
138                                      "test data");
139                 test_info = mz->addr;
140
141                 test_info->tim_mempool = rte_mempool_create("test_timer_mp",
142                                 NUM_TIMERS, sizeof(struct rte_timer), 0, 0,
143                                 NULL, NULL, NULL, NULL, rte_socket_id(), 0);
144
145                 ret = rte_timer_data_alloc(&test_info->timer_data_id);
146                 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                 *main_lcorep = rte_get_main_lcore();
154                 *mgr_lcorep = rte_get_next_lcore(*main_lcorep, 1, 1);
155                 *sec_lcorep = rte_get_next_lcore(*mgr_lcorep, 1, 1);
156
157                 ret = rte_eal_remote_launch(timer_manage_loop,
158                                             (void *)test_info,
159                                             *mgr_lcorep);
160                 TEST_ASSERT_SUCCESS(ret, "Failed to launch timer manage loop");
161
162                 ret = timer_secondary_spawn_wait(*sec_lcorep);
163                 TEST_ASSERT_SUCCESS(ret, "Secondary process execution failed");
164
165                 rte_delay_ms(2000);
166
167                 test_info->exit_flag = 1;
168                 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                 return test_info->expected_count == test_info->expired_count ?
175                         TEST_SUCCESS : TEST_FAILED;
176
177         } else if (proc_type == RTE_PROC_SECONDARY) {
178                 uint64_t ticks, timeout_ms;
179                 struct rte_timer *tim;
180                 int i;
181
182                 mz = rte_memzone_lookup(TEST_INFO_MZ_NAME);
183                 TEST_ASSERT_NOT_NULL(mz, "Couldn't lookup memzone for "
184                                      "test info");
185                 test_info = mz->addr;
186
187                 for (i = 0; i < NUM_TIMERS; i++) {
188                         rte_mempool_get(test_info->tim_mempool, (void **)&tim);
189
190                         rte_timer_init(tim);
191
192                         /* generate timeouts between 10 and 160 ms */
193                         timeout_ms = ((rte_rand() & 0xF) + 1) * 10;
194                         ticks = timeout_ms * rte_get_timer_hz() / MSECPERSEC;
195
196                         ret = rte_timer_alt_reset(test_info->timer_data_id,
197                                                   tim, ticks, SINGLE,
198                                                   test_info->mgr_lcore, NULL,
199                                                   test_info);
200                         if (ret < 0)
201                                 return TEST_FAILED;
202
203                         test_info->expected_count++;
204
205                         /* randomly leave timer running or stop it */
206                         if (rte_rand() & 1)
207                                 continue;
208
209                         ret = rte_timer_alt_stop(test_info->timer_data_id,
210                                                  tim);
211                         if (ret == 0) {
212                                 test_info->expected_count--;
213                                 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 REGISTER_TEST_COMMAND(timer_secondary_autotest, test_timer_secondary);