[dpdk-dev] [PATCH v2 2/6] ethdev: add port ownership

Neil Horman nhorman at tuxdriver.com
Fri Jan 19 02:41:22 CET 2018


On Thu, Jan 18, 2018 at 08:21:34PM +0000, Matan Azrad wrote:
> Hi Neil.
> 
> From: Neil Horman, Thursday, January 18, 2018 8:42 PM
> 
> <snip>
> > > > But thats not all.  The determination of success or failure in
> > > > claiming ownership is largely dependent on the behavior of other
> > > > threads actions, not a function of the state of the system at the moment
> > ownership is requested.
> > > > That is to say, if you have N threads, and they all create ownership
> > > > objects identified as X, x+1, X+2...X+N, only the thread with id X+N
> > > > will be able to claim ownership of any port, because they all will
> > > > have incremented the shared nex_id variable.
> > >
> > > Why? Each one will get its owner id according to some order(The critical
> > section is protected by spinlock).
> > >
> > Yes, and thats my issue here, the ordering.  Perhaps my issue is one of
> > perception.  When I consider an ownership library, what I really think about is
> > mutual exclusion (i.e. guaranteing that only one entity is capable of access to
> > a resource at any one time).  This semantics of this library don't really
> > conform to any semantics that you usually see with other mutual exclusion
> > mechanisms.  That is to say a spinlock or a mutex succedes locking if its prior
> > state is unlocked.  This library succeeds aqusition of the resource it protects if
> > and only if allocation of ownership records occurs in a particular order relative
> > to one another.  That just seems odd to me.  What advantage do these new
> > semantics have over more traditional established semantics?
> > 
> > 
> > > >  Determination of ownership by the programmer will have to be done
> > > > via debugging, and errors will likely be transient dependent on the
> > > > order in which threads execute (subject to scheduling jitter).
> > > >
> > > Yes.
> > >
> > But why put yourself through that pain?  Traditional semantics are far simpler
> > to comprehend, with and without a debugger.
> > 
> 
> Looks like I missed you, sorry:
> Please describe next:
> 
> 1. What exactly do you want to improve?(in details)
> 2. Which API specifically do you want to change(\ part of code)?
> 3. What is the missing in current code(you can answer it in V3 I sent if you want) which should be fixed?
> 
> 
> <snip> sorry for that, I think it is not relevant continue discussion if we are not fully understand each other. So let's start from the beginning "with good order :)" by answering the above questions.


Sure, this seems like a reasonable way to level set.  

I mentioned in another thread that perhaps some of my issue here is perception
regarding what is meant by ownership.  When I think of an ownership api I think
primarily of mutual exclusion (that is to say, enforcement of a single execution
context having access to a resource at any given time.  In my mind the simplest
form of ownership is a spinlock or a mutex.  A single execution context either
does or does not hold the resource at any one time.  Those contexts that attempt
to gain excusive access to the resource call an api that (depending on
implementation) either block continued execution of that thread until exclusive
access to the resource can be granted, or returns immediately with a success or
error indicator to let the caller know if access is granted.

If I were to codify this port ownership api in pseudo code it would look
something like this:

struct rte_eth_dev {

	< eth dev bits >
	rte_spinlock_t owner_lock;
	bool locked;
	pid_t owner_pid;
}


bool rte_port_claim_ownership(struct rte_eth_dev *dev)
{
	bool ret = false;

	spin_lock(dev->owner_lock);
	if (dev->locked)
		goto out;
	dev->locked = true;
	dev->owner_pid = getpid();
	ret = true;
out:
	spin_unlock(dev->lock)
	return ret;		
}


bool rte_port_release_ownership(rte_eth_dev *dev)
{

	boot ret = false;
	spin_lock(dev->owner_lock);
	if (!dev->locked)
		goto out;
	if (dev->owner_pid != getpid())
		goto out;
	dev->locked = false;
	dev_owner_pid = 0;
	ret = true;
out:
	spin_unlock(dev->owner_lock)
	return ret;
}

bool rte_port_is_owned_by(struct rte_eth_dev *dev, pid_t pid)
{
	bool ret = false;

	spin_lock(dev->owner_lock);
	if (pid)
		ret = (dev->locked && (pid == dev->owner_pid));
	else
		ret = dev->locked;
	spin_unlock(dev->owner_lock);
	return ret;
}

The idea here is that lock state is isolated from ownership information.  Any
context has the opportunity to lock the resource (in this case the eth port)
despite its ownership object.  

In comparison, your api, which is in may ways simmilar, separates the creation
of ownership objects to a separate api call, and that ownership information
embodies state that is integral to the ability to get exclusive access to the
resource.  I.E. if thread A calls your owner_new call, and then thread B calls
owner_new, thread A will never be able to get access to any port unless it calls
owner_new again.

Does that help clarify my position?

Regards
Neil

}


More information about the dev mailing list