| [c2409fd] | 1 | #include "semaphore.hfa"
 | 
|---|
 | 2 | #include "kernel_private.hfa"
 | 
|---|
 | 3 | #include <stdlib.h>
 | 
|---|
 | 4 | #include <stdio.h>
 | 
|---|
 | 5 | 
 | 
|---|
 | 6 | #include <kernel.hfa>
 | 
|---|
 | 7 | #include <stdlib.hfa>
 | 
|---|
 | 8 | #include <thread.hfa>
 | 
|---|
 | 9 | 
 | 
|---|
 | 10 | forall(dtype L | is_blocking_lock(L)) {
 | 
|---|
 | 11 | 
 | 
|---|
 | 12 |         void ?{}(base_semaphore(L) & this, int count, bool is_binary) {
 | 
|---|
 | 13 |                 this.count = count;
 | 
|---|
 | 14 |                 this.lock{};
 | 
|---|
 | 15 |                 this.blocked_threads{};
 | 
|---|
 | 16 |                 this.is_binary = is_binary;
 | 
|---|
 | 17 |         }
 | 
|---|
 | 18 | 
 | 
|---|
 | 19 |         void ^?{}(base_semaphore(L) & this) {
 | 
|---|
 | 20 |                 // default
 | 
|---|
 | 21 |         }
 | 
|---|
 | 22 | 
 | 
|---|
 | 23 |         void ?{}(binary_semaphore(L) & this) {
 | 
|---|
 | 24 |                 ((base_semaphore(L) &)this){ 1, true };
 | 
|---|
 | 25 |         }
 | 
|---|
 | 26 | 
 | 
|---|
 | 27 |         void ?{}(binary_semaphore(L) & this, int count) {
 | 
|---|
 | 28 |                 ((base_semaphore(L) &)this){ count, true };
 | 
|---|
 | 29 |         }
 | 
|---|
 | 30 | 
 | 
|---|
 | 31 |         void ^?{}(binary_semaphore(L) & this) {
 | 
|---|
 | 32 |                 // default
 | 
|---|
 | 33 |         }
 | 
|---|
 | 34 | 
 | 
|---|
 | 35 |         void ?{}(counting_semaphore(L) & this) {
 | 
|---|
 | 36 |                 ((base_semaphore(L) &)this){ 1, false };
 | 
|---|
 | 37 |         }
 | 
|---|
 | 38 | 
 | 
|---|
 | 39 |         void ?{}(counting_semaphore(L) & this, int count) {
 | 
|---|
 | 40 |                 ((base_semaphore(L) &)this){ count, false };
 | 
|---|
 | 41 |         }
 | 
|---|
 | 42 | 
 | 
|---|
 | 43 |         void ^?{}(counting_semaphore(L) & this) {
 | 
|---|
 | 44 |                 // default
 | 
|---|
 | 45 |         }
 | 
|---|
 | 46 | 
 | 
|---|
 | 47 |         void ?{}( alarm_node_semaphore(L) & this, $thread * thrd, Time alarm, Duration period, Alarm_Callback callback ) {
 | 
|---|
 | 48 |                 this.alarm_node{ thrd, alarm, period, callback };
 | 
|---|
 | 49 |         }
 | 
|---|
 | 50 | 
 | 
|---|
 | 51 |         void ^?{}( alarm_node_semaphore(L) & this ) {
 | 
|---|
 | 52 | 
 | 
|---|
 | 53 |         }
 | 
|---|
 | 54 | 
 | 
|---|
 | 55 |         void add_( base_semaphore(L) & this, struct $thread * t ) with( this ) {
 | 
|---|
 | 56 |                 lock( lock __cfaabi_dbg_ctx2 );
 | 
|---|
 | 57 |                 #if !defined( __CFA_NO_STATISTICS__ )
 | 
|---|
 | 58 |                         kernelTLS.this_stats = t->curr_cluster->stats;
 | 
|---|
 | 59 |                 #endif
 | 
|---|
 | 60 |                 unpark( t );
 | 
|---|
 | 61 |                 unlock( lock );
 | 
|---|
 | 62 |         }
 | 
|---|
 | 63 | 
 | 
|---|
 | 64 |         void remove_( base_semaphore(L) & this ) with( this ) {
 | 
|---|
 | 65 |                 V(this);
 | 
|---|
 | 66 |         }
 | 
|---|
 | 67 | 
 | 
|---|
 | 68 |         ////////////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 69 |         // These extras are needed since the inheritance is broken with traits
 | 
|---|
 | 70 |         ////////////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 71 | 
 | 
|---|
 | 72 |         void add_( binary_semaphore(L) & this, struct $thread * t ) with( this ) {
 | 
|---|
 | 73 |                 add_( (base_semaphore(L) &)this, t );
 | 
|---|
 | 74 |         }
 | 
|---|
 | 75 | 
 | 
|---|
 | 76 |         void remove_( binary_semaphore(L) & this ) with( this ) {
 | 
|---|
 | 77 |                 remove_( (base_semaphore(L) &)this );
 | 
|---|
 | 78 |         }
 | 
|---|
 | 79 | 
 | 
|---|
 | 80 |         void add_( counting_semaphore(L) & this, struct $thread * t ) with( this ) {
 | 
|---|
 | 81 |                 add_( (base_semaphore(L) &)this, t );
 | 
|---|
 | 82 |         }
 | 
|---|
 | 83 | 
 | 
|---|
 | 84 |         void remove_( counting_semaphore(L) & this ) with( this ) {
 | 
|---|
 | 85 |                 remove_( (base_semaphore(L) &)this );
 | 
|---|
 | 86 |         }
 | 
|---|
 | 87 | 
 | 
|---|
 | 88 |         ////////////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 89 |         ////////////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 90 | 
 | 
|---|
 | 91 |         void timeout_handler ( alarm_node_semaphore(L) & this ) with( this ) {
 | 
|---|
 | 92 |         // This condition_variable member is called from the kernel, and therefore, cannot block, but it can spin.
 | 
|---|
 | 93 |             lock( sem->lock __cfaabi_dbg_ctx2 );
 | 
|---|
 | 94 |             if ( (*i)->listed ) {                       // is thread on queue
 | 
|---|
 | 95 |                 info_thread(L) * copy = *i;
 | 
|---|
 | 96 |                         remove( sem->blocked_threads, i );               //remove this thread O(1)
 | 
|---|
 | 97 |                         sem->count++;
 | 
|---|
 | 98 |                         if( !copy->lock ) {
 | 
|---|
 | 99 |                                 unlock( sem->lock );
 | 
|---|
 | 100 |                                 #if !defined( __CFA_NO_STATISTICS__ )
 | 
|---|
 | 101 |                                         kernelTLS.this_stats = copy->t->curr_cluster->stats;
 | 
|---|
 | 102 |                                 #endif
 | 
|---|
 | 103 |                                 unpark( copy->t );
 | 
|---|
 | 104 |                 } else {
 | 
|---|
 | 105 |                         add_(*copy->lock, copy->t);                     // call lock's add_
 | 
|---|
 | 106 |                 }
 | 
|---|
 | 107 |             }
 | 
|---|
 | 108 |             unlock( sem->lock );
 | 
|---|
 | 109 |         }
 | 
|---|
 | 110 | 
 | 
|---|
 | 111 |         void alarm_node_sem_cast( alarm_node_t & a ) {
 | 
|---|
 | 112 |                 timeout_handler( (alarm_node_semaphore(L) &)a );
 | 
|---|
 | 113 |         }
 | 
|---|
 | 114 | 
 | 
|---|
 | 115 |         void handle_P(base_semaphore(L) & this, info_thread( L ) & i ) with( this ) {
 | 
|---|
 | 116 |                 lock( lock __cfaabi_dbg_ctx2 );
 | 
|---|
 | 117 |                 if ( count <= 0) {
 | 
|---|
 | 118 |                         append( blocked_threads, &i );
 | 
|---|
 | 119 | 
 | 
|---|
 | 120 |                         if (!is_binary) count--;
 | 
|---|
 | 121 | 
 | 
|---|
 | 122 |                         i.listed = true;
 | 
|---|
 | 123 | 
 | 
|---|
 | 124 |                         size_t recursion_count;
 | 
|---|
 | 125 |                         if (i.lock) {
 | 
|---|
 | 126 |                                 recursion_count = get_recursion_count( *i.lock );
 | 
|---|
 | 127 |                                 remove_( *i.lock );
 | 
|---|
 | 128 |                         }
 | 
|---|
 | 129 | 
 | 
|---|
 | 130 |                         unlock( lock );
 | 
|---|
 | 131 |                         park( );
 | 
|---|
 | 132 | 
 | 
|---|
 | 133 |                         if (i.lock) set_recursion_count( *i.lock, recursion_count );
 | 
|---|
 | 134 |                 } else {
 | 
|---|
 | 135 |                         if (i.lock) {
 | 
|---|
 | 136 |                                 size_t recursion_count = get_recursion_count( *i.lock );
 | 
|---|
 | 137 |                                 remove_( *i.lock );
 | 
|---|
 | 138 |                                 add_( *i.lock, i.t );
 | 
|---|
 | 139 |                                 set_recursion_count( *i.lock, recursion_count );
 | 
|---|
 | 140 |                         }
 | 
|---|
 | 141 |                         count--;
 | 
|---|
 | 142 |                         unlock( lock );
 | 
|---|
 | 143 |                 }
 | 
|---|
 | 144 |         }
 | 
|---|
 | 145 | 
 | 
|---|
 | 146 |         void handle_P_timeout(base_semaphore(L) & this, info_thread( L ) & i, Time time) with( this ) {
 | 
|---|
 | 147 |                 lock( lock __cfaabi_dbg_ctx2 );
 | 
|---|
 | 148 |                 if ( count <= 0) {
 | 
|---|
 | 149 |                         append( blocked_threads, &i );
 | 
|---|
 | 150 | 
 | 
|---|
 | 151 |                         if (!is_binary) count--;
 | 
|---|
 | 152 | 
 | 
|---|
 | 153 |                         info_thread(L) * queue_ptr = &i;
 | 
|---|
 | 154 |                         i.listed = true;
 | 
|---|
 | 155 | 
 | 
|---|
 | 156 |                         alarm_node_semaphore(L) node_wrap = { i.t, time, 0`s, alarm_node_sem_cast };
 | 
|---|
 | 157 |                         node_wrap.sem = &this;
 | 
|---|
 | 158 |                         node_wrap.i = &queue_ptr;
 | 
|---|
 | 159 | 
 | 
|---|
 | 160 |                         register_self( &node_wrap.alarm_node );
 | 
|---|
 | 161 | 
 | 
|---|
 | 162 |                         size_t recursion_count;
 | 
|---|
 | 163 |                         if (i.lock) {
 | 
|---|
 | 164 |                                 recursion_count = get_recursion_count( *i.lock );
 | 
|---|
 | 165 |                                 remove_( *i.lock );
 | 
|---|
 | 166 |                         }
 | 
|---|
 | 167 | 
 | 
|---|
 | 168 |                         unlock( lock );
 | 
|---|
 | 169 |                         park( );
 | 
|---|
 | 170 | 
 | 
|---|
 | 171 |                         if (i.lock) set_recursion_count( *i.lock, recursion_count );
 | 
|---|
 | 172 |                 } else {
 | 
|---|
 | 173 |                         count--;
 | 
|---|
 | 174 |                         unlock( lock );
 | 
|---|
 | 175 |                 }
 | 
|---|
 | 176 |         }
 | 
|---|
 | 177 | 
 | 
|---|
 | 178 |         void P(base_semaphore(L) & this) with( this ) {
 | 
|---|
 | 179 |                 info_thread( L ) i = { kernelTLS.this_thread };
 | 
|---|
 | 180 |                 handle_P(this, i);
 | 
|---|
 | 181 |         }
 | 
|---|
 | 182 | 
 | 
|---|
 | 183 |         void P(base_semaphore(L) & this, uintptr_t info) with( this ) {
 | 
|---|
 | 184 |                 info_thread( L ) i = { kernelTLS.this_thread, info };
 | 
|---|
 | 185 |                 handle_P(this, i);
 | 
|---|
 | 186 |         }
 | 
|---|
 | 187 | 
 | 
|---|
 | 188 |         void P(base_semaphore(L) & this, Duration duration) with( this ) {
 | 
|---|
 | 189 |                 info_thread( L ) i = { kernelTLS.this_thread };
 | 
|---|
 | 190 |                 handle_P_timeout(this, i, __kernel_get_time() + duration);
 | 
|---|
 | 191 |         }
 | 
|---|
 | 192 | 
 | 
|---|
 | 193 |         void P(base_semaphore(L) & this, uintptr_t info, Duration duration) with( this ) {
 | 
|---|
 | 194 |                 info_thread( L ) i = { kernelTLS.this_thread, info };
 | 
|---|
 | 195 |                 handle_P_timeout(this, i, __kernel_get_time() + duration);
 | 
|---|
 | 196 |         }
 | 
|---|
 | 197 | 
 | 
|---|
 | 198 |         void P(base_semaphore(L) & this, Time time) with( this ) {
 | 
|---|
 | 199 |                 info_thread( L ) i = { kernelTLS.this_thread };
 | 
|---|
 | 200 |                 handle_P_timeout(this, i, time);
 | 
|---|
 | 201 |         }
 | 
|---|
 | 202 | 
 | 
|---|
 | 203 |         void P(base_semaphore(L) & this, uintptr_t info, Time time) with( this ) {
 | 
|---|
 | 204 |                 info_thread( L ) i = { kernelTLS.this_thread, info };
 | 
|---|
 | 205 |                 handle_P_timeout(this, i, time);
 | 
|---|
 | 206 |         }
 | 
|---|
 | 207 | 
 | 
|---|
 | 208 |         void P(base_semaphore(L) & this, L & l ) with( this ) {
 | 
|---|
 | 209 |                 info_thread( L ) i = { kernelTLS.this_thread };
 | 
|---|
 | 210 |                 i.lock = &l;
 | 
|---|
 | 211 |                 handle_P(this, i);
 | 
|---|
 | 212 |         }
 | 
|---|
 | 213 | 
 | 
|---|
 | 214 |         void P(base_semaphore(L) & this, L & l, uintptr_t info) with( this ) {
 | 
|---|
 | 215 |                 info_thread( L ) i = { kernelTLS.this_thread, info };
 | 
|---|
 | 216 |                 i.lock = &l;
 | 
|---|
 | 217 |                 handle_P(this, i);
 | 
|---|
 | 218 |         }
 | 
|---|
 | 219 | 
 | 
|---|
 | 220 |         void P(base_semaphore(L) & this, L & l, Duration duration ) with( this ) {
 | 
|---|
 | 221 |                 info_thread( L ) i = { kernelTLS.this_thread };
 | 
|---|
 | 222 |                 i.lock = &l;
 | 
|---|
 | 223 |                 handle_P_timeout(this, i, __kernel_get_time() + duration);
 | 
|---|
 | 224 |         }
 | 
|---|
 | 225 | 
 | 
|---|
 | 226 |         void P(base_semaphore(L) & this, L & l, uintptr_t info, Duration duration) with( this ) {
 | 
|---|
 | 227 |                 info_thread( L ) i = { kernelTLS.this_thread, info };
 | 
|---|
 | 228 |                 i.lock = &l;
 | 
|---|
 | 229 |                 handle_P_timeout(this, i, __kernel_get_time() + duration);
 | 
|---|
 | 230 |         }
 | 
|---|
 | 231 | 
 | 
|---|
 | 232 |         void P(base_semaphore(L) & this, L & l, Time time) with( this ) {
 | 
|---|
 | 233 |                 info_thread( L ) i = { kernelTLS.this_thread };
 | 
|---|
 | 234 |                 i.lock = &l;
 | 
|---|
 | 235 |                 handle_P_timeout(this, i, time);
 | 
|---|
 | 236 |         }
 | 
|---|
 | 237 | 
 | 
|---|
 | 238 |         void P(base_semaphore(L) & this, L & l, uintptr_t info, Time time) with( this ) {
 | 
|---|
 | 239 |                 info_thread( L ) i = { kernelTLS.this_thread, info };
 | 
|---|
 | 240 |                 i.lock = &l;
 | 
|---|
 | 241 |                 handle_P_timeout(this, i, time);
 | 
|---|
 | 242 |         }
 | 
|---|
 | 243 | 
 | 
|---|
 | 244 |         bool tryP(base_semaphore(L) & this) with( this ) {
 | 
|---|
 | 245 |                 lock( lock __cfaabi_dbg_ctx2 );
 | 
|---|
 | 246 |                 if ( count <= 0) {
 | 
|---|
 | 247 |                         unlock( lock );
 | 
|---|
 | 248 |                         return false;
 | 
|---|
 | 249 |                 } else {
 | 
|---|
 | 250 |                         count--;
 | 
|---|
 | 251 |                 }
 | 
|---|
 | 252 |                 unlock( lock );
 | 
|---|
 | 253 |         }
 | 
|---|
 | 254 | 
 | 
|---|
 | 255 |         void V(base_semaphore(L) & this) with( this ) {
 | 
|---|
 | 256 |                 lock( lock __cfaabi_dbg_ctx2 );
 | 
|---|
 | 257 |                 if( count < 0) {
 | 
|---|
 | 258 |                         info_thread(L) * i = pop_head( blocked_threads );
 | 
|---|
 | 259 |                         i->listed = false;
 | 
|---|
 | 260 |                         count++;
 | 
|---|
 | 261 |                         if ( i != 0p ) {
 | 
|---|
 | 262 |                                 if (i->lock) {
 | 
|---|
 | 263 |                                         add_(*i->lock, i->t);
 | 
|---|
 | 264 |                                 } else {
 | 
|---|
 | 265 |                                         unpark(i->t);
 | 
|---|
 | 266 |                                 }
 | 
|---|
 | 267 |                         }
 | 
|---|
 | 268 |                 } else if (!is_binary || count == 0) {
 | 
|---|
 | 269 |                         count++;
 | 
|---|
 | 270 |                 } else {
 | 
|---|
 | 271 |                         fprintf( stderr, "A binary semaphore was V'd when it was already at 1" );
 | 
|---|
 | 272 |                 }
 | 
|---|
 | 273 |                 unlock( lock );
 | 
|---|
 | 274 |         }
 | 
|---|
 | 275 | 
 | 
|---|
 | 276 | 
 | 
|---|
 | 277 |         // TODO: Should we be able to V a binary semaphore multiple times to wake up multiple thds?
 | 
|---|
 | 278 |         // right now we can't
 | 
|---|
 | 279 |         void V(base_semaphore(L) & this, int times) with( this ) {
 | 
|---|
 | 280 |                 assert( times > 0 );
 | 
|---|
 | 281 |                 lock( lock __cfaabi_dbg_ctx2 );
 | 
|---|
 | 282 |                 while ( count < 0 && times > 0 ) {
 | 
|---|
 | 283 |                         info_thread(L) * i = pop_head( blocked_threads );
 | 
|---|
 | 284 |                         i->listed = false;
 | 
|---|
 | 285 |                         count++;
 | 
|---|
 | 286 |                         if ( i != 0p ) {
 | 
|---|
 | 287 |                                 if (i->lock) {
 | 
|---|
 | 288 |                                         add_(*i->lock, i->t);
 | 
|---|
 | 289 |                                 } else {
 | 
|---|
 | 290 |                                         unpark(i->t);
 | 
|---|
 | 291 |                                 }
 | 
|---|
 | 292 |                         }
 | 
|---|
 | 293 |                         times--;
 | 
|---|
 | 294 |                 }
 | 
|---|
 | 295 |                 if(     !is_binary ) {
 | 
|---|
 | 296 |                         count += times;
 | 
|---|
 | 297 |                 } else if (count == 0 && times > 1) {
 | 
|---|
 | 298 |                         fprintf( stderr, "A binary semaphore was V'd when it was already at 1" );
 | 
|---|
 | 299 |                 } else {
 | 
|---|
 | 300 |                         count++;
 | 
|---|
 | 301 |                 }
 | 
|---|
 | 302 |                 unlock( lock );
 | 
|---|
 | 303 |         }
 | 
|---|
 | 304 | 
 | 
|---|
 | 305 |         // void ?++(base_semaphore(L) & this) with( this ) {
 | 
|---|
 | 306 |         //      V(this);
 | 
|---|
 | 307 |         // }
 | 
|---|
 | 308 | 
 | 
|---|
 | 309 |         // void ?--(base_semaphore(L) & this) with( this ) {
 | 
|---|
 | 310 |         //      P(this);
 | 
|---|
 | 311 |         // }
 | 
|---|
 | 312 | 
 | 
|---|
 | 313 |         // void ?`V(base_semaphore(L) & this) with( this ) {
 | 
|---|
 | 314 |         //      V(this);
 | 
|---|
 | 315 |         // }
 | 
|---|
 | 316 | 
 | 
|---|
 | 317 |         // void ?`P(base_semaphore(L) & this) with( this ) {
 | 
|---|
 | 318 |         //      P(this);
 | 
|---|
 | 319 |         // }
 | 
|---|
 | 320 | 
 | 
|---|
 | 321 |         uintptr_t front(base_semaphore(L) & this) with( this ) {
 | 
|---|
 | 322 |                 info_thread(L) *front = peek(blocked_threads);
 | 
|---|
 | 323 |                 if(!blocked_threads) return 0;
 | 
|---|
 | 324 |                 return front->info;
 | 
|---|
 | 325 |         }
 | 
|---|
 | 326 | 
 | 
|---|
 | 327 |         bool empty(base_semaphore(L) & this) with( this ) {
 | 
|---|
 | 328 |                 return blocked_threads ? false : true;
 | 
|---|
 | 329 |         }
 | 
|---|
 | 330 | 
 | 
|---|
 | 331 |         int counter(base_semaphore(L) & this) with( this ) {
 | 
|---|
 | 332 |                 return count;
 | 
|---|
 | 333 |         }
 | 
|---|
 | 334 | 
 | 
|---|
 | 335 |         // these are just to allow the semaphore to be a part of the is_blocking_lock trait
 | 
|---|
 | 336 |         // they do nothing
 | 
|---|
 | 337 |         void set_recursion_count( base_semaphore(L) & this, size_t recursion ) with( this ) {
 | 
|---|
 | 338 |                 // default
 | 
|---|
 | 339 |         }
 | 
|---|
 | 340 | 
 | 
|---|
 | 341 |         size_t get_recursion_count( base_semaphore(L) & this ) with( this ) {
 | 
|---|
 | 342 |                 return 0;
 | 
|---|
 | 343 |         }
 | 
|---|
 | 344 | 
 | 
|---|
 | 345 |         ////////////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 346 |         // These extras are needed since the inheritance is broken with traits
 | 
|---|
 | 347 |         // normally I'd cast to a semaphore & to call the parent but theres no need
 | 
|---|
 | 348 |         // since these routines are so simple
 | 
|---|
 | 349 |         ////////////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 350 | 
 | 
|---|
 | 351 |         void set_recursion_count( binary_semaphore(L) & this, size_t recursion ) with( this ) {
 | 
|---|
 | 352 |                 // default
 | 
|---|
 | 353 |         }
 | 
|---|
 | 354 | 
 | 
|---|
 | 355 |         size_t get_recursion_count( binary_semaphore(L) & this ) with( this ) {
 | 
|---|
 | 356 |                 return 0;
 | 
|---|
 | 357 |         }
 | 
|---|
 | 358 | 
 | 
|---|
 | 359 |         void set_recursion_count( counting_semaphore(L) & this, size_t recursion ) with( this ) {
 | 
|---|
 | 360 |                 // default
 | 
|---|
 | 361 |         }
 | 
|---|
 | 362 | 
 | 
|---|
 | 363 |         size_t get_recursion_count( counting_semaphore(L) & this ) with( this ) {
 | 
|---|
 | 364 |                 return 0;
 | 
|---|
 | 365 |         }
 | 
|---|
 | 366 | 
 | 
|---|
 | 367 |         ////////////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 368 |         ////////////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 369 | }
 | 
|---|
 | 370 | 
 | 
|---|
 | 371 | thread T1 {};
 | 
|---|
 | 372 | thread T2 {};
 | 
|---|
 | 373 | 
 | 
|---|
 | 374 | // counting_semaphore( ) s0, s1;
 | 
|---|
 | 375 | 
 | 
|---|
 | 376 | // void main( T1 & this ) {
 | 
|---|
 | 377 | //      printf("T1 start\n");
 | 
|---|
 | 378 | //      V(s1);
 | 
|---|
 | 379 | //      P(s0);
 | 
|---|
 | 380 | //      P(s0);
 | 
|---|
 | 381 | //      V(s1, 2);
 | 
|---|
 | 382 |         
 | 
|---|
 | 383 | //      printf("T1 done\n");
 | 
|---|
 | 384 | // }
 | 
|---|
 | 385 | 
 | 
|---|
 | 386 | // void main( T2 & this ) {
 | 
|---|
 | 387 | //      printf("T2 start\n");
 | 
|---|
 | 388 | //      V(s0);
 | 
|---|
 | 389 | //      P(s1);
 | 
|---|
 | 390 | //      P(s1, s0);
 | 
|---|
 | 391 | //      P(s1);
 | 
|---|
 | 392 | //      printf("T2 done\n");
 | 
|---|
 | 393 | // }
 | 
|---|
 | 394 | 
 | 
|---|
 | 395 | int main() {
 | 
|---|
 | 396 |         printf("start\n");
 | 
|---|
 | 397 |         // processor p[2];
 | 
|---|
 | 398 |         // {
 | 
|---|
 | 399 |         //      T1 t1;
 | 
|---|
 | 400 |         //      T2 t2;
 | 
|---|
 | 401 |         // }
 | 
|---|
 | 402 |         printf("done\n");
 | 
|---|
 | 403 | }
 | 
|---|