changes
authorPeizhao Ou <peizhaoo@uci.edu>
Thu, 12 Feb 2015 06:54:45 +0000 (22:54 -0800)
committerPeizhao Ou <peizhaoo@uci.edu>
Thu, 12 Feb 2015 06:54:45 +0000 (22:54 -0800)
linuxrwlocks/Makefile
linuxrwlocks/linuxrwlocks-wildcard.h [new file with mode: 0644]
linuxrwlocks/linuxrwlocks.c
linuxrwlocks/linuxrwlocks.h [new file with mode: 0644]
linuxrwlocks/testcase1.c [new file with mode: 0644]

index 90dafcfb30dbb7656c5cc97744d68ba7fdf1482f..2940b583eab02d5a63eeec3bcf359fc4ab548ee1 100644 (file)
@@ -1,11 +1,14 @@
 include ../benchmarks.mk
 
 TESTNAME = linuxrwlocks
+WILDCARD_TESTS = testcase1
+all: $(TESTNAME) $(WILDCARD_TESTS)
 
-all: $(TESTNAME)
+$(TESTNAME): $(TESTNAME).c $(TESTNAME).h
+       $(CC) -o $@ $< $(CFLAGS) $(LDFLAGS)
 
-$(TESTNAME): $(TESTNAME).c
+$(WILDCARD_TESTS): % : %.c $(TESTNAME)-wildcard.h
        $(CC) -o $@ $< $(CFLAGS) $(LDFLAGS)
 
 clean:
