From: Peizhao Ou Date: Thu, 12 Feb 2015 06:34:47 +0000 (-0800) Subject: changes X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=0487e29583033894529edd8c8e20291aa5eefbb6;p=model-checker-benchmarks.git changes --- diff --git a/mcs-lock/Makefile b/mcs-lock/Makefile index 5a311b3..51f9891 100644 --- a/mcs-lock/Makefile +++ b/mcs-lock/Makefile @@ -2,10 +2,16 @@ include ../benchmarks.mk TESTNAME = mcs-lock -all: $(TESTNAME) +WILDCARD_TESTS = testcase1 + +all: $(TESTNAME) $(WILDCARD_TESTS) + echo $^ $(TESTNAME): $(TESTNAME).cc $(TESTNAME).h $(CXX) -o $@ $< $(CXXFLAGS) $(LDFLAGS) +$(WILDCARD_TESTS): % : %.cc $(TESTNAME)-wildcard.h + $(CXX) -o $@ $< $(CXXFLAGS) $(LDFLAGS) + clean: - rm -f $(TESTNAME) *.o + rm -f $(TESTNAME) *.o $(WILDCARD_TESTS) diff --git a/mcs-lock/mcs-lock-wildcard.h b/mcs-lock/mcs-lock-wildcard.h new file mode 100644 index 0000000..b8d92b2 --- /dev/null +++ b/mcs-lock/mcs-lock-wildcard.h @@ -0,0 +1,103 @@ +// mcs on stack + +#include +#include +#include "wildcard.h" + + +struct mcs_node { + std::atomic next; + std::atomic gate; + + mcs_node() { + next.store(0); + gate.store(0); + } +}; + +struct mcs_mutex { +public: + // tail is null when lock is not held + std::atomic m_tail; + + mcs_mutex() { + m_tail.store( NULL); + } + ~mcs_mutex() { + //ASSERT( m_tail.load() == NULL ); + } + + // Each thread will have their own guard. + class guard { + public: + mcs_mutex * m_t; + mcs_node m_node; // node held on the stack + + guard(mcs_mutex * t) : m_t(t) { t->lock(this); } + ~guard() { m_t->unlock(this); } + }; + + void lock(guard * I) { + mcs_node * me = &(I->m_node); + + // set up my node : + // not published yet so relaxed : + me->next.store(NULL, wildcard(1) ); // relaxed + me->gate.store(1, wildcard(2) ); // relaxed + + // publish my node as the new tail : + mcs_node * pred = m_tail.exchange(me, wildcard(3)); // acq_rel + if ( pred != NULL ) { + // (*1) race here + // unlock of pred can see me in the tail before I fill next + + // publish me to previous lock-holder : + pred->next.store(me, wildcard(4) ); // release + + // (*2) pred not touched any more + + // now this is the spin - + // wait on predecessor setting my flag - + rl::linear_backoff bo; + int my_gate = 1; + while ( (my_gate = me->gate.load(wildcard(5))) ) { // acquire + thrd_yield(); + } + } + } + + void unlock(guard * I) { + mcs_node * me = &(I->m_node); + + mcs_node * next = me->next.load(wildcard(6)); // acquire + if ( next == NULL ) + { + mcs_node * tail_was_me = me; + bool success; + // FIXME: SCFence infers acq_rel / release + // Could be release if wildcard(8) is acquire + if ( (success = m_tail.compare_exchange_strong( + tail_was_me,NULL,wildcard(7))) ) { // acq_rel + // got null in tail, mutex is unlocked + return; + } + + // (*1) catch the race : + rl::linear_backoff bo; + for(;;) { + // FIXME: SCFence infers relaxed / acquire + // Could be relaxed if wildcard(7) is acq_rel + next = me->next.load(wildcard(8)); // acquire + if ( next != NULL ) + break; + thrd_yield(); + } + } + + // (*2) - store to next must be done, + // so no locker can be viewing my node any more + + // let next guy in : + next->gate.store( 0, wildcard(9) ); // release + } +}; diff --git a/mcs-lock/testcase1.cc b/mcs-lock/testcase1.cc new file mode 100644 index 0000000..971bf1d --- /dev/null +++ b/mcs-lock/testcase1.cc @@ -0,0 +1,43 @@ +#include +#include + +#include "mcs-lock-wildcard.h" + +/* For data race instrumentation */ +#include "librace.h" + +struct mcs_mutex *mutex; +static uint32_t shared; + +void threadA(void *arg) +{ + mcs_mutex::guard g(mutex); + printf("store: %d\n", 17); + store_32(&shared, 17); + mutex->unlock(&g); + mutex->lock(&g); + printf("load: %u\n", load_32(&shared)); +} + +void threadB(void *arg) +{ + mcs_mutex::guard g(mutex); + printf("load: %u\n", load_32(&shared)); + mutex->unlock(&g); + mutex->lock(&g); + printf("store: %d\n", 17); + store_32(&shared, 17); +} + +int user_main(int argc, char **argv) +{ + thrd_t A, B; + + mutex = new mcs_mutex(); + + thrd_create(&A, &threadA, NULL); + thrd_create(&B, &threadB, NULL); + thrd_join(A); + thrd_join(B); + return 0; +}