From patchwork Mon Aug 21 12:58:14 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Van Haaren, Harry" X-Patchwork-Id: 27696 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [IPv6:::1]) by dpdk.org (Postfix) with ESMTP id 801E590FA; Mon, 21 Aug 2017 14:58:48 +0200 (CEST) Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by dpdk.org (Postfix) with ESMTP id 80BD07D7F for ; Mon, 21 Aug 2017 14:58:40 +0200 (CEST) Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga105.fm.intel.com with ESMTP; 21 Aug 2017 05:58:40 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos; i="5.41,409,1498546800"; d="scan'208"; a="1208383374" Received: from silpixa00398672.ir.intel.com ([10.237.223.128]) by fmsmga002.fm.intel.com with ESMTP; 21 Aug 2017 05:58:39 -0700 From: Harry van Haaren To: dev@dpdk.org Cc: Harry van Haaren Date: Mon, 21 Aug 2017 13:58:14 +0100 Message-Id: <1503320296-51122-14-git-send-email-harry.van.haaren@intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1503320296-51122-1-git-send-email-harry.van.haaren@intel.com> References: <1502800360-15782-1-git-send-email-harry.van.haaren@intel.com> <1503320296-51122-1-git-send-email-harry.van.haaren@intel.com> Subject: [dpdk-dev] [PATCH v2 13/15] service: add component runstate X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" 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 --- 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(-) diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map index 4b2c36b..05a3de1 100644 --- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map +++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map @@ -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; diff --git a/lib/librte_eal/common/include/rte_service_component.h b/lib/librte_eal/common/include/rte_service_component.h index af632c6..5e4573b 100644 --- a/lib/librte_eal/common/include/rte_service_component.h +++ b/lib/librte_eal/common/include/rte_service_component.h @@ -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 diff --git a/lib/librte_eal/common/rte_service.c b/lib/librte_eal/common/rte_service.c index 58b53b1..e7ed597 100644 --- a/lib/librte_eal/common/rte_service.c +++ b/lib/librte_eal/common/rte_service.c @@ -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 diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map index f7a7352..0e1d09b 100644 --- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map +++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map @@ -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; diff --git a/test/test/test_service_cores.c b/test/test/test_service_cores.c index 5ae7b20..ddea7f0 100644 --- a/test/test/test_service_cores.c +++ b/test/test/test_service_cores.c @@ -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");