/************************************************************************** * File name : Monitor.java * * This file is part a SCJ Level 0 and Level 1 implementation, * based on SCJ Draft, Version 0.94 25 June 2013. * * It 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 3 of the * License, or (at your option) any later version. * * This SCJ Level 0 and Level 1 implementation 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 this SCJ Level 0 and Level 1 implementation. * If not, see <http://www.gnu.org/licenses/>. * * Copyright 2012 * @authors Anders P. Ravn, Aalborg University, DK * Stephan E. Korsholm and Hans Søndergaard, * VIA University College, DK *************************************************************************/ package javax.safetycritical; import javax.safetycritical.ScjProcess.State; import vm.InterruptHandler; import icecaptools.IcecapCompileMe; final class Monitor extends vm.Monitor { int ceiling; private int synchCounter; private int priority; private ManagedSchedulable owner; private InterruptHandler clock; Monitor(int ceiling) { this.ceiling = ceiling; clock = vm.ClockInterruptHandler.instance; } public void lock() { clock.disable(); ManagedSchedulable msObj = PriorityScheduler.instance().getCurrentProcess().getTarget(); //devices.Console.println(PriorityScheduler.instance().getCurrentProcess().index + " locks "); if (owner == null) { setOwner(msObj); } if (owner == msObj) { synchCounter++; if (synchCounter == 1) { priority = ManagedSchedMethods.getPriorityParameter(msObj).getPriority(); ManagedSchedMethods.getPriorityParameter(msObj).setPriority(max(priority, ceiling) + 1); } clock.enable(); } else { // insert the process to in lock queue // process in REQUIRELOCK state ScjProcess process = ManagedSchedMethods.getScjProcess(msObj); process.state = ScjProcess.State.REQUIRELOCK; PriorityScheduler.instance(). addProcessToLockQueue(this, process); //devices.Console.println("addProcessToLockQueue: " + ManagedSchedMethods.getScjProcess(msObj).index); // transfer to the process clock.enable(); vm.ClockInterruptHandler.instance.yield(); } } @IcecapCompileMe @Override public void unlock() { clock.disable(); ManagedSchedulable msObj = PriorityScheduler.instance().getCurrentProcess().getTarget(); //devices.Console.println(PriorityScheduler.instance().getCurrentProcess().index + " unlocks"); if (owner == msObj) { synchCounter--; if (synchCounter == 0) { ManagedSchedMethods.getPriorityParameter(msObj).setPriority(priority); // get the next process that needs the lock in lock queue // and assign the lock to this process. ScjProcess process = PriorityScheduler.instance().getProcessFromLockQueue(this); //if (process != null) devices.Console.println("getProcessFromLockQueue: " + process.index); if (process != null) { setOwner(process.getTarget()); synchCounter++; priority = ManagedSchedMethods.getPriorityParameter(msObj).getPriority(); ManagedSchedMethods.getPriorityParameter(msObj).setPriority(max(priority, ceiling) + 1); // process READY process.state = State.READY; PriorityScheduler.instance().insertReadyQueue(process); //devices.Console.println("insertReadyQueue: " + process.index); } else { setOwner(null); } } } else { devices.Console.println(" Monitor.unlock: UPS, - not owner"); clock.enable(); throw new IllegalMonitorStateException("Not owner on exit"); } clock.enable(); } private void setOwner(ManagedSchedulable msObj) { owner = msObj; } private static int max(int x, int y) { if (x > y) return x; else return y; } static Monitor getMonitor(Object target) { Object obj = getAttachedMonitor(target); if (obj == null || !(obj instanceof Monitor)) { throw new IllegalMonitorStateException("the target is not a lock:" + obj.toString()); } return (Monitor) obj; } }