def __init__(self): GraphObject.__init__(self, "SystemGraph", root = True) PassManager.__init__(self, self) self.counters = [] self.tasks = [] self.functions = {} self.all_abbs = {} self.label = "SystemGraph" self.max_abb_id = 0 self.system = None self.rtsc = None self.llvmpy = None self.alarms = [] self.isrs = [] self.resources = {} self.stats = Statistics(self)
def __init__(self, configuration): GraphObject.__init__(self, "SystemGraph", root=True) PassManager.__init__(self, self) self.label = "SystemGraph" # System Objects self._counters = {} self._tasks = {} self._subtasks = {} self._alarms = {} self._isrs = {} self._resources = {} self._checkedObjects = {} self._events = {} # Application Objects self._functions = {} self._abbs = {} self.system = None self.llvmpy = None self.stats = Statistics(self) self.conf = configuration self.impl = None
source_dir = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, os.path.abspath(os.path.join(source_dir, ".."))) from generator.statistics import Statistics usage = "usage: %prog [options]" parser = optparse.OptionParser(usage=usage) parser.add_option("", "--stats-dict", metavar="STATS_DICT", help="the dict with the statistics") parser.add_option("", "--elf", metavar="ELF", help="The elf file") (options, args) = parser.parse_args() if len(args) > 0: parser.print_help() sys.exit(-1) symbols = read_symbols(options.elf) stats = Statistics.load(options.stats_dict) for abb in stats.find_all("AtomicBasicBlock").values(): if not 'generated-function' in abb: continue abb["generated-codesize"] = 0 for func in abb['generated-function']: abb["generated-codesize"] += get_size(symbols, func) stats.save(options.stats_dict)
class SystemGraph(GraphObject, PassManager): """A system graph makes up an whole system, including the to be produces system blocks""" class MockSubtaskConfig: def __init__(self): self.static_priority = 0 self.is_isr = False self.preemptable = True self.autostart = True self.basic_task = False self.max_activations = 0 def __init__(self, configuration): GraphObject.__init__(self, "SystemGraph", root=True) PassManager.__init__(self, self) self.label = "SystemGraph" # System Objects self._counters = {} self._tasks = {} self._subtasks = {} self._alarms = {} self._isrs = {} self._resources = {} self._checkedObjects = {} self._events = {} # Application Objects self._functions = {} self._abbs = {} self.system = None self.llvmpy = None self.stats = Statistics(self) self.conf = configuration self.impl = None # Accessors for System Objects @property def tasks(self): return self._tasks.values() @property def subtasks(self): return self._subtasks.values() @property def user_subtasks(self): return [x for x in self.subtasks if x.is_user_thread()] @property def real_subtasks(self): return [x for x in self.subtasks if x.is_real_thread()] @property def resources(self): return self._resources.values() @property def alarms(self): return self._alarms.values() @property def counters(self): return self._counters.values() @property def isrs(self): return self._isrs.values() @property def checkedObjects(self): return self._checkedObjects.values() @property def events(self): return self._events.values() @property def functions(self): return self._functions.values() @property def abbs(self): return self._abbs.values() @property def syscalls(self): return [x for x in self.abbs if not x.isA(S.computation)] @property def real_syscalls(self): return [ x for x in self.abbs if not x.isA(S.computation) and x.syscall_type.isRealSyscall() ] @property def implemented_syscalls(self): within_app = [ x for x in self.abbs if not x.isA(S.computation) and x.syscall_type.isImplementedSyscall() ] return within_app def find(self, cls, name): """Get System object by class and name. If system object does not exist, this function will return None. """ if issubclass(cls, Alarm): return self._alarms.get(name) if issubclass(cls, Counter): return self._counters.get(name) if issubclass(cls, Task): return self._tasks.get(name) if issubclass(cls, Resource): return self._resources.get(name) if issubclass(cls, ISR): return self._isrs.get(name) # Must be before Function, since Subtask inherits from Function if issubclass(cls, Subtask): return self._subtasks.get(name) if issubclass(cls, Function): return self._functions.get(name) if issubclass(cls, AtomicBasicBlock): return self._abbs.get(name) assert False, "cls(%s) not supported by SystemGraph.find()" % cls def get(self, cls, name): """Lile .find, but raises an exception if object does not exists""" x = self.find(cls, name) assert x is not None, "System Object not found (%s, %s)" %\ (cls, name) return x def graph_subobjects(self): """Method used by GraphObject to draw the .dot files""" objects = [] sub_objects = set() for task in self.tasks: objects.append(task) sub_objects.update(set(task.graph_subobjects())) for function in self.functions: if not self.passes["AddFunctionCalls"].is_relevant_function( function): continue if function not in sub_objects: objects.append(function) return objects def new_abb(self, bbs=[]): abb = AtomicBasicBlock(self, bbs) self._abbs[abb.get_id()] = abb return abb def remove_abb(self, abb_id): del self._abbs[abb_id] def find_syscall(self, function, syscall_type, arguments, multiple=False): abbs = [] for abb in function.abbs: if abb.isA(syscall_type) \ and (arguments == None or abb.arguments == arguments): abbs.append(abb) if multiple: return abbs assert len(abbs) == 1, "System call %s::%s(%s) is ambigious" % ( function, type, arguments) return abbs[0] def add_system_objects(self): def system_function(syscall_type): function = Function(syscall_type.name) self._functions[syscall_type.name] = function abb = self.new_abb() function.add_atomic_basic_block(abb) function.set_entry_abb(abb) abb.make_it_a_syscall(syscall_type, []) return function # Add Idle Task system_task = Task(self, "OSEK") self.system_task = system_task self._tasks["OSEK"] = system_task idle_subtask = Subtask(self, "Idle", "Idle", self.MockSubtaskConfig()) self._functions["Idle"] = idle_subtask self._subtasks["Idle"] = idle_subtask self.idle_subtask = idle_subtask system_task.add_subtask(idle_subtask) # The idle systemcall abb_computation = self.new_abb() idle_subtask.add_atomic_basic_block(abb_computation) idle_subtask.set_entry_abb(abb_computation) abb_idle = self.new_abb() idle_subtask.add_atomic_basic_block(abb_idle) abb_idle.make_it_a_syscall(S.Idle, []) # Edges abb_idle.add_cfg_edge(abb_computation, E.function_level) abb_computation.add_cfg_edge(abb_idle, E.function_level) # System Functions StartOS = system_function(S.StartOS) system_task.add_function(StartOS) # Structure for Statistics logging self.stats.add_child(self, "task", system_task) self.stats.add_child(system_task, "subtask", idle_subtask) def who_has_prio(self, priority): # We Inherit PassManager! # FIXME: Ugly hack assert self.passes["PrioritySpreadingPass"].valid return self.passes["PrioritySpreadingPass"].prio_to_participant[ priority] def fsck(self): functions = set() abbs = set() for task in self.tasks: task.fsck() assert task.system_graph == self for subtask in task.subtasks: subtask.fsck() assert subtask.system_graph == self functions.add(subtask) abbs.update(set(subtask.abbs)) assert functions.issubset(set(self.functions)) for func in self.functions: abbs.update(set(func.abbs)) for abb in abbs: abb.fsck() for system_pass in self.passes.values(): if system_pass.valid and hasattr(system_pass, "fsck"): system_pass.fsck()
def main(options, args): symbols = [x for x in read_symbols(options.elf) if x.addr] symbol_map = SymbolMap(symbols) trace_events = read_trace(options.traceplugin, options.trace) stats = Statistics.load(options.stats) for abb in stats.find_all("AtomicBasicBlock").values(): if not 'generated-function' in abb: continue abb["activations"] = [] sysgraph = stats.find_all("SystemGraph").values()[0] IncrementCounter = { "_id": id(main), "_type": "AtomicBasicBlock", "_name": "ABB-10/IncrementCounter", "generated-function": ["__OS_syscall_OSEKOS_IncrementCounter"], "activations": [], "symbols": [] } sysgraph["alarms"] = [IncrementCounter] stats.rebuild_index(sysgraph) region_iterator = iter(syscall_regions(trace_events, symbol_map)) delayed_regions = [] while region_iterator or len(delayed_regions): if region_iterator: try: syscall_region = next(region_iterator) except StopIteration: region_iterator = None print "trace-analyze: Processing %d delayed interrupt regions" % ( len(delayed_regions)) continue syscall_region, interrupt_region = cut_out_timer_interrupt( syscall_region) if interrupt_region: delayed_regions.append(interrupt_region) else: syscall_region = delayed_regions.pop() names = [x[1].name for x in syscall_region.trace if x[1]] region_length = sum([x[0] for x in syscall_region.trace]) event_type = None # fixup names with asm labels for i in range(0, len(names)): if ".asm_label.syscall_start" in names[i]: m = re.subn("^.asm_label.syscall_start_(.*)_[0-9]+$", "\\1", names[i]) names[i] = m[0] for name in names: if "__OS_syscall" in name: assert event_type is None, (names, options.stats) event_type = name if name in ("__OS_StartOS_dispatch"): assert event_type is None, (names, options.stats) event_type = name # If it does not contain a syscall, use the userland function # names (e.g. the start end markers) if event_type == None: for name in names: if "OSEKOS" in name and "__ABB" in name: # Might also be an ISR assert event_type is None or "irq_handler" in names[ 0], names event_type = name for abb in stats.find_all("AtomicBasicBlock").values(): if not 'generated-function' in abb: continue if event_type in abb["generated-function"]: trace_info = { "cycles": region_length, "trace": [(x[0], x[1].name) for x in syscall_region.trace], "start-time": syscall_region.start_time, "end-time": syscall_region.end_time, } abb["activations"].append(trace_info) if event_type == "__OS_syscall_OSEKOS_IncrementCounter": IncrementCounter["symbols"] = list( set(IncrementCounter["symbols"]) | set(names)) IncrementCounter["generated-codesize"] = 0 for symbol in IncrementCounter["symbols"]: if symbol in symbol_map: symbol = symbol_map[symbol] if symbol.size: IncrementCounter["generated-codesize"] += symbol.size print options.stats stats.save(options.stats)
class SystemGraph(GraphObject, PassManager): """A system graph makes up an whole system, including the to be produces system blocks""" def __init__(self): GraphObject.__init__(self, "SystemGraph", root = True) PassManager.__init__(self, self) self.counters = [] self.tasks = [] self.functions = {} self.all_abbs = {} self.label = "SystemGraph" self.max_abb_id = 0 self.system = None self.rtsc = None self.llvmpy = None self.alarms = [] self.isrs = [] self.resources = {} self.stats = Statistics(self) def graph_subobjects(self): objects = [] sub_objects = set() for task in self.tasks: objects.append(task) sub_objects.update(set(task.graph_subobjects())) for function in self.functions.values(): if not self.passes["AddFunctionCalls"].is_relevant_function(function): continue if not function in sub_objects: objects.append(function) return objects def find_function(self, name): """ :rtype : generator.graph.Function """ return self.functions.get(name, None) def find_abb(self, abb_id): return self.all_abbs[abb_id] def remove_abb(self, abb_id): del self.all_abbs[abb_id] def get_abbs(self): return self.all_abbs.values() def get_subtasks(self): subtasks = [] for x in self.tasks: subtasks.extend(x.subtasks) return sorted(subtasks, key=lambda t: t.name) def get_subtask(self, name): for x in self.tasks: for subtask in x.subtasks: if subtask.name == name: return subtask def find_syscall(self, function, syscall_type, arguments, multiple = False): abbs = [] for abb in function.abbs: if abb.isA(syscall_type) \ and abb.arguments == arguments: abbs.append(abb) if multiple: return abbs assert len(abbs) == 1, "System call %s::%s(%s) is ambigious" %(function, type, arguments) return abbs[0] def get_syscalls(self): return [x for x in self.get_abbs() if not x.isA(S.computation)] def scheduler_priority(self): """The scheduler priority is higher than the highest task""" return max([x.static_priority for x in self.get_subtasks()]) + 1 def read_oil_system_description(self, system): """Reads in the system description out of an OIL file and builds the tasks and subtask objects and connects them""" maxprio = 0 # Maximum task prio according to OIL file for task_desc in system.getTasks(): taskname = task_desc.name task = Task(self, "Task:" + taskname) self.tasks.append(task) self.stats.add_child(self, "task", task) subtask = Subtask(self, taskname, "OSEKOS_TASK_" + taskname) # Every subtask belongs to a task task.add_subtask(subtask) # Every subtask is also a function self.functions[subtask.function_name] = subtask self.stats.add_child(task, "subtask", subtask) assert task_desc.priority != 0, \ "No user thread can have the priority 0, reserved for the idle thread" subtask.set_static_priority(task_desc.priority) if task_desc.priority > maxprio: maxprio = task_desc.priority subtask.set_preemptable(task_desc.preemptable) subtask.set_basic_task(True) subtask.set_max_activations(task_desc.max_activations) subtask.set_autostart(task_desc.autostart) subtask.set_is_isr(False) self.stats.add_data(subtask, "is_isr", False, scalar = True) # ISR isr_prio = maxprio + 1 # ISR get priorities above maximum task prio for isr_desc in system.getISRs(): task = Task(self, "ISRTask:" + isr_desc.name) self.tasks.append(task) self.stats.add_child(self, "task", task) subtask = Subtask(self, isr_desc.name, "OSEKOS_ISR_" + isr_desc.name) task.add_subtask(subtask) self.functions[subtask.function_name] = subtask self.stats.add_child(task, "subtask", subtask) prio = isr_desc.PRIORITY if prio == -1: prio = isr_prio isr_prio = isr_prio + 1 # increment isr prio subtask.set_static_priority(prio) # Assumption: Our subtasks are non-preemptable basic-tasks subtask.set_preemptable(False) subtask.set_basic_task(True) subtask.set_max_activations(1) subtask.set_autostart(False) subtask.set_is_isr(True, isr_desc.device) self.stats.add_data(subtask, "is_isr", True, scalar = True) self.isrs.append(ISR(self, subtask)) # Counters Counter = namedtuple("Counter", ["name", "maxallowedvalue", "ticksperbase", "mincycle"]) for ctr in system.getCounters(): self.counters.append(Counter(name = ctr.name, maxallowedvalue = ctr.MAXALLOWEDVALUE, ticksperbase = ctr.TICKSPERBASE, mincycle = ctr.MINCYCLE)) # Alarms for alarm in system.getAlarms(): assert alarm.activated_task() != None, "Alarm does not activate any task! (maybe callback?)" activated_subtask = self.functions["OSEKOS_TASK_" + alarm.activated_task()] belongs_to_task = activated_subtask.task # Generate an Alarm Handler SubTask name = "OSEKOS_ALARM_HANDLER_" + alarm.name subtask = Subtask(self, alarm.name, name) subtask.set_static_priority(1<<31) subtask.set_preemptable(False) subtask.set_basic_task(True) subtask.set_max_activations(1) subtask.set_autostart(False) subtask.set_is_isr(True) # And add it to the task where the activated task belongs to belongs_to_task.add_subtask(subtask) self.functions[subtask.function_name] = subtask self.alarms.append(Alarm(self, subtask, alarm, activated_subtask)) # Resources for res in system.getResources(): self.resources[res.name] = Resource(self, res.name, res.tasks) if not "RES_SCHEDULER" in self.resources: sched = "RES_SCHEDULER" subtasks = [x.name for x in self.get_subtasks() if not x.is_isr] self.resources[sched] = Resource(self, sched, subtasks) def read_xml_system_description(self, system): """Reads in the system description out of an XML file and builds the tasks and subtask objects and connects them""" for task_desc in system.getTasks(): task = Task(self, "Task:by-event:" + task_desc.event[0]) task.set_event(task_desc.event) task.set_promises(task_desc.promises) self.tasks.append(task) self.stats.add_child(self, "task", task) for subtask_name, deadline in task_desc.subtasks.items(): isISR = system.isISR(subtask_name) if isISR: subtask = Subtask(self, subtask_name, "OSEKOS_ISR_" + subtask_name) else: subtask = Subtask(self, subtask_name, "OSEKOS_TASK_" + subtask_name) # Every subtask belongs to a task task.add_subtask(subtask) # Every subtask is also an function self.functions[subtask.function_name] = subtask self.stats.add_child(task, "subtask", subtask) subtask.set_deadline(deadline) if isISR: isr_osek = system.getISR(subtask_name) subtask.set_static_priority(isr_osek.priority) # Assumption: Our subtasks are non-preemptable basic-tasks subtask.set_preemptable(False) subtask.set_basic_task(True) subtask.set_max_activations(1) subtask.set_autostart(False) subtask.set_is_isr(True, isr_osek.device) self.stats.add_data(subtask, "is_isr", True, scalar = True) self.isrs.append(ISR(self, subtask)) else: subtask_osek = system.getSubTask(subtask_name) assert subtask_osek.static_priority != 0, \ "No user thread can have the thread ID 0, it is reserved for the Idle thread" subtask.set_static_priority(subtask_osek.static_priority) subtask.set_preemptable(subtask_osek.preemptable) subtask.set_basic_task(subtask_osek.is_basic) subtask.set_max_activations(subtask_osek.max_activations) subtask.set_autostart(subtask_osek.autostart) subtask.set_is_isr(False) self.stats.add_data(subtask, "is_isr", False, scalar = True) self.counters = system.getHardwareCounters() for alarm in system.getAlarms(): activated_subtask = self.functions["OSEKOS_TASK_" + alarm.task] belongs_to_task = activated_subtask.task # Generate a Alarm Handler SubTask name = "OSEKOS_ALARM_HANDLER_" + alarm.name subtask = Subtask(self, alarm.name, name) subtask.set_static_priority(1<<31) subtask.set_preemptable(False) subtask.set_basic_task(True) subtask.set_max_activations(1) subtask.set_autostart(False) subtask.set_is_isr(True) # And add it to the task where the activated task belongs to belongs_to_task.add_subtask(subtask) self.functions[subtask.function_name] = subtask self.alarms.append(Alarm(self, subtask, alarm, activated_subtask)) for res in system.getResources(): self.resources[res.name] = Resource(self, res.name, res.tasks) if not "RES_SCHEDULER" in self.resources: sched = "RES_SCHEDULER" subtasks = [x.name for x in self.get_subtasks() if not x.is_isr] self.resources[sched] = Resource(self, sched, subtasks) def read_llvmpy_analysis(self, llvmpy): self.llvmpy = llvmpy self.max_abb_id = 0 # Gather functions for llvmfunc,llvmbbs in self.llvmpy.functions.items(): function = self.functions.get(llvmfunc.name) if function == None: # Not existing yet, just add it... function = Function(llvmfunc.name) self.functions[llvmfunc.name] = function # Add llvm function object function.set_llvm_function(llvmfunc) # Add ABBs for bb in llvmbbs: abb = self.new_abb([bb]) function.add_atomic_basic_block(abb) # and set entry abb if bb.llvmbb is llvmfunc.entry_basic_block: function.set_entry_abb(abb) # make it a syscall and add arguments if bb.is_syscall(): abb.make_it_a_syscall(bb.get_syscall(), bb.get_syscall_arguments()) # Rename syscall in llvm IR, appending ABB id bb.rename_syscall(abb, llvmpy.get_source()) # Generate an ActivateTask for every alarm for alarm in self.alarms: activate_task = self.new_abb() alarm.handler.add_atomic_basic_block(activate_task) alarm.handler.set_entry_abb(activate_task) activate_task.make_it_a_syscall(S.ActivateTask, [alarm.subtask]) alarm.carried_syscall = activate_task # Statistic generation self.stats.add_child(alarm.handler.task, "subtask", alarm.handler) # Add all implicit intra function control flow graphs for functionname, func in self.functions.items(): for abb in func.abbs: exit_bb = abb.get_exit_bb() if not exit_bb: #logging.info("llvmpy_analysis, intra function CFG -> skipping: %s", abb.dump()) continue nextbbs = exit_bb.get_outgoing_nodes(E.basicblock_level) for bb in nextbbs: nextabb = bb.get_parent_ABB() abb.add_cfg_edge(nextabb, E.function_level) # Find all return blocks for functions for function in self.functions.values(): ret_abbs = [] for abb in function.abbs: if len(abb.get_outgoing_edges(E.function_level)) == 0: ret_abbs.append(abb) if len(ret_abbs) == 0: logging.info("Endless loop in %s", function) elif len(ret_abbs) > 1: # Add an artificial exit block abb = self.new_abb() function.add_atomic_basic_block(abb) for ret in ret_abbs: ret.add_cfg_edge(abb, E.function_level) function.set_exit_abb(abb) else: function.set_exit_abb(ret_abbs[0]) if isinstance(function, Subtask) and function.is_isr: # All ISR function get an additional iret block iret = self.new_abb() function.add_atomic_basic_block(iret) iret.make_it_a_syscall(S.iret, [function]) function.exit_abb.add_cfg_edge(iret, E.function_level) function.set_exit_abb(iret) # Gather all called Functions in the ABBs, this has to be done, after all ABBs are present for abb in self.get_abbs(): called_funcs = set() # Visit all BBs and gather all called Functions for bb in abb.get_basic_blocks(): if bb.calls_function(): callee = self.find_function(bb.calledFunc.name) if callee: called_funcs.add(callee) abb.called_functions.add(callee) # Populate function level set of called functions, needed in ABBMergePass abb.function.called_functions.update(called_funcs) def read_rtsc_analysis(self, rtsc): self.rtsc = rtsc self.max_abb_id = 0 # Add all atomic basic blocks for abb_xml in rtsc.get_abbs(): abb = AtomicBasicBlock(self, abb_xml.id) self.max_abb_id = max(self.max_abb_id, abb_xml.id) ## add to global abb dict for faster search self.all_abbs[abb.get_id()] = abb # Get function for abb function = self.functions.get(abb_xml.in_function) if function == None: # Not existing yet, just add it function = Function(abb_xml.in_function) self.functions[abb_xml.in_function] = function function.add_atomic_basic_block(abb) if abb_xml.func_entry: function.set_entry_abb(abb) # Generate an ActivateTask for every alarm for alarm in self.alarms: activate_task = self.new_abb() alarm.handler.add_atomic_basic_block(activate_task) alarm.handler.set_entry_abb(activate_task) activate_task.make_it_a_syscall(S.ActivateTask, [alarm.subtask]) alarm.carried_syscall = activate_task # Statistic generation self.stats.add_child(alarm.handler.task, "subtask", alarm.handler) self.stats.add_data(alarm.handler, "is_isr", True, scalar = True) # Add all implicit intra function control flow graphs for dep in self.rtsc.get_edges(): source = self.find_abb(dep.source) target = self.find_abb(dep.target) source.add_cfg_edge(target, E.function_level) # Find all return blocks for functions for function in self.functions.values(): ret_abbs = [] for abb in function.abbs: if len(abb.get_outgoing_edges(E.function_level)) == 0: ret_abbs.append(abb) if len(ret_abbs) == 0: logging.info("Endless loop in %s", function) elif len(ret_abbs) > 1: # Add an artificial exit block abb = self.new_abb() function.add_atomic_basic_block(abb) for ret in ret_abbs: ret.add_cfg_edge(abb, E.function_level) function.set_exit_abb(abb) else: function.set_exit_abb(ret_abbs[0]) if isinstance(function, Subtask) and function.is_isr: # All ISR function get an additional iret block iret = self.new_abb() function.add_atomic_basic_block(iret) iret.make_it_a_syscall(S.iret, [function]) function.exit_abb.add_cfg_edge(iret, E.function_level) function.set_exit_abb(iret) # Add all system calls for syscall in self.rtsc.syscalls(): abb = self.find_abb(syscall.abb) assert abb.isA(S.computation) abb.make_it_a_syscall(S.fromString(syscall.name), syscall.arguments) assert not abb.isA(S.computation) assert abb in self.get_abbs() assert len(self.get_syscalls()) >= len(self.rtsc.syscalls()) def new_abb(self, bbs=[]): self.max_abb_id += 1 abb = AtomicBasicBlock(self, self.max_abb_id, bbs) self.all_abbs[abb.get_id()] = abb return abb def add_system_objects(self): def system_function(syscall_type): function = Function(syscall_type.name) self.functions[syscall_type.name] = function abb = self.new_abb() function.add_atomic_basic_block(abb) function.set_entry_abb(abb) abb.make_it_a_syscall(syscall_type, []) return function # Add Idle Task system_task = Task(self, "OSEK") self.system_task = system_task self.tasks.append(system_task) idle_subtask = Subtask(self, "Idle", "Idle") self.functions["Idle"] = idle_subtask self.idle_subtask = idle_subtask idle_subtask.set_static_priority(0) idle_subtask.set_preemptable(True) system_task.add_subtask(idle_subtask) # The idle systemcall abb = self.new_abb() idle_subtask.add_atomic_basic_block(abb) idle_subtask.set_entry_abb(abb) idle_subtask.set_autostart(True) abb.make_it_a_syscall(S.Idle, []) # System Functions StartOS = system_function(S.StartOS) system_task.add_function(StartOS) # Structure for Statistics logging self.stats.add_child(self, "task", system_task) self.stats.add_child(system_task, "subtask", idle_subtask) def who_has_prio(self, priority): # We Inherit PassManager! assert self.passes["PrioritySpreadingPass"].valid return self.passes["PrioritySpreadingPass"].prio_to_participant[priority] def fsck(self): functions = set() abbs = set() for task in self.tasks: task.fsck() assert task.system_graph == self for subtask in task.subtasks: subtask.fsck() assert subtask.system_graph == self functions.add(subtask) abbs.update(set(subtask.abbs)) assert functions.issubset(set(self.functions.values())) for func in self.functions.values(): if func in functions: continue abbs.update(set(func.abbs)) for abb in abbs: abb.fsck() for system_pass in self.passes.values(): if system_pass.valid and hasattr(system_pass, "fsck"): system_pass.fsck()
def main(options, args): symbols = [x for x in read_symbols(options.elf) if x.addr] symbol_map = SymbolMap(symbols) trace_events = read_trace(options.traceplugin, options.trace) stats = Statistics.load(options.stats) for abb in stats.find_all("AtomicBasicBlock").values(): if not 'generated-function' in abb: continue abb["activations"] = [] sysgraph = stats.find_all("SystemGraph").values()[0] IncrementCounter = {"_id": id(main), "_type": "AtomicBasicBlock", "_name": "ABB-10/IncrementCounter", "generated-function": ["__OS_syscall_OSEKOS_IncrementCounter"], "activations": [], "symbols": []} sysgraph["alarms"] = [IncrementCounter] stats.rebuild_index(sysgraph) region_iterator = iter(syscall_regions(trace_events, symbol_map)) delayed_regions = [] while region_iterator or len(delayed_regions): if region_iterator: try: syscall_region = next(region_iterator) except StopIteration: region_iterator = None print "trace-analyze: Processing %d delayed interrupt regions" %(len(delayed_regions)) continue syscall_region, interrupt_region = cut_out_timer_interrupt(syscall_region) if interrupt_region: delayed_regions.append(interrupt_region) else: syscall_region = delayed_regions.pop() names = [x[1].name for x in syscall_region.trace if x[1]] region_length = sum([x[0] for x in syscall_region.trace]) event_type = None # fixup names with asm labels for i in range(0, len(names)): if ".asm_label.syscall_start" in names[i]: m = re.subn("^.asm_label.syscall_start_(.*)_[0-9]+$", "\\1", names[i]) names[i] = m[0] for name in names: if "__OS_syscall" in name: assert event_type is None, (names, options.stats) event_type = name if name in ("__OS_StartOS_dispatch"): assert event_type is None, (names, options.stats) event_type = name # If it does not contain a syscall, use the userland function # names (e.g. the start end markers) if event_type == None: for name in names: if "OSEKOS" in name and "__ABB" in name: # Might also be an ISR assert event_type is None or "irq_handler" in names[0], names event_type = name for abb in stats.find_all("AtomicBasicBlock").values(): if not 'generated-function' in abb: continue if event_type in abb["generated-function"]: trace_info = { "cycles": region_length, "trace": [(x[0], x[1].name) for x in syscall_region.trace], "start-time": syscall_region.start_time, "end-time": syscall_region.end_time, } abb["activations"].append(trace_info) if event_type == "__OS_syscall_OSEKOS_IncrementCounter": IncrementCounter["symbols"] = list(set(IncrementCounter["symbols"]) | set(names)) IncrementCounter["generated-codesize"] = 0 for symbol in IncrementCounter["symbols"]: if symbol in symbol_map: symbol = symbol_map[symbol] if symbol.size: IncrementCounter["generated-codesize"] += symbol.size print options.stats stats.save(options.stats)