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:
@ -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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user