def test_get_rta_of_taskset(self): tsk = Taskset("default") a = Task(2, 5000, 10000, 1, 1, 50000, 50000, 50000, 50000) b = Task(2, 5000, 10000, 2, 1, 50000, 50000, 50000, 50000) c = Task(2, 5000, 10000, 2, 1, 50000, 50000, 50000, 50000) d = Task(2, 5000, 10000, 1, 1, 50000, 50000, 50000, 50000) tsk.append(a) tsk.append(b) tsk.append(c) tsk.append(d) rta = tsk.get_high_util() self.assertEqual(rta, 0.2)
def test_get_lo_crit_utilization_of_taskset(self): tsk = Taskset("default") a = Task(1, 5000, 10000, 1, 1, 50000, 50000, 50000, 50000) b = Task(2, 5000, 10000, 2, 1, 50000, 50000, 50000, 50000) c = Task(1, 5000, 10000, 2, 1, 50000, 50000, 50000, 50000) d = Task(2, 5000, 10000, 1, 1, 50000, 50000, 50000, 50000) tsk.append(a) tsk.append(b) tsk.append(c) tsk.append(d) util = tsk.get_high_util() self.assertEqual(util, 0.2)
def __init__(self, file, folder="."): self.taskset = Taskset("ptamc") self.processed_taskset = Taskset("ptamc") self.file = folder + '/' + file self.pt_array = []
class PtAMC(AmcRtb): def __init__(self, file, folder="."): self.taskset = Taskset("ptamc") self.processed_taskset = Taskset("ptamc") self.file = folder + '/' + file self.pt_array = [] def __load_from_json(self, file=None): """Load taskset from json save.""" try: if file is None: file = self.file self.taskset.generate_taskset_from_json(file) except IOError: print("Error opening file {0}.\n".format(file)) def __assign_priorities(self): """Use amc-rtb approach to assign priority.""" self.taskset = self.assign_priorities(self.taskset) def __get_lo_crit_response_time(self, task): """get worst case response time in low crit mode.""" R_i_lo = task.c_lo high_prio_tasks = self.taskset.get_high_prio(task) for t in high_prio_tasks: R_i_lo += math.ceil(R_i_lo / t.t_lo) * t.c_lo return R_i_lo def __get_max_blocking(self, task, mode='normal'): """Determine the maximum blocking encountered by task in mode.""" B_i = 0 if mode == 'normal': interfer_tasks = self.taskset.get_taskset_low_crit_low_prio(task) for t in interfer_tasks: if self.pt_array[task.index] < self.pt_array[t.index]: B_i = max(B_i, t.c_lo) elif mode == 'high': interfer_tasks = self.taskset.get_taskset_high_crit_low_prio(task) for t in interfer_tasks: if self.pt_array[task.index] < self.pt_array[t.index]: B_i = max(B_i, t.c_hi) return B_i def __get_hi_crit_response_time(self, task): """Get worst case response time in high crit mode.""" R_i_hi = task.c_hi high_prio_tasks = self.taskset.get_taskset_low_crit_high_prio(task) for t in high_prio_tasks: R_i_hi += math.ceil(R_i_hi / t.t_hi) * t.c_lo return R_i_hi def __get_worst_case_response_time(self, task): """Get the worst case response time for task in crit transition.""" # First find the level i Busy Period in low crit mode. # tasks with priority greater than or equal to task. taskset_hep = self.taskset.get_high_equal_prio_tasks(task) B_i_lo = self.__get_max_blocking(task, "normal") LBP_i_lo = B_i_lo for t in taskset_hep: LBP_i_lo += math.ceil(LBP_i_lo / t.t_lo) * t.c_lo R_i_trans = 0 for q in range(int(math.floor(LBP_i_lo / task.t_lo))): R_i_trans = max(R_i_trans, self.__get_transition_response_time(task, q)) return R_i_trans def __get_transition_response_time(self, task, q=0): """Response time for transition from low to high crit.""" # Determine worst case starting point of task while in low criticality # mode. B_i_lo = self.__get_max_blocking(task, "normal") B_i_hi = self.__get_max_blocking(task, "high") S_i_q_lo = B_i_lo + q * task.c_lo high_prio_tasks = self.taskset.get_prio_tasks(task) for task in high_prio_tasks: S_i_q_lo += (1 + math.floor(S_i_q_lo / task.pr_lo)) * task.c_lo # Determine worst case stopping time. F_i_q_lo = S_i_q_lo + task.c_lo for t in high_prio_tasks: F_i_q_lo += (math.ceil(F_i_q_lo / t.t_lo) - (1 + math.floor(S_i_q_lo / t.t_lo)) * t.c_lo) # Determine the worst case blocking while in transition to high crit. # Assuming no offset release of the task. if q == 0: B_i_q_tran = max(B_i_hi, B_i_lo) else: B_i_q_tran = B_i_lo # Determine Worst case starting point while in criticality transition. high_prio_lo_crit_tasks = self.taskset.get_taskset_low_crit_high_prio( task) high_prio_hi_crit_tasks = self.taskset.get_taskset_high_crit_high_prio( task) S_i_q_trans = B_i_q_tran + q * task.c_lo for t in high_prio_lo_crit_tasks: S_i_q_trans += math.ceil(S_i_q_lo / t.t_lo) * t.c_lo for t in high_prio_hi_crit_tasks: S_i_q_trans += (1 + math.floor(S_i_q_trans / t.t_lo)) * t.c_hi # Worst case completion time during criticality transition when transition # occurs before S_i_q_lo. F_i_q_trans_bf = S_i_q_trans + task.c_hi for t in high_prio_hi_crit_tasks: F_i_q_trans_bf += ((math.ceil(F_i_q_trans_bf / t.t_lo) - (1 + math.floor(S_i_q_trans / t.t_lo))) * task.c_hi) # Worst case completion time during criticality transition, when transition # occurs after S_i_q_lo F_i_q_trans_af = S_i_q_lo + task.c_hi for t in high_prio_lo_crit_tasks: F_i_q_trans_af += ((math.ceil(F_i_q_lo / t.t_lo) - (1 + math.floor(S_i_q_lo / t.t_lo))) * task.c_lo) for t in high_prio_hi_crit_tasks: F_i_q_trans_af += ((math.ceil(F_i_q_trans_af / t.t_lo) - (1 + math.floor(S_i_q_lo / t.t_lo))) * t.c_hi) R_i_q = max(F_i_q_trans_bf, F_i_q_trans_af) - q * t.t_lo return R_i_q def __is_taskset_schedulable(self): """Sufficient schedulability test for pt-amc. Two necessary conditions are checked: 1. Schedulability in low criticality. 2. Schedulability in high crit in transition. """ Lo_schedulable = True Hi_schedulable = True for task in self.taskset: if self.__get_lo_crit_response_time(task) < task.d_lo: continue else: Lo_schedulable = False break if Lo_schedulable: hi_tasks = self.taskset.get_tasks_by_crit('high') for task in hi_tasks: trans_rta = self.__get_transition_response_time(task) hi_rta = self.__get_hi_crit_response_time(task) if max(trans_rta, hi_rta) < task.d_lo: continue else: Hi_schedulable = False break return Lo_schedulable and Hi_schedulable def __generate_preemption_threshold(self): """Maximal Preemption Threshold Assignment Algorithm(MPTAA) implementation. pt_array set with task preemption values, index corresponds to task index in taskset object. """ no_tasks = len(self.taskset) pt_array = [self.taskset[i].prio for i in range(no_tasks)] for i in reversed(range(no_tasks)): schedulable = True j = i + 1 while schedulable and pt_array[i] < no_tasks: self.pt_array[i] += 1 schedulable = self.__is_taskset_schedulable() if not schedulable: if pt_array[i]: pt_array[i] -= 1 else: ValueError( "Negative preemption threshold assignment.\n") j = j + 1 if j >= no_tasks: break for i in range(no_tasks): self.processed_taskset[i].pt = pt_array[ i] # Assign the calculated preemption threshold to the taskset. def get_processed_taskset(self): return self.processed_taskset def generate_ptamc(self, file): """Generate ptamc schedule for taskset given in json file.""" self.__load_from_json(file) self.__generate_preemption_threshold() return self.processed_taskset
def __init__(self, folder=None, file=None): self.folder = folder self.file = folder + '/' + file self.taskset = Taskset() self.processed_taskset = None self.slack_vectors = []
class Zss: def __init__(self, folder=None, file=None): self.folder = folder self.file = folder + '/' + file self.taskset = Taskset() self.processed_taskset = None self.slack_vectors = [] @staticmethod def __create_slack_instance(start, duration): """Create a new slack tuple: (start time, duratiom)""" slack_instance = { "budget": duration, "start": start, "deadline": start + duration } return slack_instance @staticmethod def __sort_slack(slacklist): """Sort slack by start time.""" return sorted(slacklist, key=lambda x: x[0]) def __retrieve_taskset(self): """Load tasksets from json file.""" json_taskset = [] self.taskset.generate_taskset_from_json(self.file) print("loaded {0} tasksets from files".format(len(self.taskset))) def __save_zero_slack_taskset(self): """Create output folder and save the calculated taskset.""" output_dir = self.folder + 'output' try: os.makedirs(self.folder + 'output') except OSError as exception: if exception.errno != errno.EEXIST: raise FileExistsError(errno) file_name = output_dir + str("zss") + '_taskset_processed.json' self.taskset.save_taskset_to_json(file_name) print("wrote {0} tasksets to {1} directory.\n", len(self.taskset), output_dir) @staticmethod def __get_conditional_taskset(task, taskset, condition_check): """Filter given taskset as per the given condition check function.""" filtered_taskset = [] for t in taskset: if condition_check(task, t): filtered_taskset.append(task) return filtered_taskset @staticmethod def __start_of_trailing_slack(t_i, slack_vec): """Get instance of trailing slack to given task.""" b_i = t_i.budget # Task budget. d_i = t_i.deadline # Task deadline. trailing_slack_start = -1 status = True index = 0 rev_slack_vec = sorted(slack_vec, key=lambda x: x["deadline"], reverse=True) for i, slack in enumerate(rev_slack_vec): # Slack needs to be searched for deadline upto the deadline of # task being tested. if slack.deadline <= d_i: index = i break if (index): slack_accumulated = 0 for slack in rev_slack_vec[index:]: # Search for slack instance able to meet budget in c mode. slack_accumulated += slack["budget"] if slack_accumulated >= b_i: trailing_slack_start = slack[ "start"] # Coarse starting time of slack. break if slack_accumulated <= b_i: # Couldn't find enough slack for t_i. status = False else: status = False return (status, trailing_slack_start) @staticmethod def __get_slack_upto_instance(slack_vec, slack_instance, t_i): """Total available slack upto slack_instance.""" avail_slack = 0 slack_index = 0 for index, slack in enumerate(slack_vec): if slack_instance <= slack["start"]: slack_index = index break if slack_index: for slack in slack_vec: if t_i.budget <= avail_slack: break else: avail_slack += slack["budget"] return avail_slack @staticmethod def __get_zero_slack_instant(task, norm_slack, high_slack): """Calculate the maximum available slack.""" pass @staticmethod def __get_effective_budget(task, prio, mode): """Get the effective execution budget for task.""" effective_budget = 0 if task.prio > prio: if task.crit == 'normal': effective_budget = task.b_lo else: effective_budget = task.b_hi else: if task.crit == 'high': effective_budget = task.b_lo - task.slack return effective_budget def __get_slack_vector(self, task, taskset, mode='normal'): """An ordered list of slacks available in the given given taskset. Implementation for a rate-monotonic approach. implementation and notations as per Algorithm-3 in paper. """ C_i_v = 0 R_current = C_i_v interfering_tasks_c = self.taskset.__get_taskset_high_crit_high_prio( task) interfering_tasks_n = self.taskset.__get_taskset_normal_crit_high_prio( task) while (R_current >= t.period): R_previous = R_current b = 0 while R_previous == R_current or R_current <= t: R_prevous = R_current R_current = C_i_v + self.__get_effective_budget(R_previous) b = t for task in taskset: A = math.ceil(R_previous / task.period) * task.budget if A < b: A = b I_m = task if R_previous == R_current: R_current = R_current + self.__get_effective_budget( I_m, mode) @staticmethod def __are_vectors_equal(vec1, vec2): """Vector element wise comparator""" status = True if len(vec1) != len(vec2): raise ValueError("List should be of same size.\n") len_vec = len(vec1) comparator_list = [ vec1[n].budget == vec2[n].budget for n in range(len_vec) ] for flag in comparator_list: if not flag: status = False return status def __compute_final_slack_instant(self, taskset): """Calculate the zero slack instance of taskset.""" slack_instant = None slack_before_cycle = [] slack_after_cycle = [] taskset_high_crit = taskset.__get_tasks_by_crit(taskset, 'high') while slack_before_cycle != slack_after_cycle: slack_before_cycle = slack_after_cycle for index, task in enumerate(taskset): normal_slack_vec = self.__get_slack_vector(task, taskset) high_slack_vec = self.__get_slack_vector( task, taskset_high_crit) slack_after_cycle = self.__get_zero_slack_instant( task, normal_slack_vec, high_slack_vec) # Stop when no more slack movement can be made between normal and # critical mode. if self.__are_vectors_equal(slack_before_cycle, slack_after_cycle): break def do_zero_slack_assignment(self): """public function to invoke zero slack calculation.""" for taskset in self.tasksets: zss_taskset = self.__computer_final_slack_instant(taskset)
def test_add_remove_task_from_taskset(self): a = Taskset("default") b = Task(2, 5000, 10000, 1, 1, 50000, 50000, 50000, 50000) a.append(b) c = a.pop() self.assertEqual(b.crit, c.crit)
def test_create_taskset(self): A = Taskset("default") self.assertEqual(A.scheduler, "default")