/**************************************************************************
* File name : TestPreemptiveScheduling.java
*
* This file is part a TCK implementation,
* based on SCJ Draft, Version 0.94, 25 June 2013.
*
* Copyright 2014
* @authors Anders P. Ravn, Aalborg University, DK
* Stephan E. Korsholm and Hans Søndergaard,
* VIA University College, DK
*************************************************************************/
package javax.safetycritical.test.priorityScheduling;
import javax.realtime.AbsoluteTime;
import javax.realtime.AperiodicParameters;
import javax.realtime.Clock;
import javax.realtime.HighResolutionTime;
import javax.realtime.PeriodicParameters;
import javax.realtime.PriorityParameters;
import javax.realtime.RelativeTime;
import javax.safetycritical.Launcher;
import javax.safetycritical.Mission;
import javax.safetycritical.MissionSequencer;
import javax.safetycritical.OneShotEventHandler;
import javax.safetycritical.PeriodicEventHandler;
import javax.safetycritical.Safelet;
import javax.safetycritical.StorageParameters;
import javax.safetycritical.PriorityScheduler;
import javax.safetycritical.test.safelet.TestSafelet2;
import javax.scj.util.Const;
import unitTest_Remove.TestCase;
/**
* Test of preemptive scheduling at Level 1.
* This test is inspired by the Purdue TCK, TestSchedule 405.
*
* Compile this test case with jml4c.
* Compile the packages javax.realtime and javax.safetycritical with the usual compiler.
*
* @author APR and HSO
*/
public class TestPreemptiveScheduling extends TestCase
{
static StorageParameters storageParameters_Sequencer =
new StorageParameters(
Const.OUTERMOST_SEQ_BACKING_STORE,
new long[] { Const.HANDLER_STACK_SIZE },
Const.PRIVATE_MEM,
Const.IMMORTAL_MEM,
Const.MISSION_MEM);
static StorageParameters storageParameters_Handlers =
new StorageParameters(
Const.PRIVATE_BACKING_STORE,
new long[] { Const.HANDLER_STACK_SIZE },
Const.PRIVATE_MEM,
0,
0);
/*
* The time of lowStart, highStart, highEnd, medianStart, medianEnd, lowEnd in order
*/
static final int SIZE = 6;
static private long[] timeRecord = new long[SIZE];
class SafeletStub implements Safelet<MissionStub>
{
public MissionSequencer<MissionStub> getSequencer()
{
MissionSequencer<MissionStub> seq = new SequencerStub();
return seq;
}
public long immortalMemorySize()
{
return Const.IMMORTAL_MEM;
}
public void initializeApplication()
{
}
}
class SequencerStub extends MissionSequencer<MissionStub>
{
private MissionStub mission;
SequencerStub()
{
super (new PriorityParameters (PriorityScheduler.instance().getMinPriority() + 10),
storageParameters_Sequencer);
mission = new MissionStub();
}
public MissionStub getNextMission()
{
if (mission.terminationPending())
return null;
else
return mission;
}
/*@
public behaviour
requires true;
ensures
(\forall int i; 0 <= i && i < SIZE-1;
timeRecord[i] < timeRecord[i + 1]);
@*/
public void cleanUp() {
System.out.println("\nSequencerStub.cleanUp: ... ");
for (int i = 0; i < SIZE; i++) {
System.out.println("Time " + timeRecord[i]);
}
System.out.println();
super.cleanUp();
}
}
class MissionStub extends Mission
{
public void initialize()
{
int MAX_PRIORITY = PriorityScheduler.instance().getMaxPriority();
int MIN_PRIORITY = PriorityScheduler.instance().getMinPriority();
int NOR_PRIORITY = (MAX_PRIORITY + MIN_PRIORITY)/2;
PriorityParameters high =
new PriorityParameters((MAX_PRIORITY - NOR_PRIORITY) / 2 + NOR_PRIORITY);
PriorityParameters median = new PriorityParameters(NOR_PRIORITY);
PriorityParameters low =
new PriorityParameters(NOR_PRIORITY - (NOR_PRIORITY - MIN_PRIORITY) / 2);
new PeriodicEvhStub(
low,
new PeriodicParameters(new RelativeTime (0L, 0), // start
new RelativeTime (5*1000, 0)), // period
storageParameters_Handlers,
0, 5, "Low").register();
new PeriodicEvhStub(
high,
new PeriodicParameters(new RelativeTime (20L, 0), // start
new RelativeTime (5*1000, 0)), // period
storageParameters_Handlers,
1, 2, "High" ).register();
new PeriodicEvhStub(
median,
new PeriodicParameters(new RelativeTime (40L, 0), // start
new RelativeTime (5*1000, 0)), // period
storageParameters_Handlers,
3, 4, "Median" ).register();
new OneShotEvhStub (new PriorityParameters (MAX_PRIORITY),
new RelativeTime (3*1000L, 0),
new AperiodicParameters(new RelativeTime (100, 0), null),
storageParameters_Handlers) .register();
}
public long missionMemorySize ()
{
return Const.MISSION_MEM;
}
/*@
protected behaviour
requires true;
ensures
(\forall int i; 0 <= i && i < SIZE-1;
timeRecord[i] < timeRecord[i + 1]);
@*/
protected boolean cleanUp()
{
super.cleanUp();
// devices.Console.println("\nMissionStub.cleanUp: ... \n");
// for (int i = 0; i < SIZE-1; i++)
// if (timeRecord[i] > timeRecord[i + 1])
// AllTests.result.addError(AllTests.test_PreemptiveScheduling,
// new AssertionError());
return true;
}
}
class PeriodicEvhStub extends PeriodicEventHandler
{
final int N = 3*1;
int index1, index2;
String name;
protected PeriodicEvhStub (PriorityParameters priority,
PeriodicParameters periodic,
StorageParameters storage,
int index1, int index2,
String name)
{
super(priority, periodic, storage);
this.index1 = index1; this.index2 = index2;
this.name = name;
}
public void handleAsyncEvent()
{
//devices.Console.println(name + ": begin; " + Clock.getRealtimeClock().getTime());
timeRecord[index1] = getCurrentTimeInNano();
doWork();
timeRecord[index2] = getCurrentTimeInNano();
//devices.Console.println(name + ": end; " + Clock.getRealtimeClock().getTime());
}
private void doWork()
{
int n = N*1000000;
for (int i = 0; i < n; i++)
{ i = i + 1; i = i - 1; }
}
private long getCurrentTimeInNano()
{
AbsoluteTime time = Clock.getRealtimeClock().getTime();
long nanos = time.getMilliseconds() * 1000000 + time.getNanoseconds();
if (nanos < 0)
nanos = Long.MAX_VALUE;
return nanos;
}
}
class OneShotEvhStub extends OneShotEventHandler
{
public OneShotEvhStub (PriorityParameters priority,
HighResolutionTime releaseTime,
AperiodicParameters release,
StorageParameters storage)
{
super (priority, releaseTime, release, storage);
}
public void handleAsyncEvent()
{
devices.Console.println("PreemptiveSch: OneShotEvhStub.handleAsyncEvent: requestTermination");
Mission.getMission().requestTermination();
}
}
public TestPreemptiveScheduling (String name)
{
super(name);
}
public void test (int i)
{
switch (i) {
case 1:
devices.Console.println("\nTestPreemptiveScheduling begin");
new Launcher(new TestPreemptiveScheduling.SafeletStub(), 1);
devices.Console.println("TestPreemptiveScheduling end \n");
break;
default: break;
}
}
public static final int testCount = 1;
}