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.SortedTaskSet; import mvd.jester.model.SystemManagerInterface; 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; private final TypeFunction structure; public SchmidMottok(TypeFunction structure, final SystemManagerInterface manager) { super(manager); this.responseTimes = new HashMap<>(); this.priorityManager = new RateMonotonic(); this.structure = structure; } @Override public PriorityManager getPriorityManager() { return priorityManager; } @Override public SchedulingInfo runSchedulabilityCheck(final SortedTaskSet tasks) { responseTimes.clear(); reassignNumberOfThreads(tasks); 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" + "_" + structure.getType(); } private void reassignNumberOfThreads(Set tasks) { long numberOfProcessors = manager.getNumberOfProcessors(); long occupiedProcessors = 0; for (DagTask t : tasks) { if (occupiedProcessors >= numberOfProcessors) { t.setNumberOfThreads(numberOfProcessors); } else { occupiedProcessors += t.getNumberOfThreads(); } } } private long calculateResponseTime(final Set tasks, final DagTask task) { final long minimumWcet = task.getCriticalPath(); long responseTime = minimumWcet; long previousResponseTime = 0; final long numberOfProcessors = manager.getNumberOfProcessors(); long occupiedProcessors = 0; for (final DagTask t : tasks) { if (t.getPeriod() < task.getPeriod()) { final long numberOfThreads = structure.getNumberOfThreads(t); occupiedProcessors += numberOfThreads; } } final double selfInterference = structure.getSelfInterference(task); if (occupiedProcessors + structure.getNumberOfThreads(task) <= numberOfProcessors) { return minimumWcet + (long) Math.floor(selfInterference); } else { do { previousResponseTime = responseTime; double taskInterference = 0; for (final DagTask t : tasks) { if (t.getPeriod() < task.getPeriod()) { final long numberOfThreads = structure.getNumberOfThreads(t); for (int p = 0; p < numberOfThreads; ++p) { taskInterference += Math.min( structure.getTaskInterference(t, responseTimes, responseTime, p + 1), responseTime - minimumWcet + 1); } } } taskInterference /= numberOfProcessors; long totalInterference = (long) Math.floor(taskInterference + selfInterference); if (occupiedProcessors < numberOfProcessors) { long workloadAmongRemainingProcessors = LongMath.divide(task.getWorkload() - task.getCriticalPath(), numberOfProcessors - occupiedProcessors, RoundingMode.FLOOR); totalInterference = Math.min(totalInterference, workloadAmongRemainingProcessors); } responseTime = minimumWcet + totalInterference; } while (previousResponseTime != responseTime); return responseTime; } } }