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 bd23a6a..0d750cc 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 efd2c07..502c882 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 6bd7942..4657d14 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 6bd7942..4657d14 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 bd23a6a..0d750cc 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 e9d8dd8..378124c 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 e9d8dd8..378124c 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 b077fc9..8930efa 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 277e944..34b7d6a 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 826191c..848ff66 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 8d25661..31587e1 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 4283751..46761d9 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 8948cba..d062788 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 {