diff --git a/src/backend/scheduler.cc b/src/backend/scheduler.cc index 0857e7e..92e9012 100644 --- a/src/backend/scheduler.cc +++ b/src/backend/scheduler.cc @@ -28,7 +28,7 @@ #include "singleton.tcc" #include - +#include #include #include @@ -103,14 +103,13 @@ update_future_processes(unsigned int front, auto_ptr& next_ DynamicProcess& dp = dynamic_cast(**it_ps); if(dp.get_arrival_time() == front) { - front = dp.get_elapsed_time(); // == 0 - assert(front == 0); + assert(dp.get_elapsed_time() == 0); typedef std::vector DynamicThreads; DynamicThreads dts = dp.get_dynamic_threads(); for(DynamicThreads::const_iterator it_dts = dts.begin(); it_dts != dts.end(); it_dts++) { DynamicThread& dt = **it_dts; - if(dt.get_arrival_time() == front) + if(dt.get_arrival_time() == dp.get_elapsed_time()) { dt.set_state(Schedulable::state_ready); // in this way we will never have threads ready having remaining time == 0 @@ -195,7 +194,7 @@ advance_running_process_and_thread(unsigned int front, auto_ptr& next_snapsh { DynamicThread& dt = **it_dts; if(dt.get_state() == Schedulable::state_ready) + { queue.append(dt); + } } } } - // returns false if and only if the snapshot contains a candidate running thread, + // returns true if and only if the snapshot contains a candidate running thread, // the thread's state is state_running. static bool find_a_candidate(unsigned int front, auto_ptr& next_snapshot) @@ -500,21 +501,21 @@ find_a_candidate(unsigned int front, auto_ptr& next_snapsho { DynamicThread& dt = **it_dts; if(dt.get_state() == Schedulable::state_running) - return false; + return true; } } } // if no process has been found, select the first on the ready queue. ReadyQueue& queue = next_snapshot->get_sorted_queue(); if (queue.size() == 0) - return true; + return false; DynamicThread& candidate = dynamic_cast(queue.get_item_at(0)); candidate.set_state(Schedulable::state_running); // HACK HACK HACK // we do not remove the candidate from the ready queue. this information is useful // since we chose to set the last_aquisition and the last_release just after a // successful selection. see try_to_run(). - return false; + return true; } @@ -541,6 +542,16 @@ check_if_simulation_is_terminated(unsigned int front, auto_ptr& next_snapshot) +{ + ReadyQueue& queue = next_snapshot->get_sorted_queue(); + for(unsigned int i = 0; i < queue.size(); i++) + { + std::cout << queue.get_item_at(i).get_name(); + } +} + @@ -549,8 +560,7 @@ check_if_simulation_is_terminated(unsigned int front, auto_ptr& next_snapshot) { - printf("trying to run"); - bool success = true; + bool success = false; typedef std::vector Processes; Processes ps = next_snapshot->get_processes(); for(Processes::const_iterator it_ps = ps.begin(); it_ps != ps.end(); it_ps++) @@ -565,15 +575,17 @@ try_to_run(unsigned int front, auto_ptr& next_snapshot) DynamicThread& dt = **it_dts; if(dt.get_state() == Schedulable::state_running) { + // this is our candidate + success = true; + // let's see if it is runnable or if it blocks: typedef std::vector DynamicRequests; DynamicRequests drs = dt.get_dynamic_requests(); for(DynamicRequests::const_iterator it_drs = drs.begin(); it_drs != drs.end(); it_drs++) { - printf("checking all requests"); DynamicRequest& dr = **it_drs; + // if it's time to do it, raise a request if(dr.get_state() == Request::state_future && dr.get_instant() == dt.get_elapsed_time()) { - printf("found a new request"); typedef std::vector DynamicSubRequests; DynamicSubRequests dsrs = dr.get_dynamic_subrequests(); for(DynamicSubRequests::const_iterator it_dsrs = dsrs.begin(); it_dsrs != dsrs.end(); it_dsrs++) @@ -583,7 +595,6 @@ try_to_run(unsigned int front, auto_ptr& next_snapshot) Environment::SubRequestQueue& queue = next_snapshot->get_request_queue(dsr.get_resource_key()); /// Enqueue the subrequest at the back of the queue. queue.push_back(&dsr); - printf("pushing back a request"); /// TODO: right here, right now we should call the resource policy to /// update the queue. Updates the state of the subrequest depending @@ -601,39 +612,44 @@ try_to_run(unsigned int front, auto_ptr& next_snapshot) dsr.set_state(Request::state_allocated); } } - } + } // end of request raising // if it does exist at least one unallocable request, the thread may not run! if (dr.get_state() == Request::state_unallocable) { dt.set_state(Schedulable::state_blocked); success = false; } - } - } - // HACK HACK HACK - // this check is legal, since all pointers in the sorted queue should be valid. - // if the current thread is the first in the ready queue, we need to remove it - if (next_snapshot->get_sorted_queue().size() != 0 && - &next_snapshot->get_sorted_queue().get_item_at(0) == &dt) - { - // in case of success in allocating the cpu, we must update the last_aquisition - if (success) - dt.set_last_acquisition(front); - next_snapshot->get_sorted_queue().erase_first(); - } - // if the current thread was the one that was previously running - else - { - // we must update the last_release - if (!success) - dt.set_last_release(front); - //cpu_policy.sort_queue(); - } - } - } - } - return success; -} + } // end for loop over all running thread requests + + // HACK HACK HACK + // this check is legal, since all pointers in the sorted queue should be valid. + // if the current thread is the first in the ready queue, we need to remove it + if (next_snapshot->get_sorted_queue().size() != 0 && + &next_snapshot->get_sorted_queue().get_item_at(0) == &dt) + { + // in case of success in allocating the cpu, we must update the last_aquisition + if (success) + dt.set_last_acquisition(front); + next_snapshot->get_sorted_queue().erase_first(); + } // if the current thread was the one that was previously running + else + { + // we must update the last_release + if (!success) + dt.set_last_release(front); + else + return success; + //cpu_policy.sort_queue(); + } + + + + } // end things to do if thread was running + } // end for loop over all threads of a running process + } // end if process is running + } // end for loop over all processes + return false; +}// end main loop //............................................................................. //............................................................................. @@ -686,32 +702,25 @@ Scheduler::step_forward(ConcreteHistory& concrete_history, CPUPolicy& cpu_policy build_ready_queue(next_instant, next_snapshot); // and pass it to the policy itself - if (next_snapshot->get_sorted_queue().size() != 0) - cpu_policy.sort_queue(); +// if (next_snapshot->get_sorted_queue().size() != 0) +// cpu_policy.sort_queue(); - bool found = false; - bool none_ready_or_running = false; - bool simulation_terminated = false; + bool running = false; + bool idle = false; + bool terminated = false; + do { - // If no thread is in running state, select a new thread to be - // executed (so it changes its state from ready to running). - // However, in case it hasn't to run for a strictly positive - // amount of time, put it into terminated state. (??) Then try to - // select a new schedulable, by jumping (??) to the point about - // building the ready queue. - none_ready_or_running = find_a_candidate(next_instant, next_snapshot); - if (none_ready_or_running) - simulation_terminated = check_if_simulation_is_terminated(next_instant, next_snapshot); + if (find_a_candidate(next_instant, next_snapshot)) + running = try_to_run(next_instant, next_snapshot); else - // Check pending requests for the running thread. If in the - // current instant the thread does a new unfulfillable request, - // put it in blocked state and jump (??) to the point about building - // the ready queue - found = try_to_run(next_instant, next_snapshot); + if (check_if_simulation_is_terminated(next_instant, next_snapshot)) + terminated = true; + else + idle = true; } - while (!found && !none_ready_or_running && !simulation_terminated); + while (!running && !idle && !terminated); // append the new snapshot, releasing the auto_ptr! concrete_history.append_new_environment(next_snapshot.release()); @@ -720,7 +729,7 @@ Scheduler::step_forward(ConcreteHistory& concrete_history, CPUPolicy& cpu_policy _policy = NULL; _ready_queue = NULL; - return !simulation_terminated; // watch out for the ! + return !terminated; // watch out for the ! } catch(UserInterruptException& e) { diff --git a/src/testsuite/scheduling-wizards/wizard-complex-test b/src/testsuite/scheduling-wizards/wizard-complex-test new file mode 100644 index 0000000..c6ddfb0 --- /dev/null +++ b/src/testsuite/scheduling-wizards/wizard-complex-test @@ -0,0 +1,218 @@ +set cpu-policy 1 + +add resource +forchetta +false +1 +0 + +add resource +ashi +false +2 +0 + +add resource +dita +false +10 +0 + + + +add process (name, arrival time, base priority) +Toru +1 +3 +add thread 1 (name, required cput time, arrival time, base priority) +toru-kun +4 +0 +3 + +add process (name, arrival time, base priority) +Yuki +4 +2 +add thread 2 (name, required cput time, arrival time, base priority) +yun-yun +3 +0 +2 + + +add process (name, arrival time, base priority) +Kyo +4 +4 +add thread 3 (name, required cput time, arrival time, base priority) +kyon-kyon +1 +0 +4 + +add process (name, arrival time, base priority) +Shigure +6 +0 +add thread 4 (name, required cput time, arrival time, base priority) +gure +1 +0 +0 +add request 4 1 +0 +add subrequest 4 1 1 +0 +1 +add subrequest 4 1 1 +2 +3 +add subrequest 4 1 1 +2 +4 + + + +add process (name, arrival time, base priority) +Kagura +6 +5 +add thread 5 (name, required cput time, arrival time, base priority) +kagura +10 +0 +5 +add request 5 1 +0 +add subrequest 5 1 1 +0 +5 +add subrequest 5 1 1 +2 +3 +add request 5 1 +5 +add subrequest 5 1 2 +2 +3 +add subrequest 5 1 2 +2 +3 + + + +add process (name, arrival time, base priority) +Momiji +12 +0 +add thread 6 (name, required cput time, arrival time, base priority) +momiji-kun +1 +0 +0 + +add process (name, arrival time, base priority) +Hatori +14 +0 +add thread 7 (name, required cput time, arrival time, base priority) +tori +1 +0 +0 + +add process (name, arrival time, base priority) +Hatsuharu +15 +0 +add thread 8 (name, required cput time, arrival time, base priority) +haru +1 +0 +0 + +add process (name, arrival time, base priority) +Ayame +15 +0 +add thread 9 (name, required cput time, arrival time, base priority) +aya +6 +0 +0 +add request 9 1 +2 +add subrequest 9 1 1 +2 +3 +add subrequest 9 1 1 +2 +3 +add subrequest 9 1 1 +2 +3 +add subrequest 9 1 1 +2 +3 +add subrequest 9 1 1 +2 +3 +add subrequest 9 1 1 +2 +3 +add subrequest 9 1 1 +2 +3 +add subrequest 9 1 1 +2 +3 +add subrequest 9 1 1 +2 +3 +add subrequest 9 1 1 +2 +3 + + + + + +add process (name, arrival time, base priority) +Kisa +17 +0 +add thread 10 (name, required cput time, arrival time, base priority) +kisa +2 +0 +0 + +add request 10 1 +1 +add subrequest 10 1 1 +1 +3 +add subrequest 10 1 1 +2 +3 + + +add process (name, arrival time, base priority) +Ritsu +16 +0 +add thread 11 (name, required cput time, arrival time, base priority) +ri +2 +0 +0 +add request 11 1 +0 +add subrequest 11 1 1 +0 +1 + + + +run diff --git a/src/testsuite/scheduling-wizards/wizard-gap-fail b/src/testsuite/scheduling-wizards/wizard-gap-fail index fee7748..9379855 100644 --- a/src/testsuite/scheduling-wizards/wizard-gap-fail +++ b/src/testsuite/scheduling-wizards/wizard-gap-fail @@ -1,5 +1,4 @@ set cpu-policy 3 -add resource add resource forchetta diff --git a/src/text_simulation.cc b/src/text_simulation.cc index 8dd6f55..eb579ab 100644 --- a/src/text_simulation.cc +++ b/src/text_simulation.cc @@ -1476,19 +1476,19 @@ operator<<(ostream& os, Schedulable::state state) switch (state) { case Schedulable::state_running: - os << "RUNNING"; + os << " RUNNING @"; break; case Schedulable::state_ready: - os << "READY"; + os << " READY "; break; case Schedulable::state_blocked: - os << "BLOCKED"; + os << " BLOCKED "; break; case Schedulable::state_future: - os << "FUTURE"; + os << " FUTURE "; break; case Schedulable::state_terminated: - os << "TERMINATED"; + os << " TERMINATED "; break; default: os.setstate(ios_base::failbit); @@ -1506,16 +1506,16 @@ operator<<(ostream& os, Request::state state) os << "UNALLOCABLE"; break; case Request::state_allocated: - os << "ALLOCATED"; + os << " ALLOCATED"; break; case Request::state_future: - os << "FUTURE"; + os << " FUTURE"; break; case Request::state_exhausted: - os << "EXHAUSTED"; + os << " EXHAUSTED"; break; case Request::state_allocable: - os << "ALLOCABLE"; + os << " ALLOCABLE"; break; default: os.setstate(ios_base::failbit); @@ -1529,13 +1529,6 @@ TextSimulation::update(const History& changed_history) { ostringstream oss; - /// since the history stores snapshots starting from - /// and including instant -1, the first snapshot on - /// the queue, i.e. changed_history[0] is actually - /// the snapshot corresponding to instant -1. - /// therefore, the last snapshot on the history refers - /// to instant (history.get_size() - 2). - // this is a damn uint, so we must hack and hack int printed_instant; if (changed_history.get_size() > 1) @@ -1561,17 +1554,45 @@ TextSimulation::update(const History& changed_history) p_stdout("}\n"); - p_stdout(_("RESOURCES:\n")); + const Environment::Resources& resources = env.get_resources(); + const Environment::Processes& processes = env.get_processes(); typedef Environment::Resources::const_iterator ResourceIt; + + std::string tab = " "; + std::string::size_type max = tab.size(); + for (unsigned int pi = 0; pi < processes.size(); ++pi) + { + Process& p = *processes[pi]; + if (p.get_name().size() > max + tab.size() + tab.size()) + max = p.get_name().size() - tab.size() - tab.size(); + vector threads = p.get_threads(); + for (unsigned int ti = 0; ti < threads.size(); ++ti) + { + Thread& t = *threads[ti]; + if (t.get_name().size() > max + tab.size()) + max = t.get_name().size() - tab.size();; + } + + for (ResourceIt it = resources.begin(); it != resources.end(); ++it) + { + const Resource& r = *it->second; + if (r.get_name().size() > max) + max = r.get_name().size(); + } + } + + + + p_stdout(_("RESOURCES:\n")); for (ResourceIt it = resources.begin(); it != resources.end(); ++it) { const Resource& r = *it->second; Environment::resource_key_t key = it->first; - oss << " " << key << ") " << r.get_name() << _(", with "); + oss << " " << (key < 10 ? " " : "") << key << ". " << r.get_name() << _(", with "); oss << r.get_places() << _(" places\n"); @@ -1603,20 +1624,26 @@ TextSimulation::update(const History& changed_history) p_stdout(" }\n"); } - p_stdout(_("PROCESSES:\n")); + - const Environment::Processes& processes = env.get_processes(); + + p_stdout(_("\nPROCESSES:")); + Glib::ustring space_bar_1 = " "; + space_bar_1.resize(max, ' '); + p_stdout(space_bar_1); + p_stdout(_(" state arrival requiring elapsed priority resource_id\n")); for (unsigned int pi = 0; pi < processes.size(); ++pi) { Process& p = *processes[pi]; - - oss << " " << pi + 1 << ") " << p.get_name() << " "; - oss << "[" << p.get_state() << "] "; - oss << _("arriving at ") << p.get_arrival_time() << ", "; - oss << _("requiring ") << p.get_total_cpu_time() << ", "; - oss << _("elapsed ") << p.get_elapsed_time() << ", "; - oss << _("priority ") << p.get_current_priority() << endl; + Glib::ustring upname(p.get_name()); + upname.resize(max + tab.size() + tab.size(), ' '); + oss << " " << (pi < 9 ? " " : "") << pi + 1 << ". " << upname; + oss << " " << p.get_state(); + oss << _(" ") << (p.get_arrival_time() < 10 ? " " : "") << p.get_arrival_time(); + oss << _(" ") << (p.get_total_cpu_time() < 10 ? " " : "") << p.get_total_cpu_time(); + oss << _(" ") << (p.get_elapsed_time() < 10 ? " " : "") << p.get_elapsed_time(); + oss << _(" ") << (p.get_current_priority() < 10 ? " " : "") << p.get_current_priority() << endl; p_stdout(oss.str()); oss.str(string()); @@ -1627,12 +1654,14 @@ TextSimulation::update(const History& changed_history) { Thread& t = *threads[ti]; - oss << " " << ti + 1 << ") " << t.get_name() << " "; - oss << "[" << t.get_state() << "] "; - oss << _("arriving at ") << t.get_arrival_time() << ", "; - oss << _("requiring ") << t.get_total_cpu_time() << ", "; - oss << _("elapsed ") << t.get_elapsed_time() << ", "; - oss << _("priority ") << t.get_current_priority() << endl; + Glib::ustring upname(t.get_name()); + upname.resize(max + tab.size(), ' '); + oss << " " << tab << (ti < 9 ? " " : "") << ti + 1 << ". " << upname; + oss << " " << t.get_state(); + oss << _(" ") << (t.get_arrival_time() < 10 ? " " : "") << t.get_arrival_time(); + oss << _(" ") << (t.get_total_cpu_time() < 10 ? " " : "") << t.get_total_cpu_time(); + oss << _(" ") << (t.get_elapsed_time() < 10 ? " " : "") << t.get_elapsed_time(); + oss << _(" ") << (t.get_current_priority() < 10 ? " " : "") << t.get_current_priority() << endl; p_stdout(oss.str()); oss.str(string()); @@ -1648,14 +1677,20 @@ TextSimulation::update(const History& changed_history) for (unsigned int sri = 0; sri < subrequests.size(); ++sri) { SubRequest& sr = *subrequests[sri]; - oss << _(" --> request ") << ri + 1 << "." << sri + 1 << ") "; - oss << _("at ") << r.get_instant() << " "; ResourceIt point = resources.find(sr.get_resource_key()); - oss << _("for resource ") << (point->second)->get_name() << " "; - oss << _("with id ") << sr.get_resource_key() << " "; - oss << "[" << sr.get_state() << "] "; - oss << _("requiring ") << sr.get_length() << ", "; - oss << _("remaining ") << sr.get_remaining_time() << endl; + + oss << " " << tab << " "; + oss << (ri < 9 ? " " : "") << ri + 1 << "." << sri + 1 << (sri < 9 ? " " : ""); + + Glib::ustring upname((point->second)->get_name()); + upname.resize(max, ' '); + oss << _(" ") << upname; + oss << " " << sr.get_state(); + oss << _(" ") << (r.get_instant() < 10 ? " " : "") << r.get_instant(); + oss << _(" ") << (sr.get_length() < 10 ? " " : "") << sr.get_length(); + oss << _(" ") << (sr.get_length() - sr.get_remaining_time() < 10 ? " " : "") << sr.get_length() - sr.get_remaining_time(); + + oss << _(" ") << sr.get_resource_key() << " \n"; p_stdout(oss.str()); oss.str(string());