RPA Toolkit
Using GCC atomic operations.
authorMartin Stoilov <martin@rpasearch.com>
Wed, 10 Oct 2012 04:55:52 +0000 (21:55 -0700)
committerMartin Stoilov <martin@rpasearch.com>
Wed, 10 Oct 2012 04:55:52 +0000 (21:55 -0700)
arch/unix/arm/rtypes.h
arch/unix/i386/rtypes.h
arch/unix/x86_64/rpatypes.h [deleted file]
arch/unix/x86_64/rtypes.h
arch/windows/i386/rtypes.h
rlib/ratomic.c
rlib/ratomic.h
rlib/rspinlock.c
tests/testrex/build/unix/i386/Makefile

index d417a45..065f039 100644 (file)
@@ -29,17 +29,23 @@ typedef struct {ruint32 p1; ruint32 p2;} rpair_t;
 /*
  * Atomic operations (Architecture Dependent)
  */
-#define R_ATOMIC_CMPXCHG(ptr, oldval, newval, resptr) \
-       do {*resptr = __sync_val_compare_and_swap(ptr, oldval, newval); } while (0)
+#define R_ATOMIC_CMPXCHG(ptr, oldval, newval, res) \
+       do { res = __sync_val_compare_and_swap(ptr, oldval, newval); } while (0)
 
 #define R_ATOMIC_XCHG(ptr, val) \
-       do {val = __sync_lock_test_and_set(ptr, val); } while (0)
+       do { val = __sync_lock_test_and_set(ptr, val); } while (0)
 
-#define R_ATOMIC_ADD(ptr, val) \
-       do { __sync_fetch_and_add(ptr, val); } while (0)
+#define R_ATOMIC_ADD(ptr, val, res) \
+       do { res = __sync_fetch_and_add(ptr, val); } while (0)
 
-#define R_ATOMIC_SUB(ptr, val) \
-       do { __sync_fetch_and_sub(ptr, val); } while (0)
+#define R_ATOMIC_SUB(ptr, val, res) \
+       do { res = __sync_fetch_and_sub(ptr, val); } while (0)
+
+#define R_ATOMIC_GET(ptr, res) \
+       do { __sync_synchronize (); res = *ptr; } while (0)
+
+#define R_ATOMIC_SET(ptr, val) \
+       do { *ptr = val; __sync_synchronize (); } while (0)
 
 
 
index 5465ffe..93d6829 100644 (file)
@@ -29,26 +29,23 @@ typedef struct {ruint32 p1; ruint32 p2;} rpair_t;
 /*
  * Atomic operations (Architecture Dependent)
  */
-#define R_ATOMIC_CMPXCHG(ptr, oldval, newval, resptr) \
-               do { __asm__ __volatile__ ("lock; cmpxchgl %2, %1" \
-                       : "=a" (*(resptr)), "=m" (*ptr) \
-                       : "r" (newval), "m" (*ptr), "0" (oldval)); } while (0)
+#define R_ATOMIC_CMPXCHG(ptr, oldval, newval, res) \
+       do { res = __sync_val_compare_and_swap(ptr, oldval, newval); } while (0)
 
 #define R_ATOMIC_XCHG(ptr, val) \
-               do { __asm__ __volatile__("lock; xchgl %0,%1" \
-                       :"=r" ((ruint32) val) \
-                       :"m" (*(volatile ruint32 *)ptr), "0" (val) \
-                       :"memory"); } while (0)
-
-#define R_ATOMIC_ADD(ptr, val) \
-               do { __asm__ __volatile__ ("addl %1,%0" \
-                       : "=m" (*ptr) \
-                       : "ir" (val), "m" (*ptr)); } while (0)
-
-#define R_ATOMIC_SUB(ptr, val) \
-               do { __asm__ __volatile__ ("subl %1,%0" \
-                       : "=m" (*ptr) \
-                       : "ir" (val), "m" (*ptr)); } while (0)
+       do { val = __sync_lock_test_and_set(ptr, val); } while (0)
+
+#define R_ATOMIC_ADD(ptr, val, res) \
+       do { res = __sync_fetch_and_add(ptr, val); } while (0)
+
+#define R_ATOMIC_SUB(ptr, val, res) \
+       do { res = __sync_fetch_and_sub(ptr, val); } while (0)
+
+#define R_ATOMIC_GET(ptr, res) \
+       do { __sync_synchronize (); res = *ptr; } while (0)
+
+#define R_ATOMIC_SET(ptr, val) \
+       do { *ptr = val; __sync_synchronize (); } while (0)
 
 
 #define R_DEBUG_BRAKE __asm__ ("int $3")
