#include #include #include #include #include static const unsigned N = 100_000; enum state_t { WAITED, SIGNAL, BARGE }; monitor global_data_t { thread_desc * last_thread; thread_desc * last_signaller; }; void ?{} ( global_data_t * this ) { this->last_thread = NULL; this->last_signaller = NULL; } void ^?{} ( global_data_t * this ) {} global_data_t globalA, globalB; condition cond; volatile bool done; //------------------------------------------------------------------------------ void wait_op( global_data_t * mutex a, global_data_t * mutex b, unsigned i ) { wait( &cond, (uintptr_t)this_thread ); yield( ((unsigned)rand48()) % 10 ); if(a->last_thread != a->last_signaller || b->last_thread != b->last_signaller ) { sout | "ERROR Barging detected, expected" | a->last_signaller | b->last_signaller | "got" | a->last_thread | b->last_thread | endl; abort(); } a->last_thread = b->last_thread = this_thread; yield( ((unsigned)rand48()) % 10 ); } thread Waiter {}; void main( Waiter* this ) { for( int i = 0; i < N; i++ ) { wait_op( &globalA, &globalB, i ); } } //------------------------------------------------------------------------------ void signal_op( global_data_t * mutex a, global_data_t * mutex b ) { yield( ((unsigned)rand48()) % 10 ); a->last_thread = b->last_thread = a->last_signaller = b->last_signaller = this_thread; if( !is_empty( &cond ) ) { thread_desc * next = front( &cond ); if( ! signal_block( &cond ) ) { sout | "ERROR expected to be able to signal" | endl; abort(); } yield( ((unsigned)rand48()) % 10 ); if(a->last_thread != next || b->last_thread != next) { sout | "ERROR Barging detected, expected" | next | "got" | a->last_thread | b->last_thread | endl; abort(); } } } thread Signaller {}; void main( Signaller* this ) { while( !done ) { signal_op( &globalA, &globalB ); } } //------------------------------------------------------------------------------ void barge_op( global_data_t * mutex a ) { a->last_thread = this_thread; } thread Barger {}; void main( Barger* this ) { for( unsigned i = 0; !done; i++ ) { //Choose some monitor to barge into with some irregular pattern bool choose_a = (i % 13) > (i % 17); barge_op( choose_a ? &globalA : &globalB ); } } //------------------------------------------------------------------------------ int main(int argc, char* argv[]) { rand48seed(0); done = false; processor p; { Signaller s[4]; Barger b[13]; sout | "Starting waiters" | endl; { Waiter w[3]; } sout | "Waiters done" | endl; done = true; } }