aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/unix
diff options
context:
space:
mode:
authorTorvald Riegel <triegel@redhat.com>2015-07-14 21:58:34 +0200
committerTorvald Riegel <triegel@redhat.com>2015-12-23 18:44:53 +0100
commit389fdf78b2e606387ce9d51f29e5c0a22ad9ad2a (patch)
tree3c665e20903d53ded06618a794b10d0d28292cc9 /sysdeps/unix
parent7962541a32eff5597bc4207e781cfac8d1bb0d87 (diff)
downloadglibc-389fdf78b2e606387ce9d51f29e5c0a22ad9ad2a.tar
glibc-389fdf78b2e606387ce9d51f29e5c0a22ad9ad2a.tar.gz
glibc-389fdf78b2e606387ce9d51f29e5c0a22ad9ad2a.tar.bz2
glibc-389fdf78b2e606387ce9d51f29e5c0a22ad9ad2a.zip
Do not violate mutex destruction requirements.
POSIX and C++11 require that a thread can destroy a mutex if no other thread owns the mutex, is blocked on the mutex, or will try to acquire it in the future. After destroying the mutex, it can reuse or unmap the underlying memory. Thus, we must not access a mutex' memory after releasing it. Currently, we can load the private flag after releasing the mutex, which is fixed by this patch. See https://sourceware.org/bugzilla/show_bug.cgi?id=13690 for more background. We need to call futex_wake on the lock after releasing it, however. This is by design, and can lead to spurious wake-ups on unrelated futex words (e.g., when the mutex memory is reused for another mutex). This behavior is documented in the glibc-internal futex API and in recent drafts of the Linux kernel's futex documentation (see the draft_futex branch of git://git.kernel.org/pub/scm/docs/man-pages/man-pages.git).
Diffstat (limited to 'sysdeps/unix')
-rw-r--r--sysdeps/unix/sysv/linux/lowlevellock-futex.h9
-rw-r--r--sysdeps/unix/sysv/linux/sparc/lowlevellock.h6
2 files changed, 11 insertions, 4 deletions
diff --git a/sysdeps/unix/sysv/linux/lowlevellock-futex.h b/sysdeps/unix/sysv/linux/lowlevellock-futex.h
index 59f6627bdb..40825f0306 100644
--- a/sysdeps/unix/sysv/linux/lowlevellock-futex.h
+++ b/sysdeps/unix/sysv/linux/lowlevellock-futex.h
@@ -54,8 +54,13 @@
#if IS_IN (libc) || IS_IN (rtld)
/* In libc.so or ld.so all futexes are private. */
# ifdef __ASSUME_PRIVATE_FUTEX
-# define __lll_private_flag(fl, private) \
- ((fl) | FUTEX_PRIVATE_FLAG)
+# define __lll_private_flag(fl, private) \
+ ({ \
+ /* Prevent warnings in callers of this macro. */ \
+ int __lll_private_flag_priv __attribute__ ((unused)); \
+ __lll_private_flag_priv = (private); \
+ ((fl) | FUTEX_PRIVATE_FLAG); \
+ })
# else
# define __lll_private_flag(fl, private) \
((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex))
diff --git a/sysdeps/unix/sysv/linux/sparc/lowlevellock.h b/sysdeps/unix/sysv/linux/sparc/lowlevellock.h
index 7608c01d17..9fa73371fc 100644
--- a/sysdeps/unix/sysv/linux/sparc/lowlevellock.h
+++ b/sysdeps/unix/sysv/linux/sparc/lowlevellock.h
@@ -126,17 +126,19 @@ __lll_robust_timedlock (int *futex, const struct timespec *abstime,
#define lll_unlock(lock, private) \
((void) ({ \
int *__futex = &(lock); \
+ int __private = (private); \
int __val = atomic_exchange_24_rel (__futex, 0); \
if (__glibc_unlikely (__val > 1)) \
- lll_futex_wake (__futex, 1, private); \
+ lll_futex_wake (__futex, 1, __private); \
}))
#define lll_robust_unlock(lock, private) \
((void) ({ \
int *__futex = &(lock); \
+ int __private = (private); \
int __val = atomic_exchange_rel (__futex, 0); \
if (__glibc_unlikely (__val & FUTEX_WAITERS)) \
- lll_futex_wake (__futex, 1, private); \
+ lll_futex_wake (__futex, 1, __private); \
}))
#define lll_islocked(futex) \