static inline bool trylock( TYPE id ) { // based on Lamport-Fast algorithm b[id] = true; x = id; Fence(); // force store before more loads if ( FASTPATH( y != N ) ) { b[id] = false; return false; } // if y = id; Fence(); // force store before more loads if ( FASTPATH( x != id ) ) { b[id] = false; Fence(); // OPTIONAL, force store before more loads for ( int k = 0; k < N; k += 1 ) await( ! b[k] ); if ( FASTPATH( y != id ) ) return false; } // if bool leader; if ( ! fast ) { fast = true; leader = true; } else leader = false; y = N; b[id] = false; return leader; } // WCas
static inline bool trylock( TYPE id ) { // based on Burns-Lamport algorithm b[id] = true; Fence(); // force store before more loads for ( typeof(id) thr = 0; thr < id; thr += 1 ) { if ( FASTPATH( b[thr] ) ) { b[id] = false; return false ; } // if } // for for ( typeof(id) thr = id + 1; thr < N; thr += 1 ) { await( ! b[thr] ); } // for bool leader; if ( ! fast ) { fast = true; leader = true; } else leader = false; b[id] = false; return leader; } // WCas
static void *Worker( void *arg ) { TYPE id = (size_t)arg; uint64_t entry; int other = inv( id ); // int is better than TYPE #ifdef FAST unsigned int cnt = 0, oid = id; #endif // FAST for ( int r = 0; r < RUNS; r += 1 ) { entry = 0; while ( stop == 0 ) { intents[id] = WantIn; // entry protocol last = id; // RACE Fence(); // force store before more loads if ( FASTPATH( intents[other] != DontWantIn ) ) // local spin while ( last == id ) Pause(); // busy wait CriticalSection( id ); intents[id] = DontWantIn; // exit protocol last = id; #ifdef FAST id = startpoint( cnt ); // different starting point each experiment other = inv( id ); cnt = cycleUp( cnt, NoStartPoints ); #endif // FAST entry += 1; } // while #ifdef FAST id = oid; other = inv( id ); #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
static void *Worker( void *arg ) { TYPE id = (size_t)arg; uint64_t entry; int other = inv( id ); // int is better than TYPE #ifdef FAST unsigned int cnt = 0, oid = id; #endif // FAST for ( int r = 0; r < RUNS; r += 1 ) { entry = 0; while ( stop == 0 ) { #ifdef FLICKER for ( int i = 0; i < 100; i += 1 ) cc[id] = i % 2; // flicker #endif // FLICKER cc[id] = WantIn; // declare intent Fence(); // force store before more loads while ( cc[other] == WantIn ) { if ( FASTPATH( last == id ) ) { #ifdef FLICKER for ( int i = 0; i < 100; i += 1 ) cc[id] = i % 2; // flicker #endif // FLICKER cc[id] = DontWantIn; while( cc[other] == WantIn && last == id ) Pause(); // low priority busy wait #ifdef FLICKER for ( int i = 0; i < 100; i += 1 ) cc[id] = i % 2; // flicker #endif // FLICKER cc[id] = WantIn; // declare intent Fence(); // force store before more loads } // if } // while CriticalSection( id ); if ( last != id ) { #ifdef FLICKER for ( int i = id; i < 100; i += 1 ) last = i % 2; // flicker #endif // FLICKER last = id; } // if #ifdef FLICKER for ( int i = 0; i < 100; i += 1 ) cc[id] = i % 2; // flicker #endif // FLICKER cc[id] = DontWantIn; #ifdef FAST id = startpoint( cnt ); // different starting point each experiment other = inv( id ); cnt = cycleUp( cnt, NoStartPoints ); #endif // FAST entry += 1; } // while #ifdef FAST id = oid; other = inv( id ); #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
static void *Worker( void *arg ) { TYPE id = (size_t)arg; uint64_t entry; int other = inv( id ); // int is better than TYPE #ifdef FAST unsigned int cnt = 0, oid = id; #endif // FAST for ( int r = 0; r < RUNS; r += 1 ) { entry = 0; while ( stop == 0 ) { for ( ;; ) { #ifdef FLICKER for ( int i = 0; i < 100; i += 1 ) intents[id] = i % 2; // flicker #endif // FLICKER intents[id] = WantIn; // declare intent // Necessary to prevent the read of intents[other] from floating above the assignment // intents[id] = WantIn, when the hardware determines the two subscripts are different. Fence(); // force store before more loads if ( FASTPATH( intents[other] == DontWantIn ) ) break; if ( last == id ) { #ifdef FLICKER for ( int i = 0; i < 100; i += 1 ) intents[id] = i % 2; // flicker #endif // FLICKER intents[id] = DontWantIn; // Optional fence to prevent LD of "last" from being lifted above store of // intends[id]=DontWantIn. Because a thread only writes its own id into "last", // and because of eventual consistency (writes eventually become visible), // the fence is conservative. //Fence(); // force store before more loads await( last != id ); // low priority busy wait } // if } // for CriticalSection( id ); #ifdef FLICKER for ( int i = id; i < 100; i += 1 ) last = i % 2; // flicker #endif // FLICKER last = id; // exit protocol #ifdef FLICKER for ( int i = 0; i < 100; i += 1 ) intents[id] = i % 2; // flicker #endif // FLICKER intents[id] = DontWantIn; #ifdef FAST id = startpoint( cnt ); // different starting point each experiment other = inv( id ); cnt = cycleUp( cnt, NoStartPoints ); #endif // FAST entry += 1; } // while #ifdef FAST id = oid; other = inv( id ); #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