[dpdk-dev] [PATCH 05/22] ethdev: introduce device lock

Burakov, Anatoly anatoly.burakov at intel.com
Fri Jun 15 17:42:33 CEST 2018


On 07-Jun-18 1:38 PM, Qi Zhang wrote:
> Introduce API rte_eth_dev_lock and rte_eth_dev_unlock to let
> application lock or unlock on specific ethdev, a locked device
> can't be detached, this help applicaiton to prevent unexpected
> device detaching, especially in multi-process envrionment.
> 
> Aslo the new API let application to register a callback function
> which will be invoked before a device is going to be detached,
> the return value of the function will decide if device will continue
> be detached or not, this support application to do condition check
> at runtime.
> 
> Signed-off-by: Qi Zhang <qi.z.zhang at intel.com>
> ---

<snip>

> +
> +int
> +rte_eth_dev_lock(uint16_t port_id, rte_eth_dev_lock_callback_t callback,
> +		 void *user_args)
> +{
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +
> +	if (callback == NULL)
> +		return register_lock_callback(port_id, dev_is_busy, NULL);
> +	else
> +		return register_lock_callback(port_id, callback, user_args);

As much as i don't like seeing negative errno values as return, the rest 
of ethdev library uses those, so this is OK :)

> +}
> +
> +int
> +rte_eth_dev_unlock(uint16_t port_id, rte_eth_dev_lock_callback_t callback,
> +		   void *user_args)
> +{
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +

<snip>

> + * Also, any callback function return !0 value will prevent device be
> + * detached(ref. rte_eth_dev_lock and rte_eth_dev_unlock).
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param user_args
> + *   This is parameter "user_args" be saved when callback function is
> + *   registered(rte_dev_eth_lock).
> + *
> + * @return
> + *   0  device is allowed be detached.
> + *   !0 device is not allowed be detached.

!0 can be negative or positive. Are we expecting positive return values 
from this API?

> + */
> +typedef int (*rte_eth_dev_lock_callback_t)(uint16_t port_id, void *user_args);
> +
> +/**
> + * Lock an Ethernet Device directly or register a callback function
> + * for condition check at runtime, this help application to prevent
> + * a device be detached unexpectly.
> + * NOTE: Lock a device mutliple times with same parmeter will increase
> + * a ref_count, and coresponding unlock decrease the ref_count, the
> + * device will be unlocked when ref_count reach 0.

Nitpick: "note" sections should be done with @note marker.

Also, i would mention that this is a per-process lock that does not 
affect other processes (assuming i understood the code correctly, of 
course...).

> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param callback
> + *   !NULL the callback function will be added into a pre-detach list,
> + *         it will be invoked when a device is going to be detached. The
> + *         return value will decide if continue detach the device or not.
> + *   NULL  lock the device directly, basically this just regiter a empty
> + *         callback function(dev_is_busy) that return -EBUSY, so we can
> + *         handle the pre-detach check in unified way.
> + * @param user_args
> + *   parameter will be parsed to callback function, only valid when
> + *   callback != NULL.
> + * @return
> + *   0 on success, negative on error.
> + */
> +int rte_eth_dev_lock(uint16_t port_id, rte_eth_dev_lock_callback_t callback,
> +		     void *user_args);

Nitpicks: DPDK style guide discourages using spaces as indentation 
(other parts of this patch, and other patches have this issue as well).

> +
> +/**
> + * Reverse operation of rte_eth_dev_lock.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param callback
> + *   NULL  decrease the ref_count of default callback function.
> + *   !NULL decrease the ref_count of specific callback with matched
> + *         user_args.
> + * @param user_args
> + *   parameter to match, only valid when callback != NULL.
> + * @return
> + *   0 on success, negative on error.
> + */
> +int rte_eth_dev_unlock(uint16_t port_id, rte_eth_dev_lock_callback_t callback,
> +		       void *user_args);
> +
>   #ifdef __cplusplus
>   }
>   #endif
> diff --git a/lib/librte_ethdev/rte_ethdev_lock.c b/lib/librte_ethdev/rte_ethdev_lock.c

rte_ethdev_lock.* seem to be internal-only files. Perhaps you should 
name them without the rte_ prefix to indicate that they're not exported?

> new file mode 100644
> index 000000000..688d1d70a
> --- /dev/null
> +++ b/lib/librte_ethdev/rte_ethdev_lock.c
> @@ -0,0 +1,102 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2018 Intel Corporation
> + */
> +#include "rte_ethdev_lock.h"
> +
> +struct lock_entry {
> +	TAILQ_ENTRY(lock_entry) next;
> +	rte_eth_dev_lock_callback_t callback;
> +	uint16_t port_id;

<snip>

> +register_lock_callback(uint16_t port_id,
> +		       rte_eth_dev_lock_callback_t callback,
> +		       void *user_args)
> +{
> +	struct lock_entry *le;
> +
> +	rte_spinlock_lock(&lock_entry_lock);
> +
> +	TAILQ_FOREACH(le, &lock_entry_list, next) {
> +		if (le->port_id == port_id &&
> +		    le->callback == callback &&
> +		    le->user_args == user_args)
> +			break;
> +	}
> +
> +	if (!le) {
> +		le = calloc(1, sizeof(struct lock_entry));
> +		if (!le) {

Nitpick: generally, DPDK style guide prefers "if (value)" or "if 
(!value)" to only be reserved for boolean values, and use explicit 
comparison (e.g. "if (value == NULL)" or "if (value == 0)") for all 
other cases.

-- 
Thanks,
Anatoly


More information about the dev mailing list