diff --git a/arch/unix/x86_64/rpatypes.h b/arch/unix/x86_64/rpatypes.h
deleted file mode 100644 (file)
index ecc098f..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *  Regular Pattern Analyzer Toolkit (RPA/Tk)
- *  Copyright (c) 2009-2012 Martin Stoilov
- *
- *  This program is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- *  Martin Stoilov <martin@rpasearch.com>
- */
-
-#ifndef _RPADEF_H_
-#define _RPADEF_H_
-
-
-typedef unsigned long rpa_word_t;
-typedef long rpa_sword_t;
-typedef unsigned short rpa_wchar_t;
-
-#ifndef NULL
-#ifdef __cplusplus
-#define NULL 0
-#else
-#define NULL ((void *)0)
-#endif
-#endif
-
-#endif
index 6c9f136..66cce52 100644 (file)
@@ -29,27 +29,23 @@ typedef struct {ruint32 p1; ruint32 p2;} rpair_t;
 /*
  * Atomic operations (Architecture Dependent)
  */
-#define R_ATOMIC_CMPXCHG(ptr, oldval, newval, resptr) \
-               do { __asm__ __volatile__ ("lock; cmpxchgl %2, %1" \
-                       : "=a" (*(resptr)), "=m" (*ptr) \
-                       : "r" (newval), "m" (*ptr), "0" (oldval)); } while (0)
+#define R_ATOMIC_CMPXCHG(ptr, oldval, newval, res) \
+       do { res = __sync_val_compare_and_swap(ptr, oldval, newval); } while (0)
 
 #define R_ATOMIC_XCHG(ptr, val) \
-               do { __asm__ __volatile__("lock; xchgl %0,%1" \
-                       :"=r" ( val) \
-                       :"m" (*(volatile ratomic_t *)ptr), "0" (val) \
-                       :"memory"); } while (0)
+       do { val = __sync_lock_test_and_set(ptr, val); } while (0)
 
-#define R_ATOMIC_ADD(ptr, val) \
-               do { __asm__ __volatile__ ("addl %1,%0" \
-                       : "=m" (*ptr) \
-                       : "ir" (val), "m" (*ptr)); } while (0)
+#define R_ATOMIC_ADD(ptr, val, res) \
+       do { res = __sync_fetch_and_add(ptr, val); } while (0)
 
-#define R_ATOMIC_SUB(ptr, val) \
-               do { __asm__ __volatile__ ("subl %1,%0" \
-                       : "=m" (*ptr) \
-                       : "ir" (val), "m" (*ptr)); } while (0)
+#define R_ATOMIC_SUB(ptr, val, res) \
+       do { res = __sync_fetch_and_sub(ptr, val); } while (0)
 
+#define R_ATOMIC_GET(ptr, res) \
+       do { __sync_synchronize (); res = *ptr; } while (0)
+
+#define R_ATOMIC_SET(ptr, val) \
+       do { *ptr = val; __sync_synchronize (); } while (0)
 
 #define R_DEBUG_BRAKE __asm__ ("int $3")
 #define R_ASSERT(__a__) do {if (!(__a__)) R_DEBUG_BRAKE; } while (0)
index 6c6875a..2581217 100644 (file)
@@ -29,8 +29,8 @@ typedef struct {ruint32 p1; ruint32 p2;} rpair_t;
 /*
  * Atomic operations (Architecture Dependent)
  */
-#define R_ATOMIC_CMPXCHG(ptr, oldval, newval, resptr) \
-               do { InterlockedCompareExchange (ptr, newval, oldval); *resptr = *ptr; } while (0)
+#define R_ATOMIC_CMPXCHG(ptr, oldval, newval, res) \
+               do { res = InterlockedCompareExchange (ptr, newval, oldval); } while (0)
 
 #define R_ATOMIC_XCHG(ptr, val) \
                do { val = InterlockedExchange (ptr, val); } while (0)
@@ -39,7 +39,13 @@ typedef struct {ruint32 p1; ruint32 p2;} rpair_t;
                do { InterlockedExchangeAdd (ptr, val); } while (0)
 
 #define R_ATOMIC_SUB(ptr, val) \
