void* qrcu_reader1() { int myidx; /* rcu_read_lock */ while (1) { myidx = idx; if (NONDET) { { __blockattribute__((atomic)) assume(myidx <= 0); assume(ctr1>0); ctr1++; } break; } else { if (NONDET) { { __blockattribute__((atomic)) assume(myidx > 0); assume(ctr2>0); ctr2++; } break; } else {} } } readerprogress1 = 1; /*** readerprogress[me] = 1; ***/ readerprogress1 = 2; /*** readerprogress[me] = 2 ***/ /* rcu_read_unlock */ { __blockattribute__((atomic)) if (myidx <= 0) { ctr1--; } // use ctr1 else { ctr2--; } // use ctr2 } }
void* qrcu_reader3() { int myidx; /* rcu_read_lock */ while (1) { myidx = idx; if (NONDET) { #ifdef SATABS { __CPROVER_atomic_begin(); #else { __blockattribute__((atomic)) #endif assume(myidx <= 0); assume(ctr1>0); ctr1++; #ifdef SATABS __CPROVER_atomic_end(); } #else } #endif break; } else { if (NONDET) { #ifdef SATABS { __CPROVER_atomic_begin(); #else { __blockattribute__((atomic)) #endif assume(myidx > 0); assume(ctr2>0); ctr2++; #ifdef SATABS __CPROVER_atomic_end(); } #else } #endif break; } else {} } } readerprogress3 = 1; /*** readerprogress[me] = 1; ***/ readerprogress3 = 2; /*** readerprogress[me] = 2 ***/ /* rcu_read_unlock */ #ifdef SATABS { __CPROVER_atomic_begin(); #else { __blockattribute__((atomic)) #endif if (myidx <= 0) { ctr1--; } // use ctr1 else { ctr2--; } // use ctr2 #ifdef SATABS __CPROVER_atomic_end(); } #else } #endif }
void thr4() { //reader { __blockattribute__((atomic)) assume(w==0); r = r+1; } y = x; assert(y == x); r = r-1; }
void thr3() { //writer glb_init(w==0); glb_init(r==0); { __blockattribute__((atomic)) assume(w==0); assume(r==0); w = 1; } x = 3; w = 0; }
void* qrcu_updater() { int i; int readerstart1; int readerstart2; int readerstart3; int sum; glb_init(idx==0); glb_init(ctr1==1); glb_init(ctr2==0); glb_init(readerprogress1==0); glb_init(readerprogress2==0); glb_init(readerprogress3==0); glb_init(mutex==0); /* Snapshot reader state. */ { __blockattribute__((atomic)) readerstart1 = readerprogress1; readerstart2 = readerprogress2; readerstart3 = readerprogress3; } sum_unordered; if (sum <= 1) { sum_unordered; } if (sum > 1) { acquire(mutex); if (idx <= 0) { ctr2++; idx = 1; ctr1--; } else { ctr1++; idx = 0; ctr2--; } if (idx <= 0) { while (ctr2 > 0); } else { while (ctr1 > 0); } release(mutex); } /* Verify reader progress. */ { __blockattribute__((atomic)) if (NONDET) { assume(readerstart1 == 1); assume(readerprogress1 == 1); assert(0); } else { if (NONDET) { assume(readerstart2 == 1); assume(readerprogress2 == 1); assert(0); } else { if (NONDET) { assume(readerstart2 == 1); assume(readerprogress2 == 1); assert(0); } else { } } } } }
void thr2() { //reader #ifdef SATABS { __CPROVER_atomic_begin(); #else { __blockattribute__((atomic)) #endif assume(w==0); r = r+1; #ifdef SATABS __CPROVER_atomic_end(); } #else } #endif y = x; assert(y == x); r = r-1; }
void thr1() { //writer #ifndef SATABS glb_init(w==0); glb_init(r==0); #endif #ifdef SATABS { __CPROVER_atomic_begin(); #else { __blockattribute__((atomic)) #endif assume(w==0); assume(r==0); w = 1; #ifdef SATABS __CPROVER_atomic_end(); } #else } #endif x = 3; w = 0; }
void* qrcu_reader1() { int myidx; /* rcu_read_lock */ while (1) { myidx = idx; if (NONDET) { #ifdef SATABS { __CPROVER_atomic_begin(); #else { __blockattribute__((atomic)) #endif assume(myidx <= 0); assume(ctr1>0); ctr1++; #ifdef SATABS __CPROVER_atomic_end(); } #else } #endif break; } else { if (NONDET) { #ifdef SATABS { __CPROVER_atomic_begin(); #else { __blockattribute__((atomic)) #endif assume(myidx > 0); assume(ctr2>0); ctr2++; #ifdef SATABS __CPROVER_atomic_end(); } #else } #endif break; } else {} } } /* This is a simpler code for rcu_read_lock, but the frontend generates too many transitions while (1) { myidx = idx; if (myidx <= 0 && ctr1>0) { ctr1++; break; } else { if (myidx > 0 && ctr2>0) { ctr2++; break; } else {} } } */ readerprogress1 = 1; /*** readerprogress[me] = 1; ***/ readerprogress1 = 2; /*** readerprogress[me] = 2 ***/ /* rcu_read_unlock */ #ifdef SATABS { __CPROVER_atomic_begin(); #else { __blockattribute__((atomic)) #endif if (myidx <= 0) { ctr1--; } // use ctr1 else { ctr2--; } // use ctr2 #ifdef SATABS __CPROVER_atomic_end(); } #else } #endif }
void* qrcu_updater() { int i; int readerstart1; int readerstart2; int readerstart3; int sum; #ifndef SATABS glb_init(idx==0); glb_init(ctr1==1); glb_init(ctr2==0); glb_init(readerprogress1==0); glb_init(readerprogress2==0); glb_init(readerprogress3==0); glb_init(mutex==0); #endif /* Snapshot reader state. */ #ifdef SATABS { __CPROVER_atomic_begin(); #else { __blockattribute__((atomic)) #endif readerstart1 = readerprogress1; readerstart2 = readerprogress2; readerstart3 = readerprogress3; #ifdef SATABS __CPROVER_atomic_end(); } #else } #endif sum_unordered; if (sum <= 1) { sum_unordered; } if (sum > 1) { acquire(mutex); if (idx <= 0) { ctr2++; idx = 1; ctr1--; } else { ctr1++; idx = 0; ctr2--; } if (idx <= 0) { while (ctr2 > 0); } else { while (ctr1 > 0); } release(mutex); } /* Verify reader progress. */ #ifdef SATABS { __CPROVER_atomic_begin(); #else { __blockattribute__((atomic)) #endif if (NONDET) { assume(readerstart1 == 1); assume(readerprogress1 == 1); assert(0); } else { if (NONDET) { assume(readerstart2 == 1); assume(readerprogress2 == 1); assert(0); } else { if (NONDET) { assume(readerstart2 == 1); assume(readerprogress2 == 1); assert(0); } else { } } } #ifdef SATABS __CPROVER_atomic_end(); } #else } #endif /* Frontend generates too many transitions: { __blockattribute__((atomic)) sum = 0; if (readerstart1 == 1 && readerprogress1 == 1) sum++; if (readerstart2 == 1 && readerprogress2 == 1) sum++; assert(sum == 0); } */ }
int main() { mThread = 0; start_main = 0; mStartLock = 0; __CNT__ = 0; pc1 = 1; pc2 = 1; while (1) { if (NONDET) { // thread thr1 switch (pc1) { case 1: PR_CreateThread__RES = 1; pc1 = 2; break; case 2: {__blockattribute__((atomic)) assume(mStartLock==0); mStartLock = 1; }; pc1 = 3; break; case 3: start_main = 1; pc1 = 4; break; case 4: {__blockattribute__((atomic)) if (__CNT__ == 0) { mThread = PR_CreateThread__RES; __CNT__ = __CNT__ + 1; } else { assert(0); } }; pc1 = 5; break; case 5: mStartLock = 0; pc1 = 6; break; case 6: if (mThread == 0) { pc1 = 7; break; } else { pc1 = 7; break; } } } else { // thread thr2 switch (pc2) { case 1: self = mThread; pc2 = 2; break; case 2: if (start_main == 0) { pc2 = 2; break; } else { pc2 = 3; break; } case 3: {__blockattribute__((atomic)) assume(mStartLock==0); mStartLock = 1; }; pc2 = 4; break; case 4: mStartLock = 0; pc2 = 5; break; case 5: {__blockattribute__((atomic)) rv = self; __CNT__ = __CNT__ + 1; }; pc2 = 6; break; } } }