make pointers used in robust list volatile
authorRich Felker <dalias@aerifal.cx>
Sun, 17 Aug 2014 04:46:26 +0000 (00:46 -0400)
committerRich Felker <dalias@aerifal.cx>
Sun, 17 Aug 2014 04:46:26 +0000 (00:46 -0400)
when manipulating the robust list, the order of stores matters,
because the code may be asynchronously interrupted by a fatal signal
and the kernel will then access the robust list in what is essentially
an async-signal context.

previously, aliasing considerations made it seem unlikely that a
compiler could reorder the stores, but proving that they could not be
reordered incorrectly would have been extremely difficult. instead
I've opted to make all the pointers used as part of the robust list,
including those in the robust list head and in the individual mutexes,
volatile.

in addition, the format of the robust list has been changed to point
back to the head at the end, rather than ending with a null pointer.
this is to match the documented kernel robust list ABI. the null
pointer, which was previously used, only worked because faults during
access terminate the robust list processing.

13 files changed:
arch/arm/bits/alltypes.h.in
arch/i386/bits/alltypes.h.in
arch/microblaze/bits/alltypes.h.in
arch/mips/bits/alltypes.h.in
arch/or1k/bits/alltypes.h.in
arch/powerpc/bits/alltypes.h.in
arch/sh/bits/alltypes.h.in
arch/x32/bits/alltypes.h.in
arch/x86_64/bits/alltypes.h.in
src/internal/pthread_impl.h
src/thread/pthread_mutex_trylock.c
src/thread/pthread_mutex_unlock.c
src/thread/pthread_mutexattr_setrobust.c

index bd23a6ae8da1f17bc85e1daa4b3b11f0a0f66282..0d750cc8cdb7f7337a587e4a4627aa5e68473a05 100644 (file)
@@ -17,7 +17,7 @@ TYPEDEF long time_t;
 TYPEDEF long suseconds_t;
 
 TYPEDEF struct { union { int __i[9]; unsigned __s[9]; } __u; } pthread_attr_t;
