summaryrefslogtreecommitdiff
path: root/sysdeps/unix/sysv/linux/powerpc/elision-unlock.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/unix/sysv/linux/powerpc/elision-unlock.c')
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/elision-unlock.c21
1 files changed, 14 insertions, 7 deletions
diff --git a/sysdeps/unix/sysv/linux/powerpc/elision-unlock.c b/sysdeps/unix/sysv/linux/powerpc/elision-unlock.c
index 43c5a67df2..14e0680ee9 100644
--- a/sysdeps/unix/sysv/linux/powerpc/elision-unlock.c
+++ b/sysdeps/unix/sysv/linux/powerpc/elision-unlock.c
@@ -1,5 +1,5 @@
/* elision-unlock.c: Commit an elided pthread lock.
- Copyright (C) 2015-2016 Free Software Foundation, Inc.
+ Copyright (C) 2015-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -23,18 +23,25 @@
int
__lll_unlock_elision (int *lock, short *adapt_count, int pshared)
{
+#ifndef __SPE__
/* When the lock was free we're in a transaction. */
if (*lock == 0)
__libc_tend (0);
else
{
- lll_unlock ((*lock), pshared);
+ /* Update adapt_count in the critical section to prevent a
+ write-after-destroy error as mentioned in BZ 20822. The
+ following update of adapt_count has to be contained within
+ the critical region of the fall-back lock in order to not violate
+ the mutex destruction requirements. */
+ short __tmp = atomic_load_relaxed (adapt_count);
+ if (__tmp > 0)
+ atomic_store_relaxed (adapt_count, __tmp - 1);
- /* Update the adapt count AFTER completing the critical section.
- Doing this here prevents unneeded stalling when entering
- a critical section. Saving about 8% runtime on P8. */
- if (*adapt_count > 0)
- (*adapt_count)--;
+ lll_unlock ((*lock), pshared);
}
+#else
+ lll_unlock ((*lock), pshared);
+#endif
return 0;
}