diff options
-rw-r--r-- | 073wait.cc | 144 |
1 files changed, 72 insertions, 72 deletions
diff --git a/073wait.cc b/073wait.cc index 0d7c3e4e..6f1ba14c 100644 --- a/073wait.cc +++ b/073wait.cc @@ -275,166 +275,166 @@ def main [ ] +mem: storing 11 in location 21 -//: also allow waiting on a routine to block -//: (just for tests; use wait_for_routine below wherever possible) +//: allow waiting on a routine to complete -:(scenario wait_for_routine_to_block) +:(scenario wait_for_routine) def f1 [ + # add a few routines to run 1:number/routine <- start-running f2 - wait-for-routine-to-block 1:number/routine - # now wait for f2 to run and modify location 10 before using its value - 11:number <- copy 10:number + 2:number/routine <- start-running f3 + wait-for-routine 1:number/routine + # now wait for f2 to *complete* and modify location 13 before using its value + 20:number <- copy 13:number ] def f2 [ - 10:number <- copy 34 + 10:number <- copy 0 # just padding + switch # simulate a block; routine f1 shouldn't restart at this point + 13:number <- copy 34 +] +def f3 [ + # padding routine just to help simulate the block in f2 using 'switch' + 11:number <- copy 0 + 12:number <- copy 0 ] +schedule: f1 -+run: waiting for routine 2 to block ++run: waiting for routine 2 +schedule: f2 -+schedule: waking up blocked routine 1 ++schedule: f3 ++schedule: f2 ++schedule: waking up routine 1 +schedule: f1 -# if we got the synchronization wrong we'd be storing 0 in location 11 -+mem: storing 34 in location 11 +# if we got the synchronization wrong we'd be storing 0 in location 20 ++mem: storing 34 in location 20 :(before "End routine Fields") // only if state == WAITING -int waiting_on_routine_to_block; +int waiting_on_routine; :(before "End routine Constructor") -waiting_on_routine_to_block = 0; +waiting_on_routine = 0; :(before "End Primitive Recipe Declarations") -WAIT_FOR_ROUTINE_TO_BLOCK, +WAIT_FOR_ROUTINE, :(before "End Primitive Recipe Numbers") -put(Recipe_ordinal, "wait-for-routine-to-block", WAIT_FOR_ROUTINE_TO_BLOCK); +put(Recipe_ordinal, "wait-for-routine", WAIT_FOR_ROUTINE); :(before "End Primitive Recipe Checks") -case WAIT_FOR_ROUTINE_TO_BLOCK: { +case WAIT_FOR_ROUTINE: { if (SIZE(inst.ingredients) != 1) { - raise << maybe(get(Recipe, r).name) << "'wait-for-routine-to-block' requires exactly one ingredient, but got '" << inst.original_string << "'\n" << end(); + raise << maybe(get(Recipe, r).name) << "'wait-for-routine' requires exactly one ingredient, but got '" << inst.original_string << "'\n" << end(); break; } if (!is_mu_number(inst.ingredients.at(0))) { - raise << maybe(get(Recipe, r).name) << "first ingredient of 'wait-for-routine-to-block' should be a routine id generated by 'start-running', but got '" << inst.ingredients.at(0).original_string << "'\n" << end(); + raise << maybe(get(Recipe, r).name) << "first ingredient of 'wait-for-routine' should be a routine id generated by 'start-running', but got '" << inst.ingredients.at(0).original_string << "'\n" << end(); break; } break; } :(before "End Primitive Recipe Implementations") -case WAIT_FOR_ROUTINE_TO_BLOCK: { +case WAIT_FOR_ROUTINE: { if (ingredients.at(0).at(0) == Current_routine->id) { raise << maybe(current_recipe_name()) << "routine can't wait for itself! '" << to_original_string(current_instruction()) << "'\n" << end(); break; } Current_routine->state = WAITING; - Current_routine->waiting_on_routine_to_block = ingredients.at(0).at(0); - trace(9998, "run") << "waiting for routine " << ingredients.at(0).at(0) << " to block" << end(); -//? cerr << Current_routine->id << ": waiting for routine " << ingredients.at(0).at(0) << " to block\n"; + Current_routine->waiting_on_routine = ingredients.at(0).at(0); + trace(9998, "run") << "waiting for routine " << ingredients.at(0).at(0) << end(); +//? cerr << Current_routine->id << ": waiting for routine " << ingredients.at(0).at(0) << '\n'; break; } :(before "End Scheduler State Transitions") -// Wake up any routines waiting for other routines to stop running. +// Wake up any routines waiting for other routines to complete. +// Important: this must come after the scheduler loop above giving routines +// waiting for locations to change a chance to wake up. for (int i = 0; i < SIZE(Routines); ++i) { if (Routines.at(i)->state != WAITING) continue; routine* waiter = Routines.at(i); - if (!waiter->waiting_on_routine_to_block) continue; - int id = waiter->waiting_on_routine_to_block; + if (!waiter->waiting_on_routine) continue; + int id = waiter->waiting_on_routine; assert(id != waiter->id); // routine can't wait on itself for (int j = 0; j < SIZE(Routines); ++j) { const routine* waitee = Routines.at(j); - if (waitee->id == id && waitee->state != RUNNING) { - // routine is WAITING or COMPLETED or DISCONTINUED - trace(9999, "schedule") << "waking up blocked routine " << waiter->id << end(); -//? cerr << id << " is now unblocked (" << waitee->state << "); waking up waiting routine " << waiter->id << '\n'; + if (waitee->id == id && waitee->state != RUNNING && waitee->state != WAITING) { + // routine is COMPLETED or DISCONTINUED + trace(9999, "schedule") << "waking up routine " << waiter->id << end(); +//? cerr << id << " is now done (" << waitee->state << "); waking up waiting routine " << waiter->id << '\n'; waiter->state = RUNNING; - waiter->waiting_on_routine_to_block = 0; + waiter->waiting_on_routine = 0; } } } -//: allow waiting on a routine to complete +//: also allow waiting on a routine to block +//: (just for tests; use wait_for_routine below wherever possible) -:(scenario wait_for_routine) +:(scenario wait_for_routine_to_block) def f1 [ - # add a few routines to run 1:number/routine <- start-running f2 - 2:number/routine <- start-running f3 - wait-for-routine 1:number/routine - # now wait for f2 to *complete* and modify location 13 before using its value - 20:number <- copy 13:number + wait-for-routine-to-block 1:number/routine + # now wait for f2 to run and modify location 10 before using its value + 11:number <- copy 10:number ] def f2 [ - 10:number <- copy 0 # just padding - switch # simulate a block; routine f1 shouldn't restart at this point - 13:number <- copy 34 -] -def f3 [ - # padding routine just to help simulate the block in f2 using 'switch' - 11:number <- copy 0 - 12:number <- copy 0 + 10:number <- copy 34 ] +schedule: f1 -+run: waiting for routine 2 -+schedule: f2 -+schedule: f3 ++run: waiting for routine 2 to block +schedule: f2 -+schedule: waking up routine 1 ++schedule: waking up blocked routine 1 +schedule: f1 -# if we got the synchronization wrong we'd be storing 0 in location 20 -+mem: storing 34 in location 20 +# if we got the synchronization wrong we'd be storing 0 in location 11 ++mem: storing 34 in location 11 :(before "End routine Fields") // only if state == WAITING -int waiting_on_routine; +int waiting_on_routine_to_block; :(before "End routine Constructor") -waiting_on_routine = 0; +waiting_on_routine_to_block = 0; :(before "End Primitive Recipe Declarations") -WAIT_FOR_ROUTINE, +WAIT_FOR_ROUTINE_TO_BLOCK, :(before "End Primitive Recipe Numbers") -put(Recipe_ordinal, "wait-for-routine", WAIT_FOR_ROUTINE); +put(Recipe_ordinal, "wait-for-routine-to-block", WAIT_FOR_ROUTINE_TO_BLOCK); :(before "End Primitive Recipe Checks") -case WAIT_FOR_ROUTINE: { +case WAIT_FOR_ROUTINE_TO_BLOCK: { if (SIZE(inst.ingredients) != 1) { - raise << maybe(get(Recipe, r).name) << "'wait-for-routine' requires exactly one ingredient, but got '" << inst.original_string << "'\n" << end(); + raise << maybe(get(Recipe, r).name) << "'wait-for-routine-to-block' requires exactly one ingredient, but got '" << inst.original_string << "'\n" << end(); break; } if (!is_mu_number(inst.ingredients.at(0))) { - raise << maybe(get(Recipe, r).name) << "first ingredient of 'wait-for-routine' should be a routine id generated by 'start-running', but got '" << inst.ingredients.at(0).original_string << "'\n" << end(); + raise << maybe(get(Recipe, r).name) << "first ingredient of 'wait-for-routine-to-block' should be a routine id generated by 'start-running', but got '" << inst.ingredients.at(0).original_string << "'\n" << end(); break; } break; } :(before "End Primitive Recipe Implementations") -case WAIT_FOR_ROUTINE: { +case WAIT_FOR_ROUTINE_TO_BLOCK: { if (ingredients.at(0).at(0) == Current_routine->id) { raise << maybe(current_recipe_name()) << "routine can't wait for itself! '" << to_original_string(current_instruction()) << "'\n" << end(); break; } Current_routine->state = WAITING; - Current_routine->waiting_on_routine = ingredients.at(0).at(0); - trace(9998, "run") << "waiting for routine " << ingredients.at(0).at(0) << end(); -//? cerr << Current_routine->id << ": waiting for routine " << ingredients.at(0).at(0) << '\n'; + Current_routine->waiting_on_routine_to_block = ingredients.at(0).at(0); + trace(9998, "run") << "waiting for routine " << ingredients.at(0).at(0) << " to block" << end(); +//? cerr << Current_routine->id << ": waiting for routine " << ingredients.at(0).at(0) << " to block\n"; break; } :(before "End Scheduler State Transitions") -// Wake up any routines waiting for other routines to complete. -// Important: this must come after the scheduler loop above giving routines -// waiting for locations to change a chance to wake up. +// Wake up any routines waiting for other routines to stop running. for (int i = 0; i < SIZE(Routines); ++i) { if (Routines.at(i)->state != WAITING) continue; routine* waiter = Routines.at(i); - if (!waiter->waiting_on_routine) continue; - int id = waiter->waiting_on_routine; + if (!waiter->waiting_on_routine_to_block) continue; + int id = waiter->waiting_on_routine_to_block; assert(id != waiter->id); // routine can't wait on itself for (int j = 0; j < SIZE(Routines); ++j) { const routine* waitee = Routines.at(j); - if (waitee->id == id && waitee->state != RUNNING && waitee->state != WAITING) { - // routine is COMPLETED or DISCONTINUED - trace(9999, "schedule") << "waking up routine " << waiter->id << end(); -//? cerr << id << " is now done (" << waitee->state << "); waking up waiting routine " << waiter->id << '\n'; + if (waitee->id == id && waitee->state != RUNNING) { + // routine is WAITING or COMPLETED or DISCONTINUED + trace(9999, "schedule") << "waking up blocked routine " << waiter->id << end(); +//? cerr << id << " is now unblocked (" << waitee->state << "); waking up waiting routine " << waiter->id << '\n'; waiter->state = RUNNING; - waiter->waiting_on_routine = 0; + waiter->waiting_on_routine_to_block = 0; } } } |