test/timer: exercise new APIs in secondary process
This commit adds an autotest which exercises new timer reset/stop APIs in a secondary process. Timers are created, and sometimes stopped, in the secondary process, and their expiration is checked for and handled in the primary process. Signed-off-by: Erik Gabriel Carrillo <erik.g.carrillo@intel.com>
This commit is contained in:
parent
18715a0b6f
commit
50247fe03f
@ -96,6 +96,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_STACK) += test_stack_perf.c
|
||||
SRCS-$(CONFIG_RTE_LIBRTE_TIMER) += test_timer.c
|
||||
SRCS-$(CONFIG_RTE_LIBRTE_TIMER) += test_timer_perf.c
|
||||
SRCS-$(CONFIG_RTE_LIBRTE_TIMER) += test_timer_racecond.c
|
||||
SRCS-$(CONFIG_RTE_LIBRTE_TIMER) += test_timer_secondary.c
|
||||
|
||||
SRCS-y += test_mempool.c
|
||||
SRCS-y += test_mempool_perf.c
|
||||
|
@ -109,6 +109,7 @@ test_sources = files('commands.c',
|
||||
'test_timer.c',
|
||||
'test_timer_perf.c',
|
||||
'test_timer_racecond.c',
|
||||
'test_timer_secondary.c',
|
||||
'test_ticketlock.c',
|
||||
'test_version.c',
|
||||
'virtual_pmd.c'
|
||||
|
@ -67,6 +67,7 @@ do_recursive_call(void)
|
||||
{ "test_memory_flags", no_action },
|
||||
{ "test_file_prefix", no_action },
|
||||
{ "test_no_huge_flag", no_action },
|
||||
{ "timer_secondary_spawn_wait", test_timer_secondary },
|
||||
};
|
||||
|
||||
if (recursive_call == NULL)
|
||||
@ -130,7 +131,10 @@ main(int argc, char **argv)
|
||||
}
|
||||
|
||||
#ifdef RTE_LIBRTE_TIMER
|
||||
rte_timer_subsystem_init();
|
||||
if (rte_timer_subsystem_init() < 0) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (commands_init() < 0) {
|
||||
|
@ -156,6 +156,7 @@ extern const char *prgname;
|
||||
int commands_init(void);
|
||||
|
||||
int test_mp_secondary(void);
|
||||
int test_timer_secondary(void);
|
||||
|
||||
int test_set_rxtx_conf(cmdline_fixed_string_t mode);
|
||||
int test_set_rxtx_anchor(cmdline_fixed_string_t type);
|
||||
|
215
app/test/test_timer_secondary.c
Normal file
215
app/test/test_timer_secondary.c
Normal file
@ -0,0 +1,215 @@
|
||||
/* 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_atomic.h>
|
||||
#include <rte_timer.h>
|
||||
#include <rte_cycles.h>
|
||||
#include <rte_mempool.h>
|
||||
#include <rte_random.h>
|
||||
|
||||
#include "test.h"
|
||||
#include "process.h"
|
||||
|
||||
#define NUM_TIMERS (1 << 20) /* ~1M timers */
|
||||
#define NUM_LCORES_NEEDED 3
|
||||
#define TEST_INFO_MZ_NAME "test_timer_info_mz"
|
||||
#define MSECPERSEC 1E3
|
||||
|
||||
#define launch_proc(ARGV) \
|
||||
process_dup(ARGV, sizeof(ARGV)/(sizeof(ARGV[0])), __func__)
|
||||
|
||||
struct test_info {
|
||||
unsigned int mstr_lcore;
|
||||
unsigned int mgr_lcore;
|
||||
unsigned int sec_lcore;
|
||||
uint32_t timer_data_id;
|
||||
volatile int expected_count;
|
||||
volatile int expired_count;
|
||||
struct rte_mempool *tim_mempool;
|
||||
struct rte_timer *expired_timers[NUM_TIMERS];
|
||||
int expired_timers_idx;
|
||||
volatile int exit_flag;
|
||||
};
|
||||
|
||||
static int
|
||||
timer_secondary_spawn_wait(unsigned int lcore)
|
||||
{
|
||||
char coremask[10];
|
||||
#ifdef RTE_EXEC_ENV_LINUXAPP
|
||||
char tmp[PATH_MAX] = {0};
|
||||
char prefix[PATH_MAX] = {0};
|
||||
|
||||
get_current_prefix(tmp, sizeof(tmp));
|
||||
|
||||
snprintf(prefix, sizeof(prefix), "--file-prefix=%s", tmp);
|
||||
#else
|
||||
const char *prefix = "";
|
||||
#endif
|
||||
char const *argv[] = {
|
||||
prgname,
|
||||
"-c", coremask,
|
||||
"--proc-type=secondary",
|
||||
prefix
|
||||
};
|
||||
|
||||
snprintf(coremask, sizeof(coremask), "%x", (1 << lcore));
|
||||
|
||||
return launch_proc(argv);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_expired_timer(struct rte_timer *tim)
|
||||
{
|
||||
struct test_info *test_info = tim->arg;
|
||||
|
||||
test_info->expired_count++;
|
||||
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 (!test_info->exit_flag) {
|
||||
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) {
|
||||
mz = rte_memzone_reserve(TEST_INFO_MZ_NAME, sizeof(*test_info),
|
||||
SOCKET_ID_ANY, 0);
|
||||
test_info = mz->addr;
|
||||
TEST_ASSERT_NOT_NULL(test_info, "Couldn't allocate memory for "
|
||||
"test data");
|
||||
|
||||
TEST_ASSERT(rte_lcore_count() >= NUM_LCORES_NEEDED,
|
||||
"at least %d lcores needed to run tests",
|
||||
NUM_LCORES_NEEDED);
|
||||
|
||||
test_info->tim_mempool = rte_mempool_create("test_timer_mp",
|
||||
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 *mstr_lcorep = &test_info->mstr_lcore;
|
||||
unsigned int *mgr_lcorep = &test_info->mgr_lcore;
|
||||
unsigned int *sec_lcorep = &test_info->sec_lcore;
|
||||
|
||||
*mstr_lcorep = rte_get_master_lcore();
|
||||
*mgr_lcorep = rte_get_next_lcore(*mstr_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);
|
||||
TEST_ASSERT_SUCCESS(ret, "Secondary process execution failed");
|
||||
|
||||
rte_delay_ms(2000);
|
||||
|
||||
test_info->exit_flag = 1;
|
||||
rte_eal_wait_lcore(*mgr_lcorep);
|
||||
|
||||
#ifdef RTE_LIBRTE_TIMER_DEBUG
|
||||
rte_timer_alt_dump_stats(test_info->timer_data_id, stdout);
|
||||
#endif
|
||||
|
||||
return test_info->expected_count == test_info->expired_count ?
|
||||
TEST_SUCCESS : TEST_FAILED;
|
||||
|
||||
} else if (proc_type == RTE_PROC_SECONDARY) {
|
||||
uint64_t ticks, timeout_ms;
|
||||
struct rte_timer *tim;
|
||||
int i;
|
||||
|
||||
mz = rte_memzone_lookup(TEST_INFO_MZ_NAME);
|
||||
test_info = mz->addr;
|
||||
TEST_ASSERT_NOT_NULL(test_info, "Couldn't lookup memzone for "
|
||||
"test info");
|
||||
|
||||
for (i = 0; i < NUM_TIMERS; i++) {
|
||||
rte_mempool_get(test_info->tim_mempool, (void **)&tim);
|
||||
|
||||
rte_timer_init(tim);
|
||||
|
||||
/* generate timeouts between 10 and 160 ms */
|
||||
timeout_ms = ((rte_rand() & 0xF) + 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;
|
||||
|
||||
test_info->expected_count++;
|
||||
|
||||
/* 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) {
|
||||
test_info->expected_count--;
|
||||
rte_mempool_put(test_info->tim_mempool,
|
||||
(void *)tim);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return TEST_SUCCESS;
|
||||
}
|
||||
|
||||
return TEST_FAILED;
|
||||
}
|
||||
|
||||
REGISTER_TEST_COMMAND(timer_secondary_autotest, test_timer_secondary);
|
@ -582,11 +582,6 @@ rte_timer_alt_reset(uint32_t timer_data_id, struct rte_timer *tim,
|
||||
|
||||
TIMER_DATA_VALID_GET_OR_ERR_RET(timer_data_id, timer_data, -EINVAL);
|
||||
|
||||
if (unlikely((tim_lcore != (unsigned int)LCORE_ID_ANY) &&
|
||||
!(rte_lcore_is_enabled(tim_lcore) ||
|
||||
rte_lcore_has_role(tim_lcore, ROLE_SERVICE))))
|
||||
return -1;
|
||||
|
||||
if (type == PERIODICAL)
|
||||
period = ticks;
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user