Пример #1
0
    def schedule(self, cpu):
        if len(self.ready_list) > 0:
            # Explication sur la key:
            # En priorité, on met tous les processeurs libres au début.
            # Ensuite, on trie tout par ordre décroissant de la deadline.
            # Et on départage en préférant le processeur "cpu".
            key = lambda x: (1 if (not x.running) or (not self.pseudo_job[x])
                             else 0, self.pseudo_job[x].cmp_key()
                             if x.running and self.pseudo_job[x] else None, 1
                             if x is cpu else 0)
            cpu_min = max(self.processors, key=key)

            pjob = min(self.ready_list, key=lambda x: x.cmp_key())

            if (cpu_min.running is None or self.pseudo_job[cpu_min] is None
                    or self.pseudo_job[cpu_min].cmp_key() > pjob.cmp_key()):
                self.ready_list.remove(pjob)
                if cpu_min.running and self.pseudo_job[cpu_min]:
                    self.ready_list.append(self.pseudo_job[cpu_min])
                self.pseudo_job[cpu_min] = pjob

                timer = Timer(self.sim,
                              EPDF.pseudo_terminate, (self, pjob),
                              pjob.seq * self.quantum -
                              pjob.job.computation_time,
                              cpu=cpu_min,
                              in_ms=True)
                timer.start()
                self.timers.append(timer)

                return (pjob.job, cpu_min)
        elif self.pseudo_job[cpu] is None:
            return (None, cpu)
Пример #2
0
    def conf(self, next_deadline):
        if next_deadline > self.next_deadline:
            self.next_deadline = next_deadline
            self.migrating_task1, self.migrating_task2 = \
                self.migrating_task2, self.migrating_task1
            if self.migrating_task1:
                time_a = ceil(
                    (next_deadline - self.sim.now()) * self.migrating_task1[1])
                self.timer_a = Timer(self.sim,
                                     Modified_EDF.on_end_migrating1, (self, ),
                                     time_a,
                                     cpu=self.processors[0],
                                     in_ms=False)
                self.timer_a.start()

            self.migrating_job2 = None
            if self.migrating_task2:
                time_b = int((next_deadline - self.sim.now()) *
                             (1 - self.migrating_task2[1]))
                self.timer_b = Timer(self.sim,
                                     Modified_EDF.on_start_migrating2,
                                     (self, ),
                                     time_b,
                                     cpu=self.processors[0],
                                     in_ms=False)
                self.timer_b.start()
                self.processors[0].resched()

        if self.migrating_task1:
            self.migrating_job1 = self.migrating_task1[0].job
            self.processors[0].resched()
        else:
            self.migrating_job1 = None
Пример #3
0
class RR(Scheduler):
    def init(self):
        self.ready_list = Queue()
        self.running_job = None
        self.quantum = 1 # ms
        self.timer = Timer(self.sim, RR.reschedule,
                          (self, self.processors[0]), self.quantum, one_shot=False,
                          cpu=self.processors[0])
        self.timer.start()
        
    def reschedule(self, cpu):
        if not self.ready_list.empty():
            cpu.resched()

    def on_activate(self, job):
        self.ready_list.put(job)
        job.cpu.resched()

    def on_terminated(self, job):
        self.running_job = None
        job.cpu.resched()

    def schedule(self, cpu):
        if not self.ready_list.empty():
            job = self.ready_list.get()
            if self.running_job is not None:
                self.ready_list.put(self.running_job)
            self.running_job = job
        else:
            job = self.running_job
        return (job, cpu)
Пример #4
0
    def schedule(self, cpu):
        """
        Schedule main method.
        """
        self.waiting_schedule = False
        # At the end of the interval:
        if self.sim.now() >= self.t_f:
            self.init_interval()

            # Stop current timers.
            for job, timer in self.timers.items():
                timer.stop()
            self.timers = {}

        # Set timers to stop the jobs that will run.
        for z, proc in enumerate(self.processors):
            l = self.allocations[z][1]
            if l and l[0][0] not in self.timers:
                timer = Timer(self.sim,
                              BF.end_event, (self, z, l[0][0]),
                              l[0][1],
                              cpu=proc,
                              in_ms=False)
                timer.start()
                self.timers[l[0][0]] = timer

        # Schedule the activated tasks on each processor.
        decisions = []
        for z, proc in enumerate(self.processors):
            l = self.allocations[z][1]
            if not l[0][0] or l[0][0].is_active():
                decisions.append((l[0][0] if l else None, proc))

        return decisions
Пример #5
0
    def schedule(self):
        """
        Schedule this proper sub-system.
        """
        self.to_reschedule = False
        decision = []

        self.virtual = []
        jobs = select_jobs(self.root, self.virtual)

        wakeup_delay = min(self.virtual, key=lambda s: s.budget).budget
        if wakeup_delay > 0:
            self.timer = Timer(self.sim,
                               ProperSubsystem.virtual_event,
                               (self, self.processors[0]),
                               wakeup_delay,
                               cpu=self.processors[0],
                               in_ms=False)
            self.timer.start()

        cpus = []
        for cpu in self.processors:
            if cpu.running in jobs:
                jobs.remove(cpu.running)
            else:
                cpus.append(cpu)

        for cpu in cpus:
            if jobs:
                decision.append((jobs.pop(), cpu))
            else:
                decision.append((None, cpu))

        return decision
Пример #6
0
    def schedule(self, cpu):
        decisions = []
        if self.ready_list:
            # Sort according to the laxity.
            self.ready_list.sort(key=lambda x: (x.laxity, x.absolute_deadline))

            # m : Nombre de processeurs.
            m = len(self.processors)

            # Available processors:
            l = (proc for proc in self.processors
                 if proc.running not in self.ready_list[:m])

            if len(self.ready_list) > m:
                ta = self.ready_list[m - 1]
                dmin = self.ready_list[m].absolute_deadline * \
                    self.sim.cycles_per_ms - self.sim.now()

                if self.timer:
                    self.timer.stop()
                self.timer = Timer(self.sim,
                                   MLLF.update, (self, self.processors[0]),
                                   dmin - ta.laxity,
                                   one_shot=True,
                                   cpu=self.processors[0])
                self.timer.start()

            # The first m jobs should be running:
            for job in self.ready_list[:m]:
                if not job.is_running():
                    proc = next(l)
                    decisions.append((job, proc))

        return decisions
Пример #7
0
    def conf(self, next_deadline):
        if next_deadline > self.next_deadline:
            self.next_deadline = next_deadline
            self.migrating_task1, self.migrating_task2 = self.migrating_task2, self.migrating_task1
            if self.migrating_task1:
                time_a = ceil((next_deadline - self.sim.now()) * self.migrating_task1[1])
                self.timer_a = Timer(
                    self.sim, Modified_EDF.on_end_migrating1, (self,), time_a, cpu=self.processors[0], in_ms=False
                )
                self.timer_a.start()

            self.migrating_job2 = None
            if self.migrating_task2:
                time_b = int((next_deadline - self.sim.now()) * (1 - self.migrating_task2[1]))
                self.timer_b = Timer(
                    self.sim, Modified_EDF.on_start_migrating2, (self,), time_b, cpu=self.processors[0], in_ms=False
                )
                self.timer_b.start()
                self.processors[0].resched()

        if self.migrating_task1:
            self.migrating_job1 = self.migrating_task1[0].job
            self.processors[0].resched()
        else:
            self.migrating_job1 = None
Пример #8
0
    def schedule(self, cpu):
        if len(self.ready_list) > 0:
            # Explication sur la key:
            # En priorité, on met tous les processeurs libres au début.
            # Ensuite, on trie tout par ordre décroissant de la deadline.
            # Et on départage en préférant le processeur "cpu".
            key = lambda x: (
                1 if (not x.running) or (not self.pseudo_job[x]) else 0,
                self.pseudo_job[x].cmp_key() if x.running and
                self.pseudo_job[x] else None,
                1 if x is cpu else 0
            )
            cpu_min = max(self.processors, key=key)

            pjob = min(self.ready_list, key=lambda x: x.cmp_key())

            if (cpu_min.running is None or
                    self.pseudo_job[cpu_min] is None or
                    self.pseudo_job[cpu_min].cmp_key() > pjob.cmp_key()):
                self.ready_list.remove(pjob)
                if cpu_min.running and self.pseudo_job[cpu_min]:
                    self.ready_list.append(self.pseudo_job[cpu_min])
                self.pseudo_job[cpu_min] = pjob

                timer = Timer(
                    self.sim, EPDF.pseudo_terminate, (self, pjob),
                    pjob.seq * self.quantum - pjob.job.computation_time,
                    cpu=cpu_min, in_ms=True)
                timer.start()
                self.timers.append(timer)

                return (pjob.job, cpu_min)
        elif self.pseudo_job[cpu] is None:
            return (None, cpu)
Пример #9
0
    def schedule(self, cpu):
        """
        Take the scheduling decisions.
        """
        self.waiting_schedule = False
        decisions = []
        self.h_c = [(d, t) for d, t in self.h_c if t.job.is_active()]
        heapify(self.h_c)

        if self.sim.now() == self.t_f:
            decisions = self.init_tl_plane()
        else:
            for task in self.activations:
                decisions += self.handle_evt_a(task)
            if self.evt_bc:
                decisions += self.handle_evt_bc()

        self.activations = []
        self.evt_bc = False

        if self.h_b:
            t_next = self.h_b[0][0]
            if self.h_c:
                t_next = min(t_next, self.h_c[0][0])

            self.timer = Timer(self.sim, LRE_TL.event_bc, (self,),
                               t_next - self.sim.now(),
                               cpu=self.processors[0], in_ms=False)
        else:
            self.timer = Timer(self.sim, LRE_TL.reschedule, (self,),
                               self.t_f - self.sim.now(),
                               cpu=self.processors[0], in_ms=False)
        self.timer.start()

        return decisions
Пример #10
0
    def schedule(self, cpu):
        """
        Schedule main method.
        """
        self.waiting_schedule = False
        # At the end of the interval:
        if self.sim.now() >= self.t_f:
            self.init_interval()

            # Stop current timers.
            for job, timer in self.timers.items():
                timer.stop()
            self.timers = {}

        # Set timers to stop the jobs that will run.
        for z, proc in enumerate(self.processors):
            l = self.allocations[z][1]
            if l and l[0][0] not in self.timers:
                timer = Timer(self.sim, BF.end_event,
                              (self, z, l[0][0]), l[0][1],
                              cpu=proc, in_ms=False)
                timer.start()
                self.timers[l[0][0]] = timer

        # Schedule the activated tasks on each processor.
        decisions = []
        for z, proc in enumerate(self.processors):
            l = self.allocations[z][1]
            if not l[0][0] or l[0][0].is_active():
                decisions.append((l[0][0] if l else None, proc))

        return decisions
