From 40180557c7d7bf42a1027e6253cad72bcddd90e8 Mon Sep 17 00:00:00 2001 From: tchernobog Date: Thu, 20 Jul 2006 10:36:24 +0000 Subject: [PATCH] - Bits and tits of step_forward git-svn-id: svn://svn.gna.org/svn/sgpemv2/trunk@785 3ecf2c5c-341e-0410-92b4-d18e462d057c --- src/backend/scheduler.cc | 170 +++++++++++++++++++++++++-------------- 1 file changed, 111 insertions(+), 59 deletions(-) diff --git a/src/backend/scheduler.cc b/src/backend/scheduler.cc index 9d7c776..005b441 100644 --- a/src/backend/scheduler.cc +++ b/src/backend/scheduler.cc @@ -39,6 +39,12 @@ using namespace sgpem; template class SG_DLLEXPORT Singleton; +typedef std::vector Processes; +typedef std::vector Requests; +typedef std::vector SubRequests; +typedef std::vector Threads; + + // ------------------ Static helper functions -------------- @@ -73,6 +79,50 @@ static void prepare_ready_queue(ConcreteEnvironment& snapshot, } +// For the current thread, see if there are requests that are exhausted +static void +update_requests_for_old_running_thread(DynamicThread& running_thread) +{ + Requests& reqs = running_thread.get_dynamic_requests(); + bool running_terminated = running_thread.get_state() == Schedulable::state_terminated; + + for(Requests::iterator r_it = reqs.begin(); r_it != reqs.end(); r_it++) + { + DynamicRequest& rq = **r_it; + + // If the running thread terminated uncoditionally put them in exhausted state + if(running_terminated) + { + SubRequests& subreqs = rq.get_dynamic_subrequests(); + for(SubRequests::iterator s_it = subreqs.begin(); s_it != subreqs.end(); s_it++) + (*s_it)->set_state(Request::state_exhausted); + continue; // go to next request + } + + if(rq.get_state() == Request::state_allocated) + { + /* decrease remaining time for each allocated subrequest */ + SubRequests& subreqs = rq.get_dynamic_subrequests(); + for(SubRequests::iterator s_it = subreqs.begin(); s_it != subreqs.end(); s_it++) + { + DynamicSubRequest& subr = **s_it; + if(subr.get_state() == Request::state_allocated) + subr.decrease_remaining_time(); + if(subr.get_remaining_time() == 0) + { + subr.set_state(Request::state_exhausted); + + // ___BIG___ FIXME FIXME FIXME + + + // FIXME : if exhausted, it should be taken away from the queue of the + // requested resource + + } + } + } + } //~ for(over requests) +} // --------------------------------------------------------- @@ -125,17 +175,13 @@ Scheduler::step_forward(History& history, Policy& cpu_policy) throw(UserInterrup // FIXME: handle me! I'm not just a pretty boolean, I want to be *USED*! *EXPLOITED*! // *RAPED*! *MAKE ME BLEED*! bool simulation_ended = true; // Assume we've finished. Then prove me wrong. + unsigned int current_instant = history.get_size(); /* They should be equivalent */ ConcreteHistory& concrete_history = (ConcreteHistory&) history; // Use an auto_ptr since we've some exceptions in the coming... auto_ptr new_snapshot(new ConcreteEnvironment(concrete_history.get_last_environment())); - typedef std::vector Processes; - typedef std::vector Requests; - typedef std::vector SubRequests; - typedef std::vector Threads; - Threads all_threads; DynamicThread* running_thread = NULL; @@ -182,56 +228,7 @@ Scheduler::step_forward(History& history, Policy& cpu_policy) throw(UserInterrup // 4a. Look for exhausted requests for the running thread if(running_thread != NULL) - { - Requests& reqs = running_thread->get_dynamic_requests(); - bool running_terminated = running_thread->get_state() == Schedulable::state_terminated; - - for(Requests::iterator r_it = reqs.begin(); r_it != reqs.end(); r_it++) - { - DynamicRequest& rq = **r_it; - - // If the running thread terminated uncoditionally put them in exhausted state - if(running_terminated) - { - SubRequests& subreqs = rq.get_dynamic_subrequests(); - for(SubRequests::iterator s_it = subreqs.begin(); s_it != subreqs.end(); s_it++) - (*s_it)->set_state(Request::state_exhausted); - continue; // go to next request - } - - if(rq.get_state() == Request::state_allocated) - { - /* decrease remaining time for each allocated subrequest */ - SubRequests& subreqs = rq.get_dynamic_subrequests(); - for(SubRequests::iterator s_it = subreqs.begin(); s_it != subreqs.end(); s_it++) - { - DynamicSubRequest& subr = **s_it; - if(subr.get_state() == Request::state_allocated) - subr.decrease_remaining_time(); - if(subr.get_remaining_time() == 0) - { - subr.set_state(Request::state_exhausted); - - // FIXME : if exhausted, it should be taken away from the queue of the - // requested resource - } - } - } - } //~ for(over requests) - - // FIXME we lack a way to tell and/or remember for how - // much a subrequest has been being fulfilled - // THIS MEANS this part is NOT complete - // We should check if a request has been fulfilled - - // FIXME If a request was being fulfilled to the running thread, - // we should decrease the request remaining time here. - - // This is why we kept a ref to the old running thread, - // even if it was terminated - - - } //~ if running_thread != NULL + update_requests_for_old_running_thread(*running_thread); // ---------- FIXME ---------------- @@ -250,7 +247,8 @@ Scheduler::step_forward(History& history, Policy& cpu_policy) throw(UserInterrup */ - prepare_ready_queue(*new_snapshot, all_threads); + bool preemptible_policy; + unsigned int time_slice; try { // Temporarily set the _ready_queue param and the _policy one for @@ -260,8 +258,62 @@ Scheduler::step_forward(History& history, Policy& cpu_policy) throw(UserInterrup // ?. Use the policy to sort the queue - // FIXME: how does it get the queue? - cpu_policy.sort_queue(); + preemptible_policy = cpu_policy.is_pre_emptive(); + time_slice = cpu_policy.get_time_slice(); + + // ?. See if old running_thread has to be put to ready state + // This happens when the policy makes use of preemptability by + // priority, or when a time slice ended + if(running_thread != NULL && running_thread->get_state() == Schedulable::state_running && + (preemptible_policy || + time_slice == current_instant - running_thread->get_last_acquisition()) ) + { + running_thread->set_state(Schedulable::state_ready); + running_thread->set_last_release(current_instant); + } + + + // ?. Ask the policy to sort the queue. We do this multiple time if we must select + // a new thread and it can't run for some reason (goes blocked, or terminates). + bool selected_cant_run; + do + { + selected_cant_run = false; + prepare_ready_queue(*new_snapshot, all_threads); + + if(_ready_queue->size() == 0) + break; // No sense in trying to schedule something that isn't there + + cpu_policy.sort_queue(); + + DynamicThread& candidate = (DynamicThread&) _ready_queue->get_item_at(0); + + // We could have threads with 0 duration. Silly, but possible. + if(candidate.get_total_cpu_time() - candidate.get_elapsed_time() == 0) + { + candidate.set_last_acquisition(current_instant); + candidate.set_last_release(current_instant); + candidate.set_state(Schedulable::state_terminated); + // FIXME : check requests for thread at instant 0? + selected_cant_run = true; + continue; + } + + // FIXME : check if the first thread of the queue blocks + + } + while(selected_cant_run); + + // ?. Finally select the new thread (if appropriate); now we're sure it can run + if(_ready_queue->size() > 0 && (running_thread == NULL || running_thread->get_state() != Schedulable::state_running)) + { + // Fix fields of running thread + DynamicThread& new_running = (DynamicThread&) _ready_queue->get_item_at(0); + new_running.set_state(Schedulable::state_running); + new_running.set_last_acquisition(current_instant); + } + + } catch(UserInterruptException& e) { @@ -275,7 +327,7 @@ Scheduler::step_forward(History& history, Policy& cpu_policy) throw(UserInterrup // - the user that the policy sucks // - SimulationController that everything stopped throw; - } + } // append the new snapshot... // ...and remember to release the auto_ptr!