diff options
author | Rich Felker <dalias@aerifal.cx> | 2015-03-03 22:50:02 -0500 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2015-03-03 22:50:02 -0500 |
commit | 56fbaa3bbe73f12af2bfbbcf2adb196e6f9fe264 (patch) | |
tree | 09fbe371b108e25bb2f9c90e74da356359950d29 /src | |
parent | eb4bd8d8bb5c9f535ee8250edd4efbd3d4f84c5a (diff) | |
download | musl-56fbaa3bbe73f12af2bfbbcf2adb196e6f9fe264.tar.gz musl-56fbaa3bbe73f12af2bfbbcf2adb196e6f9fe264.tar.xz musl-56fbaa3bbe73f12af2bfbbcf2adb196e6f9fe264.zip |
make all objects used with atomic operations volatile
the memory model we use internally for atomics permits plain loads of values which may be subject to concurrent modification without requiring that a special load function be used. since a compiler is free to make transformations that alter the number of loads or the way in which loads are performed, the compiler is theoretically free to break this usage. the most obvious concern is with atomic cas constructs: something of the form tmp=*p;a_cas(p,tmp,f(tmp)); could be transformed to a_cas(p,*p,f(*p)); where the latter is intended to show multiple loads of *p whose resulting values might fail to be equal; this would break the atomicity of the whole operation. but even more fundamental breakage is possible. with the changes being made now, objects that may be modified by atomics are modeled as volatile, and the atomic operations performed on them by other threads are modeled as asynchronous stores by hardware which happens to be acting on the request of another thread. such modeling of course does not itself address memory synchronization between cores/cpus, but that aspect was already handled. this all seems less than ideal, but it's the best we can do without mandating a C11 compiler and using the C11 model for atomics. in the case of pthread_once_t, the ABI type of the underlying object is not volatile-qualified. so we are assuming that accessing the object through a volatile-qualified lvalue via casts yields volatile access semantics. the language of the C standard is somewhat unclear on this matter, but this is an assumption the linux kernel also makes, and seems to be the correct interpretation of the standard.
Diffstat (limited to 'src')
-rw-r--r-- | src/aio/aio.c | 3 | ||||
-rw-r--r-- | src/dirent/__dirent.h | 2 | ||||
-rw-r--r-- | src/exit/at_quick_exit.c | 2 | ||||
-rw-r--r-- | src/exit/atexit.c | 2 | ||||
-rw-r--r-- | src/internal/libc.h | 6 | ||||
-rw-r--r-- | src/internal/pthread_impl.h | 30 | ||||
-rw-r--r-- | src/internal/stdio_impl.h | 4 | ||||
-rw-r--r-- | src/ldso/dynlink.c | 2 | ||||
-rw-r--r-- | src/locale/__setlocalecat.c | 2 | ||||
-rw-r--r-- | src/locale/dcngettext.c | 8 | ||||
-rw-r--r-- | src/malloc/lite_malloc.c | 2 | ||||
-rw-r--r-- | src/malloc/malloc.c | 10 | ||||
-rw-r--r-- | src/misc/syslog.c | 4 | ||||
-rw-r--r-- | src/prng/random.c | 2 | ||||
-rw-r--r-- | src/thread/pthread_atfork.c | 2 | ||||
-rw-r--r-- | src/thread/pthread_barrier_wait.c | 8 | ||||
-rw-r--r-- | src/thread/pthread_cond_timedwait.c | 10 | ||||
-rw-r--r-- | src/thread/pthread_key_create.c | 2 | ||||
-rw-r--r-- | src/thread/pthread_once.c | 2 | ||||
-rw-r--r-- | src/thread/sem_open.c | 2 | ||||
-rw-r--r-- | src/thread/sem_timedwait.c | 2 | ||||
-rw-r--r-- | src/thread/synccall.c | 4 | ||||
-rw-r--r-- | src/thread/vmlock.c | 2 | ||||
-rw-r--r-- | src/time/__tz.c | 2 | ||||
-rw-r--r-- | src/time/clock_gettime.c | 2 |
25 files changed, 60 insertions, 57 deletions
diff --git a/src/aio/aio.c b/src/aio/aio.c index d1ee7681..aafd8e8c 100644 --- a/src/aio/aio.c +++ b/src/aio/aio.c @@ -53,7 +53,8 @@ struct aio_thread { struct aiocb *cb; struct aio_thread *next, *prev; struct aio_queue *q; - int running, err, op; + volatile int running; + int err, op; ssize_t ret; }; diff --git a/src/dirent/__dirent.h b/src/dirent/__dirent.h index 45509e19..32871baf 100644 --- a/src/dirent/__dirent.h +++ b/src/dirent/__dirent.h @@ -4,6 +4,6 @@ struct __dirstream off_t tell; int buf_pos; int buf_end; - int lock[2]; + volatile int lock[2]; char buf[2048]; }; diff --git a/src/exit/at_quick_exit.c b/src/exit/at_quick_exit.c index 85c3d26e..34541bad 100644 --- a/src/exit/at_quick_exit.c +++ b/src/exit/at_quick_exit.c @@ -5,7 +5,7 @@ static void (*funcs[COUNT])(void); static int count; -static int lock[2]; +static volatile int lock[2]; void __funcs_on_quick_exit() { diff --git a/src/exit/atexit.c b/src/exit/atexit.c index 89ff4ff3..be827181 100644 --- a/src/exit/atexit.c +++ b/src/exit/atexit.c @@ -12,7 +12,7 @@ static struct fl void *a[COUNT]; } builtin, *head; -static int lock[2]; +static volatile int lock[2]; void __funcs_on_exit() { diff --git a/src/internal/libc.h b/src/internal/libc.h index 2eef98e4..3751cca2 100644 --- a/src/internal/libc.h +++ b/src/internal/libc.h @@ -8,9 +8,9 @@ struct __locale_map; struct __locale_struct { - int ctype_utf8; + volatile int ctype_utf8; char *messages_name; - struct __locale_map *cat[4]; + struct __locale_map *volatile cat[4]; }; struct __libc { @@ -21,7 +21,7 @@ struct __libc { size_t *auxv; volatile int threads_minus_1; FILE *ofl_head; - int ofl_lock[2]; + volatile int ofl_lock[2]; size_t tls_size; size_t page_size; volatile int uselocale_cnt; diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h index 7e7baa90..441b075f 100644 --- a/src/internal/pthread_impl.h +++ b/src/internal/pthread_impl.h @@ -38,11 +38,11 @@ struct pthread { volatile void *volatile pending; } robust_list; int unblock_cancel; - int timer_id; + volatile int timer_id; locale_t locale; - int killlock[2]; - int exitlock[2]; - int startlock[2]; + volatile int killlock[2]; + volatile int exitlock[2]; + volatile int startlock[2]; unsigned long sigmask[_NSIG/8/sizeof(long)]; void *stdio_locks; }; @@ -62,26 +62,26 @@ struct __timer { #define _a_policy __u.__i[3*__SU+2] #define _a_prio __u.__i[3*__SU+3] #define _m_type __u.__i[0] -#define _m_lock __u.__i[1] -#define _m_waiters __u.__i[2] +#define _m_lock __u.__vi[1] +#define _m_waiters __u.__vi[2] #define _m_prev __u.__p[3] #define _m_next __u.__p[4] #define _m_count __u.__i[5] #define _c_shared __u.__p[0] -#define _c_seq __u.__i[2] -#define _c_waiters __u.__i[3] +#define _c_seq __u.__vi[2] +#define _c_waiters __u.__vi[3] #define _c_clock __u.__i[4] -#define _c_lock __u.__i[8] +#define _c_lock __u.__vi[8] #define _c_head __u.__p[1] #define _c_tail __u.__p[5] -#define _rw_lock __u.__i[0] -#define _rw_waiters __u.__i[1] +#define _rw_lock __u.__vi[0] +#define _rw_waiters __u.__vi[1] #define _rw_shared __u.__i[2] -#define _b_lock __u.__i[0] -#define _b_waiters __u.__i[1] +#define _b_lock __u.__vi[0] +#define _b_waiters __u.__vi[1] #define _b_limit __u.__i[2] -#define _b_count __u.__i[3] -#define _b_waiters2 __u.__i[4] +#define _b_count __u.__vi[3] +#define _b_waiters2 __u.__vi[4] #define _b_inst __u.__p[3] #include "pthread_arch.h" diff --git a/src/internal/stdio_impl.h b/src/internal/stdio_impl.h index d659522f..e1325fe1 100644 --- a/src/internal/stdio_impl.h +++ b/src/internal/stdio_impl.h @@ -38,8 +38,8 @@ struct _IO_FILE { short dummy3; signed char mode; signed char lbf; - int lock; - int waiters; + volatile int lock; + volatile int waiters; void *cookie; off_t off; char *getln_buf; diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c index 00af8865..0bdc988c 100644 --- a/src/ldso/dynlink.c +++ b/src/ldso/dynlink.c @@ -85,7 +85,7 @@ struct dso { size_t relro_start, relro_end; void **new_dtv; unsigned char *new_tls; - int new_dtv_idx, new_tls_idx; + volatile int new_dtv_idx, new_tls_idx; struct td_index *td_index; struct dso *fini_next; char *shortname; diff --git a/src/locale/__setlocalecat.c b/src/locale/__setlocalecat.c index 1c894d9c..c93e9ba0 100644 --- a/src/locale/__setlocalecat.c +++ b/src/locale/__setlocalecat.c @@ -17,7 +17,7 @@ char *__strchrnul(const char *, int); static struct __locale_map *findlocale(const char *name, size_t n) { - static void *loc_head; + static void *volatile loc_head; struct __locale_map *p, *new, *old_head; const char *path = 0, *z; char buf[256]; diff --git a/src/locale/dcngettext.c b/src/locale/dcngettext.c index d3462fd2..0057cb56 100644 --- a/src/locale/dcngettext.c +++ b/src/locale/dcngettext.c @@ -12,7 +12,7 @@ struct binding { struct binding *next; int dirlen; - int active; + volatile int active; char *domainname; char *dirname; char buf[]; @@ -34,7 +34,7 @@ static char *gettextdir(const char *domainname, size_t *dirlen) char *bindtextdomain(const char *domainname, const char *dirname) { - static int lock[2]; + static volatile int lock[2]; struct binding *p, *q; if (!domainname) return 0; @@ -96,8 +96,8 @@ struct msgcat { struct msgcat *next; const void *map; size_t map_size; - void *plural_rule; - int nplurals; + void *volatile plural_rule; + volatile int nplurals; char name[]; }; diff --git a/src/malloc/lite_malloc.c b/src/malloc/lite_malloc.c index 673966a1..7643fc2c 100644 --- a/src/malloc/lite_malloc.c +++ b/src/malloc/lite_malloc.c @@ -12,7 +12,7 @@ void *__simple_malloc(size_t n) { static uintptr_t cur, brk; uintptr_t base, new; - static int lock[2]; + static volatile int lock[2]; size_t align=1; if (!n) n++; diff --git a/src/malloc/malloc.c b/src/malloc/malloc.c index 7932a975..70c7b3f3 100644 --- a/src/malloc/malloc.c +++ b/src/malloc/malloc.c @@ -25,7 +25,7 @@ struct chunk { }; struct bin { - int lock[2]; + volatile int lock[2]; struct chunk *head; struct chunk *tail; }; @@ -33,10 +33,10 @@ struct bin { static struct { uintptr_t brk; size_t *heap; - uint64_t binmap; + volatile uint64_t binmap; struct bin bins[64]; - int brk_lock[2]; - int free_lock[2]; + volatile int brk_lock[2]; + volatile int free_lock[2]; unsigned mmap_step; } mal; @@ -205,7 +205,7 @@ fail: static int init_malloc(size_t n) { - static int init, waiters; + static volatile int init, waiters; int state; struct chunk *c; diff --git a/src/misc/syslog.c b/src/misc/syslog.c index d5874991..b934a686 100644 --- a/src/misc/syslog.c +++ b/src/misc/syslog.c @@ -12,11 +12,11 @@ #include "libc.h" #include "atomic.h" -static int lock[2]; +static volatile int lock[2]; static char log_ident[32]; static int log_opt; static int log_facility = LOG_USER; -static int log_mask = 0xff; +static volatile int log_mask = 0xff; static int log_fd = -1; int setlogmask(int maskpri) diff --git a/src/prng/random.c b/src/prng/random.c index e250e28e..7d557d70 100644 --- a/src/prng/random.c +++ b/src/prng/random.c @@ -22,7 +22,7 @@ static int n = 31; static int i = 3; static int j = 0; static uint32_t *x = init+1; -static int lock[2]; +static volatile int lock[2]; static uint32_t lcg31(uint32_t x) { return (1103515245*x + 12345) & 0x7fffffff; diff --git a/src/thread/pthread_atfork.c b/src/thread/pthread_atfork.c index 95fce207..a40d7f63 100644 --- a/src/thread/pthread_atfork.c +++ b/src/thread/pthread_atfork.c @@ -8,7 +8,7 @@ static struct atfork_funcs { struct atfork_funcs *prev, *next; } *funcs; -static int lock[2]; +static volatile int lock[2]; void __fork_handler(int who) { diff --git a/src/thread/pthread_barrier_wait.c b/src/thread/pthread_barrier_wait.c index e15abb84..bfeb3464 100644 --- a/src/thread/pthread_barrier_wait.c +++ b/src/thread/pthread_barrier_wait.c @@ -54,10 +54,10 @@ static int pshared_barrier_wait(pthread_barrier_t *b) struct instance { - int count; - int last; - int waiters; - int finished; + volatile int count; + volatile int last; + volatile int waiters; + volatile int finished; }; int pthread_barrier_wait(pthread_barrier_t *b) diff --git a/src/thread/pthread_cond_timedwait.c b/src/thread/pthread_cond_timedwait.c index f5fd08c0..27b1a99a 100644 --- a/src/thread/pthread_cond_timedwait.c +++ b/src/thread/pthread_cond_timedwait.c @@ -29,8 +29,8 @@ int __pthread_setcancelstate(int, int *); struct waiter { struct waiter *prev, *next; - int state, barrier; - int *notify; + volatile int state, barrier; + volatile int *notify; }; /* Self-synchronized-destruction-safe lock functions */ @@ -67,7 +67,8 @@ enum { int __pthread_cond_timedwait(pthread_cond_t *restrict c, pthread_mutex_t *restrict m, const struct timespec *restrict ts) { struct waiter node = { 0 }; - int e, seq, *fut, clock = c->_c_clock, cs, shared=0, oldstate, tmp; + int e, seq, clock = c->_c_clock, cs, shared=0, oldstate, tmp; + volatile int *fut; if ((m->_m_type&15) && (m->_m_lock&INT_MAX) != __pthread_self()->tid) return EPERM; @@ -175,7 +176,8 @@ done: int __private_cond_signal(pthread_cond_t *c, int n) { struct waiter *p, *first=0; - int ref = 0, cur; + volatile int ref = 0; + int cur; lock(&c->_c_lock); for (p=c->_c_tail; n && p; p=p->prev) { diff --git a/src/thread/pthread_key_create.c b/src/thread/pthread_key_create.c index bfcd5976..198ae56e 100644 --- a/src/thread/pthread_key_create.c +++ b/src/thread/pthread_key_create.c @@ -3,7 +3,7 @@ volatile size_t __pthread_tsd_size = sizeof(void *) * PTHREAD_KEYS_MAX; void *__pthread_tsd_main[PTHREAD_KEYS_MAX] = { 0 }; -static void (*keys[PTHREAD_KEYS_MAX])(void *); +static void (*volatile keys[PTHREAD_KEYS_MAX])(void *); static void nodtor(void *dummy) { diff --git a/src/thread/pthread_once.c b/src/thread/pthread_once.c index df655ef9..a8f8aeb1 100644 --- a/src/thread/pthread_once.c +++ b/src/thread/pthread_once.c @@ -40,7 +40,7 @@ int __pthread_once(pthread_once_t *control, void (*init)(void)) { /* Return immediately if init finished before, but ensure that * effects of the init routine are visible to the caller. */ - if (*control == 2) { + if (*(volatile int *)control == 2) { a_barrier(); return 0; } diff --git a/src/thread/sem_open.c b/src/thread/sem_open.c index 9a95d257..ab884a42 100644 --- a/src/thread/sem_open.c +++ b/src/thread/sem_open.c @@ -20,7 +20,7 @@ static struct { sem_t *sem; int refcnt; } *semtab; -static int lock[2]; +static volatile int lock[2]; #define FLAGS (O_RDWR|O_NOFOLLOW|O_CLOEXEC|O_NONBLOCK) diff --git a/src/thread/sem_timedwait.c b/src/thread/sem_timedwait.c index a7488df7..8132eb1b 100644 --- a/src/thread/sem_timedwait.c +++ b/src/thread/sem_timedwait.c @@ -19,7 +19,7 @@ int sem_timedwait(sem_t *restrict sem, const struct timespec *restrict at) int r; a_inc(sem->__val+1); a_cas(sem->__val, 0, -1); - pthread_cleanup_push(cleanup, sem->__val+1); + pthread_cleanup_push(cleanup, (void *)(sem->__val+1)); r = __timedwait_cp(sem->__val, -1, CLOCK_REALTIME, at, sem->__val[2]); pthread_cleanup_pop(1); if (r && r != EINTR) { diff --git a/src/thread/synccall.c b/src/thread/synccall.c index 47d070b4..000ec4e3 100644 --- a/src/thread/synccall.c +++ b/src/thread/synccall.c @@ -14,8 +14,8 @@ static struct chain { sem_t target_sem, caller_sem; } *volatile head; -static int synccall_lock[2]; -static int target_tid; +static volatile int synccall_lock[2]; +static volatile int target_tid; static void (*callback)(void *), *context; static volatile int dummy = 0; weak_alias(dummy, __block_new_threads); diff --git a/src/thread/vmlock.c b/src/thread/vmlock.c index aba9e311..125c6dc9 100644 --- a/src/thread/vmlock.c +++ b/src/thread/vmlock.c @@ -1,6 +1,6 @@ #include "pthread_impl.h" -static int vmlock[2]; +static volatile int vmlock[2]; void __vm_lock(int inc) { diff --git a/src/time/__tz.c b/src/time/__tz.c index 4ce20258..13cb1aed 100644 --- a/src/time/__tz.c +++ b/src/time/__tz.c @@ -27,7 +27,7 @@ static char old_tz_buf[32]; static char *old_tz = old_tz_buf; static size_t old_tz_size = sizeof old_tz_buf; -static int lock[2]; +static volatile int lock[2]; static int getint(const char **p) { diff --git a/src/time/clock_gettime.c b/src/time/clock_gettime.c index 799251d8..1572de0e 100644 --- a/src/time/clock_gettime.c +++ b/src/time/clock_gettime.c @@ -26,7 +26,7 @@ void *__vdsosym(const char *, const char *); int __clock_gettime(clockid_t clk, struct timespec *ts) { #ifdef VDSO_CGT_SYM - static int (*cgt)(clockid_t, struct timespec *); + static int (*volatile cgt)(clockid_t, struct timespec *); if (!cgt) { void *f = __vdsosym(VDSO_CGT_VER, VDSO_CGT_SYM); if (!f) f = (void *)sc_clock_gettime; |