Пример #11
0
 def add_timer(self, wakeup_delay, CPU):
     if self.dummy_timer:
         self.dummy_timer.stop()
         
     self.dummy_timer = Timer(self.sim, ProperSubsystem.end_dummy,
                        (self, CPU), wakeup_delay,
                        cpu=CPU, in_ms=False)
     self.dummy_timer.start()
Пример #12
0
 def init(self):
     self.ready_list = []
     self.timer = Timer(self.sim,
                        LLF.update, (self, self.processors[0]),
                        1,
                        one_shot=False,
                        cpu=self.processors[0],
                        overhead=.001)
     self.timer.start()
Пример #13
0
 def init(self):
     self.ready_list = []
     self.delay = 2
     self.timer = Timer(self.sim,
                        RR.end_event, (self, self.processors[0]),
                        self.delay,
                        cpu=self.processors[0],
                        in_ms=True)
     self.interupt = False
Пример #14
0
class MLLF(Scheduler):
    """Modified Least Laxity First"""
    def init(self):
        self.ready_list = []
        self.timer = None

    def compute_laxity(self, cpu):
        if self.ready_list:
            for job in self.ready_list:
                job.laxity = (job.absolute_deadline - job.ret) * \
                    self.sim.cycles_per_ms - self.sim.now()
            cpu.resched()

    def on_activate(self, job):
        self.ready_list.append(job)
        self.compute_laxity(job.cpu)

    def on_terminated(self, job):
        self.ready_list.remove(job)
        self.compute_laxity(job.cpu)

    def schedule(self, cpu):
        decisions = []
        if self.ready_list:
            # Sort according to the laxity.
            self.ready_list.sort(
                key=lambda x: (x.laxity, x.absolute_deadline))

            # m : Nombre de processeurs.
            m = len(self.processors)

            # Available processors:
            l = (proc for proc in self.processors
                 if proc.running not in self.ready_list[:m])

            if len(self.ready_list) > m:
                ta = self.ready_list[m - 1]
                dmin = self.ready_list[m].absolute_deadline * \
                    self.sim.cycles_per_ms - self.sim.now()

                if self.timer:
                    self.timer.stop()
                self.timer = Timer(
                    self.sim, MLLF.compute_laxity,
                    (self, self.processors[0]), dmin - ta.laxity,
                    one_shot=True,
                    cpu=self.processors[0])
                self.timer.start()

            # The first m jobs should be running:
            for job in self.ready_list[:m]:
                if not job.is_running():
                    proc = next(l)
                    decisions.append((job, proc))

        return decisions
Пример #15
0
    def add_timer(self, wakeup_delay, CPU):
        if self.dummy_timer2:
            self.dummy_timer2.stop()

        self.dummy_timer2 = Timer(self.sim,
                                  ProperSubsystem.dummy_activated, (self, CPU),
                                  wakeup_delay,
                                  cpu=CPU,
                                  in_ms=False)
        self.dummy_timer2.start()
Пример #16
0
class EDF_modified(Scheduler):
    """
    An EDF mono-processor scheduler modified to accept migrating jobs.
    A migrating job has an infinite priority.
    """
    def init(self):
        self.ready_list = []
        self.migrating_job = None

    def _resched(self):
        self.processors[0].resched()

    def on_activate(self, job):
        self.ready_list.append(job)
        self._resched()

    def on_terminated(self, job):
        if job is self.migrating_job:
            self.migrating_job = None
        elif job in self.ready_list:
            self.ready_list.remove(job)
        self._resched()

    def accept_migrating_job(self, i, job, budget):
        self.migrating_job = job
        job.task.cpu = self.processors[0]

        # Set timer for end.
        self.timer = Timer(self.sim,
                           EDF_modified.end_migrating_job, (self, i),
                           budget,
                           cpu=self.processors[0],
                           in_ms=False)
        self.timer.start()

        self._resched()

    def end_migrating_job(self, i):
        self.processors[0].resched()
        if self.migrating_job and i < len(
                migrating_tasks[self.migrating_job.task]) - 1:
            ncpu, nbudget = migrating_tasks[self.migrating_job.task][i + 1]
            sched = map_cpu_sched[ncpu]
            sched.accept_migrating_job(i + 1, self.migrating_job, nbudget)
        self.migrating_job = None

    def schedule(self, cpu):
        if self.migrating_job:
            job = self.migrating_job
        elif self.ready_list:
            job = min(self.ready_list, key=lambda x: x.absolute_deadline)
        else:
            job = None

        return (job, cpu)
Пример #17
0
 def init(self):
     self.ready_list = []
     """
     However, LSTR
     scheduling algorithm operates on every basic time unit. Here, we consider the basic
     time unit of 1 (ms).
     """
     self.timer = Timer(self.sim,
                        LSTR.virtual_event, (self, self.processors[0]),
                        1,
                        one_shot=False)
     self.timer.start()
Пример #18
0
    def add_timer(self, wakeup_delay, CPU):

        #self.sim.logger.log("add_timer to {}".format(wakeup_delay))
        if self.dummy_timer:
            self.dummy_timer.stop()

        self.dummy_timer = Timer(self.sim,
                                 ProperSubsystem.end_dummy, (self, CPU),
                                 wakeup_delay,
                                 cpu=CPU,
                                 in_ms=False)
        self.dummy_timer.start()
Пример #19
0
class MLLF(Scheduler):
    """Modified Least Laxity First"""
    def init(self):
        self.ready_list = []
        self.timer = None

    def update(self, cpu):
        if self.ready_list:
            cpu.resched()

    def on_activate(self, job):
        self.ready_list.append(job)
        job.cpu.resched()

    def on_terminated(self, job):
        self.ready_list.remove(job)
        self.update(job.cpu)

    def schedule(self, cpu):
        decisions = []
        if self.ready_list:
            # Sort according to the laxity.
            self.ready_list.sort(key=lambda x: (x.laxity, x.absolute_deadline))

            # m : Nombre de processeurs.
            m = len(self.processors)

            # Available processors:
            l = (proc for proc in self.processors
                 if proc.running not in self.ready_list[:m])

            if len(self.ready_list) > m:
                ta = self.ready_list[m - 1]
                dmin = self.ready_list[m].absolute_deadline * \
                    self.sim.cycles_per_ms - self.sim.now()

                if self.timer:
                    self.timer.stop()
                self.timer = Timer(self.sim,
                                   MLLF.update, (self, self.processors[0]),
                                   dmin - ta.laxity,
                                   one_shot=True,
                                   cpu=self.processors[0])
                self.timer.start()

            # The first m jobs should be running:
            for job in self.ready_list[:m]:
                if not job.is_running():
                    proc = next(l)
                    decisions.append((job, proc))

        return decisions
Пример #20
0
class EDF_modified(Scheduler):
    """
    An EDF mono-processor scheduler modified to accept migrating jobs.
    A migrating job has an infinite priority.
    """
    def init(self):
        self.ready_list = []
        self.migrating_job = None

    def _resched(self):
        self.processors[0].resched()

    def on_activate(self, job):
        self.ready_list.append(job)
        self._resched()

    def on_terminated(self, job):
        if job is self.migrating_job:
            self.migrating_job = None
        elif job in self.ready_list:
            self.ready_list.remove(job)
        self._resched()

    def accept_migrating_job(self, i, job, budget):
        self.migrating_job = job
        job.task.cpu = self.processors[0]

        # Set timer for end.
        self.timer = Timer(self.sim, EDF_modified.end_migrating_job,
                           (self, i), budget, cpu=self.processors[0],
                           in_ms=False)
        self.timer.start()

        self._resched()

    def end_migrating_job(self, i):
        self.processors[0].resched()
        if self.migrating_job and i < len(migrating_tasks[self.migrating_job.task]) - 1:
            ncpu, nbudget = migrating_tasks[self.migrating_job.task][i + 1]
            sched = map_cpu_sched[ncpu]
            sched.accept_migrating_job(i + 1, self.migrating_job, nbudget)
        self.migrating_job = None

    def schedule(self, cpu):
        if self.migrating_job:
            job = self.migrating_job
        elif self.ready_list:
            job = min(self.ready_list, key=lambda x: x.absolute_deadline)
        else:
            job = None

        return (job, cpu)
Пример #21
0
    def accept_migrating_job(self, i, job, budget):
        self.migrating_job = job
        job.task.cpu = self.processors[0]

        # Set timer for end.
        self.timer = Timer(self.sim,
                           EDF_modified.end_migrating_job, (self, i),
                           budget,
                           cpu=self.processors[0],
                           in_ms=False)
        self.timer.start()

        self._resched()
Пример #22
0
    def init(self):

        self.ready_lists = [[] for _ in range(self.NUM_QUEUE)]
        self.job_timer = None
        self.timers = [self.create_timer(i) for i in range(self.NUM_QUEUE - 1)]
        self.prior_table = {}
        self.boost_timer = Timer(
            self.sim,
            MLFQ.boost_event, (self, self.processors[0]),
            self.BOOST_DELAY,
            one_shot=False,
            cpu=self.processors[0],
            in_ms=True)
        self.boost_timer.start()
        self.interupt = False
Пример #23
0
    def schedule(self, cpu):
        decisions = []
        if self.ready_list:
            # Sort according to the laxity.
            self.ready_list.sort(
                key=lambda x: (x.laxity, x.absolute_deadline))

            # m : Nombre de processeurs.
            m = len(self.processors)

            # Available processors:
            l = (proc for proc in self.processors
                 if proc.running not in self.ready_list[:m])

            if len(self.ready_list) > m:
                ta = self.ready_list[m - 1]
                dmin = self.ready_list[m].absolute_deadline * \
                    self.sim.cycles_per_ms - self.sim.now()

                if self.timer:
                    self.timer.stop()
                self.timer = Timer(
                    self.sim, MLLF.compute_laxity,
                    (self, self.processors[0]), dmin - ta.laxity,
                    one_shot=True,
                    cpu=self.processors[0])
                self.timer.start()

            # The first m jobs should be running:
            for job in self.ready_list[:m]:
                if not job.is_running():
                    proc = next(l)
                    decisions.append((job, proc))

        return decisions
Пример #24
0
 def create_timer(self, i):
     return Timer(
             self.sim,
             MLFQ.end_event, (self, self.processors[0]),
             self.QUANTUM*(2**i),
             cpu=self.processors[0],
             in_ms=True)
Пример #25
0
    def schedule(self):
        """
        Schedule this proper sub-system.
        """
        self.to_reschedule = False
        decision = []

        self.virtual = []
        jobs = select_jobs(self.root, self.virtual)

        wakeup_delay = min(self.virtual, key=lambda s: s.budget).budget
        if wakeup_delay > 0:
            self.timer = Timer(self.sim, ProperSubsystem.virtual_event,
                               (self, self.processors[0]), wakeup_delay,
                               cpu=self.processors[0], in_ms=False)
            self.timer.start()

        cpus = []
        for cpu in self.processors:
            if cpu.running in jobs:
                jobs.remove(cpu.running)
            else:
                cpus.append(cpu)

        for cpu in cpus:
            if jobs:
                decision.append((jobs.pop(), cpu))
            else:
                decision.append((None, cpu))

        return decision
Пример #26
0
    def on_activate(self, job):
        # First pseudo-activation
        pseudo_job = EPDF.PseudoJob(job, 1)

        self.pseudo_activate(pseudo_job)

        # Set next pseudo activations :
        while pseudo_job.seq * self.quantum < job.wcet:
            pseudo_job = EPDF.PseudoJob(job, pseudo_job.seq + 1)
            timer = Timer(self.sim, EPDF.pseudo_activate, (self, pseudo_job),
                          pseudo_job.release_date * self.quantum -
                          self.sim.now() / self.sim.cycles_per_ms +
                          job.activation_date, cpu=job.cpu,
                          in_ms=True)
            timer.start()
            self.timers.append(timer)
Пример #27
0
    def on_activate(self, job):

        server = self.cbs_servers[job.task]

        # If the ready list of the server is empty new runtime and deadline are computed and
        # the deadline_timer is started
        if (not server.ready_list):
            # qi < (di - t)Qi/Ti
            if not (server.current_runtime <
                    (server.current_deadline - self.sim.now_ms()) *
                    (server.maximum_runtime / server.deadline)):
                # d = t + D, q = Q
                self.cbs_servers[job.task].set(
                    self.cbs_servers[job.task].maximum_runtime,
                    self.sim.now_ms() + self.cbs_servers[job.task].deadline,
                    self.sim.now_ms(),
                    Timer(self.sim,
                          SCHED_DEADLINE.deadline_call,
                          (self, self.cbs_servers[job.task]),
                          self.cbs_servers[job.task].deadline,
                          one_shot=True,
                          cpu=self.processors[0],
                          overhead=.000))
        # The job is added to the ready_list of the server
        server.add_job(job)
        job.cpu.resched()
Пример #28
0
    def init(self):
        self.ready_list = []
        self.timers = []
        self.terminate_timers = []
        self.waiting_schedule = False
        self.running_vjobs = []

        ER_PD2.quantum = self.sim.cycles_per_ms // 10 # 0.1ms.

        #ER_PD2.quantum = 1000000
        #while not self.is_schedulable() and ER_PD2.quantum > 1000:
        #    ER_PD2.quantum /= 2

        self.timer = Timer(
            self.sim, ER_PD2.reschedule, (self, ), ER_PD2.quantum,
            cpu=self.processors[0], in_ms=False, one_shot=False)
        self.timer.start()
Пример #29
0
 def init(self):
     self.ready_list = Queue()
     self.running_job = None
     self.quantum = 1 # ms
     self.timer = Timer(self.sim, RR.reschedule,
                       (self, self.processors[0]), self.quantum, one_shot=False,
                       cpu=self.processors[0])
     self.timer.start()
Пример #30
0
    def on_activate(self, job):
        # First pseudo-activation
        pseudo_job = EPDF.PseudoJob(job, 1)

        self.pseudo_activate(pseudo_job)

        # Set next pseudo activations :
        while pseudo_job.seq * self.quantum < job.wcet:
            pseudo_job = EPDF.PseudoJob(job, pseudo_job.seq + 1)
            timer = Timer(self.sim,
                          EPDF.pseudo_activate, (self, pseudo_job),
                          pseudo_job.release_date * self.quantum -
                          self.sim.now() / self.sim.cycles_per_ms +
                          job.activation_date,
                          cpu=job.cpu,
                          in_ms=True)
            timer.start()
            self.timers.append(timer)
Пример #31
0
class LLF(Scheduler):
    """Least Laxity First"""
    def init(self):
        self.ready_list = []
        self.timer = Timer(self.sim,
                           LLF.update, (self, self.processors[0]),
                           1,
                           one_shot=False,
                           cpu=self.processors[0],
                           overhead=.001)
        self.timer.start()

    def update(self, cpu):
        if self.ready_list:
            cpu.resched()

    def on_activate(self, job):
        self.ready_list.append(job)
        job.cpu.resched()

    def on_terminated(self, job):
        self.ready_list.remove(job)
        self.update(job.cpu)

    def schedule(self, cpu):
        decisions = []
        if self.ready_list:
            # Sort according to the laxity.
            self.ready_list.sort(key=lambda x: (x.laxity, x.task.identifier))

            # m : Nombre de processeurs.
            m = len(self.processors)

            # Available processors:
            l = (proc for proc in self.processors
                 if proc.running not in self.ready_list[:m])

            # The first m jobs should be running:
            for job in self.ready_list[:m]:
                if not job.is_running():
                    proc = next(l)
                    decisions.append((job, proc))

        return decisions
Пример #32
0
class LLF(Scheduler):
    """Least Laxity First"""
    def init(self):
        self.ready_list = []
        self.timer = Timer(self.sim, LLF.compute_laxity,
                           (self, self.processors[0]), 1, one_shot=False,
                           cpu=self.processors[0], overhead=.01)
        self.timer.start()

    def compute_laxity(self, cpu):
        if self.ready_list:
            for job in self.ready_list:
                job.laxity = job.absolute_deadline - \
                    (job.ret + self.sim.now_ms())
            cpu.resched()

    def on_activate(self, job):
        self.ready_list.append(job)
        self.compute_laxity(job.cpu)

    def on_terminated(self, job):
        self.ready_list.remove(job)
        self.compute_laxity(job.cpu)

    def schedule(self, cpu):
        decisions = []
        if self.ready_list:
            # Sort according to the laxity.
            self.ready_list.sort(key=lambda x: (x.laxity, x.task.identifier))

            # m : Nombre de processeurs.
            m = len(self.processors)

            # Available processors:
            l = (proc for proc in self.processors
                 if proc.running not in self.ready_list[:m])

            # The first m jobs should be running:
            for job in self.ready_list[:m]:
                if not job.is_running():
                    proc = next(l)
                    decisions.append((job, proc))

        return decisions
Пример #33
0
 def init(self):
     self.ready_list = []
     """
     However, LSTR
     scheduling algorithm operates on every basic time unit. Here, we consider the basic
     time unit of 1 (ms).
     """
     self.timer = Timer(self.sim, LSTR.virtual_event,
                        (self, self.processors[0]), 1, one_shot=False)
     self.timer.start()
Пример #34
0
    def schedule(self, cpu):
        self.waiting_schedule = False
        self.update_budget()

        # Sort the jobs by budgets.
        sorted_budgets = sorted([(x, ceil(y)) for x, y in self.budget.items()],
                                key=lambda x: (-x[1], x[0].name))
        selected = sorted_budgets[:len(self.processors)]
        not_selected = sorted_budgets[len(self.processors):]

        # Compute the (relative) date of the next event.
        next_event = self.date_next_event(selected, not_selected)
        if next_event > 0:
            # Set a timer to reschedule the system at that date.
            self.timer_a = Timer(self.sim,
                                 LLREF.reschedule, (self, ),
                                 next_event,
                                 cpu=cpu,
                                 in_ms=False)
            self.timer_a.start()

        # Allocate the selected jobs to the processors.
        # The processors already running selected jobs are not changed.
        available_procs = []
        self.selected_jobs = [s[0] for s in selected if s[1] > 0]
        remaining_jobs = self.selected_jobs[:]
        for proc in self.processors:
            if proc.running in self.selected_jobs:
                # This processor keeps running the same job.
                remaining_jobs.remove(proc.running)
            else:
                # This processor is not running a selected job.
                available_procs.append(proc)

        # The remaining processors are running the remaining jobs or None.
        padded_remaining_jobs = remaining_jobs + \
            [None] * (len(available_procs) - len(remaining_jobs))
        # zip create a list of couples (job, proc) using the list of remaining
        # jobs and the list of available processors.
        decisions = list(zip(padded_remaining_jobs, available_procs))

        return decisions
Пример #35
0
    def accept_migrating_job(self, i, job, budget):
        self.migrating_job = job
        job.task.cpu = self.processors[0]

        # Set timer for end.
        self.timer = Timer(self.sim, EDF_modified.end_migrating_job,
                           (self, i), budget, cpu=self.processors[0],
                           in_ms=False)
        self.timer.start()

        self._resched()
Пример #36
0
    def schedule(self, cpu):
        """
        Take the scheduling decisions.
        """
        self.waiting_schedule = False
        decisions = []
        self.h_c = [(d, t) for d, t in self.h_c if t.job.is_active()]
        heapify(self.h_c)

        if self.sim.now() == self.t_f:
            decisions = self.init_tl_plane()
        else:
            for task in self.activations:
                decisions += self.handle_evt_a(task)
            if self.evt_bc:
                decisions += self.handle_evt_bc()

        self.activations = []
        self.evt_bc = False

        if self.h_b:
            t_next = self.h_b[0][0]
            if self.h_c:
                t_next = min(t_next, self.h_c[0][0])

            self.timer = Timer(self.sim,
                               LRE_TL.event_bc, (self, ),
                               t_next - self.sim.now(),
                               cpu=self.processors[0],
                               in_ms=False)
        else:
            self.timer = Timer(self.sim,
                               LRE_TL.reschedule, (self, ),
                               self.t_f - self.sim.now(),
                               cpu=self.processors[0],
                               in_ms=False)
        self.timer.start()

        return decisions
Пример #37
0
 def deadline_call(self, server):
     # This call is done when a CBS deadline expired
     # The runtime is refilled, a new deadline-server is computed and
     # the deadline-time is restarted
     if server.ready_list:
         server.set(
             server.maximum_runtime,
             self.sim.now_ms() + server.period, self.sim.now_ms(),
             Timer(self.sim,
                   SCHED_DEADLINE.deadline_call, (self, server),
                   server.deadline,
                   one_shot=True,
                   cpu=self.processors[0],
                   overhead=.000))
     server.task.cpu.resched()
Пример #38
0
    def schedule(self, cpu):
        now = self.sim.now_ms()
        remaining_time_in_window = self.windowsize - (now % self.windowsize)
        if now % self.windowsize == 0:
            self.reset_window(cpu)

        if remaining_time_in_window > 0:
            try:
                current_job = self.timeline[self.window_id][self.queue_index]
                # if job has still reserved cpu time
                if current_job.is_running() and now < current_job.absolute_burst:
                    return (current_job, cpu)
            except:
                pass            
            # burst has finished and next prioritary job is selected
            try:
                job = self.timeline[self.window_id][self.queue_index]
                priority = self.queue_index + 1
                burst = self.windowsize / 2**priority
            except Exception as e:
                available = [job for job in self.timeline[self.window_id] if job.is_active()] + self.ready_list
                if len(available):
                    # Slack time, choose random job
                    job = choice(available)
                    burst = self.default_quantum
                else:
                    # Idle
                    return (None, cpu)

            if burst == 0: # gain time
                if self.ready_list:
                    job = choice(self.ready_list)
                burst = min(self.default_quantum, remaining_time_in_window)
            else: # adjust burst
                burst = min(remaining_time_in_window, (min(burst, job.ret)))

            if burst == 0 and remaining_time_in_window > 0:
                burst = remaining_time_in_window

            #print "[{3}] JOB {0}, scheduled with burst {1} until {2}".format(job.name, burst, now+burst, now)
            self.preempt_timer = Timer(self.sim, DPSDy.reschedule,
                              (self, self.processors[0]), ceil(burst),
                              one_shot=True, cpu=self.processors[0])
            job.absolute_burst = now + burst
            self.preempt_timer.start()                    

            self.queue_index += 1
            return (job, cpu)
Пример #39
0
    def schedule(self, cpu):
        now = self.sim.now_ms()
        remaining_time_in_window = float("{0:.2f}".format(self.windowsize - (now % self.windowsize)))
        if now % self.windowsize == 0:
            self.reset_window(cpu)
            cpu.monitor.observe(ProcEvent(ProcEvent.SEPARATOR))

        if remaining_time_in_window > 0:
            try:
                current_job = self.timeline[self.window_id][self.queue_index][0]
                # if job has still reserved cpu time
                if current_job.is_running() and now < current_job.absolute_burst:
                    return (current_job, cpu)
            except:
                pass            
            # burst has finished and next prioritary job is selected
            try:
                job, burst = self.timeline[self.window_id][self.queue_index]
            except Exception as e:
                available = [job[0] for job in self.timeline[self.window_id] if job[0].is_active()] + self.ready_list
                if len(available):
                    # Slack time, choose random job
                    job = choice(available)
                    burst = self.default_quantum
                else:
                    # Idle
                    return (None, cpu)

            burst = float("{0:.2f}".format(burst))
            if burst == 0: # gain time
                if self.ready_list:
                    job = choice(self.ready_list)
                burst = self.default_quantum
            # adjust burst
            ret = float("{0:.2f}".format(job.ret))
            burst = min(remaining_time_in_window, burst, ret)

            if burst == 0 and remaining_time_in_window > 0:
                burst = remaining_time_in_window

            self.preempt_timer = Timer(self.sim, BDPS.reschedule,
                              (self, self.processors[0]), burst,
                              one_shot=True, cpu=self.processors[0])
            job.absolute_burst = now + burst
            self.preempt_timer.start()                    

            self.queue_index += 1
            return (job, cpu)
Пример #40
0
    def init(self):
        self.ready_list = []
        self.timers = []
        self.terminate_timers = []
        self.waiting_schedule = False
        self.running_vjobs = []

        ER_PD2.quantum = self.sim.cycles_per_ms // 10 # 0.1ms.

        #ER_PD2.quantum = 1000000
        #while not self.is_schedulable() and ER_PD2.quantum > 1000:
        #    ER_PD2.quantum /= 2

        self.timer = Timer(
            self.sim, ER_PD2.reschedule, (self, ), ER_PD2.quantum,
            cpu=self.processors[0], in_ms=False, one_shot=False)
        self.timer.start()
Пример #41
0
    def schedule(self, cpu):
        # update runtime of the running server on cpu if exists
        if cpu.running:
            self.cbs_servers[cpu.running.task].update_runtime(
                self.sim.now_ms())

        # List of CBS servers with a ready job which is not currently running
        ready_servers = [
            s for s in self.cbs_servers.values() if s.ready_list
            and not s.ready_list[0].is_running() and not s.is_throttled
        ]

        # Choose the job-server and processor with EDF citeria
        if ready_servers:
            # Select a free processor or, if none,
            # the one with the greatest server-deadline (self in case of equality):
            key = lambda x: (1 if not x.running else 0, self.cbs_servers[
                x.running.task].current_deadline if x.running else 0, 1
                             if x is cpu else 0)
            cpu_min = max(self.processors, key=key)

            # Select the job with the least server-deadline
            server = min(ready_servers, key=lambda x: x.current_deadline)
            job = server.ready_list[0]

            if (cpu_min.running is None
                    or self.cbs_servers[cpu_min.running.task].current_deadline
                    > self.cbs_servers[job.task].current_deadline):
                print(self.sim.now(), job.name, cpu_min.name)

                # start runtime timer of the new server selected
                self.cbs_servers[job.task].timer_runtime = Timer(
                    self.sim,
                    SCHED_DEADLINE.runtime_call,
                    (self, self.cbs_servers[job.task]),
                    self.cbs_servers[job.task].current_runtime,
                    one_shot=True,
                    cpu=self.processors[0],
                    overhead=.000)
                self.cbs_servers[job.task].timer_runtime.start()
                self.cbs_servers[job.task].last_update = self.sim.now_ms()
                # stop runtime timer for the job-server running on the selected processor
                if (cpu_min.running):
                    self.cbs_servers[cpu_min.running.task].timer_runtime.stop()

                return (job, cpu_min)
Пример #42
0
    def schedule(self, cpu):
        self.waiting_schedule = False
        self.update_budget()

        # Sort the jobs by budgets.
        sorted_budgets = sorted(
            [(x, ceil(y)) for x, y in self.budget.items()],
            key=lambda x: (-x[1], x[0].name))
        selected = sorted_budgets[:len(self.processors)]
        not_selected = sorted_budgets[len(self.processors):]

        # Compute the (relative) date of the next event.
        next_event = self.date_next_event(selected, not_selected)
        if next_event > 0:
            # Set a timer to reschedule the system at that date.
            self.timer_a = Timer(self.sim, LLREF.reschedule, (self,),
                                 next_event, cpu=cpu, in_ms=False)
            self.timer_a.start()

        # Allocate the selected jobs to the processors.
        # The processors already running selected jobs are not changed.
        available_procs = []
        self.selected_jobs = [s[0] for s in selected if s[1] > 0]
        remaining_jobs = self.selected_jobs[:]
        for proc in self.processors:
            if proc.running in self.selected_jobs:
                # This processor keeps running the same job.
                remaining_jobs.remove(proc.running)
            else:
                # This processor is not running a selected job.
                available_procs.append(proc)

        # The remaining processors are running the remaining jobs or None.
        padded_remaining_jobs = remaining_jobs + \
            [None] * (len(available_procs) - len(remaining_jobs))
        # zip create a list of couples (job, proc) using the list of remaining
        # jobs and the list of available processors.
        decisions = list(zip(padded_remaining_jobs, available_procs))

        return decisions
Пример #43
0
    def schedule(self, cpu):
        """
        Basically a EDF scheduling but using a priority attribute.
        """
        ready_jobs = [j for j in self.ready_list if j.is_active()]
        if ready_jobs:
            selected_job = None

            key = lambda x: (1 if x.running else -1, -x.running.priority
                             if x.running else 0, -1 if x is cpu else 1)
            cpu_min = min(self.processors, key=key)

            job = min(ready_jobs, key=lambda x: x.priority)
            if cpu_min.running is None or \
                    cpu_min.running.priority > job.priority:
                self.ready_list.remove(job)
                if cpu_min.running:
                    self.ready_list.append(cpu_min.running)
                selected_job = (job, cpu_min)

            # Recherche du prochain event ZeroLaxity pour configurer le timer.
            minimum = None
            for job in self.ready_list:
                zl_date = job.laxity
                if (minimum is None or minimum[0] > zl_date) and zl_date > 0:
                    minimum = (zl_date, job)

            if self.zl_timer:
                self.zl_timer[1].stop()
            if minimum:
                self.zl_timer = (minimum[0],
                                 Timer(self.sim,
                                       EDZL.zero_laxity, (self, minimum[1]),
                                       minimum[0],
                                       cpu=cpu,
                                       in_ms=False))
                self.zl_timer[1].start()

            return selected_job
Пример #44
0
    def schedule(self, cpu):
        """
        Basically a EDF scheduling but using a priority attribute.
        """
        if self.ready_list:
            selected_job = None

            key = lambda x: (1 if x.running else -1, -x.running.priority
                             if x.running else 0, -1 if x is cpu else 1)
            cpu_min = min(self.processors, key=key)

            job = min(self.ready_list, key=lambda x: x.priority)
            if cpu_min.running is None or \
                    cpu_min.running.priority > job.priority:
                self.ready_list.remove(job)
                if cpu_min.running:
                    self.ready_list.append(cpu_min.running)
                selected_job = (job, cpu_min)

            minimum = None
            for job in self.ready_list:
                zl_date = int((job.absolute_deadline - job.ret) *
                              self.sim.cycles_per_ms - self.sim.now())
                if (minimum is None or minimum[0] > zl_date) and zl_date > 0:
                    minimum = (zl_date, job)

            if self.zl_timer:
                self.zl_timer[1].stop()
            if minimum:
                self.zl_timer = (minimum[0],
                                 Timer(self.sim,
                                       G_FL_ZL.zero_laxity, (self, minimum[1]),
                                       minimum[0],
                                       cpu=cpu,
                                       in_ms=False))
                self.zl_timer[1].start()

            return selected_job
Пример #45
0
class RR(Scheduler):
    """Round Robin scheduler"""
    def init(self):
        self.ready_list = []
        self.delay = 2
        self.timer = Timer(self.sim,
                           RR.end_event, (self, self.processors[0]),
                           self.delay,
                           cpu=self.processors[0],
                           in_ms=True)
        self.interupt = False

    def on_activate(self, job):
        self.ready_list.append(job)
        job.cpu.resched()

    def on_terminated(self, job):
        if job in self.ready_list:
            self.ready_list.remove(job)
        self.timer.stop()
        job.cpu.resched()

    def end_event(self, cpu):
        self.interupt = True
        self.timer.stop()
        cpu.resched()

    def schedule(self, cpu):
        if self.ready_list:
            job = self.ready_list[0]
            if not cpu.running or self.interupt:
                self.interupt = False
                self.timer.start()
                self.ready_list.remove(job)
                if cpu.running:
                    self.ready_list.append(cpu.running)
                return (job, cpu)
        else:
            return None
Пример #46
0
class DPS(Scheduler):
    def init(self):
        self.ready_list = []
        self.windowsize = 100
        self.window_id = 0
        self.queue_index = 0
        self.default_quantum = 10
        self.window_queue = []

    def fill_window_queue(self):
        while sqrt(self.windowsize) > len(self.window_queue) and len(self.ready_list) > 0:
            self.window_queue.append(self.ready_list.pop(0))
        
    def reset_window(self, cpu):
        self.window_id += 1
        self.queue_index = 0

        # remove finished jobs
        self.window_queue = [job for job in self.window_queue if job.is_active()]
        
        # fill the window queue
        self.fill_window_queue()        
        
    def reschedule(self, cpu):
        cpu.resched()

    def on_activate(self, job):
        self.ready_list.append(job)
        job.priority = len(self.window_queue) + self.ready_list.index(job) + 1
        # deadline prediction
        job._absolute_deadline = job._task._task_info.deadline = ceil(job._activation_date + (2**job.priority) * job.wcet)
        prev = len(self.window_queue)
        self.fill_window_queue()
        if prev == 0 and len(self.window_queue) > 0:
            job.cpu.resched()

    def on_terminated(self, job):
        if job in self.ready_list:
            self.ready_list.remove(job)
        self.preempt_timer.stop()

    def schedule(self, cpu):
        now = self.sim.now_ms()
        remaining_time_in_window = self.windowsize - (now % self.windowsize)
        if now % self.windowsize == 0:
            self.reset_window(cpu)
        if remaining_time_in_window > 0:
            try:
                current_job = self.window_queue[self.queue_index]
                # if job has still reserved cpu time
                if current_job.is_running() and now < current_job.absolute_burst:
                    return (current_job, cpu)
            except:
                pass            
            # burst has finished and next prioritary job is selected
            try:
                job = self.window_queue[self.queue_index]
                priority = job.priority
                burst = self.windowsize / 2**priority
            except Exception as e:
                available = [job for job in self.window_queue if job.is_active()] + self.ready_list
                if len(available):
                    # Slack time, choose random job
                    job = choice(available)
                    burst = self.default_quantum
                else:
                    # Idle
                    return (None, cpu)

            if burst == 0:  # gain time
                if self.ready_list:
                    job = choice(self.ready_list)
                burst = min(self.default_quantum, remaining_time_in_window)
            else:  # adjust burst
                burst = min(remaining_time_in_window, (min(burst, job.ret)))

            if burst == 0 and remaining_time_in_window > 0:
                burst = remaining_time_in_window

            self.preempt_timer = Timer(self.sim, DPS.reschedule,
                              (self, self.processors[0]), ceil(burst),
                              one_shot=True, cpu=self.processors[0])
            job.absolute_burst = now + burst
            self.preempt_timer.start()                    

            self.queue_index += 1
            return (job, cpu)
Пример #47
0
class DPSDy(Scheduler):
    def init(self):
        self.ready_list = []
        self.windowsize = 100 #float(100.0)
        self.window_id = 0
        self.queue_index = 0
        self.default_quantum = 10
        self.timeline = defaultdict(list)
        self.started = False
      
    def reset_window(self, cpu):
        if self.started:
            self.window_id += 1
        else:
            self.started = True
        self.queue_index = 0
        #clean window
        self.timeline[self.window_id] = [job for job in self.timeline[self.window_id] if job.is_active()]

    def reschedule(self, cpu):
        cpu.resched()

    def on_activate(self, job):
        self.ready_list.append(job)
        prev = len(self.timeline[self.window_id])
        wcet = job.wcet
        w_id = self.window_id
        while wcet > 0:
            if sqrt(self.windowsize) > len(self.timeline[w_id]):
                self.timeline[w_id].append(job)
                wcet -= self.windowsize / 2**(self.timeline[w_id].index(job)+1)
            w_id += 1
        deadline = self.windowsize * w_id + self.windowsize
        job._absolute_deadline = job._task._task_info.deadline = deadline    
            
        if prev == 0 and len(self.timeline[self.window_id]) > 0:
            job.cpu.resched()

    def on_terminated(self, job):
        if job in self.ready_list:
            self.ready_list.remove(job)
        self.preempt_timer.stop()

    def schedule(self, cpu):
        now = self.sim.now_ms()
        remaining_time_in_window = self.windowsize - (now % self.windowsize)
        if now % self.windowsize == 0:
            self.reset_window(cpu)

        if remaining_time_in_window > 0:
            try:
                current_job = self.timeline[self.window_id][self.queue_index]
                # if job has still reserved cpu time
                if current_job.is_running() and now < current_job.absolute_burst:
                    return (current_job, cpu)
            except:
                pass            
            # burst has finished and next prioritary job is selected
            try:
                job = self.timeline[self.window_id][self.queue_index]
                priority = self.queue_index + 1
                burst = self.windowsize / 2**priority
            except Exception as e:
                available = [job for job in self.timeline[self.window_id] if job.is_active()] + self.ready_list
                if len(available):
                    # Slack time, choose random job
                    job = choice(available)
                    burst = self.default_quantum
                else:
                    # Idle
                    return (None, cpu)

            if burst == 0: # gain time
                if self.ready_list:
                    job = choice(self.ready_list)
                burst = min(self.default_quantum, remaining_time_in_window)
            else: # adjust burst
                burst = min(remaining_time_in_window, (min(burst, job.ret)))

            if burst == 0 and remaining_time_in_window > 0:
                burst = remaining_time_in_window

            #print "[{3}] JOB {0}, scheduled with burst {1} until {2}".format(job.name, burst, now+burst, now)
            self.preempt_timer = Timer(self.sim, DPSDy.reschedule,
                              (self, self.processors[0]), ceil(burst),
                              one_shot=True, cpu=self.processors[0])
            job.absolute_burst = now + burst
            self.preempt_timer.start()                    

            self.queue_index += 1
            return (job, cpu)
Пример #48
0
    def schedule(self):
        """
        Schedule this proper sub-system.
        """

        self.to_reschedule = False
        self.virtual = []
        decision = []
        processors = []
        processors = self.processors

        self.CSC(self.sim.now())

        t = self.sim.now()

        if t >= self.idleBegin and t < self.idleEnd:
            self.is_idle = True
            # add schedule event - end of idle period
            self.add_timer(self.idleEnd - t, self.processors[0])
        else:
            self.is_idle = False

        selected = select_jobs(self, self.root, self.virtual)

        idle = [s for s in selected if s.task.name == 'IdleTask']
        jobs = [
            s.job for s in selected
            if s.task.name != 'IdleTask' and s.task.name != "wcet"
        ]

        if idle:
            # CSC dual level
            if self.level % 2 == 0:
                # use busyInterval to save energy
                self.processors[0].set_dummy(self.busyEnd - t)
            # CSC primal level
            else:
                # use idleInterval to save energy
                self.processors[0].set_dummy(self.idleEnd - t)

            processors = self.processors[
                1:]  # Refresh available processors list
            decision.append(
                (None, self.processors[0]))  # Set dummy to first processor
        else:
            self.processors[0].stop_dummy()

        wakeup_delay = min([s.budget for s in self.virtual if s.budget > 0])

        if wakeup_delay > 0:
            self.timer = Timer(self.sim,
                               ProperSubsystem.virtual_event,
                               (self, self.processors[0]),
                               wakeup_delay,
                               cpu=self.processors[0],
                               in_ms=False)
            self.timer.start()

        cpus = []

        #first, leave already executing tasks on their current processors;
        for cpu in processors:
            if cpu.running in jobs:
                jobs.remove(cpu.running)  # remove job and cpu
            else:
                cpus.append(cpu)

        # second, assign previously idle tasks to their last-used processor, when its available
        aux_jobs = list(jobs)
        for job in aux_jobs:
            if job.task.last_cpu in cpus:
                decision.append((job, job.task.last_cpu))
                jobs.remove(job)
                cpus.remove(job.task.last_cpu)

        # third, assign remaining tasks to free processors arbitrarily
        for cpu in cpus:
            if jobs:
                decision.append((jobs.pop(), cpu))
            else:
                decision.append((None, cpu))

        return decision
Пример #49
0
class ProperSubsystem(object):
    """
    Proper sub-system. A proper sub-system is the set of the tasks belonging to
    a unit server (server with utilization of 1) and a set of processors.
    """
    def __init__(self, sim, root, processors, level):
        self.sim = sim
        self.root = root
        self.processors = processors
        self.level = level
        self.virtual = []
        self.last_update = 0
        self.to_reschedule = False
        self.timer = None

        self.utilization = sum(
            [s.utilization for s in root.children if s.dummyServer is False])

        self.dummy_timer = None

        self.is_idle = True
        self.keep = True

        self.idleBegin = 0
        self.idleEnd = 0

        self.busyBegin = 0
        self.busyEnd = 0

    def update_budget(self):
        """
        Update the budget of the servers.
        """

        time_since_last_update = self.sim.now() - self.last_update
        for server in self.virtual:
            server.budget -= time_since_last_update
        self.last_update = self.sim.now()

    def bug(self, subsystem):
        for cpu in subsystem.processors:
            if any(x[0] == 2 or x[0] == 3
                   for x in cpu._evts) and self.sim.now() > 0:
                return True
        return False

    def resched(self, cpu):
        """
        Plannify a scheduling decision on processor cpu. Ignore it if already
        planned.
        """

        if not self.bug(self):
            self.to_reschedule = True
            cpu.resched()

    def virtual_event(self, cpu):
        """
        Virtual scheduling event. Happens when a virtual job terminates.
        """

        self.update_budget()
        self.resched(cpu)

    def end_dummy(self, cpu):
        self.update_budget()
        self.to_reschedule = True
        self.resched(cpu)

    def add_timer(self, wakeup_delay, CPU):
        if self.dummy_timer:
            self.dummy_timer.stop()

        self.dummy_timer = Timer(self.sim,
                                 ProperSubsystem.end_dummy, (self, CPU),
                                 wakeup_delay,
                                 cpu=CPU,
                                 in_ms=False)
        self.dummy_timer.start()

    # cumulative slack computation
    def CSC(self, t):

        active_servers = [
            s for s in self.root.children
            if (s.dummyServer is False) and s.budget > 0
        ]
        servers = [s for s in self.root.children if s.dummyServer is False]
        beta = beta = sum(s.budget for s in servers)
        omega = max(0, self.root.next_deadline - t - beta)

        if self.is_idle is True:
            delta = omega

            if delta > 0:
                self.idleEnd = t + delta
                self.busyBegin = self.idleEnd
                self.busyEnd = self.idleBegin + (
                    self.idleEnd - self.idleBegin) / float(1 -
                                                           self.utilization)
            else:
                self.idleEnd = t
                self.busyBegin = self.idleEnd
                self.busyEnd = max(beta, self.busyEnd)
        else:
            if active_servers:
                self.busyEnd = max(t + beta, self.busyEnd)
            else:
                omegat = omega_t(self, servers, t, self.root.next_deadline)

                self.idleBegin = t
                self.idleEnd = self.root.next_deadline + omegat
                self.busyBegin = self.idleEnd
                self.busyEnd = self.root.next_deadline + (
                    omegat / float(1 - self.utilization))

    def schedule(self):
        """
        Schedule this proper sub-system.
        """

        self.to_reschedule = False
        self.virtual = []
        decision = []
        processors = []
        processors = self.processors

        self.CSC(self.sim.now())

        t = self.sim.now()

        if t >= self.idleBegin and t < self.idleEnd:
            self.is_idle = True
            # add schedule event - end of idle period
            self.add_timer(self.idleEnd - t, self.processors[0])
        else:
            self.is_idle = False

        selected = select_jobs(self, self.root, self.virtual)

        idle = [s for s in selected if s.task.name == 'IdleTask']
        jobs = [
            s.job for s in selected
            if s.task.name != 'IdleTask' and s.task.name != "wcet"
        ]

        if idle:
            # CSC dual level
            if self.level % 2 == 0:
                # use busyInterval to save energy
                self.processors[0].set_dummy(self.busyEnd - t)
            # CSC primal level
            else:
                # use idleInterval to save energy
                self.processors[0].set_dummy(self.idleEnd - t)

            processors = self.processors[
                1:]  # Refresh available processors list
            decision.append(
                (None, self.processors[0]))  # Set dummy to first processor
        else:
            self.processors[0].stop_dummy()

        wakeup_delay = min([s.budget for s in self.virtual if s.budget > 0])

        if wakeup_delay > 0:
            self.timer = Timer(self.sim,
                               ProperSubsystem.virtual_event,
                               (self, self.processors[0]),
                               wakeup_delay,
                               cpu=self.processors[0],
                               in_ms=False)
            self.timer.start()

        cpus = []

        #first, leave already executing tasks on their current processors;
        for cpu in processors:
            if cpu.running in jobs:
                jobs.remove(cpu.running)  # remove job and cpu
            else:
                cpus.append(cpu)

        # second, assign previously idle tasks to their last-used processor, when its available
        aux_jobs = list(jobs)
        for job in aux_jobs:
            if job.task.last_cpu in cpus:
                decision.append((job, job.task.last_cpu))
                jobs.remove(job)
                cpus.remove(job.task.last_cpu)

        # third, assign remaining tasks to free processors arbitrarily
        for cpu in cpus:
            if jobs:
                decision.append((jobs.pop(), cpu))
            else:
                decision.append((None, cpu))

        return decision
