[rtems-tools commit] gdb/python: Update the support to a recent RTEMS.

Chris Johns chrisj at rtems.org
Tue Mar 17 02:12:21 UTC 2015


Module:    rtems-tools
Branch:    master
Commit:    b117be8e1faeb5e672d63449635957950cb7b2ba
Changeset: http://git.rtems.org/rtems-tools/commit/?id=b117be8e1faeb5e672d63449635957950cb7b2ba

Author:    Chris Johns <chrisj at rtems.org>
Date:      Tue Mar 17 13:11:57 2015 +1100

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(-)

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 at 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 at 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 at rtems.org)
+# Copyright 2010-2015 Chris Johns (chrisj at 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 at 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




More information about the vc mailing list