From b117be8e1faeb5e672d63449635957950cb7b2ba Mon Sep 17 00:00:00 2001 From: Chris Johns Date: Tue, 17 Mar 2015 13:11:57 +1100 Subject: gdb/python: Update the support to a recent RTEMS. --- tools/gdb/python/chains.py | 35 ++++++++-- tools/gdb/python/classic.py | 111 +++++++++++++++--------------- tools/gdb/python/mutex.py | 128 ++++++++++++++++++++++++++++++++++ tools/gdb/python/rbtrees.py | 163 ++++++++++++++++++++++++++++++++++++++++++++ tools/gdb/python/rtems.py | 24 ++++--- tools/gdb/python/threads.py | 57 ++++++++++++---- tools/gdb/python/time.py | 79 +++++++++++++++++++++ 7 files changed, 512 insertions(+), 85 deletions(-) create mode 100644 tools/gdb/python/mutex.py create mode 100644 tools/gdb/python/rbtrees.py create mode 100644 tools/gdb/python/time.py diff --git a/tools/gdb/python/chains.py b/tools/gdb/python/chains.py index 6ae2518..58a354a 100644 --- a/tools/gdb/python/chains.py +++ b/tools/gdb/python/chains.py @@ -37,7 +37,18 @@ class node: """Manage the Chain_Node.""" def __init__(self, node_val): - self.node_val = node_val + if node_val: + if node_val.type.code == gdb.TYPE_CODE_PTR: + self.reference = node_val + self.node_val = node_val.dereference() + else: + self.node_val = node_val + self.reference = node_val.address + else: + self.node_val = node_val + + def __str__(self): + return self.to_string() def null(self): if not self.node_val: @@ -46,11 +57,11 @@ class node: def next(self): if not self.null(): - self.node_val = self.node_val['next'] + return self.node_val['next'] def previous(self): if not self.null(): - self.node_val = self.node_val['previous'] + return self.node_val['previous'] def cast(self, typename): if not self.null(): @@ -59,21 +70,31 @@ class node: return None def to_string(self): - return self.node_val['next'] + "Prev: "+self.node_val['previous'] + if self.null(): + return 'NULL' + return 'Node:%s Next:%s Prev:%s' % (self.reference, + self.node_val['next'], + self.node_val['previous']) class control: """Manage the Chain_Control.""" def __init__(self, ctrl): - self.ctrl = ctrl + if ctrl.type.code == gdb.TYPE_CODE_PTR: + self.reference = ctrl + self.ctrl = ctrl.dereference() + else: + self.ctrl = ctrl + self.reference = ctrl.address def first(self): t = node(self.ctrl['Head']['Node']) return t - def last(self): + def tail(self): return node(self.ctrl['Tail']['Node']) def empty(self): - if self.last() == self.first().next(): + if self.tail().previous() == self.reference: return True + return False diff --git a/tools/gdb/python/classic.py b/tools/gdb/python/classic.py index 44a92b4..7c004db 100644 --- a/tools/gdb/python/classic.py +++ b/tools/gdb/python/classic.py @@ -37,11 +37,12 @@ import re #ToDo This shouldn't be here import helper +import heaps +import mutex import objects +import supercore import threads import watchdog -import heaps -import supercore class attribute: """The Classic API attribute.""" @@ -111,7 +112,7 @@ class attribute: #ToDo: Move this out def to_string(self): - s = '0x%08x,' % (self.attr) + s = '(0x%08x) ' % (self.attr) if self.attrtype != 'none': for m in self.groups[self.attrtype]: v = self.attr & self.masks[m] @@ -135,44 +136,42 @@ class semaphore: "Print a classic semaphore." def __init__(self, obj): - self.reference = obj - self.object = obj.dereference() + if obj.type.code == gdb.TYPE_CODE_PTR: + self.reference = obj + self.object = obj.dereference() + else: + self.object = obj + self.reference = obj.address self.object_control = objects.control(self.object['Object']) self.attr = attribute(self.object['attribute_set'], 'semaphore') def show(self, from_tty): - print ' Name:', self.object_control.name() - print ' Attr:', self.attr.to_string() - if self.attr.test('semaphore-type', 'bin-sema') or \ - self.attr.test('semaphore-type', 'simple-bin-sema'): - core_mutex = self.object['Core_control']['mutex'] - locked = core_mutex['lock'] == 0 - if locked: - s = 'locked' - else: - s = 'unlocked' - print ' Lock:', s - print ' Nesting:', core_mutex['nest_count'] - print ' Blocked:', core_mutex['blocked_count'] - print ' Holder:', - holder = core_mutex['holder'] - if holder and locked: - holder = threads.control(holder.dereference()) - print holder.brief() - elif holder == 0 and locked: - print 'locked but no holder' - else: - print 'unlocked' - wait_queue = threads.queue(core_mutex['Wait_queue']) - tasks = wait_queue.tasks() - print ' Queue: len = %d, state = %s' % (len(tasks), - wait_queue.state()) - print ' Tasks:' - print ' Name (c:current, r:real), (id)' - for t in range(0, len(tasks)): - print ' ', tasks[t].brief(), ' (%08x)' % (tasks[t].id()) - else: - print 'semaphore' + if self.object_control.id() != 0: + print ' Name:', self.object_control.name() + print ' Id: 0x%08x (@ 0x%08x)' % (self.object_control.id(), + self.reference) + print ' Attr:', self.attr.to_string() + if self.attr.test('semaphore-type', 'bin-sema') or \ + self.attr.test('semaphore-type', 'simple-bin-sema'): + core_mutex = mutex.control(self.object['Core_control']['mutex']) + print ' Nesting:', core_mutex.nest_count() + print ' Holder:', + holder = core_mutex.holder() + if holder: + print '%s (id 0x%08x)' % (holder.brief(), holder.id()) + else: + print 'no holder (unlocked)' + wait_queue = core_mutex.wait_queue() + tasks = wait_queue.tasks() + print ' Queue: len = %d, state = %s' % (len(tasks), + wait_queue.state()) + if len(tasks) > 0: + print ' Tasks:' + print ' Name (c:current, r:real), (id)' + for t in range(0, len(tasks)): + print ' ', tasks[t].brief(), ' (%08x)' % (tasks[t].id()) + return True + return False class task: "Print a classic task" @@ -186,23 +185,27 @@ class task: #self.regs = sparc.register(self.object['Registers']) def show(self, from_tty): - cpu = self.task.executing() - if cpu == -1: - cpu = 'not executing' - print ' Id:', '0x%08x' % (self.task.id()) - print ' Name:', self.task.name() - print ' Active CPU:', cpu - print ' State:', self.task.current_state() - print ' Current:', self.task.current_priority() - print ' Real:', self.task.real_priority() - print ' Preempt:', self.task.preemptible() - print ' T Budget:', self.task.cpu_time_budget() - print ' Time:', self.task.cpu_time_used() - print ' Resources:', self.task.resource_count() - print ' Regsters:' - for name in self.regs.names(): - val = self.regs.get(name) - print ' %20s: %08x (%d)' % (name, val, val) + if self.task.id() != 0: + cpu = self.task.executing() + if cpu == -1: + cpu = 'not executing' + print ' Id:', '0x%08x (@ 0x%08x)' % (self.task.id(), + self.task.reference) + print ' Name:', self.task.name() + print ' Active CPU:', cpu + print ' State:', self.task.current_state() + print ' Current:', self.task.current_priority() + print ' Real:', self.task.real_priority() + print ' Preempt:', self.task.preemptible() + print ' T Budget:', self.task.cpu_time_budget() + print ' Time:', self.task.cpu_time_used() + print ' Resources:', self.task.resource_count() + print ' Regsters:' + for name in self.regs.names(): + val = self.regs.get(name) + print ' %20s: %08x (%d)' % (name, val, val) + return True + return False class message_queue: "Print classic messege queue" diff --git a/tools/gdb/python/mutex.py b/tools/gdb/python/mutex.py new file mode 100644 index 0000000..17f1900 --- /dev/null +++ b/tools/gdb/python/mutex.py @@ -0,0 +1,128 @@ +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2010-2015 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# +# RTEMS Mutex Support +# + +import gdb + +import objects +import percpu +import threads + +class attributes: + CORE_MUTEX_NESTING_ACQUIRES = 0 + CORE_MUTEX_NESTING_IS_ERROR = 1 + CORE_MUTEX_NESTING_BLOCKS = 2 + + CORE_MUTEX_DISCIPLINES_FIFO = 0 + CORE_MUTEX_DISCIPLINES_PRIORITY = 1 + CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT = 2 + CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING = 3 + + def __init__(self, attr): + self.attr = attr + + def lock_nesting_behaviour(self): + return self.attr['lock_nesting_behaviour'] + + def only_owner_release(self): + return self.attr['only_owner_release'] + + def discipline(self): + return self.attr['discipline'] + + def priority_ceiling(self): + return self.attr['priority_ceiling'] + + def brief(self): + s = '' + if self.lock_nesting_behaviour() == CORE_MUTEX_NESTING_ACQUIRES: + s += 'lck-nest-acquire' + elif self.lock_nesting_behaviour() == CORE_MUTEX_NESTING_IS_ERROR: + s += 'lck-nest-acquire' + elif self.lock_nesting_behaviour() == CORE_MUTEX_NESTING_BLOCKS: + s += 'lck-nest-blocks' + else: + s += 'lck-nest-bad' + if self.only_owner_release(): + s += ',owner-release' + else: + s += ',any-release' + if self.discipline() == CORE_MUTEX_DISCIPLINES_FIFO: + s += ',fifo' + elif self.discipline() == CORE_MUTEX_DISCIPLINES_PRIORITY: + s += ',pri' + elif self.discipline() == CORE_MUTEX_DISCIPLINES_INHERIT: + s += ',inherit' + elif self.discipline() == CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING: + s += ',pri-celling' + else: + s += ',dis-bad' + return s + +class control(): + ''' + CORE_mutex_Control has the following fields: + Wait_queue Thread_queue_Control + Attributes CORE_mutex_attributes + nest_count uint32_t + *holder Thread_control + queue CORE_mutex_order_list X + + where 'X' means the field is condition and may no exist. + ''' + + def __init__(self, ctrl): + if ctrl.type.code == gdb.TYPE_CODE_PTR: + self.reference = ctrl + self.ctrl = ctrl.dereference() + else: + self.ctrl = ctrl + self.reference = ctrl.address + self.attr = attributes(ctrl['Attributes']) + + def wait_queue(self): + return threads.queue(self.ctrl['Wait_queue']) + + def attributes(self): + return self.attr + + def nest_count(self): + return self.ctrl['nest_count'] + + def holder(self): + h = self.ctrl['holder'] + if h: + return threads.control(h) + return None + + def brief(self): + return "nests:%d, %s" % (self.ctrl['nest_count'], self.attr.brief()) diff --git a/tools/gdb/python/rbtrees.py b/tools/gdb/python/rbtrees.py new file mode 100644 index 0000000..2e4c9e7 --- /dev/null +++ b/tools/gdb/python/rbtrees.py @@ -0,0 +1,163 @@ +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2010-2015 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# +# RTEMS Red/Black Tree Support +# + +import gdb + +rbt_left = 0 +rbt_right = 1 + +def opp_dir(dir_): + if dir_ == rbt_left: + return rbt_right + return rbt_left + + +class node: + """Manage the RBTree_Node_struct.""" + + def __init__(self, node_ptr): + self.node_ptr = node_ptr + self.node_val = None + if node_ptr != 0: + print '}}}}' + self.node_val = node_ptr.dereference() + + def __str__(self): + return self.to_string() + + def null(self): + if not self.node_val: + return True + return False + + def pointer(self): + return self.node_ptr + + def parent(self): + if not self.null(): + return self.node_val['parent'] + return None + + def child(self): + if not self.null(): + return self.node_val['child'] + return None + + def left(self): + if not self.null(): + return self.node_val['child'][rbt_left] + return None + + def right(self): + if not self.null(): + return self.node_val['child'][rbt_right] + return None + + def next(self, dir_): + next_ = None + if not self.null(): + current = self.child(color, dir_) + if current is not None: + while current is not None: + cn = node(current) + current = cn.child(opp_dir(dir_)) + next_ = current + else: + # RBTree_Node *parent = node->parent; + # if ( parent->parent && node == parent->child[ opp_dir ] ) { + # + # node->parent + if self.parent(): + # pn = *(node->parent) or pn = *parent + pn = node(self.parent()) + if pn.parent() and (self.pointer() == pn.child(opp_dir(dir_))): + next_ = self.parent() + else: + nn = self + while pn.parent(): + if nn.pointer() != pn.child(dir_): + break + nn = pn + pn = node(pn.parent()) + if pn.parent(): + next_ = pn.pointer() + return next_ + + def predecessor(self): + return self.next(rbt_left) + + def successor(self): + return self.next(rbt_right) + + def color(self): + if not self.null(): + return self.node_val['color'] + return None + + def cast(self, typename): + if not self.null(): + nodetype = gdb.lookup_type(typename) + return self.node_val.cast(nodetype) + return None + + def off_tree(self): + if parent.null(): + return True + return False + + def to_string(self): + if self.null(): + return 'NULL' + print ']]] here' + return 'Parent:%s Child:%s Color:%s' % (self.node_val['parent'], + self.node_val['child'], + self.node_val['color']) + +class control: + """Manage the RBTree_Control.""" + + def __init__(self, ctrl): + self.ctrl = ctrl + + def root(self): + """Return the root node of the RBT.""" + return node(self.ctrl['root']) + + def first(self, dir_): + """ Return the min or max nodes of this RBT.""" + return node(self.ctrl['first'][dir_]) + + def empty(self): + if self.root().null(): + return True + return False diff --git a/tools/gdb/python/rtems.py b/tools/gdb/python/rtems.py index 534cb0d..d4317ff 100644 --- a/tools/gdb/python/rtems.py +++ b/tools/gdb/python/rtems.py @@ -72,17 +72,18 @@ class rtems_object(gdb.Command): gdb.COMPLETE_SYMBOL) def invoke(self, arg, from_tty): + vald = False for num in arg.split(): try: val = gdb.parse_and_eval(num) num = int(val) except: print 'error: "%s" is not a number' % (num) - return + return True id = objects.ident(num) if not id.valid(): print 'Invalid object id' - return + return True print 'API:%s Class:%s Node:%d Index:%d Id:%08X' % \ (id.api(), id._class(), id.node(), id.index(), id.value()) @@ -91,8 +92,9 @@ class rtems_object(gdb.Command): obj = objects.information.object(id).dereference() if objectname in self.objects: object = self.objects[objectname](obj) - object.show(from_tty) + valid = object.show(from_tty) objects.information.invalidate() + return valid class rtems_index(gdb.Command): '''Print object by index''' @@ -113,8 +115,9 @@ class rtems_index(gdb.Command): def invoke(self, arg, from_tty): maximum = objects.information.maximum(self.api, self._class) minimum_id = objects.ident(objects.information.minimum_id(self.api, self._class)) - maximum_id = objects.ident(objects.information.minimum_id(self.api, self._class)) + maximum_id = objects.ident(objects.information.maximum_id(self.api, self._class)) args = arg.split() + valid = False if len(args): for val in args: try: @@ -137,15 +140,18 @@ class rtems_index(gdb.Command): print "error: index %s is invalid" % (index) return instance = self.instance(obj) - instance.show(from_tty) + valid = instance.show(from_tty) objects.information.invalidate() else: print '-' * 70 print ' %s: %d [%08x -> %08x]' % (objects.information.name(self.api, self._class), maximum, minimum_id.value(), maximum_id.value()) + valid = True for index in range(minimum_id.index(), minimum_id.index() + maximum): - print '-' * 70 - self.invoke(str(index), from_tty) + if valid: + print '-' * 70 + valid = self.invoke(str(index), from_tty) + return valid class rtems_semaphore(rtems_index): '''semaphore subcommand''' @@ -242,11 +248,9 @@ class rtems_tod(gdb.Command): ('rtems tod', gdb.COMMAND_STATUS,gdb.COMPLETE_NONE) def invoke(self, arg, from_tty): - if arg: print "warning: commad takes no arguments!" - - obj = objects.information.object_return(self.api,self._class) + obj = objects.information.object_return(self.api, self._class) instance = supercore.time_of_day(obj) instance.show() objects.information.invalidate() diff --git a/tools/gdb/python/threads.py b/tools/gdb/python/threads.py index 1719187..690f77f 100644 --- a/tools/gdb/python/threads.py +++ b/tools/gdb/python/threads.py @@ -1,5 +1,5 @@ # RTEMS Tools Project (http://www.rtems.org/) -# Copyright 2010-2014 Chris Johns (chrisj@rtems.org) +# Copyright 2010-2015 Chris Johns (chrisj@rtems.org) # All rights reserved. # # This file is part of the RTEMS Tools package in 'rtems-tools'. @@ -36,13 +36,25 @@ import gdb import chains import objects import percpu +import rbtrees +import time def task_chain(chain): tasks = [] - node = chain.first() + if not chain.empty(): + node = chain.first() + while not node.null(): + t = control(node.cast('Thread_Control')) + tasks.append(t) + node = node(node.next()) + return tasks + +def task_tree(tree): + tasks = [] + node = tree.first(rbtrees.rbt_left) while not node.null(): tasks.append(control(node.cast('Thread_Control'))) - node.next() + node = node.next(rbtrees.rbt_left) return tasks class state(): @@ -128,6 +140,17 @@ class state(): s = self.masks[m] + ',' return s[:-1] +class cpu_usage(): + + def __init__(self, time_): + self.time = time.time(time_) + + def __str__(self): + return self.time.tostring() + + def get(self): + return self.time.get() + class wait_info(): def __init__(self, info): @@ -165,7 +188,6 @@ class registers(): return float(self.regs[reg]) return int(self.regs[reg]) - def format(self, reg): t = self.regs[reg].type if t in ['uint32_t', 'unsigned', 'unsigned long']: @@ -208,8 +230,12 @@ class control(): ''' def __init__(self, ctrl): - self.reference = ctrl - self.ctrl = ctrl.dereference() + if ctrl.type.code == gdb.TYPE_CODE_PTR: + self.reference = ctrl + self.ctrl = ctrl.dereference() + else: + self.ctrl = ctrl + self.reference = ctrl.address self.object = objects.control(ctrl['Object']) self._executing = percpu.thread_active(self.reference) self._heir = percpu.thread_heir(self.reference) @@ -245,7 +271,7 @@ class control(): return self.ctrl['cpu_time_budget'] def cpu_time_used(self): - return self.ctrl['cpu_time_used'] + return cpu_usage(self.ctrl['cpu_time_used']) def preemptible(self): return self.ctrl['is_preemptible'] @@ -259,6 +285,9 @@ class control(): def registers(self): return registers(self.ctrl['Registers']) + def is_idle(self): + return (self.id() & 0xff000000) == 0x90000000 + def brief(self): return "'%s' (c:%d, r:%d)" % \ (self.name(), self.current_priority(), self.real_priority()) @@ -266,10 +295,13 @@ class control(): class queue(): """Manage the Thread_queue_Control.""" - priority_headers = 4 - def __init__(self, que): - self.que = que + if que.type.code == gdb.TYPE_CODE_PTR: + self.reference = que + self.que = que.dereference() + else: + self.que = que + self.reference = que.address def fifo(self): return str(self.que['discipline']) == 'THREAD_QUEUE_DISCIPLINE_FIFO' @@ -284,8 +316,5 @@ class queue(): if self.fifo(): t = task_chain(chains.control(self.que['Queues']['Fifo'])) else: - t = [] - for ph in range(0, self.priority_headers): - t.extend(task_chain(chains.control( \ - self.que['Queues']['Priority'][ph]))) + t = task_tree(rbtrees.control(self.que['Queues']['Priority'])) return t diff --git a/tools/gdb/python/time.py b/tools/gdb/python/time.py new file mode 100644 index 0000000..16cf83f --- /dev/null +++ b/tools/gdb/python/time.py @@ -0,0 +1,79 @@ +# RTEMS Tools Project (http://www.rtems.org/) +# Copyright 2010-2015 Chris Johns (chrisj@rtems.org) +# All rights reserved. +# +# This file is part of the RTEMS Tools package in 'rtems-tools'. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# +# RTEMS Time Support +# + +import gdb + +class time(): + + def __init__(self, time_, ticks = False, scaler = 1000000000): + self.ticks = ticks + self.scaler = scaler + if time_.type.code == gdb.TYPE_CODE_PTR: + self.reference = time_ + self.time = time_.dereference() + else: + self.time = time_ + self.reference = time_.address + if self.time.type.strip_typedefs().tag == 'timespec': + self.timespecs = True + else: + self.timespecs = False + + def __str__(self): + return self.tostring() + + def get(self): + if self.timespecs: + return (long(self.time['tv_sec']) * 1000000000) + long(self.time['tv_nsec']) + else: + return long(self.time) * self.scaler + + def tostring(self): + if self.ticks: + return '%d ticks' % (self.time) + nsecs = self.get() + secs = nsecs / 1000000000 + nsecs = nsecs % 1000000000 + minutes = secs / 60 + secs = secs % 60 + hours = minutes / 60 + minutes = minutes % 60 + days = hours / 24 + hours = hours % 24 + t = '' + if days: + t = '%dd ' % (days) + if hours or minutes or secs: + t += '%02d:%02d:%02d ' % (hours, minutes, secs) + t += '%d nsec' % (nsecs) + return t -- cgit v1.2.3