* Copyright(c) 2017-2018 Intel Corporation.
*/
-#include <rte_atomic.h>
+#include "test.h"
+
+#include <math.h>
+
#include <rte_common.h>
#include <rte_cycles.h>
#include <rte_debug.h>
#include <rte_eal.h>
#include <rte_ethdev.h>
+
+#ifdef RTE_EXEC_ENV_WINDOWS
+static int
+test_event_timer_adapter_func(void)
+{
+ printf("event_timer_adapter not supported on Windows, skipping test\n");
+ return TEST_SKIPPED;
+}
+
+#else
+
#include <rte_eventdev.h>
#include <rte_event_timer_adapter.h>
#include <rte_mempool.h>
#include <rte_service.h>
#include <stdbool.h>
-#include "test.h"
-
/* 4K timers corresponds to sw evdev max inflight events */
#define MAX_TIMERS (4 * 1024)
#define BKT_TCK_NSEC
static struct rte_mempool *eventdev_test_mempool;
static struct rte_ring *timer_producer_ring;
static uint64_t global_bkt_tck_ns;
+static uint64_t global_info_bkt_tck_ns;
static volatile uint8_t arm_done;
+#define CALC_TICKS(tks) \
+ ceil((double)(tks * global_bkt_tck_ns) / global_info_bkt_tck_ns)
+
+
static bool using_services;
static uint32_t test_lcore1;
static uint32_t test_lcore2;
ret = rte_event_dev_info_get(evdev, &info);
TEST_ASSERT_SUCCESS(ret, "Failed to get event dev info");
- TEST_ASSERT(info.max_num_events >= (int32_t)MAX_TIMERS,
+ TEST_ASSERT(info.max_num_events < 0 ||
+ info.max_num_events >= (int32_t)MAX_TIMERS,
"ERROR max_num_events=%d < max_events=%d",
info.max_num_events, MAX_TIMERS);
}
if (rte_lcore_count() < required_lcore_count) {
- printf("%d lcores needed to run tests", required_lcore_count);
- return TEST_FAILED;
+ printf("Not enough cores for event_timer_adapter_test, expecting at least %u\n",
+ required_lcore_count);
+ return TEST_SKIPPED;
}
/* Assign lcores for various tasks */
}
static int
-_timdev_setup(uint64_t max_tmo_ns, uint64_t bkt_tck_ns)
+_timdev_setup(uint64_t max_tmo_ns, uint64_t bkt_tck_ns, uint64_t flags)
{
+ struct rte_event_timer_adapter_info info;
struct rte_event_timer_adapter_conf config = {
.event_dev_id = evdev,
.timer_adapter_id = TEST_ADAPTER_ID,
.timer_tick_ns = bkt_tck_ns,
.max_tmo_ns = max_tmo_ns,
.nb_timers = MAX_TIMERS * 10,
+ .flags = flags,
};
uint32_t caps = 0;
const char *pool_name = "timdev_test_pool";
TEST_ASSERT_SUCCESS(rte_event_timer_adapter_caps_get(evdev, &caps),
"failed to get adapter capabilities");
+
+ if (flags & RTE_EVENT_TIMER_ADAPTER_F_PERIODIC &&
+ !(caps & RTE_EVENT_TIMER_ADAPTER_CAP_PERIODIC))
+ return -ENOTSUP;
+
if (!(caps & RTE_EVENT_TIMER_ADAPTER_CAP_INTERNAL_PORT)) {
timdev = rte_event_timer_adapter_create_ext(&config,
test_port_conf_cb,
return TEST_FAILED;
}
+ rte_event_timer_adapter_get_info(timdev, &info);
+
+ global_info_bkt_tck_ns = info.min_resolution_ns;
+
return TEST_SUCCESS;
}
static int
timdev_setup_usec(void)
{
+ uint64_t flags = RTE_EVENT_TIMER_ADAPTER_F_ADJUST_RES;
+
return using_services ?
/* Max timeout is 10,000us and bucket interval is 100us */
- _timdev_setup(1E7, 1E5) :
+ _timdev_setup(1E7, 1E5, flags) :
/* Max timeout is 100us and bucket interval is 1us */
- _timdev_setup(1E5, 1E3);
+ _timdev_setup(1E5, 1E3, flags);
}
static int
timdev_setup_usec_multicore(void)
{
+ uint64_t flags = RTE_EVENT_TIMER_ADAPTER_F_ADJUST_RES;
+
return using_services ?
/* Max timeout is 10,000us and bucket interval is 100us */
- _timdev_setup(1E7, 1E5) :
+ _timdev_setup(1E7, 1E5, flags) :
/* Max timeout is 100us and bucket interval is 1us */
- _timdev_setup(1E5, 1E3);
+ _timdev_setup(1E5, 1E3, flags);
}
static int
timdev_setup_msec(void)
{
- /* Max timeout is 2 mins, and bucket interval is 100 ms */
- return _timdev_setup(180 * NSECPERSEC, NSECPERSEC / 10);
+ uint64_t flags = RTE_EVENT_TIMER_ADAPTER_F_ADJUST_RES;
+
+ /* Max timeout is 3 mins, and bucket interval is 100 ms */
+ return _timdev_setup(180 * NSECPERSEC, NSECPERSEC / 10, flags);
+}
+
+static int
+timdev_setup_msec_periodic(void)
+{
+ uint64_t flags = RTE_EVENT_TIMER_ADAPTER_F_ADJUST_RES |
+ RTE_EVENT_TIMER_ADAPTER_F_PERIODIC;
+
+ /* Periodic mode with 100 ms resolution */
+ return _timdev_setup(0, NSECPERSEC / 10, flags);
}
static int
timdev_setup_sec(void)
{
+ uint64_t flags = RTE_EVENT_TIMER_ADAPTER_F_ADJUST_RES;
+
/* Max timeout is 100sec and bucket interval is 1sec */
- return _timdev_setup(1E11, 1E9);
+ return _timdev_setup(1E11, 1E9, flags);
+}
+
+static int
+timdev_setup_sec_periodic(void)
+{
+ uint64_t flags = RTE_EVENT_TIMER_ADAPTER_F_ADJUST_RES |
+ RTE_EVENT_TIMER_ADAPTER_F_PERIODIC;
+
+ /* Periodic mode with 1 sec resolution */
+ return _timdev_setup(0, NSECPERSEC, flags);
}
static int
timdev_setup_sec_multicore(void)
{
+ uint64_t flags = RTE_EVENT_TIMER_ADAPTER_F_ADJUST_RES;
+
/* Max timeout is 100sec and bucket interval is 1sec */
- return _timdev_setup(1E11, 1E9);
+ return _timdev_setup(1E11, 1E9, flags);
}
static void
.state = RTE_EVENT_TIMER_NOT_ARMED,
};
+
rte_mempool_get(eventdev_test_mempool, (void **)&ev_tim);
*ev_tim = tim;
ev_tim->ev.event_ptr = ev_tim;
- ev_tim->timeout_ticks = 120;
+ ev_tim->timeout_ticks = CALC_TICKS(120);
TEST_ASSERT_EQUAL(rte_event_timer_arm_burst(timdev, &ev_tim, 1), 0,
"Armed timer exceeding max_timeout.");
RTE_EVENT_TIMER_ERROR_TOOLATE, ev_tim->state);
ev_tim->state = RTE_EVENT_TIMER_NOT_ARMED;
- ev_tim->timeout_ticks = 10;
+ ev_tim->timeout_ticks = CALC_TICKS(10);
TEST_ASSERT_EQUAL(rte_event_timer_arm_burst(timdev, &ev_tim, 1), 1,
"Failed to arm timer with proper timeout.");
"Armed timer failed to trigger.");
ev_tim->state = RTE_EVENT_TIMER_NOT_ARMED;
- ev_tim->timeout_ticks = 90;
+ ev_tim->timeout_ticks = CALC_TICKS(90);
TEST_ASSERT_EQUAL(rte_event_timer_arm_burst(timdev, &ev_tim, 1), 1,
"Failed to arm timer with proper timeout.");
TEST_ASSERT_EQUAL(rte_event_timer_cancel_burst(timdev, &ev_tim, 1),
.ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
.ev.event_type = RTE_EVENT_TYPE_TIMER,
.state = RTE_EVENT_TIMER_NOT_ARMED,
- .timeout_ticks = timeout_tcks,
+ .timeout_ticks = CALC_TICKS(timeout_tcks),
};
for (i = 0; i < timers; i++) {
return TEST_SUCCESS;
}
+static inline int
+test_timer_arm_periodic(void)
+{
+ TEST_ASSERT_SUCCESS(_arm_timers(1, MAX_TIMERS),
+ "Failed to arm timers");
+ /* With a resolution of 100ms and wait time of 1sec,
+ * there will be 10 * MAX_TIMERS periodic timer triggers.
+ */
+ TEST_ASSERT_SUCCESS(_wait_timer_triggers(1, 10 * MAX_TIMERS, 0),
+ "Timer triggered count doesn't match arm count");
+ return TEST_SUCCESS;
+}
+
static int
_arm_wrapper(void *arg)
{
.ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
.ev.event_type = RTE_EVENT_TYPE_TIMER,
.state = RTE_EVENT_TIMER_NOT_ARMED,
- .timeout_ticks = timeout_tcks,
+ .timeout_ticks = CALC_TICKS(timeout_tcks),
};
for (i = 0; i < timers / MAX_BURST; i++) {
return TEST_SUCCESS;
}
+static inline int
+test_timer_arm_burst_periodic(void)
+{
+ TEST_ASSERT_SUCCESS(_arm_timers_burst(1, MAX_TIMERS),
+ "Failed to arm timers");
+ /* With a resolution of 100ms and wait time of 1sec,
+ * there will be 10 * MAX_TIMERS periodic timer triggers.
+ */
+ TEST_ASSERT_SUCCESS(_wait_timer_triggers(1, 10 * MAX_TIMERS, 0),
+ "Timer triggered count doesn't match arm count");
+
+ return TEST_SUCCESS;
+}
+
static int
_arm_wrapper_burst(void *arg)
{
return TEST_SUCCESS;
}
+static inline int
+test_timer_cancel_periodic(void)
+{
+ uint64_t i;
+ struct rte_event_timer *ev_tim;
+ const struct rte_event_timer tim = {
+ .ev.op = RTE_EVENT_OP_NEW,
+ .ev.queue_id = 0,
+ .ev.sched_type = RTE_SCHED_TYPE_ATOMIC,
+ .ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
+ .ev.event_type = RTE_EVENT_TYPE_TIMER,
+ .state = RTE_EVENT_TIMER_NOT_ARMED,
+ .timeout_ticks = CALC_TICKS(1),
+ };
+
+ for (i = 0; i < MAX_TIMERS; i++) {
+ TEST_ASSERT_SUCCESS(rte_mempool_get(eventdev_test_mempool,
+ (void **)&ev_tim),
+ "mempool alloc failed");
+ *ev_tim = tim;
+ ev_tim->ev.event_ptr = ev_tim;
+
+ TEST_ASSERT_EQUAL(rte_event_timer_arm_burst(timdev, &ev_tim,
+ 1), 1, "Failed to arm timer %d",
+ rte_errno);
+
+ rte_delay_us(100 + (i % 5000));
+
+ TEST_ASSERT_EQUAL(rte_event_timer_cancel_burst(timdev,
+ &ev_tim, 1), 1,
+ "Failed to cancel event timer %d", rte_errno);
+ rte_mempool_put(eventdev_test_mempool, ev_tim);
+ }
+
+
+ TEST_ASSERT_SUCCESS(_wait_timer_triggers(30, MAX_TIMERS,
+ MAX_TIMERS),
+ "Timer triggered count doesn't match arm, cancel count");
+
+ return TEST_SUCCESS;
+}
+
static inline int
test_timer_cancel(void)
{
.ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
.ev.event_type = RTE_EVENT_TYPE_TIMER,
.state = RTE_EVENT_TIMER_NOT_ARMED,
- .timeout_ticks = 20,
+ .timeout_ticks = CALC_TICKS(20),
};
for (i = 0; i < MAX_TIMERS; i++) {
.ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
.ev.event_type = RTE_EVENT_TYPE_TIMER,
.state = RTE_EVENT_TIMER_NOT_ARMED,
- .timeout_ticks = timeout_tcks,
+ .timeout_ticks = CALC_TICKS(timeout_tcks),
};
for (i = 0; i < timers; i++) {
.ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
.ev.event_type = RTE_EVENT_TYPE_TIMER,
.state = RTE_EVENT_TIMER_NOT_ARMED,
- .timeout_ticks = timeout_tcks,
+ .timeout_ticks = CALC_TICKS(timeout_tcks),
};
int arm_count = 0;
.ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
.ev.event_type = RTE_EVENT_TYPE_TIMER,
.state = RTE_EVENT_TIMER_NOT_ARMED,
- .timeout_ticks = 20,
+ .timeout_ticks = CALC_TICKS(20),
};
for (i = 0; i < MAX_TIMERS; i++) {
.timer_tick_ns = NSECPERSEC / 10,
.max_tmo_ns = 180 * NSECPERSEC,
.nb_timers = MAX_TIMERS,
- .flags = 0,
+ .flags = RTE_EVENT_TIMER_ADAPTER_F_ADJUST_RES,
};
uint32_t caps = 0;
TEST_ASSERT_SUCCESS(rte_event_timer_adapter_free(adapter),
"Failed to free adapter");
- rte_mempool_free(eventdev_test_mempool);
-
return TEST_SUCCESS;
}
static int
adapter_start(void)
{
- TEST_ASSERT_SUCCESS(_timdev_setup(180 * NSECPERSEC,
- NSECPERSEC / 10),
- "Failed to start adapter");
- TEST_ASSERT_SUCCESS(rte_event_timer_adapter_start(timdev),
- "Failed to repeatedly start adapter");
+ TEST_ASSERT_SUCCESS(_timdev_setup(180 * NSECPERSEC, NSECPERSEC / 10,
+ RTE_EVENT_TIMER_ADAPTER_F_ADJUST_RES),
+ "Failed to start adapter");
+ TEST_ASSERT_EQUAL(rte_event_timer_adapter_start(timdev), -EALREADY,
+ "Timer adapter started without call to stop.");
return TEST_SUCCESS;
}
.ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
.ev.event_type = RTE_EVENT_TYPE_TIMER,
.state = RTE_EVENT_TIMER_NOT_ARMED,
- .timeout_ticks = 5, // expire in .5 sec
+ .timeout_ticks = CALC_TICKS(5), // expire in .5 sec
};
ret = rte_mempool_get_bulk(eventdev_test_mempool, (void **)evtims,
.ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
.ev.event_type = RTE_EVENT_TYPE_TIMER,
.state = RTE_EVENT_TIMER_NOT_ARMED,
- .timeout_ticks = 5, // expire in .5 sec
+ .timeout_ticks = CALC_TICKS(5), // expire in .5 sec
};
rte_mempool_get(eventdev_test_mempool, (void **)&evtim);
.ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
.ev.event_type = RTE_EVENT_TYPE_TIMER,
.state = RTE_EVENT_TIMER_NOT_ARMED,
- .timeout_ticks = 5, // expire in .5 sec
+ .timeout_ticks = CALC_TICKS(5), // expire in .5 sec
};
rte_mempool_get(eventdev_test_mempool, (void **)&evtim);
/* Set up an event timer */
*evtim = init_tim;
- evtim->timeout_ticks = 30, // expire in 3 secs
+ evtim->timeout_ticks = CALC_TICKS(30), // expire in 3 secs
evtim->ev.event_ptr = evtim;
ret = rte_event_timer_arm_burst(adapter, &evtim, 1);
/* Set up a timer */
*evtim = init_tim;
- evtim->timeout_ticks = 1; // expire in 0.1 sec
+ evtim->timeout_ticks = CALC_TICKS(1); // expire in 0.1 sec
evtim->ev.event_ptr = evtim;
/* Arm it */
.ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
.ev.event_type = RTE_EVENT_TYPE_TIMER,
.state = RTE_EVENT_TIMER_NOT_ARMED,
- .timeout_ticks = 5, // expire in .5 sec
+ .timeout_ticks = CALC_TICKS(5), // expire in .5 sec
};
ret = rte_mempool_get_bulk(eventdev_test_mempool, (void **)evtims,
.ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
.ev.event_type = RTE_EVENT_TYPE_TIMER,
.state = RTE_EVENT_TIMER_NOT_ARMED,
- .timeout_ticks = 5, // expire in .5 sec
+ .timeout_ticks = CALC_TICKS(5), // expire in .5 sec
};
if (!using_services)
.ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
.ev.event_type = RTE_EVENT_TYPE_TIMER,
.state = RTE_EVENT_TIMER_NOT_ARMED,
- .timeout_ticks = 5, // expire in .5 sec
+ .timeout_ticks = CALC_TICKS(5), // expire in .5 sec
};
rte_mempool_get(eventdev_test_mempool, (void **)&evtim);
*evtim = init_tim;
evtim->ev.event_ptr = evtim;
- evtim->timeout_ticks = 1801; // timeout too big
+ evtim->timeout_ticks = CALC_TICKS(1801); // timeout too big
ret = rte_event_timer_arm_burst(timdev, &evtim, 1);
TEST_ASSERT_EQUAL(ret, 0, "Expected to fail timer arm with invalid "
/* Set up a timer */
*evtim = init_tim;
evtim->ev.event_ptr = evtim;
- evtim->timeout_ticks = 30; // expire in 3 sec
+ evtim->timeout_ticks = CALC_TICKS(30); // expire in 3 sec
/* Check that cancelling an inited but unarmed timer fails */
ret = rte_event_timer_cancel_burst(adapter, &evtim, 1);
.ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
.ev.event_type = RTE_EVENT_TYPE_TIMER,
.state = RTE_EVENT_TIMER_NOT_ARMED,
- .timeout_ticks = 5, // expire in .5 sec
+ .timeout_ticks = CALC_TICKS(5), // expire in .5 sec
};
rte_mempool_get(eventdev_test_mempool, (void **)&evtim);
/* Set up a timer */
*evtim = init_tim;
evtim->ev.event_ptr = evtim;
- evtim->timeout_ticks = 30; // expire in 3 sec
+ evtim->timeout_ticks = CALC_TICKS(30); // expire in 3 sec
ret = rte_event_timer_arm_burst(adapter, &evtim, 1);
TEST_ASSERT_EQUAL(ret, 1, "Failed to arm event timer: %s\n",
.timer_tick_ns = NSECPERSEC / 10,
.max_tmo_ns = 180 * NSECPERSEC,
.nb_timers = MAX_TIMERS,
- .flags = 0,
+ .flags = RTE_EVENT_TIMER_ADAPTER_F_ADJUST_RES,
};
if (!using_services)
test_timer_state),
TEST_CASE_ST(timdev_setup_usec, timdev_teardown,
test_timer_arm),
+ TEST_CASE_ST(timdev_setup_msec_periodic, timdev_teardown,
+ test_timer_arm_periodic),
TEST_CASE_ST(timdev_setup_usec, timdev_teardown,
test_timer_arm_burst),
+ TEST_CASE_ST(timdev_setup_msec_periodic, timdev_teardown,
+ test_timer_arm_burst_periodic),
TEST_CASE_ST(timdev_setup_sec, timdev_teardown,
test_timer_cancel),
+ TEST_CASE_ST(timdev_setup_sec_periodic, timdev_teardown,
+ test_timer_cancel_periodic),
TEST_CASE_ST(timdev_setup_sec, timdev_teardown,
test_timer_cancel_random),
TEST_CASE_ST(timdev_setup_usec_multicore, timdev_teardown,
return unit_test_suite_runner(&event_timer_adptr_functional_testsuite);
}
+#endif /* !RTE_EXEC_ENV_WINDOWS */
+
REGISTER_TEST_COMMAND(event_timer_adapter_test, test_event_timer_adapter_func);