package edu.purdue.scjtck.tck; import javax.realtime.AbsoluteTime; import javax.realtime.Clock; import javax.realtime.PeriodicParameters; import javax.realtime.PriorityParameters; import javax.realtime.PriorityScheduler; import javax.realtime.RelativeTime; import javax.safetycritical.MissionSequencer; import javax.safetycritical.PeriodicEventHandler; import javax.safetycritical.StorageParameters; /** * Level 1 * * - Priority Ceiling Emulation supported one level 1+ * * TODO: this is not really testing PCE, instead it just tests that there is a * priority inversion prevention mechanism in the RI. (Priority inheritance * satisfy this test) */ public class TestSchedule404 extends TestCase { @Override protected String getArgs() { return "-L 1"; } public MissionSequencer getSequencer() { return new GeneralSingleMissionSequencer(new GeneralMission() { /* * the time of lowStart, lowEnd, highStart, highEnd, medianStart, * medianEnd in order */ private long[] _timeRecord = new long[6]; @Override public void initialize() { final MyLock lock = new MyLock(); final MyFreeLock freelock = new MyFreeLock(); int MAX_PRIORITY = PriorityScheduler.instance() .getMaxPriority(); int NOR_PRIORITY = PriorityScheduler.instance() .getNormPriority(); int MIN_PRIORITY = PriorityScheduler.instance() .getMinPriority(); 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); /* * start time order: low -> high -> median * * "high" will be blocked on "lock"; but "median" never.If the * priority ceiling protocol is implemented correctly, the * priorities of "median" and "high" should not be inverted, * i.e., they should finish in the order that they start */ new PeriodicEventHandler(low, new PeriodicParameters(null, new RelativeTime(Long.MAX_VALUE, 0)), new StorageParameters(256, new long[] { 100 }), 100) { public void handleAsyncEvent() { lock.doLow(); } }; new PeriodicEventHandler(high, new PeriodicParameters( new RelativeTime(5, 0), new RelativeTime( Long.MAX_VALUE, 0)), new StorageParameters(256, new long[] { 100 }), 100) { public void handleAsyncEvent() { lock.doHigh(); } }; new PeriodicEventHandler(median, new PeriodicParameters( new RelativeTime(10, 0), new RelativeTime( Long.MAX_VALUE, 0)), new StorageParameters(256, new long[] { 100 }), 100) { public void handleAsyncEvent() { freelock.doMedian(); } }; new Terminator(); } private long getCurrentTimeInNano() { AbsoluteTime time = Clock.getRealtimeClock().getTime(); long nanos = time.getMilliseconds() * 1000000 + time.getNanoseconds(); if (nanos < 0) nanos = Long.MAX_VALUE; return nanos; } // take around ? ms private void doWorks() { // for (int i = 0; i < 100000000; i++) // Above code takes to long in jop simulator - Tórur 22/6/2011 for (int i = 0; i < 200000; i++) ; } @Override // public void cleanup() { public void cleanUp() { for (int i = 0; i < 5; i++) if (_timeRecord[i] > _timeRecord[i + 1]) fail("Error in priority ceiling emulation"); // super.cleanup(); super.cleanUp(); } class MyLock { public synchronized void doLow() { _timeRecord[0] = getCurrentTimeInNano(); doWorks(); _timeRecord[1] = getCurrentTimeInNano(); } public synchronized void doHigh() { _timeRecord[2] = getCurrentTimeInNano(); doWorks(); _timeRecord[3] = getCurrentTimeInNano(); } } class MyFreeLock { public synchronized void doMedian() { _timeRecord[4] = getCurrentTimeInNano(); doWorks(); _timeRecord[5] = getCurrentTimeInNano(); } } }); } @Override public long immortalMemorySize() { // TODO Auto-generated method stub return 0; } }