/*
This file is part of JOP, the Java Optimized Processor
see <http://www.jopdesign.com/>
Copyright (C) 2008-2011, Martin Schoeberl (martin@jopdesign.com)
This program 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
*
*/
package javax.safetycritical;
import java.util.Vector;
import javax.realtime.AbsoluteTime;
import javax.realtime.Clock;
import com.jopdesign.sys.Memory;
import joprt.RtThread;
/**
* @author Martin Schoeberl
*
* I'm not sure that so much code shall be in this JOP specific class.
*
*/
public class JopSystem {
public static void startMission(Safelet scj) {
scj.initializeApplication();
MissionSequencer ms = scj.getSequencer();
Mission.currentSequencer = ms;
// MissionDescriptor md = ms.getInitialMission();
// TODO: there is some chaos on mission and the classes
// for it -- needs a reread on current spec
// and a fix
// MissionDescriptor md = ms.getNextMission();
// MissionDescriptor md = null;
// md.initialize();
// this should be a loop
Mission m = ms.getNextMission();
ms.current_mission = m;
// that should be done in the sequencer
// this should also run in mission memory
m.initialize();
Terminal.getTerminal().writeln("SCJ Start mission on JOP");
RtThread.startMission();
}
public void startCycle(Safelet<CyclicExecutive> scj) {
// Maximum memory size required for all
// missions in the application, should
// be known in advance
int MAX_MISSION_MEM = 1 * 106 * 1000;
Helper helper = new Helper();
CyclicExecutor cycExec = new CyclicExecutor(helper);
scj.initializeApplication();
MissionSequencer<CyclicExecutive> ms = scj.getSequencer();
Mission.currentSequencer = ms;
cycExec.ms = ms;
while (helper.nextMission) {
// Change allocation context to Mission memory
Memory.getCurrentMemory().enterPrivateMemory(MAX_MISSION_MEM,
cycExec);
}
}
class CyclicExecutor implements Runnable {
MissionSequencer<CyclicExecutive> ms;
Helper helper;
public CyclicExecutor(Helper helper) {
this.helper = helper;
}
@Override
public void run() {
CyclicExecutive ce;
// Mission object is created in Mission Memory
ce = (CyclicExecutive) ms.getNextMission();
ms.current_mission = ce;
if (ce != null) {
Terminal.getTerminal().writeln("Got new mission...");
// Current memory is mission memory
ce.phase = Mission.INITIIALIZATION;
ce.initialize();
/**
* Upon return from initialize(), the infrastructure invokes the
* mission's getSchedule method in a Level 0 run-time
* environment. The infrastructure creates an array representing
* all of the ManagedSchedulable objects that were registered by
* the initialize method and passes this array as an argument to
* the mission's getSchedule method
*/
Vector v = ce.getHandlers();
PeriodicEventHandler[] peHandlers = new PeriodicEventHandler[v
.size()];
v.copyInto(peHandlers);
ce.phase = Mission.EXECUTION;
CyclicSchedule schedule = ce.getSchedule(peHandlers);
Frame[] frames = schedule.getFrames();
/**
* The total size required can be the maximum of the backing
* store sizes needed for each handler's private memories.
*/
long maxScopeSize = 0;
long maxBsSize = 0;
for (int i = 0; i < frames.length; i++) {
for (int j = 0; j < frames[i].handlers_.length; j++) {
long k = frames[i].handlers_[j].getScopeSize();
long l = frames[i].handlers_[j].storage .getTotalBackingStoreSize();
maxScopeSize = (k > maxScopeSize) ? k : maxScopeSize;
maxBsSize = (l > maxBsSize) ? l : maxBsSize;
}
}
Memory handlerPrivMemory = new Memory((int) maxScopeSize,
(int) maxBsSize);
HandlerExecutor handlerExecutor = new HandlerExecutor();
AbsoluteTime now = new AbsoluteTime();
AbsoluteTime next = new AbsoluteTime();
next = Clock.getRealtimeClock().getTime(next).add(1000, 0);
MissionSequencer.terminationRequest = false;
while (!ce.terminationPending()) {
for (int i = 0; i < frames.length; i++) {
while (Clock.getRealtimeClock().getTime(now)
.compareTo(next) < 0) {
;
}
for (int j = 0; j < frames[i].handlers_.length; j++) {
handlerExecutor.handler = frames[i].handlers_[j];
/**
* Since no two PeriodicEventHandlers in a Level 0
* application are permitted to execute
* simultaneously, the backing store for the private
* memories may be reused. In order for this to be
* achieved, the implementation may revoke the
* backing store reservation for the private memory
* of a periodic event handler at the end of its
* release.
*/
handlerPrivMemory.enter(handlerExecutor);
}
next = next.add(frames[i].duration_, next);
if (Clock.getRealtimeClock().getTime(now)
.compareTo(next) > 0) {
// Frame overrun
Terminal.getTerminal().writeln("Frame overrun");
}
}
}
ce.phase = Mission.CLEANUP;
ce.cleanUp();
ce.phase = Mission.INACTIVE;
} else {
Terminal.getTerminal().writeln("No more missions...");
helper.nextMission = false;
}
}
}
class HandlerExecutor implements Runnable {
PeriodicEventHandler handler;
@Override
public void run() {
handler.handleAsyncEvent();
}
}
class Helper {
boolean nextMission = true;
}
// public static void runMission(Safelet scj){
//
// MissionSequencer ms = scj.getSequencer();
//
// Memory missionMem;
// Mission m;
//
// //initial mission
// m = ms.getNextMission();
//
// while(m != null){
//
// int x = (int) m.missionMemorySize();
//
// // In mission memory
// Memory.getCurrentMemory().enterPrivateMemory(x, m.start());
//
// // When we return from mission memory
// m = ms.getNextMission();
// }
// }
}