#include #include #include #include #include "bench.h" coroutine GreatSuspender {}; void ?{}( GreatSuspender & this ) { prime(this); } void main( GreatSuspender & this ) { while( true ) { suspend(); } } void resumer( GreatSuspender * this, const unsigned int NoOfTimes ) { for ( volatile unsigned int i = 0; i < NoOfTimes; i += 1 ) { resume( *this ); } } //----------------------------------------------------------------------------- // coroutine context switch long long int measure_coroutine() { const unsigned int NoOfTimes = 50000000; long long int StartTime, EndTime; GreatSuspender s; StartTime = Time(); resumer( &s, NoOfTimes ); EndTime = Time(); return ( EndTime - StartTime ) / NoOfTimes; } //----------------------------------------------------------------------------- // thread context switch long long int measure_thread() { const unsigned int NoOfTimes = 50000000; long long int StartTime, EndTime; StartTime = Time(); for ( volatile unsigned int i = 0; i < NoOfTimes; i += 1 ) { yield(); } EndTime = Time(); return ( EndTime - StartTime ) / NoOfTimes; } //----------------------------------------------------------------------------- // single monitor entry monitor mon_t {}; void dummy( mon_t & mutex m ) {} long long int measure_1_monitor_entry() { const unsigned int NoOfTimes = 5000000; long long int StartTime, EndTime; mon_t mon; StartTime = Time(); for ( volatile unsigned int i = 0; i < NoOfTimes; i += 1 ) { dummy( mon ); } EndTime = Time(); return ( EndTime - StartTime ) / NoOfTimes; } //----------------------------------------------------------------------------- // multi monitor entry void dummy( mon_t & mutex m1, mon_t & mutex m2 ) {} long long int measure_2_monitor_entry() { const unsigned int NoOfTimes = 5000000; long long int StartTime, EndTime; mon_t mon1, mon2; StartTime = Time(); for ( volatile unsigned int i = 0; i < NoOfTimes; i += 1 ) { dummy( mon1, mon2 ); } EndTime = Time(); return ( EndTime - StartTime ) / NoOfTimes; } //----------------------------------------------------------------------------- // single internal sched entry const unsigned int NoOfTimes = 500000; mon_t mon1; condition cond1a; condition cond1b; thread thrd1a { long long int * out; }; thread thrd1b {}; void ?{}( thrd1a & this, long long int * out ) { this.out = out; } void side1A( mon_t & mutex a, long long int * out ) { const unsigned int NoOfTimes = 500000; long long int StartTime, EndTime; StartTime = Time(); for( int i = 0;; i++ ) { signal(cond1a); if( i > NoOfTimes ) break; wait(cond1b); } EndTime = Time(); *out = ( EndTime - StartTime ) / NoOfTimes; } void side1B( mon_t & mutex a ) { for( int i = 0;; i++ ) { signal(cond1b); if( i > N ) break; wait(cond1a); } } void main( thrd1a & this ) { side1A( mon1, this.out ); } void main( thrd1b & this ) { side1B( mon1 ); } long long int measure_1_sched_int() { long long int t; { thrd1a a = { &t }; thrd1b b; } return t; } //----------------------------------------------------------------------------- // multi internal sched mon_t mon2; condition cond2a; condition cond2b; thread thrd2a { long long int * out; }; thread thrd2b {}; void ?{}( thrd2a & this, long long int * out ) { this.out = out; } void side2A( mon_t & mutex a, mon_t & mutex b, long long int * out ) { const unsigned int NoOfTimes = 500000; long long int StartTime, EndTime; StartTime = Time(); for( int i = 0;; i++ ) { signal(cond2a); if( i > NoOfTimes ) break; wait(cond2b); } EndTime = Time(); *out = ( EndTime - StartTime ) / NoOfTimes; } void side2B( mon_t & mutex a, mon_t & mutex b ) { for( int i = 0;; i++ ) { signal(cond2b); if( i > N ) break; wait(cond2a); } } void main( thrd2a & this ) { side2A( mon1, mon2, this.out ); } void main( thrd2b & this ) { side2B( mon1, mon2 ); } long long int measure_2_sched_int() { long long int t; { thrd2a a = { &t }; thrd2b b; } return t; } //----------------------------------------------------------------------------- // single external sched volatile int go = 0; void __attribute__((noinline)) call( mon_t & mutex m1 ) {} long long int __attribute__((noinline)) wait( mon_t & mutex m1 ) { go = 1; const unsigned int NoOfTimes = 5000000; long long int StartTime, EndTime; StartTime = Time(); for (size_t i = 0; i < NoOfTimes; i++) { waitfor(call, m1); } EndTime = Time(); go = 0; return ( EndTime - StartTime ) / NoOfTimes; } thread thrd3 {}; void ^?{}( thrd3 & mutex this ) {} void main( thrd3 & this ) { while(go == 0) { yield(); } while(go == 1) { call(mon1); } } long long int measure_1_sched_ext() { go = 0; thrd3 t; return wait(mon1); } //----------------------------------------------------------------------------- // multi external sched void __attribute__((noinline)) call( mon_t & mutex m1, mon_t & mutex m2 ) {} long long int __attribute__((noinline)) wait( mon_t & mutex m1, mon_t & mutex m2 ) { go = 1; const unsigned int NoOfTimes = 5000000; long long int StartTime, EndTime; StartTime = Time(); for (size_t i = 0; i < NoOfTimes; i++) { waitfor(call, m1, m2); } EndTime = Time(); go = 0; return ( EndTime - StartTime ) / NoOfTimes; } thread thrd4 {}; void ^?{}( thrd4 & mutex this ) {} void main( thrd4 & this ) { while(go == 0) { yield(); } while(go == 1) { call(mon1, mon2); } } long long int measure_2_sched_ext() { go = 0; thrd3 t; return wait(mon1, mon2); } //----------------------------------------------------------------------------- // main loop int main() { sout | "\tepoch:" | time(NULL) | ',' | endl; sout | "\tctxswitch: {" | endl; sout | "\t\tcoroutine: "| measure_coroutine() | ',' | endl; sout | "\t\tthread:" | measure_thread() | ',' | endl; sout | "\t}," | endl; sout | "\tmutex: [" | measure_1_monitor_entry() | ',' | measure_2_monitor_entry() | "]," | endl; sout | "\tscheduling: ["| measure_1_sched_int() | ',' | measure_2_sched_int() | ',' | measure_1_sched_ext() | ',' | measure_2_sched_ext() | "]," | endl; }