/************************************************************************** * File name : Mission.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 icecaptools.IcecapCompileMe; import javax.realtime.AbsoluteTime; import javax.safetycritical.annotate.Level; import javax.safetycritical.annotate.Phase; import javax.safetycritical.annotate.SCJAllowed; import javax.scj.util.Const; /** * An SCJ application is comprised of one or more <code>Mission</code> objects. * Each <code>Mission</code> object is implemented as a subclass of this * abstract <code>Mission</code> class. * * @version 1.2; - December 2013 * * @author Anders P. Ravn, Aalborg University, <A * HREF="mailto:apr@cs.aau.dk">apr@cs.aau.dk</A>, <br> * Hans Søndergaard, VIA University College, Denmark, <A * HREF="mailto:hso@viauc.dk">hso@via.dk</A> * * * @scjComment */ @SCJAllowed public abstract class Mission { MissionSequencer<?> currMissSeq; boolean missionTerminate = false; ManagedSchedulableSet msSetForMission; Phase phaseOfMission; protected int missionIndex = -1; static volatile Mission[] missionSet = null; boolean isMissionSetInitByThis = false; static volatile boolean isMissionSetInit = false; @SCJAllowed public Mission(AbsoluteTime start) { // ToDo: implement } @SCJAllowed public Mission() { } /** * Method to clean up after a mission terminates. <br> The infrastructure calls * <code>cleanup</code> after all <code>ManagedSchedulable</code>s * associated with this <code>Mission</code> have terminated, but before * control leaves the dedicated <code>MissionMemory</code> area. * The default implementation of <code>cleanup</code> does nothing. */ @SCJAllowed(Level.SUPPORT) protected boolean cleanUp() { return true; } @SCJAllowed @IcecapCompileMe public static Mission getMission() { Mission mission = null; if (Launcher.level == 0 && CyclicScheduler.instance().seq != null) { mission = CyclicScheduler.instance().seq.currMission; } else if (Launcher.level > 0 && PriorityScheduler.instance().getCurrentProcess() != null) { if (PriorityScheduler.instance().getCurrentProcess().getTarget() instanceof MissionSequencer) { mission = ((MissionSequencer<?>) PriorityScheduler.instance().getCurrentProcess().getTarget()).currMission; } else { mission = ManagedSchedMethods.getMission(PriorityScheduler.instance().getCurrentProcess().getTarget()); } } return mission; } @SCJAllowed public MissionSequencer<?> getSequencer() { return currMissSeq; } /** * Performs initialization of this <code>Mission</code>. The infrastructure * calls <code>initialize</code> after the <code>Mission</code> has been * instantiated and the <code>MissionMemory</code> has been resized to * match the size returned from this <code>Mission</code>'s <code> * missionMemorySize</code> method. Upon entry into the <code>initialize</code> * method, the current allocation context is the <code>MissionMemory</code> * area dedicated to this particular <code>Mission</code>. <p> * * An overridden implementation of <code>initialize</code> should instantiate * and register all <code>ManagedSchedulable</code>s that constitute this * <code>Mission</code>. The infrastructure enforces that <code> * ManagedSchedulable</code>s can only be instantiated and registered if * the infrastructure is currently executing a <code>Mission.initialize</code> method. * An exception to this rule allows a <code>MissionSequencer</code> to be * instantiated if the infrastructure is currently executing * <code>Safelet.getSequencer</code>. <p> * The infrastructure arranges to begin executing the <code>ManagedSchedulable</code>s * registered by the <code>initialize</code> method upon return from * the <code>initialize</code> method. */ @SCJAllowed(Level.SUPPORT) protected abstract void initialize(); // used in MissionSequencer.handleAsyncEvent: case State.INITIALIZE void setMissionSeq(MissionSequencer<?> missSeq) { currMissSeq = missSeq; } /** * The application developer is required to implement this method. * @return The desired size of this mission's <code>MissionMemory</code>, measured in bytes. */ @SCJAllowed(Level.SUPPORT) public abstract long missionMemorySize(); /** * This method provides a standard interface for requesting termination of a mission. <p> * The infrastructure shall: * <ol> * <li> disable all periodic event handlers associated with this <code>Mission</code>, * <li> remove handlers from <code>AperiodicEvent</code>s, * <li> clear the fire count for each of this <code>Mission</code>'s event handlers * <li> wait for all dispatched schedulables to terminate execution, * <li> invoke the <code>cleanup</code> method for each of the * <code>ManagedSchedulable</code>s associated with this mission, and * <li> invoke the <code>cleanup</code> method associated with this mission. * </ol> * <p> * * An application-specific subclass of <code>Mission</code> may override * this method in order to insert application-specific code to communicate * the intent to shutdown to specific <code>ManagedSchedulable</code>s. <p> * Control returns from <code>requestTermination</code> after it has * arranged for the required activities to be performed. * Note that those activities may not have completed. */ @SCJAllowed public final boolean requestTermination() { if (missionTerminate == false) { // called the first time during mission execution // terminate all the sequencer's MSObjects that were created by the mission. for (int i = 0; i < msSetForMission.noOfRegistered; i++) { if (msSetForMission.managedSchObjects[i] != null) { msSetForMission.managedSchObjects[i].signalTermination(); } } missionTerminate = true; return false; } else return true; // called more than once: nothing done } /** * Checks if the current mission is trying to terminate. * * @return True if and only if this <code>Mission</code> object's <code> * Mission.requestTermination</code> method has been invoked. */ public final boolean terminationPending() { return missionTerminate; } static synchronized int addNewMission(Mission mission) { for (int i = 0; i < missionSet.length; i++) { if (missionSet[i] == null) { missionSet[i] = mission; return i; } } throw new IndexOutOfBoundsException("Mission set: too small"); } void runInitialize() { vm.ClockInterruptHandler.instance.disable(); if (missionSet == null || isMissionSetInit == false) { missionSet = new Mission[Const.DEFAULT_HANDLER_NUMBER]; isMissionSetInitByThis = true; isMissionSetInit = true; } missionIndex = addNewMission(this); phaseOfMission = Phase.INITIALIZE; // used by JML ?? msSetForMission = new ManagedSchedulableSet(); initialize(); vm.ClockInterruptHandler.instance.enable(); } void runExecute() // Called in mission memory. // This implementation is for priority schedule execution. // For cyclic schedule execution, this method is overwritten in // the subclass CyclicExecutive. { vm.ClockInterruptHandler.instance.disable(); phaseOfMission = Phase.EXECUTE; ManagedSchedulableSet msSet = msSetForMission; PriorityFrame frame = PriorityScheduler.instance().pFrame; int index = missionIndex * 20; for (int i = 0; i < msSet.noOfRegistered; i++) { ManagedSchedulable ms = msSet.managedSchObjects[i]; msSet.scjProcesses[i] = ManagedSchedMethods.createScjProcess(ms); msSet.scjProcesses[i].setIndex(index); index++; frame.addProcess(msSet.scjProcesses[i]); } vm.ClockInterruptHandler.instance.enable(); } void runCleanup(MissionMemory missMem) // Called in mission memory. // This implementation is for priority schedule execution. // For cyclic schedule execution, this method is overwritten in // the subclass CyclicExecutive. { phaseOfMission = Phase.CLEANUP; // wait until (all handlers in mission have terminated) while (msSetForMission.msCount > 0) { vm.RealtimeClock.awaitNextTick(); } vm.ClockInterruptHandler.instance.disable(); for (int i = 0; i < msSetForMission.noOfRegistered; i++) { msSetForMission.scjProcesses[i] = null; msSetForMission.managedSchObjects[i] = null; } missionSet[missionIndex] = null; if (isMissionSetInitByThis == true) { isMissionSetInit = false; } cleanUp(); missMem.resetArea(); vm.ClockInterruptHandler.instance.enable(); } protected static ScjProcess getScjProcess(int missionIndex, int scjProcessIndex) { return missionSet[missionIndex].msSetForMission.scjProcesses[scjProcessIndex]; } // used for JML annotation only (not public) boolean isRegistered(ManagedSchedulable target) { return ManagedSchedMethods.isRegistered(target); } // used for JML annotation only (not public) boolean inMissionScope(ManagedSchedulable target) { return ManagedSchedMethods.isInMissionScope(target); } // used for JML annotation only (not public) boolean inMissionScope(CyclicSchedule cs) { return true; } // used for JML annotation only (not public) Phase getPhase() { return phaseOfMission; } }