AbstractSimulator.java 4.54 KB
Newer Older
1 2
package mvd.jester.simulator;

3
import java.util.Comparator;
4
import java.util.HashSet;
5
import java.util.Optional;
6
import java.util.Set;
7
import java.util.TreeSet;
8
import com.google.common.collect.TreeMultiset;
9
import mvd.jester.model.SystemSetup;
10 11
import mvd.jester.model.Task;
import mvd.jester.priority.PriorityManager;
12
import mvd.jester.priority.RateMonotonic;
13
import mvd.jester.TypeInterface;
14 15
import mvd.jester.info.SchedulingInfo;
import mvd.jester.info.TerminationInfo;
16
import mvd.jester.simulator.internals.ProcessorContext;
17
import mvd.jester.simulator.internals.TaskContextInterface;
18 19 20 21 22


/**
 * AbstractSimulator
 */
23
public abstract class AbstractSimulator implements SimulatorInterface, TypeInterface {
24 25 26

    protected final SystemSetup systemSetup;
    protected final Set<ProcessorContext> processors;
27
    protected TreeMultiset<TaskContextInterface> readyTasks;
28
    protected long hyperPeriod;
29 30 31

    AbstractSimulator(SystemSetup systemSetup) {
        this.systemSetup = systemSetup;
32
        this.readyTasks = TreeMultiset.create((t1, t2) -> new RateMonotonic().compare(t1, t2));
33 34 35 36
        processors = new HashSet<>();
        for (int i = 0; i < systemSetup.getNumberOfProcessors(); ++i) {
            processors.add(new ProcessorContext(i));
        }
37 38
        this.hyperPeriod = getHyperPeriod();

39 40
    }

41 42 43 44

    protected abstract boolean releaseTasks(long timeStep);

    @Override
45
    public SchedulingInfo runSimulation(PriorityManager priorityManager) {
46 47
        SchedulingInfo schedulingInfo = new SchedulingInfo(systemSetup.getParallelTaskRatio(),
                systemSetup.getUtilization());
48
        init(priorityManager);
49 50
        for (int t = 0; t < hyperPeriod; ++t) {
            if (!releaseTasks(t)) {
51
                throw new RuntimeException("Could not release a task. This should not happen!");
52 53
            }

54
            Set<ProcessorContext> sortedProcessors = sortProcessors(processors);
55 56 57 58 59 60 61 62 63 64 65 66 67 68

            for (ProcessorContext p : sortedProcessors) {
                for (TaskContextInterface tc : readyTasks) {
                    if (p.acceptTask(tc, t)) {
                        break;
                    }
                }

            }

            for (ProcessorContext p : processors) {
                Optional<TaskContextInterface> optionalTc = p.updateExecution(t);
                if (optionalTc.isPresent()) {
                    TaskContextInterface tc = optionalTc.get();
69 70 71
                    TerminationInfo terminationInfo =
                            new TerminationInfo(tc.getReleaseTime(), tc.getDeadline(), t);
                    schedulingInfo.addTerminationInfo(terminationInfo);
72
                    if (t >= tc.getDeadline()) {
73
                        EventPrinter.print("Time " + t + ": Task " + tc + " failed its deadline!");
74
                        schedulingInfo.setFailedTerminationInfo(terminationInfo);
75
                        return schedulingInfo;
76
                    }
77

78 79 80 81 82
                    readyTasks.remove(optionalTc.get());
                }
            }
        }

83
        return schedulingInfo;
84 85
    }

86
    private void init(PriorityManager priorityManager) {
87
        this.readyTasks = TreeMultiset.create((t1, t2) -> priorityManager.compare(t1, t2));
88 89 90
        for (ProcessorContext p : processors) {
            p.setJob(null);
        }
91
        this.hyperPeriod = getHyperPeriod();
92
    }
93

94 95
    private Set<ProcessorContext> sortProcessors(Set<ProcessorContext> processors) {
        Set<ProcessorContext> sortedProcessors = new TreeSet<>(new ProcessorComparator());
96

97 98 99 100 101
        processors.forEach(p -> sortedProcessors.add(p));

        return sortedProcessors;
    }

102 103
    private long getHyperPeriod() {
        return systemSetup.getTasks().stream().max(Comparator.comparing(Task::getPeriod)).get()
104
                .getPeriod() * 10;
105 106
    }

107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
    private class ProcessorComparator implements Comparator<ProcessorContext> {

        @Override
        public int compare(ProcessorContext p1, ProcessorContext p2) {
            if (!p1.getJob().isPresent()) {
                return -1;
            } else if (!p2.getJob().isPresent()) {
                return 1;
            } else {
                long p1Period = p1.getJob().get().getTaskContext().getTask().getPeriod();
                long p2Period = p2.getJob().get().getTaskContext().getTask().getPeriod();
                if (p1Period == p2Period) {
                    return 1;
                } else {
                    return (int) (p2.getJob().get().getTaskContext().getTask().getPeriod()
                            - p1.getJob().get().getTaskContext().getTask().getPeriod());
                }
            }
        }

    }
128
}