diff --git a/script.py b/script.py index 6506fe1..4ae9b1f 100755 --- a/script.py +++ b/script.py @@ -19,22 +19,25 @@ def main(argv): configuration.cycles_per_ms = 1 - configuration.duration = 20 * configuration.cycles_per_ms + configuration.duration = 100 * configuration.cycles_per_ms # Add tasks: configuration.add_task(name="T1", identifier=1, period=7, activation_date=0, wcet=3, deadline=7) configuration.add_task(name="T2", identifier=2, period=12, activation_date=0, wcet=3, deadline=8) + configuration.add_task(name="T4", identifier=4, period=15, + activation_date=0, wcet=5, deadline=14) configuration.add_task(name="T3", identifier=3, period=20, activation_date=0, wcet=5, deadline=9) # Add a processor: - configuration.add_processor(name="CPU 1", identifier=1) + configuration.add_processor(name="CPU 1", identifier=1, cs_overhead=1) + configuration.add_processor(name="CPU 2", identifier=2, cs_overhead=1) - # Add a scheduler: - #configuration.scheduler_info.filename = "../simso/schedulers/RM.py" - configuration.scheduler_info.clas = "simso.schedulers.RM" + # Add a scheduler: + #configuration.scheduler_info.filename = "../simso/schedulers/RM.py" + configuration.scheduler_info.clas = "simso.schedulers.RM" # Check the config before trying to run it. configuration.check_all() diff --git a/script_proba.py b/script_proba.py index 1251b99..4d26e25 100644 --- a/script_proba.py +++ b/script_proba.py @@ -18,23 +18,27 @@ def main(argv): configuration = Configuration() configuration.cycles_per_ms = 1 - + configuration.etm = "pwcet" configuration.duration = 100 * configuration.cycles_per_ms # Add tasks: configuration.add_task(name="T1", identifier=1, - activation_date=0, pwcet=[(2,0.5), (4,0.5)],pmit=[(5,0.2),(6,0.8)], deadline=6, task_type = "Probabilistic",abort_on_miss=True) + activation_date=0, pwcet=[(2, 0.5), (4, 0.5)], pmit=[(5, 0.2), (6, 0.8)], deadline=5, task_type="Probabilistic", abort_on_miss=True) configuration.add_task(name="T2", identifier=2, - activation_date=0, pwcet=[(3,0.5),(4,0.5)],pmit=[(5,0.5), (7, 0.5)], deadline=7, task_type = "Probabilistic",abort_on_miss=True) + activation_date=0, pwcet=[(3, 0.5), (4, 0.5)], pmit=[(7, 0.5), (8, 0.5)], deadline=7, task_type="Probabilistic", abort_on_miss=True) + + configuration.add_task(name="T3", identifier=3, + activation_date=0, pwcet=[(3, 0.5), (4, 0.5)], pmit=[(8, 0.5), (9, 0.5)], deadline=8, task_type="Probabilistic", abort_on_miss=True) # Add a processor: configuration.add_processor(name="CPU 1", identifier=1) + configuration.add_processor(name="CPU 2", identifier=2) # Add a scheduler: - configuration.scheduler_info.filename = "./simso/schedulers/DM_mono.py" + configuration.scheduler_info.filename = "./simso/schedulers/RM.py" # Check the config before trying to run it. configuration.check_all() @@ -49,4 +53,5 @@ def main(argv): for log in model.logs: print(log) + main(sys.argv) diff --git a/simso/core/EventQueue.py b/simso/core/EventQueue.py new file mode 100644 index 0000000..24816e5 --- /dev/null +++ b/simso/core/EventQueue.py @@ -0,0 +1,31 @@ +from collections import deque +from simpy import Event + + +class EventQueue: + """ + Class for events happening in a processor + """ + + def __init__(self, env): + self._env = env + self._evt_deque = deque([]) + self.item_ready_event = self._env.event() + + def append(self, item): + self._evt_deque.append(item) + if not self.item_ready_event.triggered: + self.item_ready_event.succeed() + + def clear_events(self, event_type): + self._evt_deque = deque( + [e for e in self._evt_deque if e[0] != event_type]) + + def popleft(self): + return self._evt_deque.popleft() + + def is_empty(self): + return not bool(self._evt_deque) + + def get_deque(self): + return self._evt_deque diff --git a/simso/core/Processor.py b/simso/core/Processor.py index 82a5dc5..7ff4e0d 100644 --- a/simso/core/Processor.py +++ b/simso/core/Processor.py @@ -6,6 +6,7 @@ from simpy import Process from simso.core.ProcEvent import ProcRunEvent, ProcIdleEvent, \ ProcOverheadEvent, ProcCxtSaveEvent, ProcCxtLoadEvent from simso.core.Monitor import Monitor +from simso.core.EventQueue import EventQueue RESCHED = 1 ACTIVATE = 2 @@ -61,7 +62,7 @@ class Processor: self.name = proc_info.name self._running = None self.was_running = None - self._evts = deque([]) + self._evts = EventQueue(model) self.sched = model.scheduler self.monitor = Monitor(env=model, name="Monitor" + proc_info.name) self._caches = [] @@ -86,10 +87,12 @@ class Processor: def terminate(self, job): self._evts.append((TERMINATE, job)) - self._running = None + if self._running == job: + self._running = None def preempt(self, job=None): - self._evts = deque([e for e in self._evts if e[0] != PREEMPT]) + # self._evts = deque([e for e in self._evts if e[0] != PREEMPT]) + self._evts.clear_events(PREEMPT) self._evts.append((PREEMPT,)) self._running = job @@ -147,8 +150,9 @@ class Processor: def run(self): while True: - if not self._evts: + if self._evts.is_empty(): job = self._running + self._evts.item_ready_event = self._model.event() if job: yield job.context_ok self.monitor.observe(ProcCxtLoadEvent()) @@ -162,24 +166,19 @@ class Processor: self.monitor.observe(ProcIdleEvent()) # Wait event. - first_yield = True - while not self._evts: - if first_yield: - yield self._model.timeout(0) - first_yield = False - else: - yield self._model.timeout(1) - if job and job.is_active(): + yield self._evts.item_ready_event + if job and job.process.is_alive: job.process.interrupt() self.monitor.observe(ProcCxtSaveEvent()) # overhead save context yield self._model.timeout(self.cs_overhead) self.monitor.observe(ProcCxtSaveEvent(terminated=True)) job.context_ok = self._model.event() + job.context_ok.succeed() evt = self._evts.popleft() if evt[0] == RESCHED: - if any(x[0] != RESCHED for x in self._evts): + if any(x[0] != RESCHED for x in self._evts.get_deque()): self._evts.append(evt) continue @@ -206,8 +205,8 @@ class Processor: elif evt[0] == RESCHED: self.monitor.observe(ProcOverheadEvent("Scheduling")) self.sched.monitor_begin_schedule(self) - while not self.sched.get_lock: - yield self._model.timeout(1) + lock_request = self.sched.get_lock() + yield lock_request decisions = self.sched.schedule(self) # overhead scheduling yield self._model.timeout(self.sched.overhead) @@ -243,5 +242,5 @@ class Processor: assert len(set(running_tasks)) == len(running_tasks), \ "Try to run a job on 2 processors simultaneously!" - self.sched.release_lock() + self.sched.release_lock(lock_request) self.sched.monitor_end_schedule(self) diff --git a/simso/core/Scheduler.py b/simso/core/Scheduler.py index faa638e..884c7bb 100644 --- a/simso/core/Scheduler.py +++ b/simso/core/Scheduler.py @@ -6,6 +6,7 @@ import importlib import pkgutil import inspect +from simpy import Resource from simso.core.Monitor import Monitor from simso.core.SchedulerEvent import SchedulerBeginScheduleEvent, \ SchedulerEndScheduleEvent, SchedulerBeginActivateEvent, \ @@ -141,7 +142,7 @@ class Scheduler(object): self.sim = sim self.processors = [] self.task_list = [] - self._lock = False + self._lock = Resource(sim) self.overhead = scheduler_info.overhead self.overhead_activate = scheduler_info.overhead_activate self.overhead_terminate = scheduler_info.overhead_terminate @@ -213,17 +214,13 @@ class Scheduler(object): Implement a lock mechanism. Override it to remove the lock or change its behavior. """ - if not self._lock: - self._lock = True - else: - return False - return True + return self._lock.request() - def release_lock(self): + def release_lock(self, request): """ Release the lock. Goes in pair with :meth:`get_lock`. """ - self._lock = False + self._lock.release(request) def monitor_begin_schedule(self, cpu): self.monitor.observe(SchedulerBeginScheduleEvent(cpu)) diff --git a/simso/core/Task.py b/simso/core/Task.py index 61bb8ed..948fcda 100644 --- a/simso/core/Task.py +++ b/simso/core/Task.py @@ -266,7 +266,7 @@ class GenericTask: self._activations_fifo.popleft() if len(self._activations_fifo) > 0: self.job = self._activations_fifo[0] - self._sim.process(self.job.activate_job()) + self.job.process = self._sim.process(self.job.activate_job()) def _job_killer(self, job): if job.end_date is None and job.computation_time < job.wcet: