- 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>;
|
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 --------------
|
// ------------------ 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*!
|
// FIXME: handle me! I'm not just a pretty boolean, I want to be *USED*! *EXPLOITED*!
|
||||||
// *RAPED*! *MAKE ME BLEED*!
|
// *RAPED*! *MAKE ME BLEED*!
|
||||||
bool simulation_ended = true; // Assume we've finished. Then prove me wrong.
|
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;
|
ConcreteHistory& concrete_history = (ConcreteHistory&) history;
|
||||||
|
|
||||||
// Use an auto_ptr since we've some exceptions in the coming...
|
// Use an auto_ptr since we've some exceptions in the coming...
|
||||||
auto_ptr<ConcreteEnvironment> new_snapshot(new ConcreteEnvironment(concrete_history.get_last_environment()));
|
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;
|
Threads all_threads;
|
||||||
DynamicThread* running_thread = NULL;
|
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
|
// 4a. Look for exhausted requests for the running thread
|
||||||
if(running_thread != NULL)
|
if(running_thread != NULL)
|
||||||
{
|
update_requests_for_old_running_thread(*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);
|
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
|
|
||||||
// ---------- FIXME ----------------
|
// ---------- 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
|
try
|
||||||
{
|
{
|
||||||
// Temporarily set the _ready_queue param and the _policy one for
|
// 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
|
// ?. Use the policy to sort the queue
|
||||||
|
|
||||||
// FIXME: how does it get the queue?
|
preemptible_policy = cpu_policy.is_pre_emptive();
|
||||||
cpu_policy.sort_queue();
|
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)
|
catch(UserInterruptException& e)
|
||||||
{
|
{
|
||||||
|
@ -275,7 +327,7 @@ Scheduler::step_forward(History& history, Policy& cpu_policy) throw(UserInterrup
|
||||||
// - the user that the policy sucks
|
// - the user that the policy sucks
|
||||||
// - SimulationController that everything stopped
|
// - SimulationController that everything stopped
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
// append the new snapshot...
|
// append the new snapshot...
|
||||||
// ...and remember to release the auto_ptr!
|
// ...and remember to release the auto_ptr!
|
||||||
|
|
Loading…
Reference in New Issue