| 1 | #include <locks.hfa>
 | 
|---|
| 2 | #include <fstream.hfa>
 | 
|---|
| 3 | #include <stdio.h>
 | 
|---|
| 4 | #include <channel.hfa>
 | 
|---|
| 5 | #include <thread.hfa>
 | 
|---|
| 6 | #include <time.hfa>
 | 
|---|
| 7 | #include <string.h>
 | 
|---|
| 8 | 
 | 
|---|
| 9 | size_t total_operations = 0;
 | 
|---|
| 10 | ssize_t Processors = 1, Tasks = 5, BarrierSize = 2;             // must be signed
 | 
|---|
| 11 | 
 | 
|---|
| 12 | typedef channel( int ) Channel;
 | 
|---|
| 13 | 
 | 
|---|
| 14 | Channel * barWait;
 | 
|---|
| 15 | Channel * entryWait;
 | 
|---|
| 16 | owner_lock o;
 | 
|---|
| 17 | 
 | 
|---|
| 18 | bool done = false;
 | 
|---|
| 19 | size_t tasks_done = 0;
 | 
|---|
| 20 | 
 | 
|---|
| 21 | static inline void initBarrier() {
 | 
|---|
| 22 |     for ( j; BarrierSize )
 | 
|---|
| 23 |         insert( *entryWait, j );
 | 
|---|
| 24 | }
 | 
|---|
| 25 | 
 | 
|---|
| 26 | static inline void barrier() {
 | 
|---|
| 27 |     int ticket = remove( *entryWait );
 | 
|---|
| 28 | 
 | 
|---|
| 29 |     if ( ticket == BarrierSize - 1 ) {
 | 
|---|
| 30 |                 for ( j; BarrierSize - 1 )
 | 
|---|
| 31 |             insert( *barWait, j );
 | 
|---|
| 32 |         return;
 | 
|---|
| 33 |         }
 | 
|---|
| 34 |     ticket = remove( *barWait );
 | 
|---|
| 35 | 
 | 
|---|
| 36 |         // last one out
 | 
|---|
| 37 |         if ( BarrierSize == 1 || ticket == BarrierSize - 2 ) {
 | 
|---|
| 38 |                 for ( j; BarrierSize )
 | 
|---|
| 39 |             insert( *entryWait, j );
 | 
|---|
| 40 |         }
 | 
|---|
| 41 | }
 | 
|---|
| 42 | 
 | 
|---|
| 43 | thread Task {};
 | 
|---|
| 44 | static inline void ?{}( Task & p, cluster & clu ) {
 | 
|---|
| 45 |     ((thread &)p){ clu };
 | 
|---|
| 46 | }
 | 
|---|
| 47 | void main(Task & this) {
 | 
|---|
| 48 |     size_t runs = 0;
 | 
|---|
| 49 |     try {
 | 
|---|
| 50 |         for ( ;; ) {
 | 
|---|
| 51 |             if ( done ) break;
 | 
|---|
| 52 |             barrier();
 | 
|---|
| 53 |             runs++;
 | 
|---|
| 54 |         }
 | 
|---|
| 55 |     } catch ( channel_closed * e ) {} 
 | 
|---|
| 56 |     lock(o);
 | 
|---|
| 57 |     total_operations += runs;
 | 
|---|
| 58 |     // sout | "P: " | runs;
 | 
|---|
| 59 |     unlock(o);
 | 
|---|
| 60 | }
 | 
|---|
| 61 | 
 | 
|---|
| 62 | 
 | 
|---|
| 63 | int main( int argc, char * argv[] ) {
 | 
|---|
| 64 |     switch ( argc ) {
 | 
|---|
| 65 |           case 3:
 | 
|---|
| 66 |                 if ( strcmp( argv[2], "d" ) != 0 ) {                    // default ?
 | 
|---|
| 67 |                         BarrierSize = ato( argv[2] );
 | 
|---|
| 68 |             if ( Processors < 1 ) fallthru default;
 | 
|---|
| 69 |                 } // if
 | 
|---|
| 70 |           case 2:
 | 
|---|
| 71 |                 if ( strcmp( argv[1], "d" ) != 0 ) {                    // default ?
 | 
|---|
| 72 |                         Processors = ato( argv[1] );
 | 
|---|
| 73 |                         if ( Processors < 1 ) fallthru default;
 | 
|---|
| 74 |                 } // if
 | 
|---|
| 75 |           case 1:                                                                                       // use defaults
 | 
|---|
| 76 |                 break;
 | 
|---|
| 77 |           default:
 | 
|---|
| 78 |                 exit | "Usage: " | argv[0]
 | 
|---|
| 79 |              | " [ processors (> 0) | 'd' (default " | Processors
 | 
|---|
| 80 |                          | ") ] [ BarrierSize (> 0) | 'd' (default " | BarrierSize
 | 
|---|
| 81 |                          | ") ]" ;
 | 
|---|
| 82 |         } // switch
 | 
|---|
| 83 |     if ( Tasks < BarrierSize )
 | 
|---|
| 84 |         Tasks = BarrierSize;
 | 
|---|
| 85 | 
 | 
|---|
| 86 |     size_t Clusters = 1;
 | 
|---|
| 87 |     // create a cluster
 | 
|---|
| 88 |     cluster clus[Clusters];
 | 
|---|
| 89 |     processor * proc[Processors];
 | 
|---|
| 90 |     for ( i; Processors ) {
 | 
|---|
| 91 |         (*(proc[i] = malloc())){clus[i % Clusters]};
 | 
|---|
| 92 |     }
 | 
|---|
| 93 | 
 | 
|---|
| 94 |     Channel entry{ BarrierSize };
 | 
|---|
| 95 |     Channel wait{ BarrierSize };
 | 
|---|
| 96 | 
 | 
|---|
| 97 |     entryWait = &entry;
 | 
|---|
| 98 |     barWait = &wait;
 | 
|---|
| 99 | 
 | 
|---|
| 100 |     initBarrier();
 | 
|---|
| 101 | 
 | 
|---|
| 102 |     sout | "start";
 | 
|---|
| 103 |     Task * t[Tasks];
 | 
|---|
| 104 | 
 | 
|---|
| 105 |     for ( i; Tasks ) {
 | 
|---|
| 106 |         (*(t[i] = malloc())){ clus[i % Clusters] };
 | 
|---|
| 107 |     }
 | 
|---|
| 108 | 
 | 
|---|
| 109 |     sleep(10`s);
 | 
|---|
| 110 |     done = true;
 | 
|---|
| 111 | 
 | 
|---|
| 112 |     sout | "sleep";
 | 
|---|
| 113 | 
 | 
|---|
| 114 |     close( entry );
 | 
|---|
| 115 |     close( wait );
 | 
|---|
| 116 | 
 | 
|---|
| 117 |     for ( i; Tasks ) {
 | 
|---|
| 118 |         delete(t[i]);
 | 
|---|
| 119 |     }
 | 
|---|
| 120 |     
 | 
|---|
| 121 |     // sout | total_operations;
 | 
|---|
| 122 | 
 | 
|---|
| 123 |     for ( i; Processors ) {
 | 
|---|
| 124 |         delete(proc[i]);
 | 
|---|
| 125 |     }
 | 
|---|
| 126 |     sout | "done";
 | 
|---|
| 127 |     return 0;
 | 
|---|
| 128 | }
 | 
|---|