From ca6e601a9d4a72b3699cca15bad12ac1716bf49a Mon Sep 17 00:00:00 2001 From: Torvald Riegel Date: Wed, 30 Nov 2016 17:53:11 +0100 Subject: Use C11-like atomics instead of plain memory accesses in x86 lock elision. 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. * include/atomic.h (__atomic_check_size_ls): New. (atomic_load_relaxed, atomic_load_acquire, atomic_store_relaxed, atomic_store_release): Use it. * sysdeps/x86/elide.h (ACCESS_ONCE): Remove. (elision_adapt, ELIDE_LOCK): Use atomics. * sysdeps/unix/sysv/linux/x86/elision-lock.c (__lll_lock_elision): Use atomics and improve code comments. * sysdeps/unix/sysv/linux/x86/elision-trylock.c (__lll_trylock_elision): Likewise. --- sysdeps/unix/sysv/linux/x86/elision-trylock.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'sysdeps/unix/sysv/linux/x86/elision-trylock.c') diff --git a/sysdeps/unix/sysv/linux/x86/elision-trylock.c b/sysdeps/unix/sysv/linux/x86/elision-trylock.c index 65d9c18584..2d44f50426 100644 --- a/sysdeps/unix/sysv/linux/x86/elision-trylock.c +++ b/sysdeps/unix/sysv/linux/x86/elision-trylock.c @@ -36,8 +36,10 @@ __lll_trylock_elision (int *futex, short *adapt_count) return an error. */ _xabort (_ABORT_NESTED_TRYLOCK); - /* Only try a transaction if it's worth it. */ - if (*adapt_count <= 0) + /* Only try a transaction if it's worth it. See __lll_lock_elision for + why we need atomic accesses. Relaxed MO is sufficient because this is + just a hint. */ + if (atomic_load_relaxed (adapt_count) <= 0) { unsigned status; @@ -55,16 +57,18 @@ __lll_trylock_elision (int *futex, short *adapt_count) if (!(status & _XABORT_RETRY)) { /* Internal abort. No chance for retry. For future - locks don't try speculation for some time. */ - if (*adapt_count != aconf.skip_trylock_internal_abort) - *adapt_count = aconf.skip_trylock_internal_abort; + locks don't try speculation for some time. See above for MO. */ + if (atomic_load_relaxed (adapt_count) + != aconf.skip_lock_internal_abort) + atomic_store_relaxed (adapt_count, aconf.skip_lock_internal_abort); } /* Could do some retries here. */ } else { - /* Lost updates are possible, but harmless. */ - (*adapt_count)--; + /* Lost updates are possible but harmless (see above). */ + atomic_store_relaxed (adapt_count, + atomic_load_relaxed (adapt_count) - 1); } return lll_trylock (*futex); -- cgit 1.4.1