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