[rtems-tools commit] Intial commit.

Chris Johns chrisj at rtems.org
Sun Aug 24 23:45:33 UTC 2014


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

Author:    Dhananjay Balan <mb.dhananjay at gmail.com>
Date:      Mon Jun 17 22:58:17 2013 +0530

Intial commit.
Chris's intial work on the extenstions.

---

 tools/gdb/python/__init__.py |   16 ++
 tools/gdb/python/chains.py   |   43 +++++
 tools/gdb/python/classic.py  |  216 +++++++++++++++++++++++++
 tools/gdb/python/objects.py  |  357 ++++++++++++++++++++++++++++++++++++++++++
 tools/gdb/python/rtems.py    |  110 +++++++++++++
 tools/gdb/python/threads.py  |  207 ++++++++++++++++++++++++
 tools/gdb/python/watchdog.py |   56 +++++++
 7 files changed, 1005 insertions(+), 0 deletions(-)

diff --git a/tools/gdb/python/__init__.py b/tools/gdb/python/__init__.py
new file mode 100644
index 0000000..0664d21
--- /dev/null
+++ b/tools/gdb/python/__init__.py
@@ -0,0 +1,16 @@
+
+if __name__ == "__main__":
+    import sys
+    import os.path
+    sys.path.append(os.path.dirname(__file__))
+    import chains
+    import rtems
+    import classic
+    import objects
+    import threads
+    reload(chains)
+    reload(rtems)
+    reload(classic)
+    reload(objects)
+    reload(threads)
+    print 'RTEMS GDB Support loaded'
diff --git a/tools/gdb/python/chains.py b/tools/gdb/python/chains.py
new file mode 100644
index 0000000..961ca2d
--- /dev/null
+++ b/tools/gdb/python/chains.py
@@ -0,0 +1,43 @@
+#
+# RTEMS Chains Support
+# Copyright 2010 Chris Johns (chrisj at rtems.org)
+#
+# $Id$
+#
+
+import gdb
+
+class node:
+    """Manage the Chain_Node."""
+
+    def __init__(self, node_val):
+        self.node_val = node_val
+
+    def null(self):
+        return self.node_val['next'] == 0
+
+    def next(self):
+        if not self.null():
+            self.node_val = self.node_val['next'].dereference()
+
+    def previous(self):
+        if not self.null():
+            self.node_val = self.node_val['previous'].dereference()
+
+    def cast(self, typename):
+        if not self.null():
+            nodetype = gdb.lookup_type(typename)
+            return self.node_val.cast(nodetype)
+        return None
+
+class control:
+    """Manage the Chain_Control."""
+
+    def __init__(self, ctrl):
+        self.ctrl = ctrl
+
+    def first(self):
+        return node(self.ctrl['first'].dereference())
+
+    def last(self):
+        return node(self.ctrl['first'])
diff --git a/tools/gdb/python/classic.py b/tools/gdb/python/classic.py
new file mode 100644
index 0000000..8748bbf
--- /dev/null
+++ b/tools/gdb/python/classic.py
@@ -0,0 +1,216 @@
+#
+# RTEMS Classic API Support
+# Copyright 2010 Chris Johns (chrisj at rtems.org)
+#
+# $Id$
+#
+
+import gdb
+import itertools
+import re
+
+import objects
+import threads
+
+class attribute:
+    """The Classic API attribute."""
+
+    groups = {
+        'none' : [],
+        'all' : ['scope',
+                 'priority',
+                 'fpu',
+                 'semaphore-type',
+                 'semaphore-pri',
+                 'semaphore-pri-ceiling',
+                 'barrier',
+                 'task'],
+        'task' : ['scope',
+                  'priority',
+                  'fpu',
+                  'task'],
+        'semaphore' : ['scope',
+                       'priority',
+                       'semaphore-type',
+                       'semaphore-pri',
+                       'semaphore-pri-ceiling'],
+        'barrier' : ['scope',
+                     'priority',
+                     'barrier']
+        }
+
+    masks = {
+        'scope' : 0x00000002,
+        'priority' : 0x00000004,
+        'fpu' : 0x00000001,
+        'semaphore-type' : 0x00000030,
+        'semaphore-pri' : 0x00000040,
+        'semaphore-pri-ceiling' : 0x00000080,
+        'barrier' : 0x00000010,
+        'task' : 0x00008000
+        }
+
+    fields = {
+        'scope' : [(0x00000000, 'local'),
+                   (0x00000002, 'global')],
+        'priority' : [(0x00000000, 'fifo'),
+                      (0x00000004, 'pri')],
+        'fpu' : [(0x00000000, 'no-fpu'),
+                 (0x00000001, 'fpu')],
+        'semaphore-type' : [(0x00000000, 'count-sema'),
+                            (0x00000010, 'bin-sema'),
+                            (0x00000020, 'simple-bin-sema')],
+        'semaphore-pri' : [(0x00000000, 'no-inherit-pri'),
+                           (0x00000040, 'inherit-pri')],
+        'semaphore-pri-ceiling' : [(0x00000000, 'no-pri-ceiling'),
+                                   (0x00000080, 'pri-ceiling')],
+        'barrier' : [(0x00000010, 'barrier-auto-release'), 
+                     (0x00000000, 'barrier-manual-release')],
+        'task' : [(0x00000000, 'app-task'),
+                  (0x00008000, 'sys-task')]
+        }
+
+    def __init__(self, attr, attrtype = 'none'):
+        if attrtype not in self.groups:
+            raise 'invalid attribute type'
+        self.attrtype = attrtype
+        self.attr = attr
+
+    def to_string(self):
+        s = '0x%08x,' % (self.attr)
+        if self.attrtype != 'none':
+            for m in self.groups[self.attrtype]:
+                v = self.attr & self.masks[m]
+                for f in self.fields[m]:
+                    if f[0] == v:
+                        s += f[1] + ','
+                        break
+        return s[:-1]
+
+    def test(self, mask, value):
+        if self.attrtype != 'none' and \
+                mask in self.groups[self.attrtype]:
+            v = self.masks[mask] & self.attr
+            for f in self.fields[mask]:
+                if v == f[0] and value == f[1]:
+                    return True
+        return False
+
+class attribute_printer:
+    
+    def __init__(self, attr):
+        self.attr = attr
+
+    def to_string(self):
+        return gdb.Value(self.attr.to_string())
+
+class semaphore_printer:
+    """Print a Semaphore_Control object. Print using the struct display hint
+    and an iterator."""
+
+    class iterator:
+        """Use an iterator for each field expanded from the id so GDB output
+        is formatted correctly."""
+
+        def __init__(self, semaphore):
+            self.semaphore = semaphore
+            self.count = 0
+
+        def __iter__(self):
+            return self
+
+        def next(self):
+            self.count += 1
+            if self.count == 1:
+                return self.semaphore['Object']
+            elif self.count == 2:
+                attr = attribute(self.semaphore['attribute_set'], 
+                                 'semaphore')
+                return attr.to_string()
+            elif self.count == 3:
+                return self.semaphore['Core_control']
+            raise StopIteration
+
+    def __init__(self, semaphore):
+        self.semaphore = semaphore
+
+    def to_string(self):
+        return ''
+
+    @staticmethod
+    def key(i):
+        if i == 0:
+            return 'Object'
+        elif i == 1:
+            return 'attribute_set'
+        elif i == 2:
+            return 'Core_control'
+        return 'bad'
+
+    def children(self):
+        counter = itertools.imap (self.key, itertools.count())
+        return itertools.izip (counter, self.iterator(self.semaphore))
+
+    def display_hint (self):
+        return 'struct'
+
+class semaphore:
+    "Print a classic semaphore."
+
+    def __init__(self, id):
+        self.id = id;
+        self.object = objects.information.object(self.id).dereference()
+        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())
+            for t in range(0, len(tasks)):
+                print '      ', tasks[t].brief(), ' (%08x)' % (tasks[t].id())
+        else:
+            print 'semaphore'
+
+class task:
+    "Print a classic tasks."
+
+    def __init__(self, id):
+        self.id = id;
+        self.task = \
+            threads.control(objects.information.object(self.id).dereference())
+        
+    def show(self, from_tty):
+        print '     Name:', self.task.name()
+        print '    State:', self.task.current_state()
+        print '  Current:', self.task.current_priority()
+        print '     Real:', self.task.real_priority()
+        print ' Suspends:', self.task.suspends()
+        print ' Post Ext:', self.task.post_task_switch_ext()
+        print '  Preempt:', self.task.preemptible()
+        print ' T Budget:', self.task.cpu_time_budget()
+        wait_info = self.task.wait_info()
+        
diff --git a/tools/gdb/python/objects.py b/tools/gdb/python/objects.py
new file mode 100644
index 0000000..22d2b2c
--- /dev/null
+++ b/tools/gdb/python/objects.py
@@ -0,0 +1,357 @@
+#
+# RTEMS Objects Support
+# Copyright 2010 Chris Johns (chrisj at rtems.org)
+#
+# $Id$
+#
+
+import gdb
+import itertools
+import re
+
+class infotables:
+    """Manage the object information tables."""
+
+    tables_types = {
+        'classic/tasks'          : ('Thread_Control',        '_RTEMS_tasks_Information'),
+        'classic/timers'         : ('Timer_Control',         '_Timers_Information'),
+        'classic/semaphores'     : ('Semaphore_Control',     '_Semaphore_Information'),
+        'classic/message_queues' : ('Message_queue_Control', '_Message_queue_Information'),
+        'classic/partitions'     : ('Partition_Control',     '_Partition_Information'),
+        'classic/regions'        : ('Region_Control',        '_Regions_Information'),
+        'classic/ports'          : ('Port_Control',          '_Port_Information'),
+        'classic/periods'        : ('Period_Control',        '_Period_Information'),
+        'classic/extensions'     : ('Extension_Control',     '_Extension_Information'),
+        'classic/barriers'       : ('Barrier_Control',       '_Barrier_Information')
+        }
+
+    def __init__(self):
+        self.invalidate()
+
+    def invalidate(self):
+        self.tables = {}
+
+    def name(self, api, _class):
+        return api + '/' + _class
+
+    def load(self, n):
+        if n in self.tables_types:
+            if n not in self.tables:
+                self.tables[n] = gdb.parse_and_eval(self.tables_types[n][1])
+
+    def get(self, api, _class):
+        n = self.name(api, _class)
+        self.load(n)
+        if n in self.tables:
+            return self.tables[n]
+        return None
+
+    def maximum(self, api, _class):
+        n = self.name(api, _class)
+        self.load(n)
+        return int(self.tables[n]['maximum'])
+
+    def object(self, id):
+        if type(id) == gdb.Value:
+            id = ident(id)
+        if type(id) == tuple:
+            api = id[0]
+            _class = id[1]
+            index = id[2]
+        else:
+            api = id.api()
+            _class = id._class()
+            index = id.index()
+        n = self.name(api, _class)
+        self.load(n)
+        max = self.maximum(api, _class)
+        if index >= max:
+            raise IndexError('object index out of range (%d)' % (max))
+        table_type = self.tables_types[n]
+        expr = '(' + table_type[0] + '*)' + \
+            table_type[1] + '.local_table[' + str(index) + ']'
+        return gdb.parse_and_eval(expr)
+
+    def is_string(self, api, _class):
+        n = self.name(api, _class)
+        self.load(n)
+        if n in self.tables:
+            if self.tables[n]['is_string']:
+                return True
+        return False
+
+#
+# Global info tables. These are global in the target.
+#
+information = infotables()
+
+class ident:
+    "An RTEMS object id with support for its bit fields."
+
+    bits = [
+        { 'index': (0, 15),
+          'node':  (0, 0),
+          'api':   (8, 10),
+          'class': (11, 15) },
+        { 'index': (0, 15),
+          'node':  (16, 23),
+          'api':   (24, 26),
+          'class': (27, 31) } 
+        ]
+
+    OBJECT_16_BITS = 0
+    OBJECT_31_BITS = 1
+
+    api_labels = [
+        'none',
+        'internal',
+        'classic',
+        'posix',
+        'itron'
+        ]
+
+    class_labels = {
+        'internal' : ('threads',
+                      'mutexes'),
+        'classic' : ('none',
+                     'tasks',
+                     'timers',
+                     'semaphores',
+                     'message_queues',
+                     'partitions',
+                     'regions',
+                     'ports',
+                     'periods',
+                     'extensions',
+                     'barriers'),
+        'posix' : ('none',
+                   'threads',
+                   'keys',
+                   'interrupts',
+                   'message_queue_fds',
+                   'message_queues',
+                   'mutexes',
+                   'semaphores',
+                   'condition_variables',
+                   'timers',
+                   'barriers',
+                   'spinlocks',
+                   'rwlocks'),
+        'itron' : ('none',
+                   'tasks',
+                   'eventflags',
+                   'mailboxes',
+                   'message_buffers',
+                   'ports',
+                   'semaphores',
+                   'variable_memory_pools',
+                   'fixed_memory_pools')
+        }
+    
+    def __init__(self, id):
+        if type(id) != gdb.Value and type(id) != int and type(id) != unicode:
+            raise TypeError('%s: must be gdb.Value, int, unicoded int' % (type(id)))
+        if type(id) == int:
+            id = gdb.Value(id)
+        self.id = id
+        if self.id.type.sizeof == 2:
+            self.idSize = self.OBJECT_16_BITS
+        else:
+            self.idSize = self.OBJECT_31_BITS
+
+    def get(self, field):
+        if field in self.bits[self.idSize]:
+            bits = self.bits[self.idSize][field]
+            if bits[1] > 0:
+                return (int(self.id) >> bits[0]) & ((1 << (bits[1] - bits[0] + 1)) - 1)
+        return 0
+
+    def value(self):
+        return int(self.id)
+
+    def index(self):
+        return self.get('index')
+
+    def node(self):
+        return self.get('node')
+
+    def api_val(self):
+        return self.get('api')
+
+    def class_val(self):
+        return self.get('class')
+
+    def api(self):
+        api = self.api_val()
+        if api < len(self.api_labels):
+            return self.api_labels[api]
+        return 'none'
+
+    def _class(self):
+        api = self.api()
+        if api == 'none':
+            return 'invalid'
+        _class = self.class_val()
+        if _class < len(self.class_labels[api]):
+            return self.class_labels[api][_class]
+        return 'invalid'
+
+    def valid(self):
+        return self.api() != 'none' and self._class() != 'invalid'
+
+class name:
+    """The Objects_Name can either be told what the name is or can take a
+    guess."""
+
+    def __init__(self, name, is_string = None):
+        self.name = name
+        if is_string == None:
+            self.is_string = 'auto'
+        else:
+            if is_string:
+                self.is_string = 'yes'
+            else:
+                self.is_string = 'no'
+
+    def __str__(self):
+        if self.is_string != 'yes':
+            u32 = int(self.name['name_u32'])
+            s = chr((u32 >> 24) & 0xff) + \
+                chr((u32 >> 16) & 0xff) + chr((u32 >> 8) & 0xff) + \
+                chr(u32 & 0xff)
+            for c in range(0,4):
+                if s[c] < ' ' or s[c] > '~':
+                    s = None
+                    break
+            if s:
+                return s
+        return str(self.name['name_p'].dereference())
+
+class control:
+    """The Objects_Control structure."""
+
+    def __init__(self, object):
+        self.object = object
+        self._id = ident(self.object['id'])
+
+    def node(self):
+        return self.object['Node']
+
+    def id(self):
+        return self.object['id']
+
+    def name(self):
+        is_string = information.is_string(self._id.api(), self._id._class())
+        return str(name(self.object['name'], is_string))
+
+class id_printer:
+    """Print an object given the ID. Print using the struct display hint and an
+    iterator."""
+
+    class iterator:
+        """Use an iterator for each field expanded from the id so GDB output
+        is formatted correctly."""
+
+        def __init__(self, id):
+            self.id = id
+            self.count = 0
+
+        def __iter__(self):
+            return self
+
+        def next(self):
+            self.count += 1
+            if self.count == 1:
+                return int(self.id.value())
+            elif self.count == 2:
+                return self.id.node()
+            elif self.count == 3:
+                return self.id.api()
+            elif self.count == 4:
+                return self.id._class()
+            elif self.count == 5:
+                return self.id.index()
+            raise StopIteration
+
+    def __init__(self, id):
+        self.id = ident(id)
+
+    def to_string(self):
+        return ''
+
+    @staticmethod
+    def key(i):
+        if i == 0:
+            return 'id'
+        elif i == 1:
+            return 'node'
+        elif i == 2:
+            return 'api'
+        elif i == 3:
+            return 'class'
+        elif i == 4:
+            return 'index'
+        return 'bad'
+
+    def children(self):
+        counter = itertools.imap (self.key, itertools.count())
+        return itertools.izip (counter, self.iterator(self.id))
+
+    def display_hint (self):
+        return 'struct'
+
+class name_printer:
+    """Pretty printer for an object's name. It has to guess the type as no
+    information is available to help determine it."""
+
+    def __init__(self, name):
+        self.name = name(name)
+
+    def to_string(self):
+        return gdb.Value(str(self.name))
+
+class control_printer:
+
+    class iterator:
+        """Use an iterator for each field expanded from the id so GDB output
+        is formatted correctly."""
+
+        def __init__(self, object):
+            self.object = object
+            self.count = 0
+
+        def __iter__(self):
+            return self
+
+        def next(self):
+            self.count += 1
+            if self.count == 1:
+                return self.object.node()
+            elif self.count == 2:
+                return self.object.id()
+            elif self.count == 3:
+                return self.object.name()
+            raise StopIteration
+
+    def to_string(self):
+        return ''
+
+    def __init__(self, object):
+        self.object = control(object)
+
+    @staticmethod
+    def key(i):
+        if i == 0:
+            return 'Node'
+        elif i == 1:
+            return 'id'
+        elif i == 2:
+            return 'name'
+        return 'bad'
+
+    def children(self):
+        counter = itertools.imap (self.key, itertools.count())
+        return itertools.izip (counter, self.iterator(self.object))
+
+    def display_hint (self):
+        return 'struct'
diff --git a/tools/gdb/python/rtems.py b/tools/gdb/python/rtems.py
new file mode 100644
index 0000000..e227c6f
--- /dev/null
+++ b/tools/gdb/python/rtems.py
@@ -0,0 +1,110 @@
+#
+# RTEMS Pretty Printers
+# Copyright 2010 Chris Johns (chrisj at rtems.org)
+#
+# $Id$
+#
+
+import gdb
+import re
+
+import objects
+import threads
+import classic
+
+nesting = 0
+
+def type_from_value(val):
+    type = val.type;
+    # If it points to a reference, get the reference.
+    if type.code == gdb.TYPE_CODE_REF:
+        type = type.target ()
+    # Get the unqualified type
+    return type.unqualified ()
+
+def register_rtems_printers (obj):
+    "Register RTEMS pretty-printers with objfile Obj."
+
+    if obj == None:
+        obj = gdb
+
+    obj.pretty_printers.append (lookup_function)
+
+def lookup_function (val):
+    "Look-up and return a pretty-printer that can print val."
+
+    global nesting
+
+    typename = str(type_from_value(val))
+
+    for function in pp_dict:
+        if function.search (typename):
+            nesting += 1
+            result = pp_dict[function] (val)
+            nesting -= 1
+            if nesting == 0:
+                objects.information.invalidate()
+            return result
+
+    # Cannot find a pretty printer.  Return None.
+    return None
+
+def build_rtems_dict():
+    pp_dict[re.compile('^rtems_id$')]   = lambda val: objects.id_printer(val)
+    pp_dict[re.compile('^Objects_Id$')] = lambda val: objects.id_printer(val)
+    pp_dict[re.compile('^Objects_Name$')] = lambda val: objects.name_printer(val)
+    pp_dict[re.compile('^Objects_Control$')] = lambda val: objects.control_printer(val)
+    pp_dict[re.compile('^States_Control$')] = lambda val: threads.state_printer(val)
+    pp_dict[re.compile('^rtems_attribute$')] = lambda val: classic.attribute_printer(val)
+    pp_dict[re.compile('^Semaphore_Control$')] = lambda val: classic.semaphore_printer(val)
+
+class rtems(gdb.Command):
+    """Prefix command for RTEMS."""
+
+    def __init__(self):
+        super(rtems, self).__init__('rtems',
+                                    gdb.COMMAND_STATUS,
+                                    gdb.COMPLETE_NONE,
+                                    True)
+
+class rtems_object(gdb.Command):
+    """Object sub-command for RTEMS"""
+
+    objects = {
+        'classic/semaphores': lambda id: classic.semaphore(id),
+        'classic/tasks': lambda id: classic.task(id)
+        }
+
+    def __init__(self):
+        self.__doc__ = 'Display the RTEMS object given a numeric ID.'
+        super(rtems_object, self).__init__('rtems object', 
+                                           gdb.COMMAND_STATUS)
+
+    def invoke(self, arg, from_tty):
+        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
+            id = objects.ident(num)
+            if not id.valid():
+                print 'Invalid object id'
+            print 'API:%s Class:%s Node:%d Index:%d Id:%08X' % \
+                (id.api(), id._class(), id.node(), id.index(), id.value())
+            objectname = id.api() + '/' + id._class()
+            if objectname in self.objects:
+                object = self.objects[objectname](id)
+                object.show(from_tty)
+        objects.information.invalidate()
+            
+#
+# Main
+#
+pp_dict = {}
+build_rtems_dict()
+gdb.pretty_printers = []
+gdb.pretty_printers.append (lookup_function)
+rtems()
+rtems_object()
diff --git a/tools/gdb/python/threads.py b/tools/gdb/python/threads.py
new file mode 100644
index 0000000..906cf5a
--- /dev/null
+++ b/tools/gdb/python/threads.py
@@ -0,0 +1,207 @@
+#
+# RTEMS Threads Support
+# Copyright 2010 Chris Johns (chrisj at rtems.org)
+#
+# $Id$
+#
+
+import gdb
+
+import chains
+import objects
+
+def task_chain(chain):
+    tasks = []
+    node = chain.first()
+    while not node.null():
+        print node.addr
+        tasks.append(control(node.cast('Thread_Control')))
+        node.next()
+    return tasks
+
+class state:
+
+    ALL_SET = 0x000fffff
+    READY = 0x00000000
+    DORMANT = 0x00000001
+    SUSPENDED = 0x00000002
+    TRANSIENT = 0x00000004
+    DELAYING = 0x00000008
+    WAITING_FOR_TIME = 0x00000010
+    WAITING_FOR_BUFFER = 0x00000020
+    WAITING_FOR_SEGMENT = 0x00000040
+    WAITING_FOR_MESSAGE = 0x00000080
+    WAITING_FOR_EVENT = 0x00000100
+    WAITING_FOR_SEMAPHORE = 0x00000200
+    WAITING_FOR_MUTEX = 0x00000400
+    WAITING_FOR_CONDITION_VARIABLE = 0x00000800
+    WAITING_FOR_JOIN_AT_EXIT = 0x00001000
+    WAITING_FOR_RPC_REPLY = 0x00002000
+    WAITING_FOR_PERIOD = 0x00004000
+    WAITING_FOR_SIGNAL = 0x00008000
+    WAITING_FOR_BARRIER = 0x00010000
+    WAITING_FOR_RWLOCK = 0x00020000
+    INTERRUPTIBLE_BY_SIGNAL = 0x10000000
+    LOCALLY_BLOCKED = \
+        WAITING_FOR_BUFFER             | \
+        WAITING_FOR_SEGMENT            | \
+        WAITING_FOR_MESSAGE            | \
+        WAITING_FOR_SEMAPHORE          | \
+        WAITING_FOR_MUTEX              | \
+        WAITING_FOR_CONDITION_VARIABLE | \
+        WAITING_FOR_JOIN_AT_EXIT       | \
+        WAITING_FOR_SIGNAL             | \
+        WAITING_FOR_BARRIER            | \
+        WAITING_FOR_RWLOCK
+    WAITING_ON_THREAD_QUEUE = \
+        LOCALLY_BLOCKED | WAITING_FOR_RPC_REPLY
+    BLOCKED = \
+        DELAYING                | \
+        WAITING_FOR_TIME        | \
+        WAITING_FOR_PERIOD      | \
+        WAITING_FOR_EVENT       | \
+        WAITING_ON_THREAD_QUEUE | \
+        INTERRUPTIBLE_BY_SIGNAL
+    
+    masks = {
+        ALL_SET : 'all-set',
+        READY : 'ready',
+        DORMANT : 'dormant',
+        SUSPENDED : 'suspended',
+        TRANSIENT : 'transient',
+        DELAYING : 'delaying',
+        WAITING_FOR_TIME : 'waiting-for-time',
+        WAITING_FOR_BUFFER : 'waiting-for-buffer',
+        WAITING_FOR_SEGMENT : 'waiting-for-segment',
+        WAITING_FOR_MESSAGE : 'waiting-for-message',
+        WAITING_FOR_EVENT : 'waiting-for-event',
+        WAITING_FOR_SEMAPHORE : 'waiting-for-semaphore',
+        WAITING_FOR_MUTEX : 'waiting-for-mutex',
+        WAITING_FOR_CONDITION_VARIABLE : 'waiting-for-condition-variable',
+        WAITING_FOR_JOIN_AT_EXIT : 'waiting-for-join-at-exit',
+        WAITING_FOR_RPC_REPLY : 'waiting-for-rpc-reply',
+        WAITING_FOR_PERIOD : 'waiting-for-period',
+        WAITING_FOR_SIGNAL : 'waiting-for-signal',
+        WAITING_FOR_BARRIER : 'waiting-for-barrier',
+        WAITING_FOR_RWLOCK : 'waiting-for-rwlock'
+        }
+        
+    def __init__(self, s):
+        self.s = s
+
+    def to_string(self):
+        if (self.s & self.LOCALLY_BLOCKED) == self.LOCALLY_BLOCKED:
+            return 'locally-blocked'
+        if (self.s & self.WAITING_ON_THREAD_QUEUE) == self.WAITING_ON_THREAD_QUEUE:
+            return 'waiting-on-thread-queue'
+        if (self.s & self.BLOCKED) == self.BLOCKED:
+            return 'blocked'
+        s = ','
+        for m in self.masks:
+            if (self.s & m) == m:
+                s = self.masks[m] + ','
+        return s[:-1]
+
+class wait_info:
+
+    def __init__(self, info):
+        self.info = info
+
+    def id(self):
+        return self.info['id']
+
+    def count(self):
+        return self.info['count']
+
+    def return_arg(self):
+        return self.info['return_argument']
+
+    def option(self):
+        return self.info['option']
+
+    def block2n(self):
+        return task_chain(chains.control(self.info['Block2n']))
+        
+    def queue(self):
+        return task_chain(chains.control(self.info['queue']))
+
+class control:
+    
+    def __init__(self, ctrl):
+        self.ctrl = ctrl
+        self.object = objects.control(ctrl['Object'])
+        
+    def id(self):
+        return self.object.id()
+
+    def name(self):
+        return self.object.name()
+
+    def current_state(self):
+        return state(self.ctrl['current_state']).to_string()
+
+    def current_priority(self):
+        return self.ctrl['current_priority']
+
+    def real_priority(self):
+        return self.ctrl['real_priority']
+
+    def suspends(self):
+        return self.ctrl['suspend_count']
+
+    def post_task_switch_ext(self):
+        return self.ctrl['do_post_task_switch_extension']
+
+    def preemptible(self):
+        return self.ctrl['is_preemptible']
+
+    def cpu_time_budget(self):
+        return self.ctrl['cpu_time_budget']
+
+    def wait_info(self):
+        return wait_info(self.ctrl['Wait'])
+
+    def brief(self):
+        return "'%s' (c:%d, r:%d)" % \
+            (self.name(), self.current_priority(), self.real_priority())
+
+class queue:
+    """Manage the Thread_queue_Control."""
+
+    priority_headers = 4
+
+    def __init__(self, que):
+        self.que = que
+
+    def fifo(self):
+        return str(self.que['discipline']) == 'THREAD_QUEUE_DISCIPLINE_FIFO'
+
+    def priority(self):
+        return str(self.que['discipline']) == 'THREAD_QUEUE_DISCIPLINE_PRIORITY'
+
+    def state(self):
+        return state(self.que['state']).to_string()
+        
+    def tasks(self):
+        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']['Fifo'])))
+        return t
+
+    def to_string(self):
+        if self.fifo():
+            s = 'fifo'
+        else:
+            s = 'priority'
+        return
+
+class state_printer:
+
+    def __init__(self, s):
+        self.s = state(s)
+
+    def to_string(self):
+        return self.s.to_string()
diff --git a/tools/gdb/python/watchdog.py b/tools/gdb/python/watchdog.py
new file mode 100644
index 0000000..0766575
--- /dev/null
+++ b/tools/gdb/python/watchdog.py
@@ -0,0 +1,56 @@
+#
+# RTEMS Watchdog Support
+# Copyright 2010 Chris Johns (chrisj at rtems.org)
+#
+# $Id$
+#
+
+import gdb
+
+import chains
+import objects
+
+class state:
+
+    INACTIVE = 0
+    BEING_INSERTED = 1
+    ACTIVE = 2
+    REMOVE_IT = 3
+    
+    states = {
+        0: 'inactive',
+        1: 'being-inserted',
+        2: 'active',
+        3: 'remove-it'
+        }
+        
+    def __init__(self, s):
+        self.s = s
+
+    def to_string(self):
+        return self.states[self.s]
+
+class control:
+
+    def __init__(self, ctrl):
+        self.ctrl = ctrl
+
+    def state(self):
+        return state(self.ctrl['state']).to_string()
+
+    def initial(self):
+        return self.ctrl['initial']
+
+    def delta_interval(self):
+        return self.ctrl['delta_interval']
+
+    def start_time(self):
+        return self.ctrl['start_time']
+
+    def stop_time(self):
+        return self.ctrl['stop_time']
+
+    def routine(self):
+        addr = self.ctrl['routine']
+        sym = gdb.lookup_symbol(addr)
+        print sym



More information about the vc mailing list