Пример #50
0
class LRE_TL(Scheduler):
    def init(self):
        """
        Initialization of the scheduler. This function is called when the
        system is ready to run.
        """
        self.t_f = 0
        self.h_b = []  # Heap of running tasks.
        self.h_c = []  # Heap of waiting tasks.
        self.h_d = []  # Heap of deadlines.
        self.pmin = min([task.period for task in self.task_list]) \
            * self.sim.cycles_per_ms
        self.evt_bc = False
        self.activations = []
        self.waiting_schedule = False

    def reschedule(self, cpu=None):
        """
        Ask for a scheduling decision. Don't call if not necessary.
        """
        if not self.waiting_schedule:
            if cpu is None:
                cpu = self.processors[0]
            cpu.resched()
            self.waiting_schedule = True

    def on_activate(self, job):
        """
        A-event.
        """
        self.activations.append(job.task)
        self.reschedule()

    def init_tl_plane(self):
        decisions = []

        for task in self.activations:
            dl = int(task.job.absolute_deadline * self.sim.cycles_per_ms)
            if dl not in self.h_d:
                heappush(self.h_d, dl)

        self.t_f = self.sim.now() + self.pmin
        if self.h_d[0] <= self.t_f:
            self.t_f = heappop(self.h_d)

        z = 0
        self.h_b = []
        self.h_c = []
        for task in self.task_list:
            l = ceil(task.wcet * (self.t_f - self.sim.now()) / task.period)
            if z < len(self.processors) and task.job.is_active():
                heappush(self.h_b, (self.sim.now() + l, task))
                decisions.append((task.job, self.processors[z]))
                z += 1
            else:
                heappush(self.h_c, (self.t_f - l, task))

        while z < len(self.processors):
            decisions.append((None, self.processors[z]))
            z += 1

        return decisions

    def handle_evt_a(self, task):
        """
        Handle an "A-Event".
        """
        decisions = []

        tasks_h_c = [t for _, t in self.h_c]
        tasks_h_b = [t for _, t in self.h_b]

        if task not in tasks_h_b and task not in tasks_h_c:
            l = ceil(task.wcet * (self.t_f - self.sim.now()) / task.period)
            if len(self.h_b) < len(self.processors):
                idle_proc = [z for z in self.processors
                             if not z.is_running()][0]
                decisions.append((task.job, idle_proc))
                heappush(self.h_b, (self.sim.now() + l, task))
            else:
                if task.wcet < task.period:
                    heappush(self.h_c, ((self.t_f - l), task))
                else:
                    key_b, task_b = heapreplace(self.h_b, (self.t_f + l, task))
                    heappush(self.h_c, (self.t_f - key_b + self.sim.now()))

        dl = int(task.job.absolute_deadline * self.sim.cycles_per_ms)
        if dl not in self.h_d:
            heappush(self.h_d, dl)

        return decisions

    def handle_evt_bc(self):
        """
        Handle a "BC-Event".
        """

        decisions = []
        while self.h_b and self.h_b[0][0] == self.sim.now():
            task_b = heappop(self.h_b)[1]

            if self.h_c:
                key_c, task_c = heappop(self.h_c)
                heappush(self.h_b, (self.t_f - key_c + self.sim.now(), task_c))
                decisions.append((task_c.job, task_b.cpu))
            else:
                decisions.append((None, task_b.cpu))

        if self.h_c:
            while self.h_c[0][0] == self.sim.now():
                key_b, task_b = heappop(self.h_b)
                key_c, task_c = heappop(self.h_c)
                key_b = self.t_f - key_b + self.sim.now()
                assert key_c != key_b, "Handle Evt BC failed."
                key_c = self.t_f - key_c + self.sim.now()
                heappush(self.h_b, (key_c, task_c))
                heappush(self.h_c, (key_b, task_b))
                decisions.append((task_c.job, task_b.cpu))

        return decisions

    def event_bc(self):
        """
        B or C event.
        """
        self.evt_bc = True
        self.reschedule()

    def schedule(self, cpu):
        """
        Take the scheduling decisions.
        """
        self.waiting_schedule = False
        decisions = []
        self.h_c = [(d, t) for d, t in self.h_c if t.job.is_active()]
        heapify(self.h_c)

        if self.sim.now() == self.t_f:
            decisions = self.init_tl_plane()
        else:
            for task in self.activations:
                decisions += self.handle_evt_a(task)
            if self.evt_bc:
                decisions += self.handle_evt_bc()

        self.activations = []
        self.evt_bc = False

        if self.h_b:
            t_next = self.h_b[0][0]
            if self.h_c:
                t_next = min(t_next, self.h_c[0][0])

            self.timer = Timer(self.sim, LRE_TL.event_bc, (self,),
                               t_next - self.sim.now(),
                               cpu=self.processors[0], in_ms=False)
        else:
            self.timer = Timer(self.sim, LRE_TL.reschedule, (self,),
                               self.t_f - self.sim.now(),
                               cpu=self.processors[0], in_ms=False)
        self.timer.start()

        return decisions
Пример #51
0
class BDPS(Scheduler):
    def init(self):
        self.ready_list = []
        self.windowsize = 100
        self.window_id = 0
        self.queue_index = 0
        self.default_quantum = 10
        self.timeline = defaultdict(list)
        self.window_usage = defaultdict(lambda: self.windowsize)
        self.started = False
        
        try:
            self.MAX_PRIORITY = self.data["max_priority"]
        except KeyError:
            self.MAX_PRIORITY = 20
        try:
            self.MAX_B = self.data["max_b"]
        except KeyError:
            self.MAX_B = 1000.0
      
    def reset_window(self, cpu):
        if self.started:
            self.window_id += 1
        else:
            self.started = True
        self.queue_index = 0
        #clean window
        self.timeline[self.window_id] = [job for job in self.timeline[self.window_id] if job[0].is_active()]

    def reschedule(self, cpu):
        cpu.resched()

    def on_activate(self, job):
        try:
            job.a = job.data['a']
            job.b = job.data['b']
        except KeyError:
            job.a = 0.0
            job.b = self.MAX_B
        if job.a == 1.0:
            job.a = 0.0
        try:
            job.priority = job.data["priority"]
        except KeyError:
            job.priority = 1.0
        
        self.ready_list.append(job)
        prev = len(self.timeline[self.window_id])
        wcet = job.wcet
        w_id = self.window_id
        while wcet > 0:
            if self.window_usage[w_id] > 0:
                f = ((job.b/float(self.MAX_B)) * ((self.MAX_PRIORITY-job.priority)/self.MAX_PRIORITY) * (1-job.a))
                slot = float("{0:.2f}".format(max(f * self.windowsize, 1.0)))
                slot = min(self.window_usage[w_id], slot)
                self.timeline[w_id].append((job, slot))
                self.window_usage[w_id] -= slot
                wcet -= slot
            w_id += 1
        deadline = self.windowsize * w_id + self.windowsize
        job._absolute_deadline = job._task._task_info.deadline = deadline    
            
        if prev == 0 and len(self.timeline[self.window_id]) > 0:
            job.cpu.resched()

    def on_terminated(self, job):
        if job in self.ready_list:
            self.ready_list.remove(job)
        self.preempt_timer.stop()
        seconds = (self.sim.now_ms() - job.activation_date) / 1000.0
        benefit = job.b * math.e ** (-job.a * seconds)
        job.add_custom_event(JobEvent(self, JobEvent.TEXTLABEL, data="{0:.2f}".format(benefit)))

    def schedule(self, cpu):
        now = self.sim.now_ms()
        remaining_time_in_window = float("{0:.2f}".format(self.windowsize - (now % self.windowsize)))
        if now % self.windowsize == 0:
            self.reset_window(cpu)
            cpu.monitor.observe(ProcEvent(ProcEvent.SEPARATOR))

        if remaining_time_in_window > 0:
            try:
                current_job = self.timeline[self.window_id][self.queue_index][0]
                # if job has still reserved cpu time
                if current_job.is_running() and now < current_job.absolute_burst:
                    return (current_job, cpu)
            except:
                pass            
            # burst has finished and next prioritary job is selected
            try:
                job, burst = self.timeline[self.window_id][self.queue_index]
            except Exception as e:
                available = [job[0] for job in self.timeline[self.window_id] if job[0].is_active()] + self.ready_list
                if len(available):
                    # Slack time, choose random job
                    job = choice(available)
                    burst = self.default_quantum
                else:
                    # Idle
                    return (None, cpu)

            burst = float("{0:.2f}".format(burst))
            if burst == 0: # gain time
                if self.ready_list:
                    job = choice(self.ready_list)
                burst = self.default_quantum
            # adjust burst
            ret = float("{0:.2f}".format(job.ret))
            burst = min(remaining_time_in_window, burst, ret)

            if burst == 0 and remaining_time_in_window > 0:
                burst = remaining_time_in_window

            self.preempt_timer = Timer(self.sim, BDPS.reschedule,
                              (self, self.processors[0]), burst,
                              one_shot=True, cpu=self.processors[0])
            job.absolute_burst = now + burst
            self.preempt_timer.start()                    

            self.queue_index += 1
            return (job, cpu)
