aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--ruby_atomic.h7
-rw-r--r--signal.c13
3 files changed, 27 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index 3ea832658e..8a05c03386 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Tue Nov 27 18:51:06 2012 Naohisa Goto <ngotogenome@gmail.com>
+
+ * ruby_atomic.h (ATOMIC_CAS): added for Solaris and other platforms.
+ * ruby_atomic.h, signal.c (NEED_RUBY_ATOMIC_OPS): renamed from
+ NEED_RUBY_ATOMIC_EXCHANGE.
+ * signal.c (ruby_atomic_compare_and_swap): naive, non-atomic
+ compare-and-swap implementation only used for platforms without
+ valid support for atomic operations.
+
Tue Nov 27 17:43:46 2012 Eric Hodel <drbrain@segment7.net>
* lib/rdoc/*: Added --root option for building documentation outside
diff --git a/ruby_atomic.h b/ruby_atomic.h
index dd23964f76..135a8c7e79 100644
--- a/ruby_atomic.h
+++ b/ruby_atomic.h
@@ -73,6 +73,7 @@ typedef unsigned int rb_atomic_t;
# define ATOMIC_DEC(var) atomic_dec_uint(&(var))
# define ATOMIC_OR(var, val) atomic_or_uint(&(var), (val))
# define ATOMIC_EXCHANGE(var, val) atomic_swap_uint(&(var), (val))
+# define ATOMIC_CAS(var, oldval, newval) atomic_cas_uint(&(var), (oldval), (newval))
# if SIZEOF_SIZE_T == SIZEOF_LONG
# define ATOMIC_SIZE_ADD(var, val) atomic_add_long(&(var), (val))
@@ -90,14 +91,18 @@ typedef unsigned int rb_atomic_t;
#else
typedef int rb_atomic_t;
-#define NEED_RUBY_ATOMIC_EXCHANGE
+#define NEED_RUBY_ATOMIC_OPS
extern rb_atomic_t ruby_atomic_exchange(rb_atomic_t *ptr, rb_atomic_t val);
+extern rb_atomic_t ruby_atomic_compare_and_swap(rb_atomic_t *ptr,
+ rb_atomic_t cmp,
+ rb_atomic_t newval);
# define ATOMIC_SET(var, val) (void)((var) = (val))
# define ATOMIC_INC(var) ((var)++)
# define ATOMIC_DEC(var) ((var)--)
# define ATOMIC_OR(var, val) ((var) |= (val))
# define ATOMIC_EXCHANGE(var, val) ruby_atomic_exchange(&(var), (val))
+# define ATOMIC_CAS(var, oldval, newval) ruby_atomic_compare_and_swap(&(var), (oldval), (newval))
# define ATOMIC_SIZE_ADD(var, val) (void)((var) += (val))
# define ATOMIC_SIZE_SUB(var, val) (void)((var) -= (val))
diff --git a/signal.c b/signal.c
index ba19e6d0af..f419d45845 100644
--- a/signal.c
+++ b/signal.c
@@ -23,7 +23,7 @@
# include "nacl/signal.h"
#endif
-#ifdef NEED_RUBY_ATOMIC_EXCHANGE
+#ifdef NEED_RUBY_ATOMIC_OPS
rb_atomic_t
ruby_atomic_exchange(rb_atomic_t *ptr, rb_atomic_t val)
{
@@ -31,6 +31,17 @@ ruby_atomic_exchange(rb_atomic_t *ptr, rb_atomic_t val)
*ptr = val;
return old;
}
+
+rb_atomic_t
+ruby_atomic_compare_and_swap(rb_atomic_t *ptr, rb_atomic_t cmp,
+ rb_atomic_t newval)
+{
+ rb_atomic_t old = *ptr;
+ if (old == cmp) {
+ *ptr = newval;
+ }
+ return old;
+}
#endif
#if defined(__BEOS__) || defined(__HAIKU__)