unrelacy: instrument relacy-marked normal loads/stores
[model-checker-benchmarks.git] / include / unrelacy.h
index d65ffc3d1b2f7168313aac05563cf19be8a5aae1..729d76fdc24b9ae10705dd762fabd01e844a0c93 100644 (file)
@@ -4,16 +4,16 @@
 #include <stdatomic.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <mutex>
+#include <condition_variable>
+
+#include <model-assert.h>
+#include <librace.h>
 
 #define $
 
-#define _TEST_ASSERT(expr) \
-       if (!(expr)) { \
-               printf("Error: assertion failed at %s:%d\n", __FILE__, __LINE__); \
-               exit(EXIT_FAILURE); \
-       }
-#define ASSERT(expr) _TEST_ASSERT(expr)
-#define RL_ASSERT(expr) _TEST_ASSERT(expr)
+#define ASSERT(expr) MODEL_ASSERT(expr)
+#define RL_ASSERT(expr) MODEL_ASSERT(expr)
 
 #define RL_NEW new
 #define RL_DELETE(expr) delete expr
 
 namespace rl {
 
+       /* This 'useless' struct is declared just so we can use partial template
+        * specialization in our store and load functions. */
+       template <typename T, size_t n>
+       struct useless {
+               static void store(void *addr, T val);
+               static T load(const void *addr);
+       };
+
+       template <typename T>
+       struct useless<T, 1> {
+               static void store(void *addr, T val) { store_8(addr, (uint8_t)val); }
+               static T load(const void *addr) { return (T)load_8(addr); }
+       };
+
+       template <typename T>
+       struct useless<T, 2> {
+               static void store(void *addr, T val) { store_16(addr, (uint16_t)val); }
+               static T load(const void *addr) { return (T)load_16(addr); }
+       };
+
+       template <typename T>
+       struct useless<T, 4> {
+               static void store(void *addr, T val) { store_32(addr, (uint32_t)val); }
+               static T load(const void *addr) { return (T)load_32(addr); }
+       };
+
+       template <typename T>
+       struct useless<T, 8> {
+               static void store(void *addr, T val) { store_64(addr, (uint64_t)val); }
+               static T load(const void *addr) { return (T)load_64(addr); }
+       };
+
        template <typename T>
        struct var {
-               var() { value = 0; }
-               var(T v) { value = v; }
-               var(var const& r) { value = r.value; }
+               var() { useless<T, sizeof(T)>::store(&value, 0); }
+               var(T v) { useless<T, sizeof(T)>::store(&value, v); }
+               var(var const& r) {
+                       value = r.value;
+               }
                ~var() { }
 
-               void operator = (T v) { value = v; }
-               T operator () () { return value; }
-               void operator += (T v) { value += v; }
-               bool operator == (const struct var<T> v) const { return value == v.value; }
+               void operator = (T v) { useless<T, sizeof(T)>::store(&value, v); }
+               T operator () () { return useless<T, sizeof(T)>::load(&value); }
+               void operator += (T v) {
+                       useless<T, sizeof(T)>::store(&value,
+                                       useless<T, sizeof(T)>::load(&value) + v);
+               }
+               bool operator == (const struct var<T> v) const { return useless<T, sizeof(T)>::load(&value) == useless<T, sizeof(T)>::load(&v.value); }
 
                T value;
        };