This commit adds a new flag that the component (or "backend")
can use to indicate readyness. The service function callback
will not be called until the component sets itself as ready.
The use-case behind adding this feature is eg: a service that
requires configuration before it can start. Any service that
emulates an ethdev will have rte_eth_dev_configure() called,
and only after that the service will know how many queues/etc
to allocate. Once that configuration is complete, the service
marks itself as ready using rte_service_component_runstate_set().
This feature request results from prototyping services, and
requiring a flag in each service to note "internal" readyness.
Instead that logic is now lifted to the service library.
The unit tests have been updated to test the component runstate.
Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com>
---
lib/librte_eal/bsdapp/eal/rte_eal_version.map | 1 +
.../common/include/rte_service_component.h | 17 +++++++++++
lib/librte_eal/common/rte_service.c | 34 +++++++++++++++++-----
lib/librte_eal/linuxapp/eal/rte_eal_version.map | 1 +
test/test/test_service_cores.c | 32 +++++++++++++++-----
5 files changed, 70 insertions(+), 15 deletions(-)
@@ -214,6 +214,7 @@ EXPERIMENTAL {
rte_eal_hotplug_remove;
rte_service_component_register;
rte_service_component_unregister;
+ rte_service_component_runstate_set;
rte_service_dump;
rte_service_get_by_id;
rte_service_get_by_name;
@@ -135,6 +135,23 @@ int32_t rte_service_start_with_defaults(void);
* @warning
* @b EXPERIMENTAL: this API may change without prior notice
*
+ * Set the backend runstate of a component.
+ *
+ * This function allows services to be registered at startup, but not yet
+ * enabled to run by default. When the service has been configured (via the
+ * usual method; eg rte_eventdev_configure, the service can mark itself as
+ * ready to run. The differentiation between backend runstate and
+ * service_runstate is that the backend runstate is set by the service
+ * component while the service runstate is reserved for application usage.
+ *
+ * @retval 0 Success
+ */
+int32_t rte_service_component_runstate_set(uint32_t id, uint32_t runstate);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
* Initialize the service library.
*
* In order to use the service library, it must be initialized. EAL initializes
@@ -71,7 +71,8 @@ struct rte_service_spec_impl {
rte_atomic32_t execute_lock;
/* API set/get-able variables */
- int32_t runstate;
+ int8_t app_runstate;
+ int8_t comp_runstate;
uint8_t internal_flags;
/* per service statistics */
@@ -273,15 +274,30 @@ rte_service_component_unregister(uint32_t id)
}
int32_t
+rte_service_component_runstate_set(uint32_t id, uint32_t runstate)
+{
+ struct rte_service_spec_impl *s;
+ SERVICE_VALID_GET_OR_ERR_RET(id, s, -EINVAL);
+
+ if (runstate)
+ s->comp_runstate = RUNSTATE_RUNNING;
+ else
+ s->comp_runstate = RUNSTATE_STOPPED;
+
+ rte_smp_wmb();
+ return 0;
+}
+
+int32_t
rte_service_runstate_set(uint32_t id, uint32_t runstate)
{
struct rte_service_spec_impl *s;
SERVICE_VALID_GET_OR_ERR_RET(id, s, -EINVAL);
if (runstate)
- s->runstate = RUNSTATE_RUNNING;
+ s->app_runstate = RUNSTATE_RUNNING;
else
- s->runstate = RUNSTATE_STOPPED;
+ s->app_runstate = RUNSTATE_STOPPED;
rte_smp_wmb();
return 0;
@@ -292,8 +308,10 @@ rte_service_runstate_get(uint32_t id)
{
struct rte_service_spec_impl *s;
SERVICE_VALID_GET_OR_ERR_RET(id, s, -EINVAL);
-
- return (s->runstate == RUNSTATE_RUNNING) && (s->num_mapped_cores > 0);
+ rte_smp_rmb();
+ return (s->app_runstate == RUNSTATE_RUNNING) &&
+ (s->comp_runstate == RUNSTATE_RUNNING) &&
+ (s->num_mapped_cores > 0);
}
static inline void
@@ -328,7 +346,8 @@ rte_service_runner_func(void *arg)
if (!service_valid(i))
continue;
struct rte_service_spec_impl *s = &rte_services[i];
- if (s->runstate != RUNSTATE_RUNNING ||
+ if (s->comp_runstate != RUNSTATE_RUNNING ||
+ s->app_runstate != RUNSTATE_RUNNING ||
!(service_mask & (UINT64_C(1) << i)))
continue;
@@ -596,8 +615,7 @@ rte_service_lcore_stop(uint32_t lcore)
for (i = 0; i < RTE_SERVICE_NUM_MAX; i++) {
int32_t enabled =
lcore_states[i].service_mask & (UINT64_C(1) << i);
- int32_t service_running = rte_services[i].runstate !=
- RUNSTATE_STOPPED;
+ int32_t service_running = rte_service_runstate_get(i);
int32_t only_core = rte_services[i].num_mapped_cores == 1;
/* if the core is mapped, and the service is running, and this
@@ -219,6 +219,7 @@ EXPERIMENTAL {
rte_eal_hotplug_remove;
rte_service_component_register;
rte_service_component_unregister;
+ rte_service_component_runstate_set;
rte_service_dump;
rte_service_get_by_id;
rte_service_get_by_name;
@@ -166,9 +166,12 @@ dummy_register(void)
"Invalid name");
snprintf(service.name, sizeof(service.name), DUMMY_SERVICE_NAME);
- TEST_ASSERT_EQUAL(0, rte_service_component_register(&service, NULL),
+ uint32_t id;
+ TEST_ASSERT_EQUAL(0, rte_service_component_register(&service, &id),
"Failed to register valid service");
+ rte_service_component_runstate_set(id, 1);
+
return TEST_SUCCESS;
}
@@ -470,13 +473,11 @@ service_threaded_test(int mt_safe)
if (mt_safe) {
service.callback = dummy_mt_safe_cb;
service.capabilities |= RTE_SERVICE_CAP_MT_SAFE;
- } else {
- /* initialize to pass, see callback comment for details */
- test_params[1] = 1;
+ } else
service.callback = dummy_mt_unsafe_cb;
- }
- TEST_ASSERT_EQUAL(0, rte_service_component_register(&service, NULL),
+ uint32_t id;
+ TEST_ASSERT_EQUAL(0, rte_service_component_register(&service, &id),
"Register of MT SAFE service failed");
const uint32_t sid = 0;
@@ -494,9 +495,26 @@ service_threaded_test(int mt_safe)
rte_service_lcore_stop(slcore_1);
rte_service_lcore_stop(slcore_2);
+ TEST_ASSERT_EQUAL(0, test_params[1],
+ "Service run with component runstate = 0");
+
+ /* enable backend runstate: the service should run after this */
+ rte_service_component_runstate_set(id, 1);
+
+ /* initialize to pass, see callback comment for details */
+ if (!mt_safe)
+ test_params[1] = 1;
+
+ rte_service_lcore_start(slcore_1);
+ rte_service_lcore_start(slcore_2);
+
+ /* wait for the worker threads to run */
+ rte_delay_ms(500);
+ rte_service_lcore_stop(slcore_1);
+ rte_service_lcore_stop(slcore_2);
+
TEST_ASSERT_EQUAL(1, test_params[1],
"MT Safe service not run by two cores concurrently");
-
TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 0),
"Failed to stop MT Safe service");