Commit b00f2d0e by Michael Schmid

Simulator now works

parent 36080fd3
......@@ -7,6 +7,8 @@ import mvd.jester.model.SystemManager;
import mvd.jester.model.SystemManager.DagTaskBuilder;
import mvd.jester.priority.RateMonotonic;
import mvd.jester.simulator.GlobalScheduler;
import mvd.jester.simulator.model.ExtendedSubtaskContext;
import mvd.jester.simulator.model.JobContext;
import mvd.jester.tests.AbstractTest;
import mvd.jester.tests.FonsecaNelis;
import mvd.jester.tests.MelaniButtazzo;
......@@ -25,7 +27,8 @@ public class App {
GlobalScheduler scheduler = new GlobalScheduler(new RateMonotonic(), 4);
DagTaskBuilder builder = new DagTaskBuilder().setNumberOfProcessors(4);
scheduler.schedule(builder.generateTaskSet(3), 10000);
scheduler.schedule(builder.generateTaskSet(1.0), 10000);
// {
// SystemManager manager = new SystemManager(8);
// DagTaskBuilder builder = new DagTaskBuilder();
......
......@@ -98,4 +98,9 @@ public class DagTask implements Task {
return numberOfThreads;
}
@Override
public String toString() {
return "(P=" + period + ", D=" + deadline + ")";
}
}
......@@ -27,4 +27,10 @@ public class Subtask {
public void setRelativeCompletionTime(long relativeCompletionTime) {
this.relativeCompletionTime = relativeCompletionTime;
}
@Override
public String toString() {
return "(C=" + wcet + ")";
}
}
......@@ -160,10 +160,10 @@ public class SystemManager {
private long numberOfProcessors = 8;
private long minimumWcet = 1;
private long maximumWcet = 100;
private long maxNumberOfBranches = 5;
private long depth = 2;
private long maxNumberOfBranches = 3; // TODO: Change back to 5
private long depth = 1; // TODO: Change back to 2
private long p_par = 80;
private long p_add = 20;
private long p_add = 10; // TODO: Change back to 20
public DagTaskBuilder() {
}
......@@ -252,8 +252,8 @@ public class SystemManager {
return new DagTask(jobDag, period, numberOfProcessors);
}
private Subtask join(final DirectedAcyclicGraph<Subtask, DefaultEdge> jobDag, final Subtask current,
final Set<Subtask> childs) {
private Subtask join(final DirectedAcyclicGraph<Subtask, DefaultEdge> jobDag,
final Subtask current, final Set<Subtask> childs) {
if (childs.size() > 0) {
final Subtask job = new Subtask(randomWcet());
jobDag.addVertex(job);
......
......@@ -4,37 +4,43 @@ import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import org.jgrapht.Graphs;
import mvd.jester.model.DagTask;
import mvd.jester.model.Subtask;
import mvd.jester.priority.PriorityManager;
import mvd.jester.simulator.events.*;
import mvd.jester.simulator.exceptions.DeadlineMissedException;
import mvd.jester.simulator.exceptions.SchedulingException;
import mvd.jester.simulator.model.ExtendedSubtaskContext;
import mvd.jester.simulator.model.JobContext;
import mvd.jester.simulator.model.ProcessorContext;
import mvd.jester.simulator.model.ProcessorContext.ProcessorComparator;
public class GlobalScheduler {
private final int nbProcessors;
private final PriorityManager priorityManager;
public GlobalScheduler(PriorityManager priorityManager, int nbProcessors) {
public GlobalScheduler(final PriorityManager priorityManager, final int nbProcessors) {
this.priorityManager = priorityManager;
this.nbProcessors = nbProcessors;
}
public void schedule(Set<DagTask> taskSet, long duration) {
SchedulingContext sc = new SchedulingContext(priorityManager, nbProcessors, duration);
public void schedule(final Set<DagTask> taskSet, final long duration) {
final SchedulingContext sc = new SchedulingContext(priorityManager, nbProcessors, duration);
taskSet.forEach(t -> sc.events.offer(new TaskReleasedEvent(0, t)));
while (!sc.events.isEmpty()) {
IEvent event = sc.events.poll();
final IEvent event = sc.events.poll();
updateExecution(sc, event.getTime());
handle(event, sc);
}
}
private void handle(IEvent event, SchedulingContext sc) {
private void handle(final IEvent event, final SchedulingContext sc) {
event.log();
switch (event.getType()) {
case SUBTASK_ACTIVATED:
......@@ -58,6 +64,9 @@ public class GlobalScheduler {
case JOB_ACTIVATED:
handleJobActivated((JobActivatedEvent) event, sc);
break;
case JOB_COMPLETED:
handleJobCompleted((JobCompletedEvent) event, sc);
break;
case TASK_RELEASED:
handleTaskReleased((TaskReleasedEvent) event, sc);
break;
......@@ -67,62 +76,78 @@ public class GlobalScheduler {
}
}
private void handleSubtaskActivated(SubtaskActivatedEvent event, SchedulingContext sc) {
Subtask subtask = event.getSubtask();
JobContext job = event.getJobContext();
private void handleJobCompleted(final JobCompletedEvent event, final SchedulingContext sc) {
if (event.getTime() > event.getJobContext().getDeadline()) {
throw new DeadlineMissedException(event.getJobContext() + " misses its deadline");
}
}
private void handleSubtaskActivated(final SubtaskActivatedEvent event,
final SchedulingContext sc) {
final Subtask subtask = event.getSubtask();
final JobContext job = event.getJobContext();
sc.waitingQueue.offer(new ExtendedSubtaskContext(job, subtask));
updateAdmission(sc, event.getTime());
}
private void handleSubtaskCheckCompleted(SubtaskCheckCompletedEvent event,
SchedulingContext sc) {
ProcessorContext processor = event.getProcessor();
if (processor.isIdle() || !processor.getSubtask().get().equals(event.getSubtaskContext())) {
private void handleSubtaskCheckCompleted(final SubtaskCheckCompletedEvent event,
final SchedulingContext sc) {
final ProcessorContext processor = event.getProcessor();
if (processor.isIdle()) {
throw new SchedulingException(
processor + " should execute " + event.getSubtaskContext());
}
Optional<ExtendedSubtaskContext> context = processor.getSubtask();
final Optional<ExtendedSubtaskContext> context = processor.getSubtask();
if (context.isPresent() && context.get().getRemainingExecutionTime() == 0) {
sc.events.offer(new SubtaskStoppedEvent(event.getTime(), context.get(), processor));
}
}
private void handleSubtaskCompleted(SubtaskCompletedEvent event, SchedulingContext sc) {
ExtendedSubtaskContext subtask = event.getSubtaskContext();
JobContext job = subtask.getJobContext();
private void handleSubtaskCompleted(final SubtaskCompletedEvent event,
final SchedulingContext sc) {
final ExtendedSubtaskContext subtask = event.getSubtaskContext();
final JobContext job = subtask.getJobContext();
DagTask task = subtask.getJobContext().getTask();
List<Subtask> successor = Graphs.successorListOf(task.getJobDag(), subtask.getSubtask());
job.registerFinishedSubtask(subtask);
final DagTask task = subtask.getJobContext().getTask();
final List<Subtask> successor =
Graphs.successorListOf(task.getJobDag(), subtask.getSubtask());
if (successor.isEmpty()) {
sc.events.offer(new JobCompletedEvent(event.getTime(), job));
updateAdmission(sc, event.getTime());
} else {
for (Subtask s : successor) {
final List<Subtask> finishedSubtasks = job.getFinishedSubtasks().stream()
.map(esc -> esc.getSubtask()).collect(Collectors.toList());
for (final Subtask s : successor) {
final List<Subtask> predecessors = Graphs.predecessorListOf(task.getJobDag(), s);
if (finishedSubtasks.containsAll(predecessors)) {
sc.events.offer(new SubtaskActivatedEvent(event.getTime(), job, s));
}
}
}
}
private void handleSubtaskPreempted(SubtaskPreemptedEvent event, SchedulingContext sc) {
ProcessorContext processor = event.getProcessor();
long time = event.getTime();
sc.events.offer(new SubtaskStoppedEvent(time, event.getNextSubtask(), processor));
sc.events.offer(new SubtaskStartedEvent(time, event.getSubtaskContext(), processor));
private void handleSubtaskPreempted(final SubtaskPreemptedEvent event,
final SchedulingContext sc) {
final ProcessorContext processor = event.getProcessor();
final long time = event.getTime();
sc.events.offer(new SubtaskStartedEvent(time, event.getNextSubtask(), processor));
sc.events.offer(new SubtaskStoppedEvent(time, event.getSubtaskContext(), processor));
}
private void handleSubtaskStarted(SubtaskStartedEvent event, SchedulingContext sc) {
long time = event.getTime();
ProcessorContext processor = event.getProcessor();
ExtendedSubtaskContext context = event.getSubtaskContext();
private void handleSubtaskStarted(final SubtaskStartedEvent event, final SchedulingContext sc) {
final long time = event.getTime();
final ProcessorContext processor = event.getProcessor();
final ExtendedSubtaskContext context = event.getSubtaskContext();
if (processor.accept(context, time)) {
sc.events.offer(new SubtaskCheckCompletedEvent(
time + context.getRemainingExecutionTime(), context, processor));
}
}
private void handleSubtaskStopped(SubtaskStoppedEvent event, SchedulingContext sc) {
ExtendedSubtaskContext context = event.getSubtaskContext();
ProcessorContext processor = event.getProcessor();
private void handleSubtaskStopped(final SubtaskStoppedEvent event, final SchedulingContext sc) {
final ExtendedSubtaskContext context = event.getSubtaskContext();
final ProcessorContext processor = event.getProcessor();
if (context.getRemainingExecutionTime() > 0) {
sc.waitingQueue.offer(context);
} else {
......@@ -131,30 +156,33 @@ public class GlobalScheduler {
processor.free();
}
private void handleJobActivated(JobActivatedEvent event, SchedulingContext sc) {
JobContext job = event.getJobContext();
private void handleJobActivated(final JobActivatedEvent event, final SchedulingContext sc) {
final JobContext job = event.getJobContext();
DagTask task = job.getTask();
long nextRelease = event.getTime() + task.getPeriod();
final DagTask task = job.getTask();
final long nextRelease = event.getTime() + task.getPeriod();
if (nextRelease < sc.duration) {
JobContext nextJob = new JobContext(task, nextRelease);
final JobContext nextJob = new JobContext(task, nextRelease);
sc.events.offer(new JobActivatedEvent(nextRelease, nextJob));
}
sc.events.offer(new SubtaskActivatedEvent(event.getTime(), job, job.getSource()));
}
private void handleTaskReleased(TaskReleasedEvent event, SchedulingContext sc) {
DagTask task = event.getTask();
long release = event.getTime();
JobContext job = new JobContext(task, release);
private void handleTaskReleased(final TaskReleasedEvent event, final SchedulingContext sc) {
final DagTask task = event.getTask();
final long release = event.getTime();
final JobContext job = new JobContext(task, release);
sc.events.offer(new JobActivatedEvent(release, job));
}
private void updateAdmission(SchedulingContext sc, long time) {
for (ProcessorContext processor : sc.processors) {
private void updateAdmission(final SchedulingContext sc, final long time) {
Set<ProcessorContext> sortedProcessors =
new TreeSet<>(new ProcessorComparator(priorityManager));
sortedProcessors.addAll(sc.processors);
for (final ProcessorContext processor : sortedProcessors) {
if (processor.canAccept(sc.waitingQueue.peek(), priorityManager)) {
ExtendedSubtaskContext context = sc.waitingQueue.poll();
final ExtendedSubtaskContext context = sc.waitingQueue.poll();
if (processor.isIdle()) {
sc.events.offer(new SubtaskStartedEvent(time, context, processor));
} else {
......@@ -165,8 +193,8 @@ public class GlobalScheduler {
}
}
private void updateExecution(SchedulingContext sc, long time) {
for (ProcessorContext processor : sc.processors) {
private void updateExecution(final SchedulingContext sc, final long time) {
for (final ProcessorContext processor : sc.processors) {
processor.update(time);
}
}
......@@ -178,8 +206,8 @@ public class GlobalScheduler {
private final WaitQueue waitingQueue;
private final long duration;
private SchedulingContext(PriorityManager priorityManager, int nbProcessors,
long duration) {
private SchedulingContext(final PriorityManager priorityManager, final int nbProcessors,
final long duration) {
this.events = new EventQueue(priorityManager);
this.waitingQueue = new WaitQueue(priorityManager);
this.processors = new HashSet<>();
......
......@@ -3,7 +3,7 @@ package mvd.jester.simulator.events;
import mvd.jester.simulator.model.ExtendedSubtaskContext;
import mvd.jester.simulator.model.JobContext;
public abstract class AbstractContextEvent extends AbstractSubtaskEvent implements ISubtaskEvent {
public abstract class AbstractContextEvent extends AbstractSubtaskEvent {
private final ExtendedSubtaskContext subtask;
......@@ -13,7 +13,7 @@ public abstract class AbstractContextEvent extends AbstractSubtaskEvent implemen
this.subtask = subtask;
}
@Override
// @Override
public ExtendedSubtaskContext getSubtaskContext() {
return subtask;
}
......
......@@ -2,7 +2,7 @@ package mvd.jester.simulator.events;
import mvd.jester.simulator.model.JobContext;
public abstract class AbstractSubtaskEvent extends AbstractEvent {
public abstract class AbstractSubtaskEvent extends AbstractEvent implements ISubtaskEvent {
private final JobContext jobContext;
......
......@@ -5,7 +5,7 @@ import mvd.jester.simulator.model.JobContext;
public interface ISubtaskEvent extends IEvent {
public ExtendedSubtaskContext getSubtaskContext();
// public ExtendedSubtaskContext getSubtaskContext();
public JobContext getJobContext();
......
......@@ -3,25 +3,15 @@ package mvd.jester.simulator.events;
import mvd.jester.model.Subtask;
import mvd.jester.simulator.model.JobContext;
public class SubtaskActivatedEvent extends AbstractEvent {
public class SubtaskActivatedEvent extends AbstractSubtaskEvent {
private final JobContext job;
private final Subtask subtask;
public SubtaskActivatedEvent(final long time, final JobContext job, final Subtask subtask) {
super(EventType.SUBTASK_ACTIVATED, time);
this.job = job;
super(EventType.SUBTASK_ACTIVATED, time, job);
this.subtask = subtask;
}
/**
* @return the job
*/
public JobContext getJobContext() {
return job;
}
/**
* @return the subtask
*/
......@@ -31,7 +21,7 @@ public class SubtaskActivatedEvent extends AbstractEvent {
@Override
protected String getLoggingMessage() {
return "Subtask " + getSubtask() + " released";
return "Subtask " + getSubtask() + " of task " + getJobContext().getTask() + " released";
}
}
......@@ -10,7 +10,8 @@ public class SubtaskCompletedEvent extends AbstractContextEvent {
@Override
protected String getLoggingMessage() {
return "Subtask " + getSubtaskContext() + " completed";
return "Subtask " + getSubtaskContext() + " of task " + getJobContext().getTask()
+ " completed";
}
}
......@@ -16,6 +16,6 @@ public class TaskReleasedEvent extends AbstractEvent {
@Override
public String getLoggingMessage() {
return "task " + getTask() + " started";
return "Task " + getTask() + " started";
}
}
......@@ -15,4 +15,9 @@ public class ExtendedSubtaskContext extends SubtaskContext {
public JobContext getJobContext() {
return jobContext;
}
@Override
public String toString() {
return getSubtask() + " of task " + getJobContext().getTask();
}
}
package mvd.jester.simulator.model;
import java.util.HashSet;
import java.util.Set;
import org.jgrapht.experimental.dag.DirectedAcyclicGraph;
import org.jgrapht.graph.DefaultEdge;
import mvd.jester.model.DagTask;
......@@ -11,6 +13,7 @@ public class JobContext {
private final long releaseTime;
private final long deadline;
private final Subtask source;
private final Set<ExtendedSubtaskContext> finishedSubtasks;
// private long activeThreads; // TODO: Use threads
public JobContext(DagTask task, long releaseTime) {
......@@ -18,6 +21,7 @@ public class JobContext {
this.releaseTime = releaseTime;
this.deadline = releaseTime + task.getDeadline();
this.source = findSource(task);
this.finishedSubtasks = new HashSet<>();
// this.activeThreads = task.getNumberOfThreads();
}
......@@ -59,8 +63,26 @@ public class JobContext {
return releaseTime;
}
/**
* @return the finishedSubtasks
*/
public Set<ExtendedSubtaskContext> getFinishedSubtasks() {
return finishedSubtasks;
}
public void registerFinishedSubtask(ExtendedSubtaskContext subtaskContext) {
if (!finishedSubtasks.add(subtaskContext)) {
throw new RuntimeException(
"Subtask could not be added to finished subtask which means it was executed twice!");
}
}
public boolean checkRemainingThreads() {
return false;
return true; // TODO: implement check in future
}
public String toString() {
return "of task " + getTask();
}
}
package mvd.jester.simulator.model;
import java.util.Comparator;
import java.util.Optional;
import mvd.jester.priority.PriorityManager;
import mvd.jester.simulator.exceptions.DeadlineMissedException;
......@@ -96,4 +97,28 @@ public class ProcessorContext {
return "Processor " + processorId;
}
public static class ProcessorComparator implements Comparator<ProcessorContext> {
private final PriorityManager priorityManager;
public ProcessorComparator(PriorityManager priorityManager) {
this.priorityManager = priorityManager;
}
@Override
public int compare(ProcessorContext p1, ProcessorContext p2) {
if (!p1.getSubtask().isPresent()) {
return -1;
} else if (!p2.getSubtask().isPresent()) {
return 1;
} else {
// Sort in reverse
return priorityManager.compare(p2.currentSubtask.get().getJobContext(),
p1.currentSubtask.get().getJobContext());
}
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment