- 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:
parent
bfbcc71e72
commit
40180557c7
|
@ -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!
|
||||
|
|
Loading…
Reference in New Issue