/************************************************************************** * File name : TestPriorityCeilingEmulation.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.PriorityScheduler; import javax.safetycritical.Safelet; import javax.safetycritical.Services; import javax.safetycritical.StorageParameters; import javax.scj.util.Const; import unitTest_Remove.TestCase; /** * Test of preemptive scheduling at Level 1. * This test is inspired by the example in Section 11.8 of * Burns and Wellings: Real-Time Systems and Programming Languages, 4th edition. * Table 11.11 in the book gives an overview of the tasks and * their execution sequences. * Figure 11.9 shows the actual execution when ICPP is used. * * @author APR and HSO */ public class TestPriorityCeilingEmulation 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 aStart, dStart, dEnd, cStart, cEnd, bStart, bEnd, aEnd in order */ static final int SIZE = 8; 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() + 1), storageParameters_Sequencer); mission = new MissionStub(); } public MissionStub getNextMission() { if (mission.terminationPending()) return null; else return mission; } } class MissionStub extends Mission { public void initialize() { Q q = new Q(); V v = new V(); int MAX_PRIORITY = PriorityScheduler.instance().getMaxPriority(); int MIN_PRIORITY = PriorityScheduler.instance().getMinPriority(); int NOR_PRIORITY = (MAX_PRIORITY + MIN_PRIORITY)/2; PriorityParameters a_Priority = new PriorityParameters(NOR_PRIORITY + 1); PriorityParameters b_Priority = new PriorityParameters(NOR_PRIORITY + 2); PriorityParameters c_Priority = new PriorityParameters(NOR_PRIORITY + 3); PriorityParameters d_Priority = new PriorityParameters(NOR_PRIORITY + 4); devices.Console.println("Priorities: a: " + a_Priority.getPriority() + "; b: " + b_Priority.getPriority() + "; c: " + c_Priority.getPriority() + "; d: " + d_Priority.getPriority() +"\n"); new a_PEvhStub( a_Priority, new PeriodicParameters(new RelativeTime ( 0*tickTime, 0), // start new RelativeTime (25*tickTime, 0)), // period storageParameters_Handlers, q, "a").register(); new b_PEvhStub( b_Priority, new PeriodicParameters(new RelativeTime ( 2*tickTime, 0), // start new RelativeTime (25*tickTime, 0)), // period storageParameters_Handlers, "b").register(); new c_PEvhStub( c_Priority, new PeriodicParameters(new RelativeTime ( 2*tickTime, 0), // start new RelativeTime (25*tickTime, 0)), // period storageParameters_Handlers, v, "c").register(); new d_PEvhStub( d_Priority, new PeriodicParameters(new RelativeTime ( 4*tickTime, 0), // start new RelativeTime (25*tickTime, 0)), // period storageParameters_Handlers, q, v, "d").register(); new OneShotEvhStub (new PriorityParameters (MAX_PRIORITY), new RelativeTime (20*tickTime, 0), new AperiodicParameters(new RelativeTime (500, 0), null), storageParameters_Handlers) .register(); Services.setCeiling(q, d_Priority.getPriority()); Services.setCeiling(v, d_Priority.getPriority()); } 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() { 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_PriorityCeilingEmulation, // AllTests.assertionError); return true; } } static final long tickTime = 3*100L; static final int N = 3*1; static void tick() { int n = N*1000000; for (int i = 0; i < n; i++) { i = i + 1; i = i - 1; } } static void e_Method() { tick(); } static long getCurrentTimeInNano() { AbsoluteTime time = Clock.getRealtimeClock().getTime(); long nanos = time.getMilliseconds() * 1000000 + time.getNanoseconds(); if (nanos < 0) nanos = Long.MAX_VALUE; return nanos; } class Q { public synchronized void a_Method() { tick(); tick(); tick(); tick(); } public synchronized void d_Method() { tick(); } } class V { public synchronized void c_Method() { tick(); tick(); } public synchronized void d_Method() { tick(); } } class a_PEvhStub extends PeriodicEventHandler { Q q; String name; protected a_PEvhStub (PriorityParameters priority, PeriodicParameters periodic, StorageParameters storage, Q q, String name) { super(priority, periodic, storage); this.q = q; this.name = name; } public void handleAsyncEvent() { timeRecord[0] = getCurrentTimeInNano(); devices.Console.println("0 " + name + ": begin"); e_Method(); q.a_Method(); e_Method(); devices.Console.println("7 " + name + ": end; \n"); timeRecord[7] = getCurrentTimeInNano(); } } class b_PEvhStub extends PeriodicEventHandler { String name; protected b_PEvhStub (PriorityParameters priority, PeriodicParameters periodic, StorageParameters storage, String name) { super(priority, periodic, storage); this.name = name; } public void handleAsyncEvent() { timeRecord[5] = getCurrentTimeInNano(); devices.Console.println("5 " + name + ": begin"); e_Method(); e_Method(); devices.Console.println("6 " + name + ": end;"); timeRecord[6] = getCurrentTimeInNano(); } } class c_PEvhStub extends PeriodicEventHandler { V v; String name; protected c_PEvhStub (PriorityParameters priority, PeriodicParameters periodic, StorageParameters storage, V v, String name) { super(priority, periodic, storage); this.v = v; this.name = name; } public void handleAsyncEvent() { timeRecord[3] = getCurrentTimeInNano(); devices.Console.println("3 " + name + ": begin"); e_Method(); v.c_Method(); e_Method(); devices.Console.println("4 " + name + ": end;"); timeRecord[4] = getCurrentTimeInNano(); } } class d_PEvhStub extends PeriodicEventHandler { Q q; V v; String name; protected d_PEvhStub (PriorityParameters priority, PeriodicParameters periodic, StorageParameters storage, Q q, V v, String name) { super(priority, periodic, storage); this.q = q; this.v = v; this.name = name; } public void handleAsyncEvent() { timeRecord[1] = getCurrentTimeInNano(); devices.Console.println("1 " + name + ": begin"); e_Method(); e_Method(); q.d_Method(); v.d_Method(); e_Method(); devices.Console.println("2 " + name + ": end;"); timeRecord[2] = getCurrentTimeInNano(); } } 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("PriorityCeiling: OneShotEvhStub.handleAsyncEvent: requestTermination \n"); Mission.getMission().requestTermination(); } } public TestPriorityCeilingEmulation (String name) { super(name); } public void test (int i) { switch (i) { case 1: devices.Console.println("\nTestPriorityCeilingEmulation begin"); new Launcher(new TestPriorityCeilingEmulation.SafeletStub(), 1); devices.Console.println("TestPriorityCeilingEmulation end \n"); break; default: break; } } public static final int testCount = 1; }