-               do { InterlockedExchangeAdd (ptr, -val); } while (0)
+               do { InterlockedExchangeSubtract (ptr, val); } while (0)
+
+#define R_ATOMIC_GET(ptr, res) \
+       do { res = *ptr; } while (0)
+
+#define R_ATOMIC_SET(ptr, val) \
+       do { *ptr = val; } while (0)
 
 
 #define R_DEBUG_BRAKE do { __asm int 3 } while (0)
index 5f3955b..d162977 100644 (file)
 
 rboolean r_atomic_compare_and_exchange(volatile ratomic_t *ptr, ratomic_t oldval, ratomic_t newval)
 {
-       volatile ratomic_t result;
+       volatile ratomic_t res;
 
-       R_ATOMIC_CMPXCHG(ptr, oldval, newval, &result);
-       return (result == oldval);
+       R_ATOMIC_CMPXCHG(ptr, oldval, newval, res);
+       return (res == oldval);
 }
 
 
@@ -38,13 +38,31 @@ ratomic_t r_atomic_exchange(volatile ratomic_t *ptr, volatile ratomic_t val)
 }
 
 
-void r_atomic_add(volatile ratomic_t *ptr, ratomic_t val)
+ratomic_t r_atomic_add(volatile ratomic_t *ptr, ratomic_t val)
 {
-       R_ATOMIC_ADD(ptr, val);
+       ratomic_t res = 0;
+       R_ATOMIC_ADD(ptr, val, res);
+       return res;
 }
 
 
-void r_atomic_sub(volatile ratomic_t *ptr, ratomic_t val)
+ratomic_t r_atomic_sub(volatile ratomic_t *ptr, ratomic_t val)
 {
-       R_ATOMIC_SUB(ptr, val);
+       ratomic_t res = 0;
+       R_ATOMIC_SUB(ptr, val, res);
+       return res;
+}
+
+
+ratomic_t r_atomic_get(volatile ratomic_t *ptr)
+{
+       ratomic_t res;
+       R_ATOMIC_GET(ptr, res);
+       return res;
+}
+
+
+void r_atomic_set(volatile ratomic_t *ptr, ratomic_t val)
+{
+       R_ATOMIC_SET(ptr, val);
 }
index 6172be3..beb6e31 100644 (file)
@@ -28,8 +28,10 @@ extern "C" {
 
 rboolean r_atomic_compare_and_exchange(volatile ratomic_t *ptr, ratomic_t oldval, ratomic_t newval);
 ratomic_t r_atomic_exchange(volatile ratomic_t *ptr, volatile ratomic_t val);
-void r_atomic_add(volatile ratomic_t *ptr, ratomic_t val);
-void r_atomic_sub(volatile ratomic_t *ptr, ratomic_t val);
+ratomic_t r_atomic_add(volatile ratomic_t *ptr, ratomic_t val);
+ratomic_t r_atomic_sub(volatile ratomic_t *ptr, ratomic_t val);
+ratomic_t r_atomic_get(volatile ratomic_t *ptr);
+void r_atomic_set(volatile ratomic_t *ptr, ratomic_t val);
 
 #ifdef __cplusplus
 }
index 71d0ae8..e098a69 100644 (file)
@@ -24,7 +24,7 @@
 
 void r_spinlock_init(rspinlock_t *lock)
 {
-       *lock = 0;
+       r_atomic_set(lock, 0);
 }
 
 
@@ -32,13 +32,9 @@ void r_spinlock_lock(rspinlock_t *lock)
 {
        while (1)
        {
-               if (!r_atomic_exchange(lock, R_SPINLOCK_BUSY))
+               if (r_atomic_compare_and_exchange(lock, 0, R_SPINLOCK_BUSY))
                        return;
-               while (*lock) {
-                       /*
-                        * Spin...
-                        */
-               }
+
        }
 }
 
@@ -51,5 +47,5 @@ void r_spinlock_unlock(rspinlock_t *lock)
 
 rboolean r_spinlock_trylock(rspinlock_t *lock)
 {
-       return (!r_atomic_exchange(lock, R_SPINLOCK_BUSY));
+       return (r_atomic_compare_and_exchange(lock, 0, R_SPINLOCK_BUSY));
 }
index 66e21bf..eeb7c66 100644 (file)
@@ -26,4 +26,4 @@ CFLAGS := $(CFLAGS)
 LDFLAGS = $(MACH)
 
 
-include ../testrpa2.mk
+include ../testrex.mk