-       rm -f $(TESTNAME) *.o
+       rm -f $(TESTNAME) *.o $(WILDCARD_TESTS)
diff --git a/linuxrwlocks/linuxrwlocks-wildcard.h b/linuxrwlocks/linuxrwlocks-wildcard.h
new file mode 100644 (file)
index 0000000..1a75594
--- /dev/null
@@ -0,0 +1,276 @@
+#include <stdio.h>
+#include <threads.h>
+#include <stdatomic.h>
+#include "wildcard.h" 
+
+#include "librace.h"
+
+#define RW_LOCK_BIAS            0x00100000
+#define WRITE_LOCK_CMP          RW_LOCK_BIAS
+
+/** Example implementation of linux rw lock along with 2 thread test
+ *  driver... */
+
+/**
+       Properties to check:
+       1. At most 1 thread can acquire the write lock, and at the same time, no
+               other threads can acquire any lock (including read/write lock).
+       2. At most RW_LOCK_BIAS threads can successfully acquire the read lock.
+       3. A read_unlock release 1 read lock, and a write_unlock release the write
+       lock. They can not release a lock that they don't acquire.
+       ###
+       4. Read_lock and write_lock can not be grabbed at the same time.
+       5. Happpens-before relationship should be checked and guaranteed, which
+       should be as the following:
+               a. read_unlock hb-> write_lock
+               b. write_unlock hb-> write_lock
+               c. write_unlock hb-> read_lock
+*/
+
+/**
+       Interesting point for locks:
+       a. If the users unlock() before any lock(), then the model checker will fail.
+       For this case, we can not say that the data structure is buggy, how can we
+       tell them from a real data structure bug???
+       b. We should specify that for a specific thread, successful locks and
+       unlocks should always come in pairs. We could make this check as an
+       auxiliary check since it is an extra rule for how the interfaces should called.
+*/
+
+/**
+       @Begin
+       @Global_define:
+               bool __writer_lock_acquired = false;
+               int __reader_lock_cnt = 0;
+       
+       @Happens_before:
+               # Since commit_point_set has no ID attached, A -> B means that for any B,
+               # the previous A happens before B.
+               Read_Unlock -> Write_Lock
+               Read_Unlock -> Write_Trylock(HB_Write_Trylock_Succ)
+               
+               Write_Unlock -> Write_Lock
+               Write_Unlock -> Write_Trylock(HB_Write_Trylock_Succ)
+
+               Write_Unlock -> Read_Lock
+               Write_Unlock -> Read_Trylock(HB_Read_Trylock_Succ)
+       @End
+*/
+
+/**
+       */
+
+typedef union {
+       atomic_int lock;
+} rwlock_t;
+
+static inline int read_can_lock(rwlock_t *lock)
+{
+       // relaxed
+       return atomic_load_explicit(&lock->lock, wildcard(1)) > 0;
+}
+
+static inline int write_can_lock(rwlock_t *lock)
+{
+       // relaxed
+       return atomic_load_explicit(&lock->lock, wildcard(2)) == RW_LOCK_BIAS;
+}
+
+
+/**
+       @Begin
+       @Interface: Read_Lock
+       @Commit_point_set:
+               Read_Lock_Success_1 | Read_Lock_Success_2
+       @Check:
+               !__writer_lock_acquired
+       @Action:
+               @Code:
+               __reader_lock_cnt++;
+       @End
+*/
+static inline void read_lock(rwlock_t *rw)
+{
+       // acquire
+       int priorvalue = atomic_fetch_sub_explicit(&rw->lock, 1, wildcard(3));
+       /**
+               @Begin
+               @Commit_point_define_check: __ATOMIC_RET__ > 0
+               @Label:Read_Lock_Success_1
+               @End
+       */
+       while (priorvalue <= 0) {
+               // relaxed
+               atomic_fetch_add_explicit(&rw->lock, 1, wildcard(4));
+               // relaxed
+               while (atomic_load_explicit(&rw->lock, wildcard(5)) <= 0) {
+                       thrd_yield();
+               }
+               // acquire
+               priorvalue = atomic_fetch_sub_explicit(&rw->lock, 1, wildcard(6));
+               /**
+                       @Begin
+                       @Commit_point_define_check: __ATOMIC_RET__ > 0
+                       @Label:Read_Lock_Success_2
+                       @End
+               */
+       }
+}
+
+
+/**
+       @Begin
+       @Interface: Write_Lock
+       @Commit_point_set:
+               Write_Lock_Success_1 | Write_Lock_Success_2
+       @Check:
+               !__writer_lock_acquired && __reader_lock_cnt == 0
+       @Action:
+               @Code:
+               __writer_lock_acquired = true;
+       @End
+*/
+static inline void write_lock(rwlock_t *rw)
+{
+       // acquire
+       int priorvalue = atomic_fetch_sub_explicit(&rw->lock, RW_LOCK_BIAS, wildcard(7));
+       /**
+               @Begin
+               @Commit_point_define_check: __ATOMIC_RET__ == RW_LOCK_BIAS
+               @Label: Write_Lock_Success_1
+               @End
+       */
+       while (priorvalue != RW_LOCK_BIAS) {
+               // relaxed
+               atomic_fetch_add_explicit(&rw->lock, RW_LOCK_BIAS, wildcard(8));
+               // relaxed
+               while (atomic_load_explicit(&rw->lock, wildcard(9)) != RW_LOCK_BIAS) {
+                       thrd_yield();
+               }
+               // acquire
+               priorvalue = atomic_fetch_sub_explicit(&rw->lock, RW_LOCK_BIAS, wildcard(10));
+               /**
+                       @Begin
+                       @Commit_point_define_check: __ATOMIC_RET__ == RW_LOCK_BIAS
+                       @Label: Write_Lock_Success_2
+                       @End
+               */
+       }
+}
+
+/**
+       @Begin
+       @Interface: Read_Trylock
+       @Commit_point_set:
+               Read_Trylock_Point
+       @Condition:
+               __writer_lock_acquired == false
+       @HB_condition:
+               HB_Read_Trylock_Succ :: __RET__ == 1
+       @Action:
+               @Code:
+               if (COND_SAT)
+                       __reader_lock_cnt++;
+       @Post_check:
+               COND_SAT ? __RET__ == 1 : __RET__ == 0
+       @End
+*/
+static inline int read_trylock(rwlock_t *rw)
+{
+       // acquire
+       int priorvalue = atomic_fetch_sub_explicit(&rw->lock, 1, wildcard(11));
+       /**
+               @Begin
+               @Commit_point_define_check: true
+               @Label:Read_Trylock_Point
+               @End
+       */
+       if (priorvalue > 0)
+               return 1;
+       
+       // relaxed
+       atomic_fetch_add_explicit(&rw->lock, 1, wildcard(12));
+       return 0;
+}
+
+/**
+       @Begin
+       @Interface: Write_Trylock
+       @Commit_point_set:
+               Write_Trylock_Point
+       @Condition:
+               !__writer_lock_acquired && __reader_lock_cnt == 0
+       @HB_condition:
+               HB_Write_Trylock_Succ :: __RET__ == 1
+       @Action:
+               @Code:
+               if (COND_SAT)
+                       __writer_lock_acquired = true;
+       @Post_check:
+               COND_SAT ? __RET__ == 1 : __RET__ == 0
+       @End
+*/
+static inline int write_trylock(rwlock_t *rw)
+{
+       // acquire
+       int priorvalue = atomic_fetch_sub_explicit(&rw->lock, RW_LOCK_BIAS, wildcard(13));
+       /**
+               @Begin
+               @Commit_point_define_check: true
+               @Label: Write_Trylock_Point
+               @End
+       */
+       if (priorvalue == RW_LOCK_BIAS)
+               return 1;
+
+       // relaxed
+       atomic_fetch_add_explicit(&rw->lock, RW_LOCK_BIAS, wildcard(14));
+       return 0;
+}
+
+/**
+       @Begin
+       @Interface: Read_Unlock
+       @Commit_point_set: Read_Unlock_Point
+       @Check:
+               __reader_lock_cnt > 0 && !__writer_lock_acquired
+       @Action: 
+               @Code:
+               reader_lock_cnt--;
+       @End
+*/
+static inline void read_unlock(rwlock_t *rw)
+{
+       // release
+       atomic_fetch_add_explicit(&rw->lock, 1, wildcard(15));
+       /**
+               @Begin
+               @Commit_point_define_check: true
+               @Label: Read_Unlock_Point
+               @End
+       */
+}
+
+/**
+       @Begin
+       @Interface: Write_Unlock
+       @Commit_point_set: Write_Unlock_Point
+       @Check:
+               reader_lock_cnt == 0 && writer_lock_acquired
+       @Action: 
+               @Code:
+               __writer_lock_acquired = false;
+       @End
+*/
+
+static inline void write_unlock(rwlock_t *rw)
+{
+       // release
+       atomic_fetch_add_explicit(&rw->lock, RW_LOCK_BIAS, wildcard(16));
+       /**
+               @Begin
+               @Commit_point_define_check: true
+               @Label: Write_Unlock_Point
+               @End
+       */
+}
index be3550e11e3c8f8740b4c1a47458180f57994a3a..bf60f16f94da5993ec62d2a9b93f8e8324a95c92 100644 (file)
@@ -3,80 +3,7 @@
 #include <stdatomic.h>
 
 #include "librace.h"
