/**************************************************************************
* File name : ScjProcess.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
*
* Description:
*
* Revision history:
* date init comment
*
*************************************************************************/
package javax.safetycritical;
import icecaptools.IcecapCompileMe;
import javax.realtime.AbsoluteTime;
import javax.realtime.Clock;
import javax.realtime.PeriodicParameters;
import javax.realtime.PriorityParameters;
import javax.realtime.RelativeTime;
import javax.safetycritical.ManagedMemory.ImmortalMemory;
import javax.scj.util.Const;
import javax.scj.util.Priorities;
import vm.Memory;
import vm.ProcessLogic;
import vm.RealtimeClock;
/**
* Defines the VM process context for an executing Java program.
*
* @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 - implementation issue: infrastructure class; not part of the SCJ
* specification.
*/
class ScjProcess implements Comparable<ScjProcess> {
vm.Process process;
ManagedSchedulable msObject;
int state;
Clock rtClock;
AbsoluteTime next; // next activation time
RelativeTime start;
RelativeTime period;
int index = -999; // The index of the ScjProcesses; used by
// PriorityScheduler; -999 is 'no index set'
Object monitorLock = null;
AbsoluteTime next_temp = null;
boolean isNotified = false;
interface State {
public final static byte NEW = 0;
public final static byte READY = 1;
public final static byte EXECUTING = 2;
public final static byte BLOCKED = 3;
public final static byte SLEEPING = 4;
public final static byte HANDLED = 5;
public final static byte TERMINATED = 6;
public final static byte WAITING = 7;
public final static byte REQUIRELOCK = 8;
}
private ExceptionReporter exceptionReporter;
/**
* The constructor initializes a new VM process object
*
* @param target
* is the handler containing the handleAsyncEvent method
* to be executed
* @param stack
* is the run time stack
*/
ScjProcess(ManagedSchedulable ms, int[] stack) {
this.rtClock = Clock.getRealtimeClock();
this.next = new AbsoluteTime(this.rtClock);
this.msObject = ms;
this.state = State.NEW;
this.exceptionReporter = new ExceptionReporter();
this.process = new vm.Process(new ProcessLogic() {
public void run() {
try {
runLogic (msObject);
} catch (Exception e) {
Const.reporter.processExecutionError(e);
} finally {
if (msObject instanceof PeriodicEventHandler) {
next.add(period, next); // next = next + period
}
state = State.HANDLED;
//devices.Console.println("ScjProcess: " + process + ", HANDLED");
}
}
public void catchError(final Throwable t) {
exceptionReporter.t = t;
try {
ImmortalMemory immortal =
ManagedMemory.ImmortalMemory.instance();
if (immortal != null) {
immortal.executeInArea(exceptionReporter);
} else {
Memory.executeInHeap(exceptionReporter);
}
} catch (OutOfMemoryError o) {
Const.reporter.processOutOfMemoryError(o);
}
}
}, stack);
this.process.initialize();
rtClock.getTime(this.next);
setRelease (msObject);
setProcess (msObject);
}
private void runLogic (ManagedSchedulable ms)
{
if (ms instanceof ManagedEventHandler)
((ManagedEventHandler) ms).privateMemory.enter(ms); // execute logic;
else if (ms instanceof ManagedThread)
((ManagedThread) ms).privateMemory.enter(ms);
else // (ms is instanceof ManagedLongEventHandler)
((ManagedLongEventHandler) ms).privateMemory.enter(ms);
}
private void setRelease (ManagedSchedulable ms)
{
if (ms instanceof PeriodicEventHandler) {
this.start = ((PeriodicParameters) ((PeriodicEventHandler) ms).release)
.getStart();
this.period = ((PeriodicParameters) ((PeriodicEventHandler) ms).release)
.getPeriod();
next.add(start, next); // next = next + start
}
else if (ms instanceof OneShotEventHandler) {
if (((OneShotEventHandler) ms).releaseTime instanceof RelativeTime) {
RelativeTime releaseTime = (RelativeTime) ((OneShotEventHandler) ms).releaseTime;
next.add(releaseTime, next); // next = next + releaseTime
} else {
AbsoluteTime releaseTime = (AbsoluteTime) ((OneShotEventHandler) ms).releaseTime;
int compare = releaseTime.compareTo(Clock.getRealtimeClock().getTime(new AbsoluteTime(rtClock)));
if (compare < 0)
next.add(new RelativeTime(), next);
else
next.set(releaseTime);
}
}
// else
// devices.Console.println("UPS: ScjProcess.setRelease: more cases?");
}
private void setProcess (ManagedSchedulable ms)
{
if (ms instanceof ManagedEventHandler)
((ManagedEventHandler) ms).process = this;
else if (ms instanceof ManagedThread)
((ManagedThread) ms).process = this;
else // (ms is instanceof ManagedLongEventHandler)
((ManagedLongEventHandler) ms).process = this;
}
private static class ExceptionReporter implements Runnable {
Throwable t;
public void run() {
Const.reporter.processExecutionError(t);
}
}
public String toString() {
return ("ScjProcess:" + msObject + " index: " + index);
}
/**
* Compares this process with the parameter process. HSO: The ordering of
* the processes are done after growing priorities.
*
* APR: The ordering of the processes are done after next release and
* priority:
*
* The "smallest" of the two processes is the process with the smallest (the
* first) next release time; if the processes have the same release time,
* the process with the highest priority comes first (is the "smallest").
*/
public int compareTo(ScjProcess process) {
// HSO: two queues in PriorityFrame: PriorityQueue and SleepingQueue (works)
// return (this.target.priority - process.target.priority)
if (msObject instanceof ManagedEventHandler
&& process.msObject instanceof ManagedEventHandler)
return (((ManagedEventHandler) msObject).priority.getPriority() -
((ManagedEventHandler) process.msObject).priority.getPriority());
if (msObject instanceof ManagedThread
&& process.msObject instanceof ManagedThread)
return (((ManagedThread) msObject).priority.getPriority() -
((ManagedThread) process.msObject).priority.getPriority());
if (msObject instanceof ManagedLongEventHandler
&& process.msObject instanceof ManagedLongEventHandler)
return (((ManagedLongEventHandler) msObject).priority.getPriority() -
((ManagedLongEventHandler) process.msObject).priority.getPriority());
return -999; // HSO: not finished
}
ManagedSchedulable getTarget() {
return msObject;
}
void setIndex(int index) {
this.index = index;
}
/**
* Idle process is created and put in readyQueue, so that readyQueue will
* never be empty. Idle process has lowest priority. <br>
*
* Idle process is a periodic handler with "infinite" period.
*/
static ScjProcess idleProcess;
/**
* Creates and returns the singleton idle process. If idle process is
* already created, no new process is created.
*
* @return Returns the singleton idle process.
*/
static ScjProcess createIdleProcess() {
if (idleProcess == null) {
PeriodicEventHandler peh = new PeriodicEventHandler(
new PriorityParameters(Priorities.MIN_PRIORITY),
new PeriodicParameters(
new RelativeTime(
Clock.getRealtimeClock()), // start (0,0)
Const.INFINITE_TIME), // period
new StorageParameters(
2*Const.IDLE_BACKING_STORE,
new long[] { Const.IDLE_PROCESS_STACK_SIZE },
2*Const.IDLE_BACKING_STORE,
0,
0
)) {
public void handleAsyncEvent() {
yield();
}
@IcecapCompileMe
private void yield() {
while (true) {
RealtimeClock.awaitNextTick();
}
}
};
ScjProcess process = new ScjProcess(peh, new int[Const.IDLE_PROCESS_STACK_SIZE]);
process.rtClock.getTime(process.next);
process.index = -1;
idleProcess = process;
}
return idleProcess;
}
public void start() {
process.initialize();
}
String print() {
return ("name: " + this.msObject + " index: " + index);
}
protected boolean nextState(PriorityFrame pFrame) {
return false;
}
protected void gotoNextState(PriorityFrame pFrame) {
}
void switchToPrivateMemArea() { ; }
}