atomics: readd some emulation

This time it's emulation that's supposed to work (not just dummied out).
Unlike the previous emulation, no mpv code has to be disabled, and
everything should work (albeit possibly a bit slowly). On the other
hand, it's not possible to implement this kind of emulation without
compiler support. We use GNU statement expressions and __typeof__ in
this case.

This code is inactive if stdatomic.h is available.
This commit is contained in:
wm4 2016-09-06 20:13:30 +02:00
parent 2a4e7dcaad
commit c6b7a4dace
3 changed files with 53 additions and 2 deletions

View File

@ -80,6 +80,49 @@ typedef struct { volatile unsigned long long v; } atomic_ullong;
if (!ok_) *(old) = val_; \
ok_; })
#elif defined(__GNUC__)
#include <pthread.h>
extern pthread_mutex_t mp_atomic_mutex;
#define atomic_load(p) \
({ __typeof__(p) p_ = (p); \
pthread_mutex_lock(&mp_atomic_mutex); \
__typeof__(p_->v) v = p_->v; \
pthread_mutex_unlock(&mp_atomic_mutex); \
v; })
#define atomic_store(p, val) \
({ __typeof__(val) val_ = (val); \
__typeof__(p) p_ = (p); \
pthread_mutex_lock(&mp_atomic_mutex); \
p_->v = val_; \
pthread_mutex_unlock(&mp_atomic_mutex); })
#define atomic_fetch_op(a, b, op) \
({ __typeof__(a) a_ = (a); \
__typeof__(b) b_ = (b); \
pthread_mutex_lock(&mp_atomic_mutex); \
__typeof__(a_->v) v = a_->v; \
a_->v = v op b_; \
pthread_mutex_unlock(&mp_atomic_mutex); \
v; })
#define atomic_fetch_add(a, b) atomic_fetch_op(a, b, +)
#define atomic_fetch_and(a, b) atomic_fetch_op(a, b, &)
#define atomic_fetch_or(a, b) atomic_fetch_op(a, b, |)
#define atomic_compare_exchange_strong(p, old, new) \
({ __typeof__(p) p_ = (p); \
__typeof__(old) old_ = (old); \
__typeof__(new) new_ = (new); \
pthread_mutex_lock(&mp_atomic_mutex); \
int res = p_->v == *old_; \
if (res) { \
p_->v = new_; \
} else { \
*old_ = p_->v; \
} \
pthread_mutex_unlock(&mp_atomic_mutex); \
res; })
#else
# error "this should have been a configuration error, report a bug please"
#endif /* no atomics */

View File

@ -75,6 +75,10 @@
#define FULLCONFIG "(missing)\n"
#endif
#if !(HAVE_STDATOMIC || HAVE_ATOMIC_BUILTINS || HAVE_SYNC_BUILTINS)
pthread_mutex_t mp_atomic_mutex = PTHREAD_MUTEX_INITIALIZER;
#endif
enum exit_reason {
EXIT_NONE,
EXIT_NORMAL,

View File

@ -148,6 +148,10 @@ main_dependencies = [
'func': check_pthreads,
'req': True,
'fmsg': 'Unable to find pthreads support.'
}, {
'name': 'gnuc',
'desc': 'GNU C extensions',
'func': check_statement([], "__GNUC__"),
}, {
'name': 'stdatomic',
'desc': 'stdatomic.h',
@ -173,10 +177,10 @@ main_dependencies = [
'deps_neg': [ 'stdatomic', 'atomic-builtins' ],
}, {
'name': 'atomics',
'desc': 'compiler support for usable thread synchronization built-ins',
'desc': 'stdatomic.h support or emulation',
'func': check_true,
'req': True,
'deps_any': ['stdatomic', 'atomic-builtins', 'sync-builtins'],
'deps_any': ['stdatomic', 'atomic-builtins', 'sync-builtins', 'gnuc'],
}, {
'name': 'c11-tls',
'desc': 'C11 TLS support',