-TYPEDEF struct { union { int __i[6]; void *__p[6]; } __u; } pthread_mutex_t;
+TYPEDEF struct { union { int __i[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t;
 TYPEDEF struct { union { int __i[12]; void *__p[12]; } __u; } pthread_cond_t;
 TYPEDEF struct { union { int __i[8]; void *__p[8]; } __u; } pthread_rwlock_t;
 TYPEDEF struct { union { int __i[5]; void *__p[5]; } __u; } pthread_barrier_t;
index efd2c077396426a536e91c5aed33b2baa82291e0..502c882265dd29a68bc8add3aa966e9f1c6ab9a5 100644 (file)
@@ -31,7 +31,7 @@ TYPEDEF long time_t;
 TYPEDEF long suseconds_t;
 
 TYPEDEF struct { union { int __i[9]; unsigned __s[9]; } __u; } pthread_attr_t;
-TYPEDEF struct { union { int __i[6]; void *__p[6]; } __u; } pthread_mutex_t;
+TYPEDEF struct { union { int __i[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t;
 TYPEDEF struct { union { int __i[12]; void *__p[12]; } __u; } pthread_cond_t;
 TYPEDEF struct { union { int __i[8]; void *__p[8]; } __u; } pthread_rwlock_t;
 TYPEDEF struct { union { int __i[5]; void *__p[5]; } __u; } pthread_barrier_t;
index 6bd79429e57bba0f76b1223cd75804e22d2ece9e..4657d14da6d59b703ef5c8b8841d198bcd40c1b3 100644 (file)
@@ -17,7 +17,7 @@ TYPEDEF long time_t;
 TYPEDEF long suseconds_t;
 
 TYPEDEF struct { union { int __i[9]; unsigned __s[9]; } __u; } pthread_attr_t;
-TYPEDEF struct { union { int __i[6]; void *__p[6]; } __u; } pthread_mutex_t;
+TYPEDEF struct { union { int __i[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t;
 TYPEDEF struct { union { int __i[12]; void *__p[12]; } __u; } pthread_cond_t;
 TYPEDEF struct { union { int __i[8]; void *__p[8]; } __u; } pthread_rwlock_t;
 TYPEDEF struct { union { int __i[5]; void *__p[5]; } __u; } pthread_barrier_t;
index 6bd79429e57bba0f76b1223cd75804e22d2ece9e..4657d14da6d59b703ef5c8b8841d198bcd40c1b3 100644 (file)
@@ -17,7 +17,7 @@ TYPEDEF long time_t;
 TYPEDEF long suseconds_t;
 
 TYPEDEF struct { union { int __i[9]; unsigned __s[9]; } __u; } pthread_attr_t;
-TYPEDEF struct { union { int __i[6]; void *__p[6]; } __u; } pthread_mutex_t;
+TYPEDEF struct { union { int __i[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t;
 TYPEDEF struct { union { int __i[12]; void *__p[12]; } __u; } pthread_cond_t;
 TYPEDEF struct { union { int __i[8]; void *__p[8]; } __u; } pthread_rwlock_t;
 TYPEDEF struct { union { int __i[5]; void *__p[5]; } __u; } pthread_barrier_t;
index bd23a6ae8da1f17bc85e1daa4b3b11f0a0f66282..0d750cc8cdb7f7337a587e4a4627aa5e68473a05 100644 (file)
@@ -17,7 +17,7 @@ TYPEDEF long time_t;
 TYPEDEF long suseconds_t;
 
 TYPEDEF struct { union { int __i[9]; unsigned __s[9]; } __u; } pthread_attr_t;
-TYPEDEF struct { union { int __i[6]; void *__p[6]; } __u; } pthread_mutex_t;
+TYPEDEF struct { union { int __i[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t;
 TYPEDEF struct { union { int __i[12]; void *__p[12]; } __u; } pthread_cond_t;
 TYPEDEF struct { union { int __i[8]; void *__p[8]; } __u; } pthread_rwlock_t;
 TYPEDEF struct { union { int __i[5]; void *__p[5]; } __u; } pthread_barrier_t;
index e9d8dd8a90cb53d474dbf1bf11192de77fc46636..378124ca1dafeea7cd51ae4d250d369e784b3e7f 100644 (file)
@@ -17,7 +17,7 @@ TYPEDEF long time_t;
 TYPEDEF long suseconds_t;
 
 TYPEDEF struct { union { int __i[9]; unsigned __s[9]; } __u; } pthread_attr_t;
-TYPEDEF struct { union { int __i[6]; void *__p[6]; } __u; } pthread_mutex_t;
+TYPEDEF struct { union { int __i[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t;
 TYPEDEF struct { union { int __i[12]; void *__p[12]; } __u; } pthread_cond_t;
 TYPEDEF struct { union { int __i[8]; void *__p[8]; } __u; } pthread_rwlock_t;
 TYPEDEF struct { union { int __i[5]; void *__p[5]; } __u; } pthread_barrier_t;
index e9d8dd8a90cb53d474dbf1bf11192de77fc46636..378124ca1dafeea7cd51ae4d250d369e784b3e7f 100644 (file)
@@ -17,7 +17,7 @@ TYPEDEF long time_t;
 TYPEDEF long suseconds_t;
 
 TYPEDEF struct { union { int __i[9]; unsigned __s[9]; } __u; } pthread_attr_t;
-TYPEDEF struct { union { int __i[6]; void *__p[6]; } __u; } pthread_mutex_t;
+TYPEDEF struct { union { int __i[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t;
 TYPEDEF struct { union { int __i[12]; void *__p[12]; } __u; } pthread_cond_t;
 TYPEDEF struct { union { int __i[8]; void *__p[8]; } __u; } pthread_rwlock_t;
 TYPEDEF struct { union { int __i[5]; void *__p[5]; } __u; } pthread_barrier_t;
index b077fc930114d25d0a5487678caa92ab67365eb5..8930efa3c2dbde995f8f8af6e9909c3658fa5a5f 100644 (file)
@@ -22,7 +22,7 @@ TYPEDEF long long time_t;
 TYPEDEF long long suseconds_t;
 
 TYPEDEF struct { union { int __i[14]; unsigned long __s[7]; } __u; } pthread_attr_t;
-TYPEDEF struct { union { int __i[10]; void *__p[5]; } __u; } pthread_mutex_t;
+TYPEDEF struct { union { int __i[10]; volatile void *volatile __p[5]; } __u; } pthread_mutex_t;
 TYPEDEF struct { union { int __i[12]; void *__p[6]; } __u; } pthread_cond_t;
 TYPEDEF struct { union { int __i[14]; void *__p[7]; } __u; } pthread_rwlock_t;
 TYPEDEF struct { union { int __i[8]; void *__p[4]; } __u; } pthread_barrier_t;
index 277e94480825e9b5c62cf8956d1ed52c4a4f2512..34b7d6ac2373e3ca61ecbac7302fee961b837a43 100644 (file)
@@ -22,7 +22,7 @@ TYPEDEF long time_t;
 TYPEDEF long suseconds_t;
 
 TYPEDEF struct { union { int __i[14]; unsigned long __s[7]; } __u; } pthread_attr_t;
-TYPEDEF struct { union { int __i[10]; void *__p[5]; } __u; } pthread_mutex_t;
+TYPEDEF struct { union { int __i[10]; volatile void *volatile __p[5]; } __u; } pthread_mutex_t;
 TYPEDEF struct { union { int __i[12]; void *__p[6]; } __u; } pthread_cond_t;
 TYPEDEF struct { union { int __i[14]; void *__p[7]; } __u; } pthread_rwlock_t;
 TYPEDEF struct { union { int __i[8]; void *__p[4]; } __u; } pthread_barrier_t;
index 826191c2dc77cb6f0fbf7e538f9ec29c4da91055..848ff668cd6656043fc535320435273cb8be830c 100644 (file)
@@ -33,9 +33,9 @@ struct pthread {
        pthread_attr_t attr;
        volatile int dead;
        struct {
-               void **head;
+               volatile void *volatile head;
                long off;
-               void *pending;
+               volatile void *volatile pending;
        } robust_list;
        int unblock_cancel;
        int timer_id;
index 8d25661481854652ea89e72646d4dd4dea22469d..31587e1f3f58d93b64c1507892e723531e450edf 100644 (file)
@@ -9,6 +9,7 @@ int __pthread_mutex_trylock_owner(pthread_mutex_t *m)
 
        if (!self->robust_list.off) {
                __syscall(SYS_set_robust_list, &self->robust_list, 3*sizeof(long));
+               self->robust_list.head = &self->robust_list.head;
                self->robust_list.off = (char*)&m->_m_lock-(char *)&m->_m_next;
        }
 
@@ -29,10 +30,11 @@ int __pthread_mutex_trylock_owner(pthread_mutex_t *m)
                return EBUSY;
        }
 
-       m->_m_next = self->robust_list.head;
+       volatile void *next = self->robust_list.head;
+       m->_m_next = next;
        m->_m_prev = &self->robust_list.head;
-       if (self->robust_list.head)
-               self->robust_list.head[-1] = &m->_m_next;
+       if (next != &self->robust_list.head) *(volatile void *volatile *)
+               ((char *)next - sizeof(void *)) = &m->_m_next;
        self->robust_list.head = &m->_m_next;
        self->robust_list.pending = 0;
 
index 4283751619681a42ca0198ad3cef43e0e85ae88b..46761d9aec4c4c3465ca10b89e2baf1ad4399e56 100644 (file)
@@ -21,8 +21,11 @@ int pthread_mutex_unlock(pthread_mutex_t *m)
                        self->robust_list.pending = &m->_m_next;
                        __vm_lock_impl(+1);
                }
-               *(void **)m->_m_prev = m->_m_next;
-               if (m->_m_next) ((void **)m->_m_next)[-1] = m->_m_prev;
+               volatile void *prev = m->_m_prev;
+               volatile void *next = m->_m_next;
+               *(volatile void *volatile *)prev = next;
+               if (next != &self->robust_list.head) *(volatile void *volatile *)
+                       ((char *)next - sizeof(void *)) = prev;
        }
        cont = a_swap(&m->_m_lock, (type & 8) ? 0x40000000 : 0);
        if (type != PTHREAD_MUTEX_NORMAL && !priv) {
index 8948cbafbbc88268889d63569abe463fbd11ca71..d06278894a47cd5bb44a1d12e7f525d34ecb777e 100644 (file)
@@ -4,16 +4,18 @@
 void __do_private_robust_list()
 {
        pthread_t self = __pthread_self();
-       void **p, **prev, **next;
+       volatile void *volatile *p;
+       volatile void *volatile *prev;
+       volatile void *volatile *next;
        pthread_mutex_t *m;
 
-       for (prev=0, p=self->robust_list.head; p; p=next) {
+       prev = &self->robust_list.head;
+       for (p=self->robust_list.head; p&&p!=&self->robust_list.head; p=next) {
                next = *p;
                m = (void *)((char *)p - offsetof(pthread_mutex_t, _m_next));
                if (!(m->_m_type & 128)) {
                        int waiters = m->_m_waiters;
-                       if (prev) *prev = next;
-                       else self->robust_list.head = next;
+                       *prev = next;
                        int cont = a_swap(&m->_m_lock, self->tid|0x40000000);
                        if (cont < 0 || waiters) __wake(&m->_m_lock, 1, 1);
                } else {