- Bits and tits of step_forward

git-svn-id: svn://svn.gna.org/svn/sgpemv2/trunk@785 3ecf2c5c-341e-0410-92b4-d18e462d057c
This commit is contained in:
tchernobog 2006-07-20 10:36:24 +00:00
parent bfbcc71e72
commit 40180557c7
1 changed files with 111 additions and 59 deletions

View File

@ -39,6 +39,12 @@ using namespace sgpem;
template class SG_DLLEXPORT Singleton<Scheduler>;
typedef std::vector<DynamicProcess*> Processes;
typedef std::vector<DynamicRequest*> Requests;
typedef std::vector<DynamicSubRequest*> SubRequests;
typedef std::vector<DynamicThread*> 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<ConcreteEnvironment> new_snapshot(new ConcreteEnvironment(concrete_history.get_last_environment()));
typedef std::vector<DynamicProcess*> Processes;
typedef std::vector<DynamicRequest*> Requests;
typedef std::vector<DynamicSubRequest*> SubRequests;
typedef std::vector<DynamicThread*> 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!