xref: /dpdk/app/test/test_timer_secondary.c (revision 3c60274c0995a7a74c5550d2f5bbcfbd9d548515)
150247fe0SErik Gabriel Carrillo /* SPDX-License-Identifier: BSD-3-Clause
250247fe0SErik Gabriel Carrillo  * Copyright(c) 2019 Intel Corporation
350247fe0SErik Gabriel Carrillo  */
450247fe0SErik Gabriel Carrillo 
550247fe0SErik Gabriel Carrillo #include <stdio.h>
650247fe0SErik Gabriel Carrillo #include <string.h>
750247fe0SErik Gabriel Carrillo 
850247fe0SErik Gabriel Carrillo #include <rte_eal.h>
950247fe0SErik Gabriel Carrillo #include <rte_lcore.h>
1050247fe0SErik Gabriel Carrillo #include <rte_debug.h>
1150247fe0SErik Gabriel Carrillo #include <rte_memzone.h>
1250247fe0SErik Gabriel Carrillo #include <rte_timer.h>
1350247fe0SErik Gabriel Carrillo #include <rte_cycles.h>
1450247fe0SErik Gabriel Carrillo #include <rte_mempool.h>
1550247fe0SErik Gabriel Carrillo #include <rte_random.h>
1650247fe0SErik Gabriel Carrillo 
1750247fe0SErik Gabriel Carrillo #include "test.h"
18*3c60274cSJie Zhou 
19*3c60274cSJie Zhou #ifdef RTE_EXEC_ENV_WINDOWS
20*3c60274cSJie Zhou int
test_timer_secondary(void)21*3c60274cSJie Zhou test_timer_secondary(void)
22*3c60274cSJie Zhou {
23*3c60274cSJie Zhou 	printf("timer_secondary not supported on Windows, skipping test\n");
24*3c60274cSJie Zhou 	return TEST_SKIPPED;
25*3c60274cSJie Zhou }
26*3c60274cSJie Zhou #else
27*3c60274cSJie Zhou 
2850247fe0SErik Gabriel Carrillo #include "process.h"
2950247fe0SErik Gabriel Carrillo 
3050247fe0SErik Gabriel Carrillo #define NUM_TIMERS		(1 << 20) /* ~1M timers */
3150247fe0SErik Gabriel Carrillo #define NUM_LCORES_NEEDED	3
3250247fe0SErik Gabriel Carrillo #define TEST_INFO_MZ_NAME	"test_timer_info_mz"
3350247fe0SErik Gabriel Carrillo #define MSECPERSEC		1E3
3450247fe0SErik Gabriel Carrillo 
3571bdd8a1SPavan Nikhilesh #define launch_proc(ARGV) process_dup(ARGV, RTE_DIM(ARGV), __func__)
3650247fe0SErik Gabriel Carrillo 
3750247fe0SErik Gabriel Carrillo struct test_info {
38cb056611SStephen Hemminger 	unsigned int main_lcore;
3950247fe0SErik Gabriel Carrillo 	unsigned int mgr_lcore;
4050247fe0SErik Gabriel Carrillo 	unsigned int sec_lcore;
4150247fe0SErik Gabriel Carrillo 	uint32_t timer_data_id;
4250247fe0SErik Gabriel Carrillo 	volatile int expected_count;
4350247fe0SErik Gabriel Carrillo 	volatile int expired_count;
4450247fe0SErik Gabriel Carrillo 	struct rte_mempool *tim_mempool;
4550247fe0SErik Gabriel Carrillo 	struct rte_timer *expired_timers[NUM_TIMERS];
4650247fe0SErik Gabriel Carrillo 	int expired_timers_idx;
4750247fe0SErik Gabriel Carrillo 	volatile int exit_flag;
4850247fe0SErik Gabriel Carrillo };
4950247fe0SErik Gabriel Carrillo 
5050247fe0SErik Gabriel Carrillo static int
timer_secondary_spawn_wait(unsigned int lcore)5150247fe0SErik Gabriel Carrillo timer_secondary_spawn_wait(unsigned int lcore)
5250247fe0SErik Gabriel Carrillo {
5350247fe0SErik Gabriel Carrillo 	char coremask[10];
5450247fe0SErik Gabriel Carrillo #ifdef RTE_EXEC_ENV_LINUXAPP
5550247fe0SErik Gabriel Carrillo 	char tmp[PATH_MAX] = {0};
5650247fe0SErik Gabriel Carrillo 	char prefix[PATH_MAX] = {0};
5750247fe0SErik Gabriel Carrillo 
5850247fe0SErik Gabriel Carrillo 	get_current_prefix(tmp, sizeof(tmp));
5950247fe0SErik Gabriel Carrillo 
6050247fe0SErik Gabriel Carrillo 	snprintf(prefix, sizeof(prefix), "--file-prefix=%s", tmp);
6150247fe0SErik Gabriel Carrillo #else
6250247fe0SErik Gabriel Carrillo 	const char *prefix = "";
6350247fe0SErik Gabriel Carrillo #endif
6450247fe0SErik Gabriel Carrillo 	char const *argv[] = {
6550247fe0SErik Gabriel Carrillo 		prgname,
6650247fe0SErik Gabriel Carrillo 		"-c", coremask,
6750247fe0SErik Gabriel Carrillo 		"--proc-type=secondary",
6850247fe0SErik Gabriel Carrillo 		prefix
6950247fe0SErik Gabriel Carrillo 	};
7050247fe0SErik Gabriel Carrillo 
7150247fe0SErik Gabriel Carrillo 	snprintf(coremask, sizeof(coremask), "%x", (1 << lcore));
7250247fe0SErik Gabriel Carrillo 
7350247fe0SErik Gabriel Carrillo 	return launch_proc(argv);
7450247fe0SErik Gabriel Carrillo }
7550247fe0SErik Gabriel Carrillo 
7650247fe0SErik Gabriel Carrillo static void
handle_expired_timer(struct rte_timer * tim)7750247fe0SErik Gabriel Carrillo handle_expired_timer(struct rte_timer *tim)
7850247fe0SErik Gabriel Carrillo {
7950247fe0SErik Gabriel Carrillo 	struct test_info *test_info = tim->arg;
8050247fe0SErik Gabriel Carrillo 
8150247fe0SErik Gabriel Carrillo 	test_info->expired_count++;
8250247fe0SErik Gabriel Carrillo 	test_info->expired_timers[test_info->expired_timers_idx++] = tim;
8350247fe0SErik Gabriel Carrillo }
8450247fe0SErik Gabriel Carrillo 
8550247fe0SErik Gabriel Carrillo static int
timer_manage_loop(void * arg)8650247fe0SErik Gabriel Carrillo timer_manage_loop(void *arg)
8750247fe0SErik Gabriel Carrillo {
8850247fe0SErik Gabriel Carrillo #define TICK_MSECS 1
8950247fe0SErik Gabriel Carrillo 	uint64_t tick_cycles = TICK_MSECS * rte_get_timer_hz() / MSECPERSEC;
9050247fe0SErik Gabriel Carrillo 	uint64_t prev_tsc = 0, cur_tsc, diff_tsc;
9150247fe0SErik Gabriel Carrillo 	struct test_info *test_info = arg;
9250247fe0SErik Gabriel Carrillo 
9350247fe0SErik Gabriel Carrillo 	while (!test_info->exit_flag) {
9450247fe0SErik Gabriel Carrillo 		cur_tsc = rte_rdtsc();
9550247fe0SErik Gabriel Carrillo 		diff_tsc = cur_tsc - prev_tsc;
9650247fe0SErik Gabriel Carrillo 
9750247fe0SErik Gabriel Carrillo 		if (diff_tsc > tick_cycles) {
9850247fe0SErik Gabriel Carrillo 			/* Scan timer list for expired timers */
9950247fe0SErik Gabriel Carrillo 			rte_timer_alt_manage(test_info->timer_data_id,
10050247fe0SErik Gabriel Carrillo 					     NULL,
10150247fe0SErik Gabriel Carrillo 					     0,
10250247fe0SErik Gabriel Carrillo 					     handle_expired_timer);
10350247fe0SErik Gabriel Carrillo 
10450247fe0SErik Gabriel Carrillo 			/* Return expired timer objects back to mempool */
10550247fe0SErik Gabriel Carrillo 			rte_mempool_put_bulk(test_info->tim_mempool,
10650247fe0SErik Gabriel Carrillo 					     (void **)test_info->expired_timers,
10750247fe0SErik Gabriel Carrillo 					     test_info->expired_timers_idx);
10850247fe0SErik Gabriel Carrillo 
10950247fe0SErik Gabriel Carrillo 			test_info->expired_timers_idx = 0;
11050247fe0SErik Gabriel Carrillo 
11150247fe0SErik Gabriel Carrillo 			prev_tsc = cur_tsc;
11250247fe0SErik Gabriel Carrillo 		}
11350247fe0SErik Gabriel Carrillo 
11450247fe0SErik Gabriel Carrillo 		rte_pause();
11550247fe0SErik Gabriel Carrillo 	}
11650247fe0SErik Gabriel Carrillo 
11750247fe0SErik Gabriel Carrillo 	return 0;
11850247fe0SErik Gabriel Carrillo }
11950247fe0SErik Gabriel Carrillo 
12050247fe0SErik Gabriel Carrillo int
test_timer_secondary(void)12150247fe0SErik Gabriel Carrillo test_timer_secondary(void)
12250247fe0SErik Gabriel Carrillo {
12350247fe0SErik Gabriel Carrillo 	int proc_type = rte_eal_process_type();
12450247fe0SErik Gabriel Carrillo 	const struct rte_memzone *mz;
12550247fe0SErik Gabriel Carrillo 	struct test_info *test_info;
12650247fe0SErik Gabriel Carrillo 	int ret;
12750247fe0SErik Gabriel Carrillo 
12850247fe0SErik Gabriel Carrillo 	if (proc_type == RTE_PROC_PRIMARY) {
129e0f4a0edSDavid Marchand 		if (rte_lcore_count() < NUM_LCORES_NEEDED) {
130e0f4a0edSDavid Marchand 			printf("Not enough cores for test_timer_secondary, expecting at least %u\n",
131e0f4a0edSDavid Marchand 			       NUM_LCORES_NEEDED);
132e0f4a0edSDavid Marchand 			return TEST_SKIPPED;
133e0f4a0edSDavid Marchand 		}
134e0f4a0edSDavid Marchand 
13550247fe0SErik Gabriel Carrillo 		mz = rte_memzone_reserve(TEST_INFO_MZ_NAME, sizeof(*test_info),
13650247fe0SErik Gabriel Carrillo 					 SOCKET_ID_ANY, 0);
137fb9b862eSMin Hu (Connor) 		TEST_ASSERT_NOT_NULL(mz, "Couldn't allocate memory for "
13850247fe0SErik Gabriel Carrillo 				     "test data");
139fb9b862eSMin Hu (Connor) 		test_info = mz->addr;
14050247fe0SErik Gabriel Carrillo 
14150247fe0SErik Gabriel Carrillo 		test_info->tim_mempool = rte_mempool_create("test_timer_mp",
14250247fe0SErik Gabriel Carrillo 				NUM_TIMERS, sizeof(struct rte_timer), 0, 0,
14350247fe0SErik Gabriel Carrillo 				NULL, NULL, NULL, NULL, rte_socket_id(), 0);
14450247fe0SErik Gabriel Carrillo 
14550247fe0SErik Gabriel Carrillo 		ret = rte_timer_data_alloc(&test_info->timer_data_id);
14650247fe0SErik Gabriel Carrillo 		TEST_ASSERT_SUCCESS(ret, "Failed to allocate timer data "
14750247fe0SErik Gabriel Carrillo 				    "instance");
14850247fe0SErik Gabriel Carrillo 
149cb056611SStephen Hemminger 		unsigned int *main_lcorep = &test_info->main_lcore;
15050247fe0SErik Gabriel Carrillo 		unsigned int *mgr_lcorep = &test_info->mgr_lcore;
15150247fe0SErik Gabriel Carrillo 		unsigned int *sec_lcorep = &test_info->sec_lcore;
15250247fe0SErik Gabriel Carrillo 
153cb056611SStephen Hemminger 		*main_lcorep = rte_get_main_lcore();
154cb056611SStephen Hemminger 		*mgr_lcorep = rte_get_next_lcore(*main_lcorep, 1, 1);
15550247fe0SErik Gabriel Carrillo 		*sec_lcorep = rte_get_next_lcore(*mgr_lcorep, 1, 1);
15650247fe0SErik Gabriel Carrillo 
15750247fe0SErik Gabriel Carrillo 		ret = rte_eal_remote_launch(timer_manage_loop,
15850247fe0SErik Gabriel Carrillo 					    (void *)test_info,
15950247fe0SErik Gabriel Carrillo 					    *mgr_lcorep);
16050247fe0SErik Gabriel Carrillo 		TEST_ASSERT_SUCCESS(ret, "Failed to launch timer manage loop");
16150247fe0SErik Gabriel Carrillo 
16250247fe0SErik Gabriel Carrillo 		ret = timer_secondary_spawn_wait(*sec_lcorep);
16350247fe0SErik Gabriel Carrillo 		TEST_ASSERT_SUCCESS(ret, "Secondary process execution failed");
16450247fe0SErik Gabriel Carrillo 
16550247fe0SErik Gabriel Carrillo 		rte_delay_ms(2000);
16650247fe0SErik Gabriel Carrillo 
16750247fe0SErik Gabriel Carrillo 		test_info->exit_flag = 1;
16850247fe0SErik Gabriel Carrillo 		rte_eal_wait_lcore(*mgr_lcorep);
16950247fe0SErik Gabriel Carrillo 
17050247fe0SErik Gabriel Carrillo #ifdef RTE_LIBRTE_TIMER_DEBUG
17150247fe0SErik Gabriel Carrillo 		rte_timer_alt_dump_stats(test_info->timer_data_id, stdout);
17250247fe0SErik Gabriel Carrillo #endif
17350247fe0SErik Gabriel Carrillo 
17450247fe0SErik Gabriel Carrillo 		return test_info->expected_count == test_info->expired_count ?
17550247fe0SErik Gabriel Carrillo 			TEST_SUCCESS : TEST_FAILED;
17650247fe0SErik Gabriel Carrillo 
17750247fe0SErik Gabriel Carrillo 	} else if (proc_type == RTE_PROC_SECONDARY) {
17850247fe0SErik Gabriel Carrillo 		uint64_t ticks, timeout_ms;
17950247fe0SErik Gabriel Carrillo 		struct rte_timer *tim;
18050247fe0SErik Gabriel Carrillo 		int i;
18150247fe0SErik Gabriel Carrillo 
18250247fe0SErik Gabriel Carrillo 		mz = rte_memzone_lookup(TEST_INFO_MZ_NAME);
183fb9b862eSMin Hu (Connor) 		TEST_ASSERT_NOT_NULL(mz, "Couldn't lookup memzone for "
18450247fe0SErik Gabriel Carrillo 				     "test info");
185fb9b862eSMin Hu (Connor) 		test_info = mz->addr;
18650247fe0SErik Gabriel Carrillo 
18750247fe0SErik Gabriel Carrillo 		for (i = 0; i < NUM_TIMERS; i++) {
18850247fe0SErik Gabriel Carrillo 			rte_mempool_get(test_info->tim_mempool, (void **)&tim);
18950247fe0SErik Gabriel Carrillo 
19050247fe0SErik Gabriel Carrillo 			rte_timer_init(tim);
19150247fe0SErik Gabriel Carrillo 
19250247fe0SErik Gabriel Carrillo 			/* generate timeouts between 10 and 160 ms */
19350247fe0SErik Gabriel Carrillo 			timeout_ms = ((rte_rand() & 0xF) + 1) * 10;
19450247fe0SErik Gabriel Carrillo 			ticks = timeout_ms * rte_get_timer_hz() / MSECPERSEC;
19550247fe0SErik Gabriel Carrillo 
19650247fe0SErik Gabriel Carrillo 			ret = rte_timer_alt_reset(test_info->timer_data_id,
19750247fe0SErik Gabriel Carrillo 						  tim, ticks, SINGLE,
19850247fe0SErik Gabriel Carrillo 						  test_info->mgr_lcore, NULL,
19950247fe0SErik Gabriel Carrillo 						  test_info);
20050247fe0SErik Gabriel Carrillo 			if (ret < 0)
20150247fe0SErik Gabriel Carrillo 				return TEST_FAILED;
20250247fe0SErik Gabriel Carrillo 
20350247fe0SErik Gabriel Carrillo 			test_info->expected_count++;
20450247fe0SErik Gabriel Carrillo 
20550247fe0SErik Gabriel Carrillo 			/* randomly leave timer running or stop it */
20650247fe0SErik Gabriel Carrillo 			if (rte_rand() & 1)
20750247fe0SErik Gabriel Carrillo 				continue;
20850247fe0SErik Gabriel Carrillo 
20950247fe0SErik Gabriel Carrillo 			ret = rte_timer_alt_stop(test_info->timer_data_id,
21050247fe0SErik Gabriel Carrillo 						 tim);
21150247fe0SErik Gabriel Carrillo 			if (ret == 0) {
21250247fe0SErik Gabriel Carrillo 				test_info->expected_count--;
21350247fe0SErik Gabriel Carrillo 				rte_mempool_put(test_info->tim_mempool,
21450247fe0SErik Gabriel Carrillo 						(void *)tim);
21550247fe0SErik Gabriel Carrillo 			}
21650247fe0SErik Gabriel Carrillo 
21750247fe0SErik Gabriel Carrillo 		}
21850247fe0SErik Gabriel Carrillo 
21950247fe0SErik Gabriel Carrillo 		return TEST_SUCCESS;
22050247fe0SErik Gabriel Carrillo 	}
22150247fe0SErik Gabriel Carrillo 
22250247fe0SErik Gabriel Carrillo 	return TEST_FAILED;
22350247fe0SErik Gabriel Carrillo }
22450247fe0SErik Gabriel Carrillo 
225*3c60274cSJie Zhou #endif /* !RTE_EXEC_ENV_WINDOWS */
226*3c60274cSJie Zhou 
22750247fe0SErik Gabriel Carrillo REGISTER_TEST_COMMAND(timer_secondary_autotest, test_timer_secondary);
228