summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2016-09-06 20:13:30 +0200
committerwm4 <wm4@nowhere>2016-09-06 20:15:07 +0200
commitc6b7a4dacee3067ad00abdb3abf71c7e8eb62e78 (patch)
treec397ec6d8704c62657a15d31077ce9e848605a89
parent2a4e7dcaade6e4e772f614d931eeee59c9e768c9 (diff)
downloadmpv-c6b7a4dacee3067ad00abdb3abf71c7e8eb62e78.tar.bz2
mpv-c6b7a4dacee3067ad00abdb3abf71c7e8eb62e78.tar.xz
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.
-rw-r--r--osdep/atomics.h43
-rw-r--r--player/main.c4
-rw-r--r--wscript8
3 files changed, 53 insertions, 2 deletions
diff --git a/osdep/atomics.h b/osdep/atomics.h
index bfcaa38977..1d5134f646 100644
--- a/osdep/atomics.h
+++ b/osdep/atomics.h
@@ -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 */
diff --git a/player/main.c b/player/main.c
index 0bf207f5b7..b1aa30f9c3 100644
--- a/player/main.c
+++ b/player/main.c
@@ -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,
diff --git a/wscript b/wscript
index 5553b23c72..7eed072bb6 100644
--- a/wscript
+++ b/wscript
@@ -149,6 +149,10 @@ main_dependencies = [
'req': True,
'fmsg': 'Unable to find pthreads support.'
}, {
+ 'name': 'gnuc',
+ 'desc': 'GNU C extensions',
+ 'func': check_statement([], "__GNUC__"),
+ }, {
'name': 'stdatomic',
'desc': 'stdatomic.h',
'func': check_libs(['atomic'],
@@ -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',