| [a33a5e2] | 1 | #include <select.hfa>
 | 
|---|
 | 2 | #include <thread.hfa>
 | 
|---|
 | 3 | #include <channel.hfa>
 | 
|---|
 | 4 | 
 | 
|---|
 | 5 | channel(long long int) A, B, C;
 | 
|---|
 | 6 | 
 | 
|---|
 | 7 | volatile bool done = false;
 | 
|---|
 | 8 | long long int globalTotal = 0;
 | 
|---|
 | 9 | 
 | 
|---|
 | 10 | thread Server1 {};
 | 
|---|
 | 11 | void main( Server1 & this ) {
 | 
|---|
 | 12 |     long long int a, b, c, i = 0, myTotal = 0;
 | 
|---|
 | 13 |     for( ;;i++ ) {
 | 
|---|
| [a882b68] | 14 |         when( i % 2 == 0 ) waituntil( a << A ) { myTotal += a; }
 | 
|---|
 | 15 |         or when( i % 4 < 2 ) waituntil( b << B ) { myTotal += b; }
 | 
|---|
 | 16 |         or waituntil( c << C ) { if ( c == -1 ) break; myTotal += c; }
 | 
|---|
| [a33a5e2] | 17 |         or when( i % 8 < 4 ) else {}
 | 
|---|
 | 18 |     }
 | 
|---|
 | 19 |     __atomic_fetch_add( &globalTotal, myTotal, __ATOMIC_SEQ_CST );
 | 
|---|
 | 20 | }
 | 
|---|
 | 21 | 
 | 
|---|
 | 22 | thread Drainer {}; // ensures that the changing when states of Server1 don't result in a deadlock
 | 
|---|
 | 23 | void main( Drainer & this ) {
 | 
|---|
| [a882b68] | 24 |     long long int a, b, c, myTotal = 0;
 | 
|---|
 | 25 |     for( ;; ) {
 | 
|---|
 | 26 |         waituntil( a << A ) { myTotal += a; }
 | 
|---|
 | 27 |         or waituntil( b << B ) { myTotal += b; }
 | 
|---|
 | 28 |         or waituntil( c << C ) { if ( c == -1 ) break; myTotal += c; }
 | 
|---|
 | 29 |         or else {}
 | 
|---|
| [a33a5e2] | 30 |     }
 | 
|---|
 | 31 |     __atomic_fetch_add( &globalTotal, myTotal, __ATOMIC_SEQ_CST );
 | 
|---|
 | 32 | }
 | 
|---|
 | 33 | 
 | 
|---|
 | 34 | thread Churner {}; // performs non-waituntil try insert/remove operations to add churn/interference
 | 
|---|
 | 35 | void main( Churner & this ) {
 | 
|---|
 | 36 |     long long int out, myTotal = 0;
 | 
|---|
 | 37 |     bool success;
 | 
|---|
 | 38 |     while( !done ) {
 | 
|---|
 | 39 |         try_insert( A, 0 );
 | 
|---|
 | 40 |         try_insert( B, 0 );
 | 
|---|
 | 41 |         try_insert( C, 0 );
 | 
|---|
| [a882b68] | 42 |         [out, success] = try_remove( A );
 | 
|---|
| [a33a5e2] | 43 |         if ( success ) myTotal += out;
 | 
|---|
| [a882b68] | 44 |         [out, success] = try_remove( B );
 | 
|---|
| [a33a5e2] | 45 |         if ( success ) myTotal += out;
 | 
|---|
| [a882b68] | 46 |         [out, success] = try_remove( C );
 | 
|---|
| [a33a5e2] | 47 |         if ( success ) myTotal += out;
 | 
|---|
 | 48 |     }
 | 
|---|
 | 49 |     __atomic_fetch_add( &globalTotal, myTotal, __ATOMIC_SEQ_CST );
 | 
|---|
 | 50 | }
 | 
|---|
 | 51 | 
 | 
|---|
 | 52 | size_t numtimes = 100000;
 | 
|---|
 | 53 | size_t numServers = 3;
 | 
|---|
 | 54 | int main( int argc, char * argv[] ) {
 | 
|---|
 | 55 |     if ( argc == 2 )
 | 
|---|
 | 56 |         numtimes = atoi( argv[1] );
 | 
|---|
 | 57 | 
 | 
|---|
 | 58 |     processor p[numServers + 2];
 | 
|---|
 | 59 |     A{5};
 | 
|---|
 | 60 |     B{5};
 | 
|---|
 | 61 |     C{5};
 | 
|---|
 | 62 | 
 | 
|---|
 | 63 |     long long int total = 0;
 | 
|---|
 | 64 |     printf("start\n");
 | 
|---|
 | 65 |     {
 | 
|---|
 | 66 |         Server1 s[numServers];
 | 
|---|
 | 67 |         Drainer d;
 | 
|---|
 | 68 |         {
 | 
|---|
 | 69 |             Churner c;
 | 
|---|
 | 70 |             for( long long int j = 0; j < numtimes; j++ ) {
 | 
|---|
| [a882b68] | 71 |                 when( j % 2 == 0 ) waituntil( j >> A ) { total += j; }
 | 
|---|
 | 72 |                 or when( j % 4 < 2 ) waituntil( j >> B ) { total += j; }
 | 
|---|
 | 73 |                 and when( j % 8 < 4 ) waituntil( j >> C ) { total += j; }
 | 
|---|
| [a33a5e2] | 74 |             }
 | 
|---|
 | 75 |             done = true;
 | 
|---|
 | 76 |             printf("terminating churner\n");
 | 
|---|
 | 77 |         }
 | 
|---|
 | 78 |         printf("waiting for empty channels\n");
 | 
|---|
| [a882b68] | 79 |         while( get_count( A ) > 0 || get_count( B ) > 0 || get_count( C ) > 0 ) { }
 | 
|---|
| [a33a5e2] | 80 |         printf("sending sentinels\n");
 | 
|---|
 | 81 |         for ( i; numServers + 1 ) insert( C, -1 );
 | 
|---|
 | 82 |         printf("joining servers\n");
 | 
|---|
 | 83 |     }
 | 
|---|
 | 84 |     if ( total != globalTotal ) 
 | 
|---|
 | 85 |         printf("CHECKSUM MISMATCH!! Main thread got %lld, server sum is %lld\n", total, globalTotal);
 | 
|---|
 | 86 |     printf("done\n");
 | 
|---|
 | 87 | }
 | 
|---|