// src/testsuite/test-history.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 3 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, see http://www.gnu.org/licenses/. /* This executable tests for workingness of the SimulationWidget class, * and nothing else. */ #include "gettext.h" #include // Needed for a bug in gtkmm 2.22 #include "cairo_elements.hh" #include "cairo_widget.hh" #include "holt_container_window.hh" #include "holt_widget.hh" #include "simulation_widget.hh" #include "sgpemv2/cpu_policies_gatekeeper.hh" #include "sgpemv2/cpu_policy.hh" #include "sgpemv2/cpu_policy_manager.hh" #include "sgpemv2/resource_policies_gatekeeper.hh" #include "sgpemv2/resource_policy.hh" #include "sgpemv2/resource_policy_manager.hh" #include "sgpemv2/history_observer.hh" #include "sgpemv2/scheduler.hh" #include "sgpemv2/simulation.hh" #include "sgpemv2/simulation_observer.hh" #include "sgpemv2/process.hh" #include "sgpemv2/resource.hh" #include "sgpemv2/thread.hh" #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace sgpem; using namespace std; using Glib::ustring; // ------------------------------------------------------ // // PRRPolicy class // // ------------------------------------------------------ /** An hard-coded Priority Round Robin policy * it adds a new constructor taking the quantum size (time slice)*/ class PRRPolicy : public CPUPolicy { public: PRRPolicy() { _instance = this; } PRRPolicy(int quantum) : _quantum(quantum) { _instance = this; } static PRRPolicy& get_instance() { if (!_instance) _instance = new PRRPolicy(3); // quantum size return *_instance; } virtual ~PRRPolicy() {} virtual void configure() throw(UserInterruptException, MalformedPolicyException) {} virtual void sort_queue() const throw(UserInterruptException) { // here a lot of fun, exactly O(n^2) fun! // ReadyQueue sl = History.get_instance().get_simulation_status_at(get_current_time()); ReadyQueue* sl = Scheduler::get_instance().get_ready_queue(); if(sl && sl->size()>=2) { for (size_t i = 0; i < sl->size(); i++) { for (size_t j = 0; j < sl->size() - 1; j++) { if ( (sl->get_item_at(j).get_current_priority() < sl->get_item_at(j + 1).get_current_priority()) || ((sl->get_item_at(j).get_current_priority() == sl->get_item_at(j + 1).get_current_priority()) && (sl->get_item_at(j).get_last_acquisition() > sl->get_item_at(j + 1).get_last_acquisition())) ) { sl->swap(j, j + 1); } } } } } /* int get_id() const { return 42; } */ virtual Glib::ustring get_description() const { return "42"; } virtual Glib::ustring get_name() const { return "FourtyTwo"; } virtual bool is_pre_emptive() const throw(UserInterruptException, MalformedPolicyException) { return true; } virtual int get_time_slice() const throw(UserInterruptException, MalformedPolicyException) { return _quantum; } PolicyParameters& get_parameters() { return _parameters; } virtual void activate() throw(UserInterruptException, MalformedPolicyException) { } virtual void deactivate() { } protected: PolicyParameters _parameters; // int _id; int _quantum; private: static PRRPolicy* _instance; }; PRRPolicy* PRRPolicy::_instance=0; // ------------------------------------------------------ // // DummyPolicyManager class // // ------------------------------------------------------ class DummyPolicyManager : public CPUPolicyManager { public: /** \brief CPUPolicyManager constructor * * Saves ``this'' pointer into the _registered attribute, so it can access * it when requested. This is done so that concrete subclasses can be defined * even if they are found in external dynamic modules not known at compile time. * * For the moment, just an instance of CPUPolicyManager can be saved. This will * be expanded in next milestones. */ DummyPolicyManager() { _policies.push_back(new PRRPolicy); } virtual ~DummyPolicyManager() { } /** Gets THE policy (the only today) used. Next versions will implement some other kind. \return A reference to the policy. FIXME deprecated */ //virtual CPUPolicy& get_policy() = 0; /** Init (or reset if yet initialized) the manager. FIXME deprecated */ virtual void init() { } virtual const std::vector& get_avail_policies() { return _policies; } protected: virtual void collect_policies() { } }; // ------------------------------------------------------ // // MainWindow class // // contains and controls the tested widget // // ------------------------------------------------------ class MainWindow : public Gtk::Window { public: MainWindow(Simulation& simulation); virtual ~MainWindow(); protected: virtual void on_button_start_clicked(); virtual void on_button_stop_clicked(); virtual void on_button_pause_clicked(); virtual void on_button_runmode_clicked(); virtual void on_button_showthreads_clicked(); virtual void on_buttons_radio_clicked(); virtual void on_buttons_radio_disp_clicked(); virtual bool on_timer_timeout(); // TestWidget _test_widget; SimulationWidget _simulation_widget; HoltWidget _holt_widget; Gtk::Button _start_button; Gtk::Button _stop_button; Gtk::Button _pause_button; Gtk::CheckButton _runmode_button; Gtk::CheckButton _showthreads_button; Gtk::RadioButton _noscale_radio; Gtk::RadioButton _fit_radio; Gtk::RadioButton _stretch_radio; Gtk::RadioButton _horizontal_radio; Gtk::RadioButton _vertical_radio; Gtk::RadioButton _circular_radio; Gtk::HBox _buttons_box; Gtk::HBox _buttons2_box; Gtk::VBox _main_box; Gtk::ScrolledWindow _simulation_scroller; Gtk::ScrolledWindow _holt_scroller; Simulation::state _sim_state; HoltContainerWindow _holt_container; }; MainWindow::MainWindow(Simulation& simulation) : _simulation_widget(simulation), _holt_widget(simulation), _start_button("Start"), _stop_button("Stop"), _pause_button("Pause"), _runmode_button("Continue"), _showthreads_button("Show threads"), _noscale_radio("no scale"), _fit_radio("scale all"), _stretch_radio("stretch"), _horizontal_radio("dispose horizontal"), _vertical_radio("dispose vertical"), _circular_radio("dispose circular"), _sim_state(Simulation::state_stopped), _holt_container(simulation) { // This just sets the title of our new window. set_title("Holt Graph Widget Test"); add(_main_box); _buttons_box.pack_start(_start_button); _start_button.show(); _buttons_box.pack_start(_stop_button); _stop_button.show(); _buttons_box.pack_start(_pause_button); _pause_button.show(); _buttons_box.pack_start(_runmode_button); _runmode_button.set_active(false); _runmode_button.show(); _buttons_box.pack_start(_showthreads_button); _showthreads_button.set_active(false); _showthreads_button.show(); // scale radio buttons Gtk::RadioButton::Group group = _noscale_radio.get_group(); _fit_radio.set_group(group); _stretch_radio.set_group(group); _buttons_box.pack_start(_noscale_radio); _noscale_radio.set_active(); _noscale_radio.show(); _buttons_box.pack_start(_fit_radio); _fit_radio.show(); _buttons_box.pack_start(_stretch_radio); _stretch_radio.show(); _main_box.pack_start(_buttons_box, Gtk::PACK_SHRINK); _buttons_box.show(); _simulation_scroller.add(_simulation_widget); _simulation_widget.show(); _simulation_scroller.show(); _main_box.pack_start(_simulation_scroller); // dispose radio buttons Gtk::RadioButton::Group group2 = _horizontal_radio.get_group(); _vertical_radio.set_group(group2); _circular_radio.set_group(group2); _buttons2_box.pack_start(_horizontal_radio); _horizontal_radio.set_active(); _horizontal_radio.show(); _buttons2_box.pack_start(_vertical_radio); _vertical_radio.show(); _buttons2_box.pack_start(_circular_radio); _circular_radio.show(); _main_box.pack_start(_buttons2_box, Gtk::PACK_SHRINK); _buttons2_box.show(); _holt_scroller.add(_holt_widget); _holt_widget.show(); _holt_scroller.show(); _main_box.pack_start(_holt_scroller); _main_box.show(); // connect after standard signal handler _start_button.signal_clicked().connect( sigc::mem_fun(*this, &MainWindow::on_button_start_clicked), true ); _stop_button.signal_clicked().connect( sigc::mem_fun(*this, &MainWindow::on_button_stop_clicked), true ); _pause_button.signal_clicked().connect( sigc::mem_fun(*this, &MainWindow::on_button_pause_clicked), true ); _runmode_button.signal_clicked().connect( sigc::mem_fun(*this, &MainWindow::on_button_runmode_clicked), true ); _showthreads_button.signal_clicked().connect( sigc::mem_fun(*this, &MainWindow::on_button_showthreads_clicked), true ); _noscale_radio.signal_clicked().connect( sigc::mem_fun(*this, &MainWindow::on_buttons_radio_clicked), true ); _fit_radio.signal_clicked().connect( sigc::mem_fun(*this, &MainWindow::on_buttons_radio_clicked), true ); _stretch_radio.signal_clicked().connect( sigc::mem_fun(*this, &MainWindow::on_buttons_radio_clicked), true ); _horizontal_radio.signal_clicked().connect( sigc::mem_fun(*this, &MainWindow::on_buttons_radio_disp_clicked), true ); _vertical_radio.signal_clicked().connect( sigc::mem_fun(*this, &MainWindow::on_buttons_radio_disp_clicked), true ); _circular_radio.signal_clicked().connect( sigc::mem_fun(*this, &MainWindow::on_buttons_radio_disp_clicked), true ); Glib::signal_timeout().connect(sigc::mem_fun(*this, &MainWindow::on_timer_timeout), 1000); on_button_runmode_clicked(); on_button_showthreads_clicked(); //is equivalent to: /* const Glib::RefPtr timeout_source = Glib::TimeoutSource::create(1000); timeout_source->connect(sigc::ptr_fun(&timeout_handler)); timeout_source->attach(Glib::MainContext::get_default()); */ _holt_container.set_keep_above(); // _holt_container.set_deletable(false); _holt_container.show(); } MainWindow::~MainWindow() { } void MainWindow::on_button_start_clicked() { std::cout << "on_button_start_clicked" << endl; if(_sim_state == Simulation::state_stopped || _sim_state == Simulation::state_paused) { if(!_runmode_button.get_active()) { // one step - drive directly simulation Simulation& simu = Simulation::get_instance(); simu.run(); _sim_state = simu.get_state(); // _simulation_widget.redraw(); } else { _sim_state = Simulation::state_running; } } } void MainWindow::on_button_stop_clicked() { std::cout << "on_button_stop_clicked" << endl; if(_sim_state == Simulation::state_running || _sim_state == Simulation::state_paused) { _sim_state = Simulation::state_stopped; Simulation::get_instance().stop(); // _simulation_widget.redraw(); } } void MainWindow::on_button_pause_clicked() { std::cout << "on_button_pause_clicked" << endl; if(_sim_state == Simulation::state_running) { _sim_state = Simulation::state_paused; } else if(_sim_state == Simulation::state_paused) { _sim_state = Simulation::state_running; } } void MainWindow::on_button_runmode_clicked() { std::cout << "on_button_runmode_clicked" << endl; } void MainWindow::on_button_showthreads_clicked() { std::cout << "on_button_showthreads_clicked" << endl; _simulation_widget.set_show_threads(_showthreads_button.get_active()); _simulation_widget.resize_redraw(); _holt_widget.set_show_threads(_showthreads_button.get_active()); _holt_widget.resize_redraw(); } void MainWindow::on_buttons_radio_clicked() { std::cout << "on_buttons_radio_clicked" << endl; if(_noscale_radio.get_active()) { // std::cout << "scaling_none" << endl; _simulation_widget.set_scaling_mode(CairoWidget::scaling_none); _holt_widget.set_scaling_mode(CairoWidget::scaling_none); } else if(_fit_radio.get_active()) { // std::cout << "scaling_min" << endl; _simulation_widget.set_scaling_mode(CairoWidget::scaling_min); _holt_widget.set_scaling_mode(CairoWidget::scaling_min); } else { // std::cout << "scaling_all" << endl; _simulation_widget.set_scaling_mode(CairoWidget::scaling_all); _holt_widget.set_scaling_mode(CairoWidget::scaling_all); } _simulation_widget.resize_redraw(); _simulation_widget.set_size_request (20, 20); _holt_widget.resize_redraw(); _holt_widget.set_size_request (20, 20); } void MainWindow::on_buttons_radio_disp_clicked() { std::cout << "on_buttons_radio_disp_clicked" << endl; if(_horizontal_radio.get_active()) { // std::cout << "_horizontal_radio" << endl; _holt_widget.set_arrange_mode(HoltWidget::arrange_horizontal); } else if(_vertical_radio.get_active()) { // std::cout << "_vertical_radio" << endl; _holt_widget.set_arrange_mode(HoltWidget::arrange_vertical); } else { // std::cout << "_circular_radio" << endl; _holt_widget.set_arrange_mode(HoltWidget::arrange_circular); } _holt_widget.resize_redraw(); } bool MainWindow::on_timer_timeout() { // std::cout << "Timer sim stat= " << _sim_state << endl; if(_sim_state == Simulation::state_running) { Simulation& simu = Simulation::get_instance(); simu.run(); // _simulation_widget.redraw(); if(simu.get_state()==Simulation::state_stopped) _sim_state = Simulation::state_stopped; } return true; } // utility functions... // insert some resources, processes, threads, requests, subrequests void fillHistory(History &hist); // print entire environment into the passed ostream void dumpEnvironment(const Environment& env, ostream &os); // return the Schedulable::state readable string Glib::ustring get_schedulable_state_name(Schedulable::state st); // return the Request::state readable string Glib::ustring get_request_state_name(Request::state st); // return the Simulation::state readable string Glib::ustring get_simulation_state_name(Simulation::state st); // ------------------------------------------------------ // // program main // // ------------------------------------------------------ int main(int argc, char** argv) { ostream& info = cout; // actually unused test - leave for future use // ostream& test = cerr; Gtk::Main kit(argc, argv); // Set up Glib thread support Glib::thread_init(); info << "test-holt - start \n"; Simulation& simu = Simulation::get_instance(); info << "gets simulation \n"; History& hist = Simulation::get_instance().get_history(); ResourcePolicyManager & rpm = *ResourcePoliciesGatekeeper::get_instance().get_registered().at(0); Simulation::get_instance().set_resource_policy(rpm.get_avail_policies().at(0)); info << "gets history \n"; DummyPolicyManager dummy_manager; const std::vector& policies = dummy_manager.get_avail_policies(); CPUPolicy* pol = policies[0]; info << "policy " << pol->get_name() << endl; fillHistory(hist); info << "history filled \n"; simu.set_policy(pol); info << "policy activated \n"; simu.set_mode(Simulation::mode_step_by_step); info << "simulation set_mode single step\n"; info << "START environment dump \n"; dumpEnvironment(hist.get_last_environment(), info); info << "END environment dump \n"; info << "simulation state: " << get_simulation_state_name(simu.get_state()) << endl; MainWindow win(simu); win.set_border_width(10); win.resize (900, 600); Gtk::Main::run(win); return 0; } // insert some resources, processes, threads, requests, subrequests void fillHistory(History &hist) { // insert resources to delete soon // this create a numbering of keys starting from 2... // serves to prove correct save/restore independent from key numbering // add a resource - name, preemptable, places, availability History::ResourcePair respair0 = hist.add_resource(Glib::ustring("Resource 0"), false, 1, 2); // add a resource - name, preemptable, places, availability History::ResourcePair respair00 = hist.add_resource(Glib::ustring("Resource 00"), false, 1, 2); // add a resource - name, preemptable, places, availability History::ResourcePair respair = hist.add_resource(Glib::ustring("Resource 1"), false, 1, 2); // add a resource - name, preemptable, places, availability History::ResourcePair respair2 = hist.add_resource(Glib::ustring("Very Long Named Resource 2"), false, 1, 2); // delete resources to kreate a key numbering hole // hist.remove(respair0.first); // hist.remove(respair00.first); // add a process - name, arrival time, priority Process& p1 = hist.add_process(Glib::ustring("Process 1"), 0, 2); // name, arrival time, priority // add a process - name, arrival time, priority Process& p2 = hist.add_process(Glib::ustring("Process 2"), 7, 3); // name, arrival time, priority // add a process - name, arrival time, priority Process& p3 = hist.add_process(Glib::ustring("Process 3"), 5, 5); // name, arrival time, priority // add a process - name, arrival time, priority Process& p4 = hist.add_process(Glib::ustring("Very Long Named Process 4 with more and more characters"), 9, 1); // name, arrival time, priority // add a thread - name, parent, cpu time, arrival time, priority Thread& p1_t1 = hist.add_thread(Glib::ustring("P1 - Th 1"), p1, 14, 0, 2); // add a thread - name, parent, cpu time, arrival time, priority /* Thread& p1_t2 = */ hist.add_thread(Glib::ustring("P1 - Th 2"), p1, 3, 3, 5); // add a thread - name, parent, cpu time, arrival time, priority /* Thread& p1_t3 = */ hist.add_thread(Glib::ustring("P1 - Th 3"), p1, 4, 3, 5); // add a thread - name, parent, cpu time, arrival time, priority /*Thread& p1_t4 = */ hist.add_thread(Glib::ustring("P1 - Th 4"), p1, 5, 3, 4); // add a thread - name, parent, cpu time, arrival time, priority Thread& p2_t1 = hist.add_thread(Glib::ustring("P2 - Th 1"), p2, 20, 0, 2); // add a thread - name, parent, cpu time, arrival time, priority Thread& p3_t1 = hist.add_thread(Glib::ustring("P3 - Th 2"), p3, 12, 0, 2); // add a thread - name, parent, cpu time, arrival time, priority /* Thread& p4_t1 = */ hist.add_thread(Glib::ustring("P4 - Th 1"), p4, 7, 0, 2); // add a thread - name, parent, cpu time, arrival time, priority /* Thread& p4_t2 = */ hist.add_thread(Glib::ustring("P4 - Th 2"), p4, 3, 6, 2); // add a request - Thread, time Request& req1 = hist.add_request(p1_t1, 3); // add a sub request - Request, resource_key, duration, places /* SubRequest& req1_sub1 = */ hist.add_subrequest(req1, respair.first, 6); // add a request - Thread, time Request& req2 = hist.add_request(p2_t1, 1); // add a sub request - Request, resource_key, duration, places /* SubRequest& req2_sub1 = */ hist.add_subrequest(req2, respair.first, 4); // add a request - Thread, time Request& req3 = hist.add_request(p3_t1, 0); // add a sub request - Request, resource_key, duration, places /* SubRequest& req3_sub1 = */ hist.add_subrequest(req3, respair.first, 5); // add a request - Thread, time Request& req3bis = hist.add_request(p3_t1, 7); // add a sub request - Request, resource_key, duration, places /* SubRequest& req3bis_sub1 = */ hist.add_subrequest(req3bis, respair.first, 5); } Glib::ustring get_schedulable_state_name(Schedulable::state st) { switch(st) { case Schedulable::state_running: return Glib::ustring("Schedulable::state_running"); // break; case Schedulable::state_ready: return Glib::ustring("Schedulable::state_ready"); // break; case Schedulable::state_blocked: return Glib::ustring("Schedulable::state_blocked"); // break; case Schedulable::state_future: return Glib::ustring("Schedulable::state_future"); // break; case Schedulable::state_terminated: return Glib::ustring("Schedulable::state_terminated"); // break; default: return Glib::ustring("Schedulable::state_UNKNOWN"); // break; } } Glib::ustring get_request_state_name(Request::state st) { switch(st) { case Request::state_unallocable: return Glib::ustring("Request::state_unallocable"); // break; case Request::state_allocated: return Glib::ustring("Request::state_allocated"); // break; case Request::state_future: return Glib::ustring("Request::state_future"); // break; case Request::state_exhausted: return Glib::ustring("Request::state_exhausted"); // break; case Request::state_allocable: return Glib::ustring("Request::state_allocable"); // break; default: return Glib::ustring("Request::state_UNKNOWN"); // break; } } Glib::ustring get_simulation_state_name(Simulation::state st) { switch(st) { case Simulation::state_running: return Glib::ustring("Simulation::state_running"); // break; case Simulation::state_paused: return Glib::ustring("Simulation::state_paused"); // break; case Simulation::state_stopped: return Glib::ustring("Simulation::state_stopped"); // break; default: return Glib::ustring("Simulation::state_UNKNOWN"); // break; } } // print entire environment into the passed ostream void dumpEnvironment(const Environment& env, ostream &os) { os << "dump environment start " << endl; const Environment::Resources& rvect = env.get_resources(); typedef Environment::Resources::const_iterator res_iterator; res_iterator riter = rvect.begin(); while (riter != rvect.end()) { Resource* r = (*riter).second; os << " resource name: " << r->get_name() /* << " key: " << (*riter).first */ << " places: " << r->get_places() << endl; riter++; } const Environment::Processes& pvect = env.get_processes(); typedef std::vector::const_iterator proc_iterator; proc_iterator iter = pvect.begin(); proc_iterator end = pvect.end(); while (iter != end) { Process* p = (*iter); os << " process name: " << p->get_name() << " arrival_time: " << p->get_arrival_time() << " base_priority: " << p->get_base_priority() << " " << get_schedulable_state_name(p->get_state()) << endl; iter++; typedef std::vector Threads; typedef std::vector::const_iterator thr_iterator; const Threads& tvect = p->get_threads(); thr_iterator iter1 = tvect.begin(); thr_iterator end1 = tvect.end(); while (iter1 != end1) { Thread* t = (*iter1); os << " thread name: " << t->get_name() << " arrival_time: " << t->get_arrival_time() << " base_priority: " << t->get_base_priority() << " " << get_schedulable_state_name(t->get_state()) << endl; typedef std::vector Requests; typedef std::vector::const_iterator req_iterator; const Requests& rvect = t->get_requests(); req_iterator iter2 = rvect.begin(); req_iterator end2 = rvect.end(); while (iter2 != end2) { Request* r = (*iter2); os << " request arrival_time: " << r->get_instant() << endl; typedef std::vector SubRequests; typedef std::vector::const_iterator subreq_iterator; const SubRequests& srvect = r->get_subrequests(); subreq_iterator iter3 = srvect.begin(); subreq_iterator end3 = srvect.end(); while (iter3 != end3) { SubRequest* sr = (*iter3); os << " sub request: " /* << " resource_key: " << sr->get_resource_key() */; Environment::Resources::const_iterator pos = env.get_resources().find(sr->get_resource_key()); if (pos != env.get_resources().end()) { os << " name: " << pos->second->get_name(); } os << " length: " << sr->get_length() << " " << get_request_state_name(sr->get_state()) << endl; iter3++; } iter2++; } iter1++; } } os << "dump environment end " << endl << endl; }