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>
Acked-by: Pavan Nikhilesh <pbhagavatula@caviumnetworks.com>
rte_eal_hotplug_remove;
rte_service_component_register;
rte_service_component_unregister;
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;
rte_service_dump;
rte_service_get_by_id;
rte_service_get_by_name;
*/
int32_t rte_service_start_with_defaults(void);
*/
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
/**
* @warning
* @b EXPERIMENTAL: this API may change without prior notice
rte_atomic32_t execute_lock;
/* API set/get-able variables */
rte_atomic32_t execute_lock;
/* API set/get-able variables */
+ int8_t app_runstate;
+ int8_t comp_runstate;
uint8_t internal_flags;
/* per service statistics */
uint8_t internal_flags;
/* per service statistics */
+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)
{
int32_t
rte_service_runstate_set(uint32_t id, uint32_t runstate)
{
SERVICE_VALID_GET_OR_ERR_RET(id, s, -EINVAL);
if (runstate)
SERVICE_VALID_GET_OR_ERR_RET(id, s, -EINVAL);
if (runstate)
- s->runstate = RUNSTATE_RUNNING;
+ s->app_runstate = RUNSTATE_RUNNING;
- s->runstate = RUNSTATE_STOPPED;
+ s->app_runstate = RUNSTATE_STOPPED;
{
struct rte_service_spec_impl *s;
SERVICE_VALID_GET_OR_ERR_RET(id, s, -EINVAL);
{
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);
if (!service_valid(i))
continue;
struct rte_service_spec_impl *s = &rte_services[i];
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;
!(service_mask & (UINT64_C(1) << i)))
continue;
for (i = 0; i < RTE_SERVICE_NUM_MAX; i++) {
int32_t enabled =
lcore_states[i].service_mask & (UINT64_C(1) << i);
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
int32_t only_core = rte_services[i].num_mapped_cores == 1;
/* if the core is mapped, and the service is running, and this
rte_eal_hotplug_remove;
rte_service_component_register;
rte_service_component_unregister;
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;
rte_service_dump;
rte_service_get_by_id;
rte_service_get_by_name;
"Invalid name");
snprintf(service.name, sizeof(service.name), DUMMY_SERVICE_NAME);
"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");
"Failed to register valid service");
+ rte_service_component_runstate_set(id, 1);
+
if (mt_safe) {
service.callback = dummy_mt_safe_cb;
service.capabilities |= RTE_SERVICE_CAP_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;
service.callback = dummy_mt_unsafe_cb;
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;
"Register of MT SAFE service failed");
const uint32_t sid = 0;
rte_service_lcore_stop(slcore_1);
rte_service_lcore_stop(slcore_2);
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(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");
TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 0),
"Failed to stop MT Safe service");