static void *Worker( void *arg ) { TYPE id = (size_t)arg; uint64_t entry; #ifdef FAST unsigned int cnt = 0, oid = id; #endif // FAST unsigned int lid; // local id at each tree level for ( int r = 0; r < RUNS; r += 1 ) { entry = 0; while ( stop == 0 ) { lid = id; // entry protocol for ( int lv = 0; lv < depth; lv += 1 ) { binary_prologue( lid & 1, &t[lv][lid >> 1] ); lid >>= 1; // advance local id for next tree level } // for CriticalSection( id ); for ( int lv = depth - 1; lv >= 0; lv -= 1 ) { // exit protocol, retract reverse order lid = id >> lv; binary_epilogue( lid & 1, &t[lv][lid >> 1] ); } // for #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
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; #ifdef FAST unsigned int cnt = 0, oid = id; #endif // FAST uint64_t entry; for ( int r = 0; r < RUNS; r += 1 ) { entry = 0; while ( stop == 0 ) { L0: control[id] = WantIn; // entry protocol Fence(); // force store before more loads L1: for ( int j = turn; j != id; j = cycleDown( j, N ) ) if ( control[j] != DontWantIn ) { Pause(); goto L1; } // restart search control[id] = EnterCS; Fence(); // force store before more loads for ( int j = N - 1; j >= 0; j -= 1 ) if ( j != id && control[j] == EnterCS ) goto L0; CriticalSection( id ); // cycle through threads if ( control[turn] == DontWantIn || turn == id ) // exit protocol turn = cycleDown( turn, N ); control[id] = DontWantIn; #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
static void *Worker( void *arg ) { const 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 ) { L0: intents[id] = DontWantIn; // entry protocol Fence(); // force store before more loads for ( int j = 0; j < id; j += 1 ) if ( intents[j] == WantIn ) { Pause(); goto L0; } intents[id] = WantIn; Fence(); // force store before more loads for ( int j = 0; j < id; j += 1 ) if ( intents[j] == WantIn ) goto L0; L1: for ( int j = id + 1; j < N; j += 1 ) if ( intents[j] == WantIn ) { Pause(); goto L1; } CriticalSection( id ); // critical section intents[id] = DontWantIn; // 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
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