Author: Armin Rigo <[email protected]>
Branch: stm-gc-2
Changeset: r63494:c58a07fafc8b
Date: 2013-04-18 16:52 +0200
http://bitbucket.org/pypy/pypy/changeset/c58a07fafc8b/

Log:    Add fetch_and_add to the C sources and expose it via
        rlib.atomic_ops.

diff --git a/rpython/rlib/atomic_ops.py b/rpython/rlib/atomic_ops.py
--- a/rpython/rlib/atomic_ops.py
+++ b/rpython/rlib/atomic_ops.py
@@ -1,11 +1,10 @@
 import py
-from pypy.tool.autopath import pypydir
 from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
 
 
-cdir = py.path.local(pypydir) / 'translator' / 'stm'
-cdir2 = py.path.local(pypydir) / 'translator' / 'c'
+cdir = py.path.local(__file__).join('..', '..', 'translator', 'stm')
+cdir2 = py.path.local(__file__).join('..', '..', 'translator', 'c')
 
 eci = ExternalCompilationInfo(
     include_dirs = [cdir, cdir2],
@@ -15,9 +14,16 @@
            bool_cas((volatile unsigned long*)(ptr),  \\
                     (unsigned long)(old),            \\
                     (unsigned long)(_new))
+#define pypy_fetch_and_add(ptr, value)                    \\
+           fetch_and_add((volatile unsigned long*)(ptr),  \\
+                         (unsigned long)(value))
 '''],
 )
 
 
 bool_cas = rffi.llexternal('pypy_bool_cas', [llmemory.Address]*3, lltype.Bool,
                            compilation_info=eci, macro=True)
+fetch_and_add = rffi.llexternal('pypy_fetch_and_add', [llmemory.Address,
+                                                       lltype.Signed],
+                                lltype.Signed,
+                                compilation_info=eci, macro=True)
diff --git a/rpython/rlib/test/test_atomic_ops.py 
b/rpython/rlib/test/test_atomic_ops.py
--- a/rpython/rlib/test/test_atomic_ops.py
+++ b/rpython/rlib/test/test_atomic_ops.py
@@ -1,4 +1,4 @@
-from rpython.rlib.atomic_ops import bool_cas
+from rpython.rlib.atomic_ops import bool_cas, fetch_and_add
 from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
 
 
@@ -21,11 +21,28 @@
     assert rffi.cast(lltype.Signed, a[0]) == 43
     #
     lltype.free(a, flavor='raw')
-    return 0
 
-def test_translate_bool_cas():
+def test_fetch_and_add():
+    a = lltype.malloc(ARRAY, 1, flavor='raw')
+    a[0] = rffi.cast(llmemory.Address, 42)
+    #
+    res = fetch_and_add(rffi.cast(llmemory.Address, a), -2)
+    assert res == 42
+    assert rffi.cast(lltype.Signed, a[0]) == 40
+    res = fetch_and_add(rffi.cast(llmemory.Address, a), 3)
+    assert res == 40
+    assert rffi.cast(lltype.Signed, a[0]) == 43
+    #
+    lltype.free(a, flavor='raw')
+
+def test_translate():
     from rpython.translator.c.test.test_genc import compile
 
-    f = compile(test_bool_cas, [])
+    def llf():
+        test_bool_cas()
+        test_fetch_and_add()
+        return 0
+
+    f = compile(llf, [])
     res = f()
     assert res == 0
diff --git a/rpython/translator/stm/src_stm/atomic_ops.h 
b/rpython/translator/stm/src_stm/atomic_ops.h
--- a/rpython/translator/stm/src_stm/atomic_ops.h
+++ b/rpython/translator/stm/src_stm/atomic_ops.h
@@ -21,11 +21,13 @@
 
 #ifdef __llvm__
 #  define HAS_SYNC_BOOL_COMPARE_AND_SWAP
+#  define HAS_SYNC_FETCH_AND_ADD
 #endif
 
 #ifdef __GNUC__
 #  if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)
 #    define HAS_SYNC_BOOL_COMPARE_AND_SWAP
+#    define HAS_SYNC_FETCH_AND_ADD
 #  endif
 #endif
 
@@ -59,6 +61,35 @@
 /* end */
 #endif
 
+#ifdef HAS_SYNC_FETCH_AND_ADD
+#  define fetch_and_add __sync_fetch_and_add
+#else
+/* x86 (32 bits and 64 bits) */
+static inline Unsigned
+fetch_and_add(volatile Unsigned *ptr, Unsigned value)
+{
+    Unsigned prev;
+#if defined(__amd64__)
+    assert(sizeof(Unsigned) == 8);
+#elif defined(__i386__)
+    assert(sizeof(Unsigned) == 4);
+#else
+#   error "the custom version of fetch_and_add() is only for x86 or x86-64"
+#endif
+    asm volatile("lock;"
+#if defined(__amd64__)
+                 "xaddq %1, %2;"
+#else
+                 "xaddl %1, %2;"
+#endif
+                 : "=r"(prev)
+                 : "0"(value), "m"(*ptr)
+                 : "memory");
+    return prev;
+}
+/* end */
+#endif
+
 
 static inline void spinloop(void)
 {
diff --git a/rpython/translator/stm/test/test_stmgcintf.c 
b/rpython/translator/stm/test/test_stmgcintf.c
--- a/rpython/translator/stm/test/test_stmgcintf.c
+++ b/rpython/translator/stm/test/test_stmgcintf.c
@@ -73,6 +73,33 @@
 
 /************************************************************/
 
+void test_bool_cas(void)
+{
+    volatile Unsigned bv = 10;
+
+    assert(bool_cas(&bv, 10, 15));
+    assert(bv == 15);
+    assert(!bool_cas(&bv, 10, 15));
+    assert(bv == 15);
+    assert(!bool_cas(&bv, 10, 25));
+    assert(bv == 15);
+    assert(bool_cas(&bv, 15, 14));
+    assert(bv == 14);
+}
+
+void test_fetch_and_add(void)
+{
+    volatile Unsigned bv = 14;
+
+    assert(fetch_and_add(&bv, 2) == 14);
+    assert(bv == 16);
+    assert(fetch_and_add(&bv, 7) == 16);
+    assert(fetch_and_add(&bv, (Unsigned)-1) == 23);
+    assert(bv == 22);
+}
+
+/************************************************************/
+
 void test_set_get_del(void)
 {
     stm_set_tls((void *)42);
@@ -365,6 +392,9 @@
 
 int main(int argc, char **argv)
 {
+    XTEST(bool_cas);
+    XTEST(fetch_and_add);
+
     DescriptorInit();
     XTEST(set_get_del);
     XTEST(run_all_transactions);
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to