Пример #52
0
class LLREF2(Scheduler):
    def init(self):
        self.selected_jobs = []  # Jobs currently running.
        self.budget = {}  # Budgets for the active jobs.
        self.next_deadline = 0
        self.waiting_schedule = False
        self.last_update = 0  # Used to update the budget.

    def reschedule(self, cpu=None):
        """
        Ask for a scheduling decision. Don't call if not necessary.
        """
        if not self.waiting_schedule:
            if cpu is None:
                cpu = self.processors[0]
            cpu.resched()
            self.waiting_schedule = True

    def on_activate(self, job):
        """
        Deal with a job activation. The budget for this job is computed.
        """
        if job.wcet == 0:
            return

        # Compute budget for this newly activated job
        window = self.next_deadline - self.sim.now()
        self.budget[job] = window * job.wcet / job.period

        # Find the next absolute deadline among the ready jobs.
        m_dl = min([rjob.absolute_deadline for rjob in self.budget.keys()]) \
            * self.sim.cycles_per_ms

        # Refill the budgets if we change the interval
        if m_dl != self.next_deadline:
            window = m_dl - self.next_deadline
            self.next_deadline = m_dl
            for j in self.budget.keys():
                self.budget[j] += window * j.wcet / j.period

        # There's a new job, the system should be rescheduled.
        self.reschedule()

    def on_terminated(self, job):
        if job in self.budget:
            del self.budget[job]

    def update_budget(self):
        """
        Remove budget from the currently executing jobs.
        """
        time_since_last_update = self.sim.now() - self.last_update
        for job in self.selected_jobs:
            if job in self.budget:
                if job.is_active():
                    self.budget[job] -= time_since_last_update
                else:
                    del self.budget[job]
        self.last_update = self.sim.now()

    def date_next_event(self, selected, not_selected):
        next_event = None

        if selected:
            next_bottom_hitting = min(ceil(y) for _, y in selected)
            next_event = next_bottom_hitting

        if not_selected:
            next_ceiling_hitting = self.next_deadline - self.sim.now() \
                - ceil(max(y for _, y in not_selected))
            if next_event is None or next_ceiling_hitting < next_event:
                next_event = next_ceiling_hitting

        return next_event if next_event else 0

    def select_jobs(self):
        window = self.next_deadline - self.sim.now()
        res = [(job, b) for job, b in self.budget.items()
               if window <= ceil(b) and job.is_active()]
        for job, b in sorted(self.budget.items(), key=lambda x: -x[1]):
            if b > 0 and (job, b) not in res and job.is_active():
                res.append((job, b))

        return (res[:len(self.processors)], res[len(self.processors):])

    def schedule(self, cpu):
        self.waiting_schedule = False
        self.update_budget()

        # Sort the jobs by budgets.
        selected, not_selected = self.select_jobs()

        # Compute the (relative) date of the next event.
        next_event = self.date_next_event(selected, not_selected)
        if next_event > 0:
            # Set a timer to reschedule the system at that date.
            self.timer_a = Timer(self.sim, LLREF2.reschedule, (self,),
                                 next_event, cpu=cpu, in_ms=False)
            self.timer_a.start()

        # Allocate the selected jobs to the processors.
        # The processors already running selected jobs are not changed.
        available_procs = []
        self.selected_jobs = [s[0] for s in selected]
        remaining_jobs = self.selected_jobs[:]
        for proc in self.processors:
            if proc.running in self.selected_jobs:
                # This processor keeps running the same job.
                remaining_jobs.remove(proc.running)
            else:
                # This processor is not running a selected job.
                available_procs.append(proc)

        # The remaining processors are running the remaining jobs or None.
        padded_remaining_jobs = remaining_jobs + \
            [None] * (len(available_procs) - len(remaining_jobs))
        # zip create a list of couples (job, proc) using the list of remaining
        # jobs and the list of available processors.
        decisions = list(zip(padded_remaining_jobs, available_procs))

        return decisions
Пример #53
0
    def schedule_0(self):
        """
        Schedule this proper sub-system.
        """

        self.to_reschedule = False
        decision = []            

        self.virtual = []

        active_servers = [s for s in self.root.children if not s.dummyServer and s.budget > 0]
        
        if self.is_idle is True and self.keep is False and active_servers:
            self.sim.logger.log("was idle in t {}".format(self.processors[0].name))
            servers = [s for s in self.root.children if not s.dummyServer]
            
            # Prolongamento do job dummy liberado em idle_time
            self.slack = algorithm_1(self, servers, self.sim.now())

            # tempo de computação total do job dummy liberado em idle_time
            delta = self.sim.now() - self.idle_time + self.slack
            self.sim.logger.log("original slack {} omega {}".format(self.slack, self.sim.now() - self.idle_time))

            # período ocioso exato delta
            self.processors[0].set_idle(delta)

            # Se houve prolongamento, o nível continua ocioso
            if self.slack > 0:
                self.add_timer(self.slack, self.processors[0])
                self.keep = True    
                self.is_idle = False
                
                self.slack += self.sim.now()
            # Caso contrário, o nível fica ocupado
            else:
                self.is_idle = False
                self.keep = False
        elif active_servers and self.sim.now() >= self.slack:
            self.is_idle = False
            self.keep = False

            # Processor level control
            if not self.busy:
                self.busy = True

            self.sim.logger.log("Servidores ativos, BUSY {}, slack {}".format(self.processors[0].name, self.slack))
        else:
            self.sim.logger.log("Sem servidores ativos, IDLE {}, slack {}".format(self.processors[0].name, self.slack))
            self.is_idle = True
            self.idle_time = self.sim.now()

            # se o tempo acabar antes de aglomerar
            # Sinaliza início da ociosidade para energy
            self.processors[0]._power.flag(self.sim.now())

        
        selected = select_jobs(self, self.root, self.virtual)

        idle = [s for s in selected if s.task.name == 'IdleTask']
        jobs = [s.job for s in selected if s.task.name != 'IdleTask' and s.task.name != "wcet"]


        """if (idle and not self.keep):
            
            servers = [s for s in self.root.children if not s.dummyServer]
            
            start_slack = min(servers, key=lambda s: s.next_deadline).next_deadline - self.sim.now()

            if start_slack > 2:

                self.slack = uni_algorithm_1(self, servers, self.sim.now()+start_slack)
                self.slack += start_slack

                #self.sim.logger.log("slack {}, sub {}, start {}".format(self.slack, self.identifier, start_slack))

                
                if int(self.slack) > 0 and self.utilization < 0.985:
                    self.add_timer(self.slack, self.processors[0])
                    self.keep = True
                else:
                    self.is_idle = False
                    self.keep = False
            
        """
        wakeup_delay = min([s.budget for s in self.virtual if s.budget > 0])
        
        
        """old = self.virtual
        while wakeup_delay == 0:
            old.remove(min_s)
            min_s = min(old, key=lambda s: s.budget)
            wakeup_delay = min_s.budget"""
        
        if wakeup_delay > 0:
            self.timer = Timer(self.sim, ProperSubsystem.virtual_event,
                                   (self, self.processors[0]), wakeup_delay,
                                   cpu=self.processors[0], in_ms=False)
            self.timer.start()

        cpus = []

        #first, leave already executing tasks on their current processors;
        for cpu in self.processors:
            if cpu.running in jobs:
                #cpus.append(cpu)
                jobs.remove(cpu.running) # remove job and cpu
            else:
                cpus.append(cpu)

        # second, assign previously idle tasks to their last-used processor, when its available
        aux_jobs = list(jobs)
        for job in aux_jobs:
            if job.task.last_cpu in cpus:
                decision.append((job, job.task.last_cpu))
                jobs.remove(job)
                cpus.remove(job.task.last_cpu)

       
        # third, assign remaining tasks to free processors arbitrarily
        for cpu in cpus:
            if jobs:
                decision.append((jobs.pop(), cpu))
            else:
                
                period = 0
                
                """if self.keep and self.slack > 0:
                    period = self.slack
                    #self.sim.logger.log("slack {}".format(self.slack))
                    self.slack = 0 
                    cpu.set_idle(period)
                elif not self.keep and idle:
                    period = next_activation(idle.pop()) - self.sim.now()
                    #self.sim.logger.log("next_activation {}".format(period))
                    cpu.set_idle(period)                
                """
                decision.append((None, cpu))
       
        return decision
Пример #54
0
class ProperSubsystem(object):
    """
    Proper sub-system. A proper sub-system is the set of the tasks belonging to
    a unit server (server with utilization of 1) and a set of processors.
    """

    def __init__(self, sim, root, processors):
        self.sim = sim
        self.root = root
        self.processors = processors
        self.virtual = []
        self.last_update = 0
        self.to_reschedule = False
        self.timer = None

    def update_budget(self):
        """
        Update the budget of the servers.
        """
        time_since_last_update = self.sim.now() - self.last_update
        for server in self.virtual:
            server.budget -= time_since_last_update
        self.last_update = self.sim.now()

    def resched(self, cpu):
        """
        Plannify a scheduling decision on processor cpu. Ignore it if already
        planned.
        """
        if not self.to_reschedule:
            self.to_reschedule = True
            cpu.resched()

    def virtual_event(self, cpu):
        """
        Virtual scheduling event. Happens when a virtual job terminates.
        """
        self.update_budget()
        self.resched(cpu)

    def schedule(self):
        """
        Schedule this proper sub-system.
        """
        self.to_reschedule = False
        decision = []

        self.virtual = []
        jobs = select_jobs(self.root, self.virtual)

        wakeup_delay = min(self.virtual, key=lambda s: s.budget).budget
        if wakeup_delay > 0:
            self.timer = Timer(self.sim, ProperSubsystem.virtual_event,
                               (self, self.processors[0]), wakeup_delay,
                               cpu=self.processors[0], in_ms=False)
            self.timer.start()

        cpus = []
        for cpu in self.processors:
            if cpu.running in jobs:
                jobs.remove(cpu.running)
            else:
                cpus.append(cpu)

        for cpu in cpus:
            if jobs:
                decision.append((jobs.pop(), cpu))
            else:
                decision.append((None, cpu))

        return decision
Пример #55
0
 def init(self):
     self.ready_list = []
     self.timer = Timer(self.sim, LLF.compute_laxity,
                        (self, self.processors[0]), 1, one_shot=False,
                        cpu=self.processors[0], overhead=.01)
     self.timer.start()
Пример #56
0
class LSTR(Scheduler):
    """
    Least Slack Time Rate First
    """

    def init(self):
        self.ready_list = []
        """
        However, LSTR
        scheduling algorithm operates on every basic time unit. Here, we consider the basic
        time unit of 1 (ms).
        """
        self.timer = Timer(self.sim, LSTR.virtual_event,
                           (self, self.processors[0]), 1, one_shot=False)
        self.timer.start()

    def virtual_event(self, cpu):
        self.reschedule(cpu)

    def reschedule(self, cpu):
        if self.ready_list:
            cpu.resched()

    def LSTR_rank(self, job):
        """
        calculates rank described in LSTR algorithm for given job
        return value should be non-negative, negative value means that job has passed deadline
        """
        if not job:
            return 0
        # print(job.absolute_deadline, job.deadline)
        din = job.absolute_deadline - self.sim.now_ms()
        if din == 0:
            return 0
        return job.ret / din

    def on_activate(self, job):
        self.ready_list.append(job)
        self.reschedule(job.cpu)

    def on_terminated(self, job):
        self.ready_list.remove(job)
        self.reschedule(job.cpu)

    def schedule(self, cpu):
        decision = []
        if self.ready_list:
            self.ready_list.sort(key=self.LSTR_rank, reverse=True)
            number_of_processors = len(self.processors)
            jobs = self.ready_list[:number_of_processors]

            available_proc = [p for p in self.processors if p.running not in jobs]
            for job in jobs:
                if job.is_running():
                    continue
                for cpu in available_proc:
                    job_on_cpu_rank = self.LSTR_rank(cpu.running)
                    if job_on_cpu_rank < self.LSTR_rank(job):
                        decision.append((job, cpu))
                        available_proc.remove(cpu)
                        break
        return decision
