From mboxrd@z Thu Jan 1 00:00:00 1970 From: Pavan Nikhilesh Bhagavatula Subject: Re: [PATCH 1/2] service: add function for app lcore to run service Date: Wed, 25 Oct 2017 15:51:26 +0530 Message-ID: <20171025102125.GA29948@PBHAGAVATULA-LT> References: <1508779012-56186-1-git-send-email-harry.van.haaren@intel.com> <1508779012-56186-2-git-send-email-harry.van.haaren@intel.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Cc: dev@dpdk.org To: Harry van Haaren Return-path: Received: from NAM01-BN3-obe.outbound.protection.outlook.com (mail-bn3nam01on0086.outbound.protection.outlook.com [104.47.33.86]) by dpdk.org (Postfix) with ESMTP id 4F8131B93B for ; Wed, 25 Oct 2017 12:21:52 +0200 (CEST) Content-Disposition: inline In-Reply-To: <1508779012-56186-2-git-send-email-harry.van.haaren@intel.com> List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" On Mon, Oct 23, 2017 at 06:16:51PM +0100, Harry van Haaren wrote: > This commit adds a new function which allows an application lcore > (aka; *not* a dedicated service-lcore) to run a service. This > function is required to allow applications to gradually port > functionality to using services, while still being able to run > ordinary application functions. > > This requirement became clear when a patch to the existing > eventdev/pipeline sample app was modified to use a service-core > for scheduling - and that same core should be capable of running > the "worker()" function from the application too. > > This patch refactors the existing running code into a smaller > "service_run" function, which can be called by the dedicated > service-core loop, and the newly added function. > > Signed-off-by: Harry van Haaren > > [1] http://dpdk.org/ml/archives/dev/2017-October/079876.html > --- > lib/librte_eal/bsdapp/eal/rte_eal_version.map | 1 + > lib/librte_eal/common/include/rte_service.h | 21 +++++++++ > lib/librte_eal/common/rte_service.c | 59 ++++++++++++++++--------- > lib/librte_eal/linuxapp/eal/rte_eal_version.map | 1 + > 4 files changed, 61 insertions(+), 21 deletions(-) > > diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map > index 080896f..ee8dc98 100644 > --- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map > +++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map > @@ -229,6 +229,7 @@ EXPERIMENTAL { > rte_service_map_lcore_set; > rte_service_probe_capability; > rte_service_reset; > + rte_service_run_iter_on_app_lcore; > rte_service_runstate_get; > rte_service_runstate_set; > rte_service_set_stats_enable; > diff --git a/lib/librte_eal/common/include/rte_service.h b/lib/librte_eal/common/include/rte_service.h > index 21da739..63d3170 100644 > --- a/lib/librte_eal/common/include/rte_service.h > +++ b/lib/librte_eal/common/include/rte_service.h > @@ -211,6 +211,27 @@ int32_t rte_service_runstate_get(uint32_t id); > * @warning > * @b EXPERIMENTAL: this API may change without prior notice > * > + * This function runs a service callback from a non-service lcore context. > + * The *id* of the service to be run is passed in, and the service-callback > + * is executed on the calling lcore immediately if possible. If the service is > + * not multi-thread capable and another thread is currently executing it, this > + * function returns without running the callback. > + * > + * Note that any thread calling this function MUST be a DPDK EAL thread, as > + * the *rte_lcore_id* function is used to access internal data structures. > + * > + * @retval 0 Service was run on the calling thread successfully > + * @retval -EBUSY Another lcore is executing the service, and it is not a > + * multi-thread safe service, so the service was not run on this lcore > + * @retval -ENOEXEC Service is not in a runnable state > + * @retval -EINVAL Invalid service id > + */ > +int32_t rte_service_run_iter_on_app_lcore(uint32_t id); > + > +/** > + * @warning > + * @b EXPERIMENTAL: this API may change without prior notice > + * > * Start a service core. > * > * Starting a core makes the core begin polling. Any services assigned to it > diff --git a/lib/librte_eal/common/rte_service.c b/lib/librte_eal/common/rte_service.c > index e598e16..4e27f75 100644 > --- a/lib/librte_eal/common/rte_service.c > +++ b/lib/librte_eal/common/rte_service.c > @@ -331,6 +331,42 @@ rte_service_runner_do_callback(struct rte_service_spec_impl *s, > s->spec.callback(userdata); > } > > + > +static inline int32_t > +service_run(uint32_t i, struct core_state *cs, uint64_t service_mask) > +{ > + if (!service_valid(i)) > + return -EINVAL; > + struct rte_service_spec_impl *s = &rte_services[i]; > + if (s->comp_runstate != RUNSTATE_RUNNING || > + s->app_runstate != RUNSTATE_RUNNING || > + !(service_mask & (UINT64_C(1) << i))) > + return -ENOEXEC; > + > + /* check do we need cmpset, if MT safe or <= 1 core > + * mapped, atomic ops are not required. > + */ > + const int use_atomics = (service_mt_safe(s) == 0) && > + (s->num_mapped_cores > 1); > + if (use_atomics) { > + if (!rte_atomic32_cmpset((uint32_t *)&s->execute_lock, 0, 1)) > + return -EBUSY; > + > + rte_service_runner_do_callback(s, cs, i); > + rte_atomic32_clear(&s->execute_lock); > + } else > + rte_service_runner_do_callback(s, cs, i); > + > + return 0; > +} > + > +int32_t rte_service_run_iter_on_app_lcore(uint32_t id) > +{ > + /* run service on calling core, using all-ones as the service mask */ > + struct core_state *cs = &lcore_states[rte_lcore_id()]; > + return service_run(id, cs, UINT64_MAX); > +} > + > static int32_t > rte_service_runner_func(void *arg) > { > @@ -343,27 +379,8 @@ rte_service_runner_func(void *arg) > const uint64_t service_mask = cs->service_mask; > > for (i = 0; i < RTE_SERVICE_NUM_MAX; i++) { > - if (!service_valid(i)) > - continue; > - struct rte_service_spec_impl *s = &rte_services[i]; > - if (s->comp_runstate != RUNSTATE_RUNNING || > - s->app_runstate != RUNSTATE_RUNNING || > - !(service_mask & (UINT64_C(1) << i))) > - continue; > - > - /* check do we need cmpset, if MT safe or <= 1 core > - * mapped, atomic ops are not required. > - */ > - const int use_atomics = (service_mt_safe(s) == 0) && > - (s->num_mapped_cores > 1); > - if (use_atomics) { > - uint32_t *lock = (uint32_t *)&s->execute_lock; > - if (rte_atomic32_cmpset(lock, 0, 1)) { > - rte_service_runner_do_callback(s, cs, i); > - rte_atomic32_clear(&s->execute_lock); > - } > - } else > - rte_service_runner_do_callback(s, cs, i); > + /* return value ignored as no change to code flow */ > + service_run(i, cs, service_mask); > } > > rte_smp_rmb(); > diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map > index c173ccf..c4d2c27 100644 > --- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map > +++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map > @@ -233,6 +233,7 @@ EXPERIMENTAL { > rte_service_map_lcore_set; > rte_service_probe_capability; > rte_service_reset; > + rte_service_run_iter_on_app_lcore; > rte_service_runstate_get; > rte_service_runstate_set; > rte_service_set_stats_enable; > -- > 2.7.4 > Acked-by: Pavan Nikhilesh