///////////////////////////////////////////////////////////////////////////// // // Bossa, a framework for scheduler programming // Copyright (C) 2005 Ecole des Mines de Nantes and // Department of Computer Science, University of Copenhagen // // This file is part of Bossa. // // Bossa is free software; you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation; either version 2.1 of the License, or // any later version. // // Bossa 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 Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with Bossa; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // Please send remarks, questions and bug reports to bossa@emn.fr // or to: // // Gilles Muller // Ecole des Mines de Nantes, // La Chantrerie - 4, rue Alfred Kastler. B.P. 20722 // 44307 NANTES Cedex 3, FRANCE // /////////////////////////////////////////////////////////////////////////////// high_res scheduler RMu = { process = { time period; // Fixed attributes cycles wcet; timer period_timer; // Timers int missed_deadlines; } // bool trace_on = false; states = { RUNNING running : process; READY ready : select queue; READY yield : process; BLOCKED blocked : queue; BLOCKED computation_ended : queue; TERMINATED terminated; } ordering_criteria = { lowest period } /* trace 500 { events = { unblock.timer.* }; expressions = { periods, sched_yields, schedules, absolute_deadline }; test = { trace_on }; } */ handler (event e) { On block.* { e.target => blocked; } On unblock.preemptive { if (e.target in blocked) { if ((!empty(running)) && (e.target > running)) { running => ready; } e.target => ready; } } On unblock.nonpreemptive { if (e.target in blocked) { e.target => ready; } } On yield.system.pause.*, yield.user.* { e.target => yield; } On yield.system.immediate.* { if (e.target in running) { e.target => ready; } } On bossa.schedule { if (empty(ready)) { yield => ready; } select() => running; if (!empty(yield)) { yield => ready; } } On system.clocktick { } On process.end { e.target => terminated; } On preempt { running => ready; } On unblock.timer.period_timer { start_relative_timer(e.target.period_timer,e.target.period); if (e.target in computation_ended) { e.target => ready; if ((!empty(running)) && (e.target > running)) { running => ready; } } else { e.target.missed_deadlines++; } } } interface = { void sched_yield(process p) { p => computation_ended; } void attach (process p, cycles period, cycles wcet) { cycles x = wcet; p.period = make_cycle_time(0,period); x = time_to_subjiffies(p.period); p.wcet = wcet; p.missed_deadlines = 0; start_relative_timer(p.period_timer,p.period); p => ready; } void detach (process p) { } int get_missed_deadlines (process p) { return p.missed_deadlines; } /* void start_trace() { trace_on = true; } void stop_trace() { trace_on = false; } */ } }