[前][次][番号順一覧][スレッド一覧]

ruby-changes:39417

From: nobu <ko1@a...>
Date: Thu, 6 Aug 2015 10:44:19 +0900 (JST)
Subject: [ruby-changes:39417] nobu:r51498 (trunk): ruby_atomic.h: atomic VALUE operations

nobu	2015-08-06 10:44:03 +0900 (Thu, 06 Aug 2015)

  New Revision: 51498

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=51498

  Log:
    ruby_atomic.h: atomic VALUE operations
    
    * ruby_atomic.h (ATOMIC_VALUE_EXCHANGE, ATOMIC_VALUE_CAS): add
      atomic operations for VALUE.

  Modified files:
    trunk/ChangeLog
    trunk/eval.c
    trunk/gc.c
    trunk/node.c
    trunk/ruby_atomic.h
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 51497)
+++ ChangeLog	(revision 51498)
@@ -1,3 +1,8 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Thu Aug  6 10:44:00 2015  Nobuyoshi Nakada  <nobu@r...>
+
+	* ruby_atomic.h (ATOMIC_VALUE_EXCHANGE, ATOMIC_VALUE_CAS): add
+	  atomic operations for VALUE.
+
 Thu Aug  6 08:15:49 2015  Aaron Patterson <tenderlove@r...>
 
 	* ext/openssl/lib/openssl/ssl.rb (module OpenSSL): move
Index: ruby_atomic.h
===================================================================
--- ruby_atomic.h	(revision 51497)
+++ ruby_atomic.h	(revision 51498)
@@ -17,8 +17,7 @@ typedef unsigned int rb_atomic_t; https://github.com/ruby/ruby/blob/trunk/ruby_atomic.h#L17
 # define ATOMIC_SIZE_ADD(var, val) __atomic_fetch_add(&(var), (val), __ATOMIC_SEQ_CST)
 # define ATOMIC_SIZE_SUB(var, val) __atomic_fetch_sub(&(var), (val), __ATOMIC_SEQ_CST)
 