Пример #57
0
class U_EDF(Scheduler):
    def init(self):
        self.al = {}
        self.timer = None
        self.toresched = False
        self.running_jobs = {}
        self.last_event = 0
        self.newly_activated = False

        self.ui = {task: task.wcet / task.period for task in self.task_list}

    def reschedule(self):
        if not self.toresched:
            self.processors[0].resched()
        self.toresched = True

    def hp(self, job):
        for task in self.sorted_task_list:
            if task.job is job:
                return
            else:
                yield task.job

    def res(self, job, j, t1, t2):
        s = self.s[job]
        u = max(0, min(1, (s + self.ui[job.task] - j)))\
            - max(0, min(1, (s - j)))
        return (t2 - t1) * u

    def bdg(self, job, j, t2):
        return self.al[job][j] + self.res(
            job, j, job.absolute_deadline * self.sim.cycles_per_ms, t2)

    def compute_al(self):
        t = self.sim.now()
        cycles_per_ms = self.sim.cycles_per_ms

        self.sorted_task_list = sorted(
            self.task_list,
            key=lambda t: (t.job.absolute_deadline, t.identifier))

        self.s = {}
        for task in self.task_list:
            self.al[task.job] = [0] * len(self.processors)
            self.s[task.job] = sum(self.ui[x.task] for x in self.hp(task.job))

        for task in self.sorted_task_list:
            job = task.job

            if not job.is_active():
                continue

            for j in range(len(self.processors)):
                almax = (job.absolute_deadline * cycles_per_ms - t) \
                    - sum(self.bdg(x, j, job.absolute_deadline * cycles_per_ms)
                          for x in self.hp(job)) - sum(self.al[job])
                self.al[job][j] = int(ceil(min(
                    almax, job.ret * self.sim.cycles_per_ms
                    - sum(self.al[job]))))

    def on_activate(self, job):
        self.newly_activated = True
        self.reschedule()

    def update_al(self):
        delta = self.sim.now() - self.last_event

        for job, j in self.running_jobs.items():
            self.al[job][j] -= delta

    def schedule(self, cpu):
        self.toresched = False

        if self.newly_activated:
            self.compute_al()
            self.newly_activated = False
        else:
            self.update_al()

        self.last_event = self.sim.now()

        next_event = None
        decisions = []
        selected_jobs = {}

        # Select the jobs:
        for j, proc in enumerate(self.processors):
            eligible = [task.job for task in self.task_list
                        if task.job.is_active()
                        and task.job not in selected_jobs
                        and task.job in self.al
                        and self.al[task.job][j] > 0]

            if not eligible:
                continue

            job = min(eligible,
                      key=lambda x: (x.absolute_deadline, x.task.identifier))
            if next_event is None or next_event > self.al[job][j]:
                next_event = self.al[job][j]
            selected_jobs[job] = j

        # Set the timer for the next event:
        if self.timer:
            self.timer.stop()
            self.timer = None
        if next_event is not None:
            self.timer = Timer(self.sim, U_EDF.reschedule, (self,),
                               next_event, self.processors[0], in_ms=False)
            self.timer.start()

        # Bind jobs to processors:
        jobs = list(selected_jobs.keys())
        available_procs = list(self.processors)
        was_not_running = []
        for job in jobs:
            if job in self.running_jobs:
                available_procs.remove(job.cpu)
            else:
                was_not_running.append(job)

        remaining_jobs = []
        for job in was_not_running:
            if job.cpu in available_procs:
                decisions.append((job, job.cpu))
                available_procs.remove(job.cpu)
            else:
                remaining_jobs.append(job)

        for p, job in enumerate(remaining_jobs):
            decisions.append((job, available_procs[p]))

        self.running_jobs = selected_jobs

        return decisions
Пример #58
0
class ER_PD2(Scheduler):
    def init(self):
        self.ready_list = []
        self.timers = []
        self.terminate_timers = []
        self.waiting_schedule = False
        self.running_vjobs = []

        ER_PD2.quantum = self.sim.cycles_per_ms // 10 # 0.1ms.

        #ER_PD2.quantum = 1000000
        #while not self.is_schedulable() and ER_PD2.quantum > 1000:
        #    ER_PD2.quantum /= 2

        self.timer = Timer(
            self.sim, ER_PD2.reschedule, (self, ), ER_PD2.quantum,
            cpu=self.processors[0], in_ms=False, one_shot=False)
        self.timer.start()

    def is_schedulable(self, q=None):
        load = 0.0
        cycles_per_ms = self.sim.cycles_per_ms
        for task in self.task_list:
            wcet = rounded_wcet_cycles(task, q)
            load += wcet / task.period
            if wcet > task.period * cycles_per_ms \
                    or load > len(self.processors) * cycles_per_ms:
                return False
        return True

    def reschedule(self, cpu=None):
        """
        Ask for a scheduling decision. Don't call if not necessary.
        """
        if not self.waiting_schedule:
            if cpu is None:
                cpu = self.processors[0]
            cpu.resched()
            self.waiting_schedule = True

    def virtual_terminate(self, virtual_job):
        pjob = virtual_job.get_next_job()
        if not pjob or not virtual_job.job.is_active():
            self.ready_list.remove(virtual_job)

    def on_activate(self, job):
        virtual_job = VirtualJob(job)
        self.ready_list.append(virtual_job)

        if self.sim.now() == 0:
            self.reschedule()

    def schedule(self, cpu):
        self.waiting_schedule = False

        decisions = []

        for vjob in self.running_vjobs:
            self.virtual_terminate(vjob)

        vjobs = [vjob for vjob in self.ready_list if vjob.job.is_active()]

        self.running_vjobs = sorted(
            vjobs,
            key=lambda x: x.get_current_job().cmp_key()
        )[:len(self.processors)]

        selected_jobs = [vjob.job for vjob in self.running_vjobs]
        remaining_jobs = selected_jobs[:]
        available_procs = []

        # Remove from the list of remaining jobs the jobs that already runs.
        for proc in self.processors:
            if proc.running in selected_jobs:
                # This processor keeps running the same job.
                remaining_jobs.remove(proc.running)
            else:
                # This processor is not running a selected job.
                available_procs.append(proc)

        # Jobs not currently running
        for vjob in self.running_vjobs:
            if vjob.job in remaining_jobs:
                decisions.append((vjob.job, available_procs.pop()))

        # Unused processors
        for proc in available_procs:
            decisions.append((None, proc))

        return decisions
Пример #59
0
class Modified_EDF(Scheduler):
    def init(self):
        self.ready_list = []

        self.migrating_task1 = None  # sous la forme (task, rate)
        self.migrating_task2 = None
        self.migrating_job1 = None
        self.migrating_job2 = None

        self.next_deadline = 0

    def on_activate(self, job):
        self.ready_list.append(job)
        job.cpu.resched()

    def on_terminated(self, job):
        self.ready_list.remove(job)
        job.cpu.resched()

    def conf(self, next_deadline):
        if next_deadline > self.next_deadline:
            self.next_deadline = next_deadline
            self.migrating_task1, self.migrating_task2 = self.migrating_task2, self.migrating_task1
            if self.migrating_task1:
                time_a = ceil((next_deadline - self.sim.now()) * self.migrating_task1[1])
                self.timer_a = Timer(
                    self.sim, Modified_EDF.on_end_migrating1, (self,), time_a, cpu=self.processors[0], in_ms=False
                )
                self.timer_a.start()

            self.migrating_job2 = None
            if self.migrating_task2:
                time_b = int((next_deadline - self.sim.now()) * (1 - self.migrating_task2[1]))
                self.timer_b = Timer(
                    self.sim, Modified_EDF.on_start_migrating2, (self,), time_b, cpu=self.processors[0], in_ms=False
                )
                self.timer_b.start()
                self.processors[0].resched()

        if self.migrating_task1:
            self.migrating_job1 = self.migrating_task1[0].job
            self.processors[0].resched()
        else:
            self.migrating_job1 = None

    def on_end_migrating1(self):
        self.migrating_job1 = None
        self.processors[0].resched()

    def on_start_migrating2(self):
        self.migrating_job2 = self.migrating_task2[0].job
        self.processors[0].resched()

    def schedule(self, cpu):
        if self.migrating_job1 and self.migrating_job1.is_active():
            return (self.migrating_job1, cpu)
        if self.migrating_job2 and self.migrating_job2.is_active():
            return (self.migrating_job2, cpu)

        if self.ready_list:
            job = min(self.ready_list, key=lambda x: x.absolute_deadline)
        else:
            job = None

        return (job, cpu)
Пример #60
0
    def schedule(self, cpu):
        self.toresched = False

        if self.newly_activated:
            self.compute_al()
            self.newly_activated = False
        else:
            self.update_al()

        self.last_event = self.sim.now()

        next_event = None
        decisions = []
        selected_jobs = {}

        # Select the jobs:
        for j, proc in enumerate(self.processors):
            eligible = [task.job for task in self.task_list
                        if task.job.is_active()
                        and task.job not in selected_jobs
                        and task.job in self.al
                        and self.al[task.job][j] > 0]

            if not eligible:
                continue

            job = min(eligible,
                      key=lambda x: (x.absolute_deadline, x.task.identifier))
            if next_event is None or next_event > self.al[job][j]:
                next_event = self.al[job][j]
            selected_jobs[job] = j

        # Set the timer for the next event:
        if self.timer:
            self.timer.stop()
            self.timer = None
        if next_event is not None:
            self.timer = Timer(self.sim, U_EDF.reschedule, (self,),
                               next_event, self.processors[0], in_ms=False)
            self.timer.start()

        # Bind jobs to processors:
        jobs = list(selected_jobs.keys())
        available_procs = list(self.processors)
        was_not_running = []
        for job in jobs:
            if job in self.running_jobs:
                available_procs.remove(job.cpu)
            else:
                was_not_running.append(job)

        remaining_jobs = []
        for job in was_not_running:
            if job.cpu in available_procs:
                decisions.append((job, job.cpu))
                available_procs.remove(job.cpu)
            else:
                remaining_jobs.append(job)

        for p, job in enumerate(remaining_jobs):
            decisions.append((job, available_procs[p]))

        self.running_jobs = selected_jobs

        return decisions