-
-#define RW_LOCK_BIAS            0x00100000
-#define WRITE_LOCK_CMP          RW_LOCK_BIAS
-
-/** Example implementation of linux rw lock along with 2 thread test
- *  driver... */
-
-typedef union {
-       atomic_int lock;
-} rwlock_t;
-
-static inline int read_can_lock(rwlock_t *lock)
-{
-       return atomic_load_explicit(&lock->lock, memory_order_relaxed) > 0;
-}
-
-static inline int write_can_lock(rwlock_t *lock)
-{
-       return atomic_load_explicit(&lock->lock, memory_order_relaxed) == RW_LOCK_BIAS;
-}
-
-static inline void read_lock(rwlock_t *rw)
-{
-       int priorvalue = atomic_fetch_sub_explicit(&rw->lock, 1, memory_order_acquire);
-       while (priorvalue <= 0) {
-               atomic_fetch_add_explicit(&rw->lock, 1, memory_order_relaxed);
-               while (atomic_load_explicit(&rw->lock, memory_order_relaxed) <= 0) {
-                       thrd_yield();
-               }
-               priorvalue = atomic_fetch_sub_explicit(&rw->lock, 1, memory_order_acquire);
-       }
-}
-
-static inline void write_lock(rwlock_t *rw)
-{
-       int priorvalue = atomic_fetch_sub_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_acquire);
-       while (priorvalue != RW_LOCK_BIAS) {
-               atomic_fetch_add_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_relaxed);
-               while (atomic_load_explicit(&rw->lock, memory_order_relaxed) != RW_LOCK_BIAS) {
-                       thrd_yield();
-               }
-               priorvalue = atomic_fetch_sub_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_acquire);
-       }
-}
-
-static inline int read_trylock(rwlock_t *rw)
-{
-       int priorvalue = atomic_fetch_sub_explicit(&rw->lock, 1, memory_order_acquire);
-       if (priorvalue > 0)
-               return 1;
-
-       atomic_fetch_add_explicit(&rw->lock, 1, memory_order_relaxed);
-       return 0;
-}
-
-static inline int write_trylock(rwlock_t *rw)
-{
-       int priorvalue = atomic_fetch_sub_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_acquire);
-       if (priorvalue == RW_LOCK_BIAS)
-               return 1;
-
-       atomic_fetch_add_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_relaxed);
-       return 0;
-}
-
-static inline void read_unlock(rwlock_t *rw)
-{
-       atomic_fetch_add_explicit(&rw->lock, 1, memory_order_release);
-}
-
-static inline void write_unlock(rwlock_t *rw)
-{
-       atomic_fetch_add_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_release);
-}
+#include "linuxrwlocks.h"
 
 rwlock_t mylock;
 int shareddata;
