From 29d91569a2614d4e0e685ff5e06b7a5a12aaf1a5 Mon Sep 17 00:00:00 2001 From: pramalhe Date: Wed, 27 May 2015 23:55:49 +0200 Subject: [PATCH] Added CRTurn and CRHandover --- CorreiaRamalheteHandover.c | 135 +++++++++++++++++++++++++++++++++++++ CorreiaRamalheteTurn.c | 116 +++++++++++++++++++++++++++++++ 2 files changed, 251 insertions(+) create mode 100644 CorreiaRamalheteHandover.c create mode 100644 CorreiaRamalheteTurn.c diff --git a/CorreiaRamalheteHandover.c b/CorreiaRamalheteHandover.c new file mode 100644 index 0000000..0077aef --- /dev/null +++ b/CorreiaRamalheteHandover.c @@ -0,0 +1,135 @@ +// Correia and Ramalhete CRHandover, Mutual Exclusion - Two linear wait software solutions +// https://github.com/pramalhe/ConcurrencyFreaks/tree/master/papers/cralgorithm-2015.pdf +// +// Shared words = 2N+1 +// Number of states = 3 + 2 +// Starvation-Free = yes, with N +// Minimum SC stores = 1 + 1 +// Minimum SC loads = 2 + 2 + +enum Intent { UNLOCKED, WAITING, LOCKED }; +enum Handover { NOTMINE, MYTURN }; + +static volatile TYPE *states CALIGN; // shared +static volatile TYPE *handover CALIGN; // shared +static volatile TYPE hoEnabled CALIGN; // shared + +inline static const int validate_left(const int id) { + for (int i = 0; i < id; i++) { + if (states[i] != UNLOCKED) return 0; + } + return 1; +} + +inline static const int validate_right(const int id) { + for (int i = id + 1; i < N; i++) { + if (states[i] == LOCKED) return 0; + } + return 1; +} + +static void *Worker( void *arg ) { + TYPE id = (size_t)arg; + uint64_t entry; +#ifdef FAST + unsigned int cnt = 0, oid = id; +#endif // FAST + + for ( int r = 0; r < RUNS; r += 1 ) { + entry = 0; + while ( stop == 0 ) { + int i, isFirstTime = 1; + while (1) { + while (hoEnabled) { + if (isFirstTime) { states[id] = WAITING; Fence(); isFirstTime = 0; } + if (handover[id] == MYTURN) { + handover[id] = NOTMINE; + states[id] = LOCKED; + goto LCS; // fast-path under high contention + } + Pause(); + } + isFirstTime = 0; + states[id] = LOCKED; + Fence(); + for (i = 0; i < id; i++) { + if (states[i] != UNLOCKED) break; + } + if (i != id) { + states[id] = WAITING; + Fence(); + while (!hoEnabled) { + for (i = 0; i < id; i++) { + if (states[i] != UNLOCKED) break; + } + if (i == id) break; + Pause(); + } + continue; + } + while (!hoEnabled) { + for (i = id + 1; i < N; i++) { + if (states[i] == LOCKED) break; + } + if (i == N && !hoEnabled) goto LCS; + } + states[id] = WAITING; + Fence(); + } + LCS: CriticalSection( id ); // critical section + for (int i = id + 1; i < N; i++) { + if (states[i] == WAITING) { + if (!hoEnabled) hoEnabled = 1; + handover[i] = MYTURN; + states[id] = UNLOCKED; + goto LEND; + } + } + for (int i = 0; i < id; i++) { + if (states[i] == WAITING) { + if (!hoEnabled) hoEnabled = 1; + handover[i] = MYTURN; + states[id] = UNLOCKED; + goto LEND; + } + } + // There are no successors at all + if (hoEnabled) hoEnabled = 0; + states[id] = UNLOCKED; + LEND: +#ifdef FAST + id = startpoint( cnt ); // different starting point each experiment + cnt = cycleUp( cnt, NoStartPoints ); +#endif // FAST + entry += 1; + } // while +#ifdef FAST + id = oid; +#endif // FAST + entries[r][id] = entry; + __sync_fetch_and_add( &Arrived, 1 ); + while ( stop != 0 ) Pause(); + __sync_fetch_and_add( &Arrived, -1 ); + } // for + return NULL; +} // Worker + +void ctor() { + states = Allocator( sizeof(typeof(states[0])) * N ); + handover = Allocator( sizeof(typeof(handover[0])) * N ); + for ( int i = 0; i < N; i += 1 ) { // initialize shared data + states[i] = UNLOCKED; + handover[i] = NOTMINE; + } // for + hoEnabled = 0; // false +} // ctor + +void dtor() { + free( (void *)states ); + free( (void *)handover ); +} // dtor + +// Local Variables: // +// tab-width: 4 // +// compile-command: "gcc -Wall -std=gnu99 -O3 -DNDEBUG -fno-reorder-functions -DPIN -DAlgorithm=CorreiaRamalheteHandover Harness.c -lpthread -lm" // +// End: // diff --git a/CorreiaRamalheteTurn.c b/CorreiaRamalheteTurn.c new file mode 100644 index 0000000..93cd430 --- /dev/null +++ b/CorreiaRamalheteTurn.c @@ -0,0 +1,116 @@ +// Correia and Ramalhete CRTurn, Mutual Exclusion - Two linear wait software solutions +// https://github.com/pramalhe/ConcurrencyFreaks/tree/master/papers/cralgorithm-2015.pdf +// +// Shared words = N+1 +// Number of states = 3 +// Starvation-Free = yes, with N +// Minimum SC stores = 1 + 1 +// Minimum SC loads = N+2 + +enum Intent { UNLOCKED, WAITING, LOCKED }; + +static volatile TYPE *states CALIGN; // shared +static volatile TYPE turn CALIGN; // shared + +inline static const int validate_left(const int id, const int lturn) { + int i; + if (lturn > id) { + for (i = lturn; i < N; i++) { + if (states[i] != UNLOCKED) return 0; + } + for (i = 0; i < id; i++) { + if (states[i] != UNLOCKED) return 0; + } + } else { + for (i = lturn; i < id; i++) { + if (states[i] != UNLOCKED) return 0; + } + } + return 1; +} + +inline static const int validate_right(const int id, const int lturn) { + int i; + if (lturn <= id) { + for (i = id + 1; i < N; i++) { + if (states[i] == LOCKED) return 0; + } + for (i = 0; i < lturn; i++) { + if (states[i] == LOCKED) return 0; + } + } else { + for (i = id + 1; i < lturn; i++) { + if (states[i] == LOCKED) return 0; + } + } + return 1; +} + +static void *Worker( void *arg ) { + TYPE id = (size_t)arg; + uint64_t entry; +#ifdef FAST + unsigned int cnt = 0, oid = id; +#endif // FAST + + for ( int r = 0; r < RUNS; r += 1 ) { + entry = 0; + while ( stop == 0 ) { + states[id] = LOCKED; + Fence(); + while (1) { + TYPE lturn = turn; + if (!validate_left(id, lturn)) { + states[id] = WAITING; + Fence(); + while (1) { + if (validate_left(id, lturn) && lturn == turn) break; + Pause(); + lturn = turn; + } + states[id] = LOCKED; + Fence(); + continue; + } + while (lturn == turn) { + if (validate_right(id, lturn)) break; + Pause(); + } + if (lturn == turn) break; + } + CriticalSection( id ); // critical section + turn = (turn+1) % N; + states[id] = UNLOCKED; // exit protocol +#ifdef FAST + id = startpoint( cnt ); // different starting point each experiment + cnt = cycleUp( cnt, NoStartPoints ); +#endif // FAST + entry += 1; + } // while +#ifdef FAST + id = oid; +#endif // FAST + entries[r][id] = entry; + __sync_fetch_and_add( &Arrived, 1 ); + while ( stop != 0 ) Pause(); + __sync_fetch_and_add( &Arrived, -1 ); + } // for + return NULL; +} // Worker + +void ctor() { + states = Allocator( sizeof(typeof(states[0])) * N ); + for ( int i = 0; i < N; i += 1 ) { // initialize shared data + states[i] = UNLOCKED; + } // for + turn = 0; +} // ctor + +void dtor() { + free( (void *)states ); +} // dtor + +// Local Variables: // +// tab-width: 4 // +// compile-command: "gcc -Wall -std=gnu99 -O3 -DNDEBUG -fno-reorder-functions -DPIN -DAlgorithm=CorreiaRamalheteTurn Harness.c -lpthread -lm" // +// End: //