package mvd.jester.tests; import java.math.RoundingMode; import java.util.HashMap; import java.util.Map; import java.util.Set; import com.google.common.math.LongMath; import mvd.jester.info.SchedulingInfo; import mvd.jester.info.TerminationInfo; import mvd.jester.model.DagTask; import mvd.jester.model.Segment; import mvd.jester.model.SortedTaskSet; import mvd.jester.model.SystemManager; import mvd.jester.model.Task; import mvd.jester.priority.PriorityManager; import mvd.jester.priority.RateMonotonic; /** * SchmidMottok */ public class SchmidMottok extends AbstractTest { private final Map responseTimes; private final PriorityManager priorityManager; public SchmidMottok(final SystemManager manager) { super(manager); this.responseTimes = new HashMap<>(); this.priorityManager = new RateMonotonic(); } @Override public PriorityManager getPriorityManager() { return priorityManager; } @Override public SchedulingInfo runSchedulabilityCheck(final SortedTaskSet tasks) { responseTimes.clear(); for (final DagTask t : tasks) { final long responseTime = calculateResponseTime(tasks, t); responseTimes.put(t, new TerminationInfo(t.getDeadline(), responseTime)); } return new SchedulingInfo(responseTimes.values()); } @Override public String getName() { return "SchmidMottok"; } private long calculateResponseTime(final Set tasks, final DagTask task) { final long minimumWcet = task.getCriticalPath(); long responseTime = minimumWcet; long previousResponseTime = 0; do { previousResponseTime = responseTime; double taskInterference = 0; for (final DagTask t : tasks) { if (t.getPeriod() < task.getPeriod()) { final long numberOfThreads = t.getNumberOfThreads(); for (int p = 0; p < numberOfThreads; ++p) { taskInterference += Math.min(getTaskInterference(t, responseTime, p + 1), responseTime - minimumWcet + 1); } } } taskInterference /= manager.getNumberOfProcessors(); final double selfInterference = getSelfInterference(task); final long totalInterference = (long) Math.floor(taskInterference + selfInterference); responseTime = minimumWcet + totalInterference; } while (previousResponseTime != responseTime); return responseTime; } private double getSelfInterference(final DagTask task) { // final long numberOfThreads = task.getNumberOfThreads(); // TODO: Change back to number of threads final long numberOfThreads = manager.getNumberOfProcessors(); double interference = task.getWorkload() - task.getCriticalPath(); interference /= numberOfThreads; return interference; } private double getTaskInterference(final DagTask task, final long interval, final long parallelism) { if (responseTimes.containsKey(task)) { final long responseTime = responseTimes.get(task).getResponseTime(); final long minWcet = task.getCriticalPath(); final long period = task.getPeriod(); final long amountOfJobs = (LongMath.divide(interval + responseTime - minWcet, period, RoundingMode.FLOOR) + 1); double workload = 0; for (final Segment s : task.getWorkloadDistribution()) { final long numberOfThreads = s.getNumberOfJobs() > 1 ? task.getNumberOfThreads() : 1; if (numberOfThreads >= parallelism) { workload += s.getNumberOfJobs() * s.getJobWcet() / numberOfThreads; } } final double interference = amountOfJobs * workload; return interference; } else { throw new RuntimeException("Task was not found in task set!"); } } }