diff --git a/linuxrwlocks/linuxrwlocks.h b/linuxrwlocks/linuxrwlocks.h
new file mode 100644 (file)
index 0000000..1e300ab
--- /dev/null
@@ -0,0 +1,78 @@
+#include <stdio.h>
+#include <stdatomic.h>
+
+#include "librace.h"
+
+#define RW_LOCK_BIAS            0x00100000
+#define WRITE_LOCK_CMP          RW_LOCK_BIAS
+
+/** Example implementation of linux rw lock along with 2 thread test
+ *  driver... */
+
+typedef union {
+       atomic_int lock;
+} rwlock_t;
+
+static inline int read_can_lock(rwlock_t *lock)
+{
+       return atomic_load_explicit(&lock->lock, memory_order_relaxed) > 0;
+}
+
+static inline int write_can_lock(rwlock_t *lock)
+{
+       return atomic_load_explicit(&lock->lock, memory_order_relaxed) == RW_LOCK_BIAS;
+}
+
+static inline void read_lock(rwlock_t *rw)
+{
+       int priorvalue = atomic_fetch_sub_explicit(&rw->lock, 1, memory_order_acquire);
+       while (priorvalue <= 0) {
+               atomic_fetch_add_explicit(&rw->lock, 1, memory_order_relaxed);
+               while (atomic_load_explicit(&rw->lock, memory_order_relaxed) <= 0) {
+                       thrd_yield();
+               }
+               priorvalue = atomic_fetch_sub_explicit(&rw->lock, 1, memory_order_acquire);
+       }
+}
+
+static inline void write_lock(rwlock_t *rw)
+{
+       int priorvalue = atomic_fetch_sub_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_acquire);
+       while (priorvalue != RW_LOCK_BIAS) {
+               atomic_fetch_add_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_relaxed);
+               while (atomic_load_explicit(&rw->lock, memory_order_relaxed) != RW_LOCK_BIAS) {
+                       thrd_yield();
+               }
+               priorvalue = atomic_fetch_sub_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_acquire);
+       }
+}
+
+static inline int read_trylock(rwlock_t *rw)
+{
+       int priorvalue = atomic_fetch_sub_explicit(&rw->lock, 1, memory_order_acquire);
+       if (priorvalue > 0)
+               return 1;
+
+       atomic_fetch_add_explicit(&rw->lock, 1, memory_order_relaxed);
+       return 0;
+}
+
+static inline int write_trylock(rwlock_t *rw)
+{
+       int priorvalue = atomic_fetch_sub_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_acquire);
+       if (priorvalue == RW_LOCK_BIAS)
+               return 1;
+
+       atomic_fetch_add_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_relaxed);
+       return 0;
+}
+
+static inline void read_unlock(rwlock_t *rw)
+{
+       atomic_fetch_add_explicit(&rw->lock, 1, memory_order_release);
+}
+
+static inline void write_unlock(rwlock_t *rw)
+{
+       atomic_fetch_add_explicit(&rw->lock, RW_LOCK_BIAS, memory_order_release);
+}
diff --git a/linuxrwlocks/testcase1.c b/linuxrwlocks/testcase1.c
new file mode 100644 (file)
index 0000000..0becb24
--- /dev/null
@@ -0,0 +1,72 @@
+#include <stdio.h>
+#include <threads.h>
+#include <stdatomic.h>
+#include "wildcard.h" 
+
+#include "librace.h"
+#include "linuxrwlocks-wildcard.h"
+
+rwlock_t mylock;
+int shareddata;
+
+atomic_int x, y;
+
+static void a(void *obj)
+{
+       write_lock(&mylock);
+       atomic_store_explicit(&x, 17, relaxed);
+       write_unlock(&mylock);
+
+/*
+
+       if (!write_can_lock(&mylock))
+               return;
+
+       if (write_trylock(&mylock)) {
+               atomic_store_explicit(&x, 17, relaxed);
+               write_unlock(&mylock);
+       }
+*/
+}
+
+static void b(void *obj)
+{
+
+       write_lock(&mylock);
+       atomic_store_explicit(&x, 16, relaxed);
+       write_unlock(&mylock);
+
+       read_lock(&mylock);
+       atomic_load_explicit(&x, relaxed);
+       read_unlock(&mylock);
+
+/*
+       if (write_trylock(&mylock)) {
+               atomic_store_explicit(&x, 16, relaxed);
+               write_unlock(&mylock);
+       }
+
+       if (!read_can_lock(&mylock))
+               return;
+       if (read_trylock(&mylock)) {
+               atomic_load_explicit(&x, relaxed);
+               read_unlock(&mylock);
+       }
+*/
+}
+
+int user_main(int argc, char **argv)
+{
+       thrd_t t1, t2;
+       atomic_init(&mylock.lock, RW_LOCK_BIAS);
+       atomic_init(&x, 0);
+       atomic_init(&y, 0);
+
+       thrd_create(&t1, (thrd_start_t)&a, NULL);
+       thrd_create(&t2, (thrd_start_t)&b, NULL);
+
+       thrd_join(t1);
+       thrd_join(t2);
+
+       return 0;
+}