1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-28 00:21:52 +03:00

S390: Adjust lock elision code after review.

This patch adjusts s390 specific lock elision code after review
of the following patches:
-S390: Use own tbegin macro instead of __builtin_tbegin.
(8bfc4a2ab4)
-S390: Use new __libc_tbegin_retry macro in elision-lock.c.
(53c5c3d5ac)
-S390: Optimize lock-elision by decrementing adapt_count at unlock.
(dd037fb3df)

The futex value is not tested before starting a transaction,
__glibc_likely is used instead of __builtin_expect and comments
are adjusted.

ChangeLog:

	* sysdeps/unix/sysv/linux/s390/htm.h: Adjust comments.
	* sysdeps/unix/sysv/linux/s390/elision-unlock.c: Likewise.
	* sysdeps/unix/sysv/linux/s390/elision-lock.c: Adjust comments.
	(__lll_lock_elision): Do not test futex before starting a
	transaction.  Use __glibc_likely instead of __builtin_expect.
	* sysdeps/unix/sysv/linux/s390/elision-trylock.c: Adjust comments.
	(__lll_trylock_elision): Do not test futex before starting a
	transaction.  Use __glibc_likely instead of __builtin_expect.
This commit is contained in:
Stefan Liebler
2017-01-20 09:53:04 +01:00
parent 56009aa33c
commit 03b007771b
5 changed files with 65 additions and 43 deletions

View File

@ -51,31 +51,29 @@ __lll_trylock_elision (int *futex, short *adapt_count)
critical section uses lock elision) and outside of transactions. Thus,
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.
Do not begin a transaction if another cpu has locked the
futex with normal locking. If adapt_count is zero, it remains and the
next pthread_mutex_lock call will try to start a transaction again. */
if (atomic_load_relaxed (futex) == 0
&& atomic_load_relaxed (adapt_count) <= 0 && aconf.try_tbegin > 0)
sufficient. */
if (atomic_load_relaxed (adapt_count) <= 0 && aconf.try_tbegin > 0)
{
int status = __libc_tbegin ((void *) 0);
if (__builtin_expect (status == _HTM_TBEGIN_STARTED,
_HTM_TBEGIN_STARTED))
if (__glibc_likely (status == _HTM_TBEGIN_STARTED))
{
/* Check the futex to make sure nobody has touched it in the
mean time. This forces the futex into the cache and makes
sure the transaction aborts if some other cpu uses the
lock (writes the futex). */
if (__builtin_expect (atomic_load_relaxed (futex) == 0, 1))
sure the transaction aborts if another thread acquires the lock
concurrently. */
if (__glibc_likely (atomic_load_relaxed (futex) == 0))
/* Lock was free. Return to user code in a transaction. */
return 0;
/* Lock was busy. Fall back to normal locking. Since we are in
a non-nested transaction there is no need to abort, which is
expensive. Simply end the started transaction. */
/* Lock was busy. Fall back to normal locking.
This can be the case if e.g. adapt_count was decremented to zero
by a former release and another thread has been waken up and
acquired it.
Since we are in a non-nested transaction there is no need to abort,
which is expensive. Simply end the started transaction. */
__libc_tend ();
/* Note: Changing the adapt_count here might abort a transaction on a
different cpu, but that could happen anyway when the futex is
different CPU, but that could happen anyway when the futex is
acquired, so there's no need to check the nesting depth here.
See above for why relaxed MO is sufficient. */
if (aconf.skip_lock_busy > 0)
@ -93,6 +91,7 @@ __lll_trylock_elision (int *futex, short *adapt_count)
/* Could do some retries here. */
}
/* Use normal locking as fallback path if transaction does not succeed. */
/* Use normal locking as fallback path if the transaction does not
succeed. */
return lll_trylock (*futex);
}