[PATCH] Use C11-like atomics instead of plain memory accesses in x86 lock elision.

Stefan Liebler stli@linux.vnet.ibm.com
Fri Dec 2 15:38:00 GMT 2016


Hi Torvald,

On 12/02/2016 10:56 AM, Torvald Riegel wrote:
> This uses atomic operations to access lock elision metadata that is
> accessed concurrently (ie, adapt_count fields).  The size of the data is
> less than a word but accessed only with atomic loads and stores;
> therefore, we add support for shorter-size atomic load and stores too.
>
> Once committed, I will add a note to the Concurrency page on the wiki.
> The reason for just enabling shorter-size atomic loads and stores is
> that so far, we have no need for shorter-size atomic read-modify-write
> operations, and it would be harder to enable these on certain archs than
> just loads and stores.
>
> Other architectures that use lock elision should apply similar changes.
>
> Tested on x86_64-linux.
>
 > diff --git a/sysdeps/unix/sysv/linux/x86/elision-lock.c 
b/sysdeps/unix/sysv/linux/x86/elision-lock.c
 > index 5e66960..384c48e 100644
 > --- a/sysdeps/unix/sysv/linux/x86/elision-lock.c
 > +++ b/sysdeps/unix/sysv/linux/x86/elision-lock.c
 > @@ -44,7 +44,11 @@
 >  int
 >  __lll_lock_elision (int *futex, short *adapt_count, EXTRAARG int 
private)
 >  {
 > -  if (*adapt_count <= 0)
 > +  /* adapt_count is accessed inside and outside of transactions 
concurrently,
 > +     so we need to use atomic accesses to avoid data races. 
However, the
 > +     value of adapt_count is just a hint, so relaxed MO accesses are
 > +     sufficient.  */
 >

Can you extend the comment about the access of adapt_count "inside" of a 
transaction?
If the reader thinks about one call of pthread_mutex_lock, the 
adapt_count is not accessed inside a transaction:
/* mut_a->elision (=adapt_count) is loaded before starting the 
transaction or acquiring the lock.  If the transaction is aborted, it is 
accessed without an acquired lock.   */
pthread_mutex_lock(mut_a)
pthread_mutex_unlock(mut_a)

Only if you have a nested transaction, adapt_count is accessed within a 
transaction:
/* mut_a->elision (=adapt_count) is accessed before starting the 
transaction or aquiring the lock.  */
pthread_mutex_lock(mut_a)

/* mut_b->elision (=adapt_count) is accessed within the transaction 
started while locking mut_a.  */
pthread_mutex_lock(mut_b)

pthread_mutex_unlock(mut_b)
pthread_mutex_unlock(mut_a)

On 12/02/2016 10:56 AM, Torvald Riegel wrote:
 > @@ -70,15 +74,23 @@ __lll_lock_elision (int *futex, short 
*adapt_count, EXTRAARG int private)
 >  			&& _XABORT_CODE (status) == _ABORT_LOCK_BUSY)
 >  	        {
 >  		  /* Right now we skip here.  Better would be to wait a bit
 > -		     and retry.  This likely needs some spinning.  */
 > -		  if (*adapt_count != aconf.skip_lock_busy)
 > -		    *adapt_count = aconf.skip_lock_busy;
 > +		     and retry.  This likely needs some spinning.
 > +		     While the transaction already ensures atomicity, we use
 > +		     atomic accesses here too just for consistency, and to
 > +		     make a potential future transition to C11 atomic data
 > +		     types easier.
 >
Here we are not within a transaction as _xbegin has not returned 
_XBEGIN_STARTED or the transaction started successfully but was aborted 
because the lock was busy.

I'll post a similar patch for s390.

Bye.
Stefan



More information about the Libc-alpha mailing list