- Write interface for HistoryObserver - Remove obsolete interfaces git-svn-id: svn://svn.gna.org/svn/sgpemv2/trunk@690 3ecf2c5c-341e-0410-92b4-d18e462d057c
213 lines
7 KiB
C++
213 lines
7 KiB
C++
// src/backend/scheduler.cc - Copyright 2005, 2006, University
|
|
// of Padova, dept. of Pure and Applied
|
|
// Mathematics
|
|
//
|
|
// This file is part of SGPEMv2.
|
|
//
|
|
// This is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation; either version 2 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// SGPEMv2 is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with SGPEMv2; if not, write to the Free Software
|
|
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
#include "policy.hh"
|
|
#include "scheduler.hh"
|
|
#include "policy_manager.hh"
|
|
#include "policies_gatekeeper.hh"
|
|
#include "user_interrupt_exception.hh"
|
|
|
|
// Do not include full template definition in the header file
|
|
#include "singleton.tcc"
|
|
|
|
#include <iostream>
|
|
using namespace std;
|
|
using namespace sgpem;
|
|
|
|
// Explicit template instantiation to allow to export symbols from the DSO.
|
|
template class SG_DLLEXPORT Singleton<Scheduler>;
|
|
|
|
//private constructor. The parameter is discarded
|
|
Scheduler::Scheduler()
|
|
: _policy_manager(PolicyManager::get_registered_manager())
|
|
{
|
|
_policy_manager.init();
|
|
}
|
|
|
|
ReadyQueue*
|
|
Scheduler::get_ready_queue()
|
|
{
|
|
// FIXME return the correct queue accordingly to the value returned by Policy::wants()
|
|
return &_ready_queue;
|
|
}
|
|
|
|
|
|
/** \note E' fondamentale che questo metodo memorizzi localmente qualora la politica
|
|
attuale sia a prerilascio o meno, e la durata del quanto di tempo, in quanto la politica
|
|
e' libera di variare questi parametri a piacere durante l'esecuzione della simulazione
|
|
*/
|
|
void
|
|
Scheduler::reset_status()
|
|
{
|
|
_ready_queue.clear();
|
|
History::get_instance().truncate_at(0);
|
|
// restore the policy
|
|
}
|
|
|
|
/* void
|
|
Scheduler::set_policy(Policy* p)
|
|
{
|
|
_policy_manager.set_policy(p);
|
|
}*/
|
|
|
|
|
|
Policy&
|
|
Scheduler::get_policy()
|
|
{
|
|
//return _policy_manager.get_policy();
|
|
return *PoliciesGatekeeper::get_instance().get_current_policy(&History::get_instance());
|
|
}
|
|
|
|
|
|
void
|
|
Scheduler::step_forward() throw(UserInterruptException)
|
|
{
|
|
try
|
|
{
|
|
Policy& policy = get_policy();
|
|
|
|
History& h = History::get_instance();
|
|
//******************
|
|
//check for arrivals and prepare the queue
|
|
//******************
|
|
smart_ptr<ReadyQueue> initial = h.get_simulation_status_at(h.get_current_time());
|
|
if (!initial)
|
|
{
|
|
cout << _("\nNo initial state inserted!!\n");
|
|
return;
|
|
}
|
|
_ready_queue.clear();
|
|
|
|
|
|
//adds running schedulable
|
|
smart_ptr<DynamicSchedulable> running_ptr = h.get_scheduled_at(h.get_current_time());
|
|
if (running_ptr)
|
|
_ready_queue.add_at_top(*running_ptr);
|
|
|
|
//adds the READY ones
|
|
for(uint rea = 0; rea < initial->size(); rea++)
|
|
if (initial->get_item_at(rea)->get_state() == DynamicSchedulable::state_ready)
|
|
_ready_queue.add_at_bottom(*initial->get_item_at(rea));
|
|
|
|
//adds each new ready schedulable and sorts the queue
|
|
for(uint i = 0; i < initial->size(); i++)
|
|
if (initial->get_item_at(i)->get_state() == DynamicSchedulable::state_future
|
|
&& (int)initial->get_item_at(i)->get_schedulable()->get_arrival_time() == h.get_current_time())
|
|
{
|
|
//cout << "\nnuovo running: " << initial->get_item_at(i)->get_schedulable()->get_name();
|
|
|
|
//restore the old running schedulable
|
|
if (policy.is_pre_emptive() == false && running_ptr)
|
|
_ready_queue.remove(0);
|
|
|
|
//adds the NEW one
|
|
_ready_queue.add_at_bottom(*initial->get_item_at(i));
|
|
_ready_queue.get_item_at(_ready_queue.size() - 1)->set_state(DynamicSchedulable::state_ready);
|
|
initial->get_item_at(i)->set_state(DynamicSchedulable::state_ready);
|
|
|
|
// Sort the queue
|
|
policy.sort_queue();
|
|
|
|
//restore the old running schedulable
|
|
if (policy.is_pre_emptive() == false && running_ptr)
|
|
_ready_queue.add_at_top(*running_ptr);
|
|
}
|
|
|
|
|
|
//****************
|
|
// Check for termination
|
|
//****************
|
|
|
|
if (running_ptr && running_ptr->get_cpu_time_left() == 0)
|
|
{
|
|
//there is a running schedulable and it's terminated. Append at the bottom with the state TERMINATED
|
|
for(uint i = 0; i < _ready_queue.size(); i++)
|
|
if (*_ready_queue.get_item_at(i) == *running_ptr)
|
|
{
|
|
_ready_queue.add_at_bottom(*_ready_queue.get_item_at(i));
|
|
_ready_queue.remove(i);
|
|
_ready_queue.get_item_at(_ready_queue.size() - 1)->set_state(DynamicSchedulable::state_terminated);
|
|
break;
|
|
}
|
|
//cout << "\nTERMINATO!!";
|
|
running_ptr = NULL;
|
|
|
|
//IF _ready_queue.size() == 0 sort_queue(...) is called but has no effect!!
|
|
policy.sort_queue();
|
|
}
|
|
|
|
//*****************
|
|
// Check for time slice
|
|
//*****************
|
|
if (policy.get_time_slice() != numeric_limits<int>::max()) //time-slice
|
|
policy.sort_queue();
|
|
|
|
//******************
|
|
// Create the final list of schedulable
|
|
//******************
|
|
|
|
|
|
if (_ready_queue.size() != 0 && (_ready_queue.get_item_at(0)->get_state() == DynamicSchedulable::state_ready
|
|
|| _ready_queue.get_item_at(0)->get_state() == DynamicSchedulable::state_running))
|
|
{
|
|
//the first ready element IS the running one (if != *running_ptr then there is a CONTEXT SWICH)
|
|
_ready_queue.get_item_at(0)->set_state(DynamicSchedulable::state_running);
|
|
_ready_queue.get_item_at(0)->give_cpu_time(1);
|
|
}
|
|
|
|
//all the others are ready
|
|
for (uint i = 1; i < _ready_queue.size(); i++)
|
|
if (_ready_queue.get_item_at(i)->get_state() == DynamicSchedulable::state_running)
|
|
_ready_queue.get_item_at(i)->set_state(DynamicSchedulable::state_ready);
|
|
|
|
//append blocked, future, and terminated schedulables
|
|
for (uint i = 0; i < initial->size(); i++)
|
|
if(initial->get_item_at(i)->get_state() == DynamicSchedulable::state_blocked
|
|
|| initial->get_item_at(i)->get_state() == DynamicSchedulable::state_future
|
|
|| initial->get_item_at(i)->get_state() == DynamicSchedulable::state_terminated)
|
|
_ready_queue.add_at_bottom(*initial->get_item_at(i));
|
|
|
|
cout << "\n";
|
|
/* for (uint i = 0; i < _ready_queue.size(); i++)
|
|
cout << " " << _ready_queue.get_item_at(i)->get_schedulable()->get_name()
|
|
<<"_" << _ready_queue.get_item_at(i)->get_state();
|
|
*/
|
|
h.enqueue_slice(_ready_queue);
|
|
}
|
|
catch( UserInterruptException e )
|
|
{
|
|
_policy_manager.init();
|
|
|
|
throw;
|
|
|
|
//TODO Do we need to perform some cleanup operation here?
|
|
// Do we need to update something?
|
|
|
|
// https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1165761&group_id=5470
|
|
// maybe it's that??? oh, damn.
|
|
// or maybe not. see http://www.python.org/doc/2.4.2/api/initialization.html
|
|
|
|
// Tell:
|
|
// - the user that the policy sucks
|
|
// - SimulationController that everything stopped
|
|
}
|
|
}
|
|
|