Event devices can indicate pre-scheduling capabilities using
`RTE_EVENT_DEV_CAP_EVENT_PRESCHEDULE` and
`RTE_EVENT_DEV_CAP_EVENT_PRESCHEDULE_ADAPTIVE` via the event
device
info function `info.event_dev_cap`.
Applications can select the pre-schedule type and configure it through
`rte_event_dev_config.preschedule_type` during `rte_event_dev_configure`.
The supported pre-schedule types are:
* `RTE_EVENT_DEV_PRESCHEDULE_NONE` - No pre-scheduling.
* `RTE_EVENT_DEV_PRESCHEDULE` - Always issue a pre-schedule on
dequeue.
* `RTE_EVENT_DEV_PRESCHEDULE_ADAPTIVE` - Delay issuing pre-schedule
until
there are no forward progress constraints with the held flow contexts.
Signed-off-by: Pavan Nikhilesh <pbhagavat...@marvell.com>
---
app/test/test_eventdev.c | 63 +++++++++++++++++++++
doc/guides/prog_guide/eventdev/eventdev.rst | 22 +++++++
lib/eventdev/rte_eventdev.h | 48 ++++++++++++++++
3 files changed, 133 insertions(+)
diff --git a/app/test/test_eventdev.c b/app/test/test_eventdev.c index
e4e234dc98..cf496ee88d 100644
--- a/app/test/test_eventdev.c
+++ b/app/test/test_eventdev.c
@@ -1250,6 +1250,67 @@ test_eventdev_profile_switch(void)
return TEST_SUCCESS;
}
+static int
+preschedule_test(rte_event_dev_preschedule_type_t preschedule_type,
+const char *preschedule_name) {
+#define NB_EVENTS 1024
+ uint64_t start, total;
+ struct rte_event ev;
+ int rc, cnt;
+
+ ev.event_type = RTE_EVENT_TYPE_CPU;
+ ev.queue_id = 0;
+ ev.op = RTE_EVENT_OP_NEW;
+ ev.u64 = 0xBADF00D0;
+
+ for (cnt = 0; cnt < NB_EVENTS; cnt++) {
+ ev.flow_id = cnt;
+ rc = rte_event_enqueue_burst(TEST_DEV_ID, 0, &ev, 1);
+ TEST_ASSERT(rc == 1, "Failed to enqueue event");
+ }
+
+ RTE_SET_USED(preschedule_type);
+ total = 0;
+ while (cnt) {
+ start = rte_rdtsc_precise();
+ rc = rte_event_dequeue_burst(TEST_DEV_ID, 0, &ev, 1, 0);
+ if (rc) {
+ total += rte_rdtsc_precise() - start;
+ cnt--;
+ }
+ }
+ printf("Preschedule type : %s, avg cycles %" PRIu64 "\n",
preschedule_name,
+ total / NB_EVENTS);
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_eventdev_preschedule_configure(void)
+{
+ struct rte_event_dev_config dev_conf;
+ struct rte_event_dev_info info;
+ int rc;
+
+ rte_event_dev_info_get(TEST_DEV_ID, &info);
+
+ if ((info.event_dev_cap &
RTE_EVENT_DEV_CAP_EVENT_PRESCHEDULE)
== 0)
+ return TEST_SKIPPED;
+
+ devconf_set_default_sane_values(&dev_conf, &info);
+ dev_conf.preschedule_type = RTE_EVENT_DEV_PRESCHEDULE;
+ rc = rte_event_dev_configure(TEST_DEV_ID, &dev_conf);
+ TEST_ASSERT_SUCCESS(rc, "Failed to configure eventdev");
+
+ rc = preschedule_test(RTE_EVENT_DEV_PRESCHEDULE_NONE,
"RTE_EVENT_DEV_PRESCHEDULE_NONE");
+ rc |= preschedule_test(RTE_EVENT_DEV_PRESCHEDULE,
"RTE_EVENT_DEV_PRESCHEDULE");
+ if (info.event_dev_cap &
RTE_EVENT_DEV_CAP_EVENT_PRESCHEDULE_ADAPTIVE)
+ rc |=
preschedule_test(RTE_EVENT_DEV_PRESCHEDULE_ADAPTIVE,
+
"RTE_EVENT_DEV_PRESCHEDULE_ADAPTIVE");
+
+ return rc;
+}
+
static int
test_eventdev_close(void)
{
@@ -1310,6 +1371,8 @@ static struct unit_test_suite
eventdev_common_testsuite = {
test_eventdev_start_stop),
TEST_CASE_ST(eventdev_configure_setup,
eventdev_stop_device,
test_eventdev_profile_switch),
+ TEST_CASE_ST(eventdev_configure_setup, NULL,
+ test_eventdev_preschedule_configure),
TEST_CASE_ST(eventdev_setup_device,
eventdev_stop_device,
test_eventdev_link),
TEST_CASE_ST(eventdev_setup_device,
eventdev_stop_device,
diff --git a/doc/guides/prog_guide/eventdev/eventdev.rst
b/doc/guides/prog_guide/eventdev/eventdev.rst
index fb6dfce102..341b9bb2c6 100644
--- a/doc/guides/prog_guide/eventdev/eventdev.rst
+++ b/doc/guides/prog_guide/eventdev/eventdev.rst
@@ -357,6 +357,28 @@ Worker path:
// Process the event received.
}
+Event Pre-scheduling
+~~~~~~~~~~~~~~~~~~~~
+
+Event pre-scheduling improves scheduling performance by assigning
+events to event ports in advance when dequeues are issued.
+The `rte_event_dequeue_burst` operation initiates the pre-schedule
+operation, which completes in parallel without affecting the dequeued
event
flow contexts and dequeue latency.
+On the next dequeue operation, the pre-scheduled events are dequeued
+and pre-schedule is initiated again.
+
+An application can use event pre-scheduling if the event device
+supports it at either device level or at a individual port level.
+The application can check pre-schedule capability by checking if
+``rte_event_dev_info.event_dev_cap``
+has the bit ``RTE_EVENT_DEV_CAP_PRESCHEDULE`` set, if present
+pre-scheduling can be enabled at device configuration time by setting
appropriate pre-schedule type in ``rte_event_dev_config.preschedule``.
+
+Currently, the following pre-schedule types are supported:
+ * ``RTE_EVENT_DEV_PRESCHEDULE_NONE`` - No pre-scheduling.
+ * ``RTE_EVENT_DEV_PRESCHEDULE`` - Always issue a pre-schedule when
dequeue is issued.
+ * ``RTE_EVENT_DEV_PRESCHEDULE_ADAPTIVE`` - Issue pre-schedule when
dequeue is issued and there are
+ no forward progress constraints.
+
Starting the EventDev
~~~~~~~~~~~~~~~~~~~~~
diff --git a/lib/eventdev/rte_eventdev.h b/lib/eventdev/rte_eventdev.h
index
08e5f9320b..5ea7f5a07b 100644
--- a/lib/eventdev/rte_eventdev.h
+++ b/lib/eventdev/rte_eventdev.h
@@ -446,6 +446,30 @@ struct rte_event;
* @see RTE_SCHED_TYPE_PARALLEL
*/
+#define RTE_EVENT_DEV_CAP_EVENT_PRESCHEDULE (1ULL << 16) /**<
Event
+device supports event pre-scheduling.
+ *
+ * When this capability is available, the application can enable event
+pre-scheduling on the event
+ * device to pre-schedule events to a event port when
+`rte_event_dequeue_burst()`
+ * is issued.
+ * The pre-schedule process starts with the `rte_event_dequeue_burst()`
+call and the
+ * pre-scheduled events are returned on the next
`rte_event_dequeue_burst()`
call.
+ *
+ * @see rte_event_dev_configure()
+ */
+
+#define RTE_EVENT_DEV_CAP_EVENT_PRESCHEDULE_ADAPTIVE (1ULL <<
17)
/**<
+Event device supports adaptive event pre-scheduling.
+ *
+ * When this capability is available, the application can enable
+adaptive pre-scheduling
+ * on the event device where the events are pre-scheduled when there
+are no forward
+ * progress constraints with the currently held flow contexts.
+ * The pre-schedule process starts with the `rte_event_dequeue_burst()`
+call and the
+ * pre-scheduled events are returned on the next
`rte_event_dequeue_burst()`
call.
+ *
+ * @see rte_event_dev_configure()
+ */
+
/* Event device priority levels */
#define RTE_EVENT_DEV_PRIORITY_HIGHEST 0
/**< Highest priority level for events and queues.
@@ -680,6 +704,25 @@ rte_event_dev_attr_get(uint8_t dev_id, uint32_t
attr_id,
* @see rte_event_dequeue_timeout_ticks(), rte_event_dequeue_burst()
*/
+typedef enum {
+ RTE_EVENT_DEV_PRESCHEDULE_NONE = 0,
+ /* Disable pre-schedule across the event device or on a given event
port.
+ * @ref rte_event_dev_config.preschedule_type
+ */
+ RTE_EVENT_DEV_PRESCHEDULE,
+ /* Enable pre-schedule always across the event device or a given event
port.
+ * @ref rte_event_dev_config.preschedule_type
+ * @see RTE_EVENT_DEV_CAP_EVENT_PRESCHEDULE
+ */
+ RTE_EVENT_DEV_PRESCHEDULE_ADAPTIVE,
+ /* Enable adaptive pre-schedule across the event device or a given
event
port.
+ * Delay issuing pre-schedule until there are no forward progress
constraints with
+ * the held flow contexts.
+ * @ref rte_event_dev_config.preschedule_type
+ * @see RTE_EVENT_DEV_CAP_EVENT_PRESCHEDULE_ADAPTIVE
+ */
+} rte_event_dev_preschedule_type_t;
+
/** Event device configuration structure */ struct rte_event_dev_config {
uint32_t dequeue_timeout_ns;
@@ -752,6 +795,11 @@ struct rte_event_dev_config {
* optimized for single-link usage, this field is a hint for how many
* to allocate; otherwise, regular event ports and queues will be used.
*/
+ rte_event_dev_preschedule_type_t preschedule_type;
+ /**< Event pre-schedule type to use across the event device, if
supported.
+ * @see RTE_EVENT_DEV_CAP_EVENT_PRESCHEDULE
+ * @see RTE_EVENT_DEV_CAP_EVENT_PRESCHEDULE_ADAPTIVE
+ */
};
/**
--
2.25.1