-# define ATOMIC_PTR_EXCHANGE(var, val) __atomic_exchange_n(&(var), (val), __ATOMIC_SEQ_CST)
-# define ATOMIC_PTR_CAS(var, oldval, newval) ATOMIC_CAS(var, oldval, newval)
+# define RUBY_ATOMIC_GENERIC_MACRO 1
 
 #elif defined HAVE_GCC_SYNC_BUILTINS
 /* @shyouhei hack to support atomic operations in case of gcc. Gcc
@@ -36,8 +35,7 @@ typedef unsigned int rb_atomic_t; /* Any https://github.com/ruby/ruby/blob/trunk/ruby_atomic.h#L35
 # define ATOMIC_SIZE_ADD(var, val) __sync_fetch_and_add(&(var), (val))
 # define ATOMIC_SIZE_SUB(var, val) __sync_fetch_and_sub(&(var), (val))
 
-# define ATOMIC_PTR_EXCHANGE(var, val) __sync_lock_test_and_set(&(var), (val))
-# define ATOMIC_PTR_CAS(var, oldval, newval) ATOMIC_CAS(var, oldval, newval)
+# define RUBY_ATOMIC_GENERIC_MACRO 1
 
 #elif defined _WIN32
 #if defined _MSC_VER && _MSC_VER > 1200
@@ -135,9 +133,9 @@ extern rb_atomic_t ruby_atomic_compare_a https://github.com/ruby/ruby/blob/trunk/ruby_atomic.h#L133
 
 # define ATOMIC_SIZE_ADD(var, val) (void)((var) += (val))
 # define ATOMIC_SIZE_SUB(var, val) (void)((var) -= (val))
-# define ATOMIC_SIZE_EXCHANGE(var, val) atomic_size_exchange(&(var), (val))
+# define ATOMIC_SIZE_EXCHANGE(var, val) ruby_atomic_size_exchange(&(var), (val))
 static inline size_t
-atomic_size_exchange(size_t *ptr, size_t val)
+ruby_atomic_size_exchange(size_t *ptr, size_t val)
 {
     size_t old = *ptr;
     *ptr = val;
@@ -158,14 +156,77 @@ atomic_size_exchange(size_t *ptr, size_t https://github.com/ruby/ruby/blob/trunk/ruby_atomic.h#L156
 # define ATOMIC_SIZE_CAS(var, oldval, val) ATOMIC_CAS(var, oldval, val)
 #endif
 
+#if RUBY_ATOMIC_GENERIC_MACRO
+# ifndef ATOMIC_PTR_EXCHANGE
+#   define ATOMIC_PTR_EXCHANGE(var, val) ATOMIC_EXCHANGE(var, val)
+# endif
+# ifndef ATOMIC_PTR_CAS
+#   define ATOMIC_PTR_CAS(var, oldval, newval) ATOMIC_CAS(var, oldval, newval)
+# endif
+
+# ifndef ATOMIC_VALUE_EXCHANGE
+#   define ATOMIC_VALUE_EXCHANGE(var, val) ATOMIC_EXCHANGE(var, val)
+# endif
+# ifndef ATOMIC_VALUE_CAS
+#   define ATOMIC_VALUE_CAS(var, oldval, val) ATOMIC_CAS(var, oldval, newval)
+# endif
+#endif
+
 #ifndef ATOMIC_PTR_EXCHANGE
 # if SIZEOF_VOIDP == SIZEOF_SIZE_T
 #   define ATOMIC_PTR_EXCHANGE(var, val) (void *)ATOMIC_SIZE_EXCHANGE(*(size_t *)&(var), (size_t)(val))
+# else
+#   define ATOMIC_PTR_EXCHANGE(var, val) ruby_atomic_ptr_exchange((const void **)&(var), (val))
+static inline void *
+ruby_atomic_ptr_exchange(const void **ptr, const void *val)
+{
+    const void *const old = *ptr;
+    *ptr = val;
+    return (void *)old;
+}
 # endif
 #endif
 #ifndef ATOMIC_PTR_CAS
 # if SIZEOF_VOIDP == SIZEOF_SIZE_T
 #   define ATOMIC_PTR_CAS(var, oldval, val) (void *)ATOMIC_SIZE_CAS(*(size_t *)&(var), (size_t)(oldval), (size_t)(val))
+# else
+#   define ATOMIC_PTR_CAS(var, oldval, val) ruby_atomic_ptr_cas(&(var), (oldval), (val))
+static inline void *
+ruby_atomic_ptr_cas(const void **ptr, const void *oldval, const void *val)
+{
+    const void *const old = *ptr;
+    if (old == oldval) *ptr = val;
+    return (void *)old;
+}
+# endif
+#endif
+
+#ifndef ATOMIC_VALUE_EXCHANGE
+# if SIZEOF_VALUE == SIZEOF_SIZE_T
+#   define ATOMIC_VALUE_EXCHANGE(var, val) ATOMIC_SIZE_EXCHANGE(*(size_t *)&(var), (size_t)(val))
+# else
+#   define ATOMIC_VALUE_EXCHANGE(var, val) ruby_atomic_value_exchange(&(var), (val))
+static inline VALUE
+ruby_atomic_value_exchange(VALUE *ptr, VALUE val)
+{
+    const VALUE old = *ptr;
+    *ptr = val;
+    return old;
+}
+# endif
+#endif
+#ifndef ATOMIC_VALUE_CAS
+# if SIZEOF_VALUE == SIZEOF_SIZE_T
+#   define ATOMIC_VALUE_CAS(var, oldval, val) ATOMIC_SIZE_CAS(*(size_t *)&(var), (size_t)(oldval), (size_t)(val))
+# else
+#   define ATOMIC_VALUE_CAS(var, oldval, val) ruby_atomic_value_cas(&(var), (oldval), (val))
+static inline VALUE
+ruby_atomic_value_cas(VALUE *ptr, VALUE oldval, VALUE val)
+{
+    const VALUE old = *ptr;
+    if (old == oldval) *ptr = val;
+    return old;
+}
 # endif
 #endif
 
Index: eval.c
===================================================================
--- eval.c	(revision 51497)
+++ eval.c	(revision 51498)
@@ -200,7 +200,7 @@ ruby_cleanup(volatile int ex) https://github.com/ruby/ruby/blob/trunk/eval.c#L200
 
     state = 0;
     for (nerr = 0; nerr < numberof(errs); ++nerr) {
-	VALUE err = ATOMIC_SIZE_EXCHANGE(errs[nerr], Qnil);
+	VALUE err = ATOMIC_VALUE_EXCHANGE(errs[nerr], Qnil);
 
 	if (!RTEST(err)) continue;
 
Index: gc.c
===================================================================
--- gc.c	(revision 51497)
+++ gc.c	(revision 51498)
@@ -2633,7 +2633,7 @@ finalize_deferred(rb_objspace_t *objspac https://github.com/ruby/ruby/blob/trunk/gc.c#L2633
 {
     VALUE zombie;
 
-    while ((zombie = (VALUE)ATOMIC_PTR_EXCHANGE(heap_pages_deferred_final, 0)) != 0) {
+    while ((zombie = ATOMIC_VALUE_EXCHANGE(heap_pages_deferred_final, 0)) != 0) {
 	finalize_list(objspace, zombie);
     }
 }
Index: node.c
===================================================================
--- node.c	(revision 51497)
+++ node.c	(revision 51498)
@@ -1090,11 +1090,9 @@ rb_alloc_tmp_buffer(volatile VALUE *stor https://github.com/ruby/ruby/blob/trunk/node.c#L1090
 void
 rb_free_tmp_buffer(volatile VALUE *store)
 {
-    VALUE s = *store;
-    *store = 0;
+    VALUE s = ATOMIC_VALUE_EXCHANGE(*store, 0);
     if (s) {
-	void *ptr = RNODE(s)->u1.node;
-	RNODE(s)->u1.node = 0;
+	void *ptr = ATOMIC_PTR_EXCHANGE(RNODE(s)->u1.node, 0);
 	RNODE(s)->u3.cnt = 0;
 	xfree(ptr);
     }

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]