source: rtems-tools/tools/gdb/python/threads.py @ b117be8

4.104.11
Last change on this file since b117be8 was b117be8, checked in by Chris Johns <chrisj@…>, on Mar 17, 2015 at 2:11:57 AM

gdb/python: Update the support to a recent RTEMS.

  • Property mode set to 100644
File size: 10.0 KB
Line 
1# RTEMS Tools Project (http://www.rtems.org/)
2# Copyright 2010-2015 Chris Johns (chrisj@rtems.org)
3# All rights reserved.
4#
5# This file is part of the RTEMS Tools package in 'rtems-tools'.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions are met:
9#
10# 1. Redistributions of source code must retain the above copyright notice,
11# this list of conditions and the following disclaimer.
12#
13# 2. Redistributions in binary form must reproduce the above copyright notice,
14# this list of conditions and the following disclaimer in the documentation
15# and/or other materials provided with the distribution.
16#
17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27# POSSIBILITY OF SUCH DAMAGE.
28#
29
30#
31# RTEMS Threads Support
32#
33
34import gdb
35
36import chains
37import objects
38import percpu
39import rbtrees
40import time
41
42def task_chain(chain):
43    tasks = []
44    if not chain.empty():
45        node = chain.first()
46        while not node.null():
47            t = control(node.cast('Thread_Control'))
48            tasks.append(t)
49            node = node(node.next())
50    return tasks
51
52def task_tree(tree):
53    tasks = []
54    node = tree.first(rbtrees.rbt_left)
55    while not node.null():
56        tasks.append(control(node.cast('Thread_Control')))
57        node = node.next(rbtrees.rbt_left)
58    return tasks
59
60class state():
61
62    ALL_SET = 0x000fffff
63    READY = 0x00000000
64    DORMANT = 0x00000001
65    SUSPENDED = 0x00000002
66    TRANSIENT = 0x00000004
67    DELAYING = 0x00000008
68    WAITING_FOR_TIME = 0x00000010
69    WAITING_FOR_BUFFER = 0x00000020
70    WAITING_FOR_SEGMENT = 0x00000040
71    WAITING_FOR_MESSAGE = 0x00000080
72    WAITING_FOR_EVENT = 0x00000100
73    WAITING_FOR_SEMAPHORE = 0x00000200
74    WAITING_FOR_MUTEX = 0x00000400
75    WAITING_FOR_CONDITION_VARIABLE = 0x00000800
76    WAITING_FOR_JOIN_AT_EXIT = 0x00001000
77    WAITING_FOR_RPC_REPLY = 0x00002000
78    WAITING_FOR_PERIOD = 0x00004000
79    WAITING_FOR_SIGNAL = 0x00008000
80    WAITING_FOR_BARRIER = 0x00010000
81    WAITING_FOR_RWLOCK = 0x00020000
82    INTERRUPTIBLE_BY_SIGNAL = 0x10000000
83    LOCALLY_BLOCKED = \
84        WAITING_FOR_BUFFER             | \
85        WAITING_FOR_SEGMENT            | \
86        WAITING_FOR_MESSAGE            | \
87        WAITING_FOR_SEMAPHORE          | \
88        WAITING_FOR_MUTEX              | \
89        WAITING_FOR_CONDITION_VARIABLE | \
90        WAITING_FOR_JOIN_AT_EXIT       | \
91        WAITING_FOR_SIGNAL             | \
92        WAITING_FOR_BARRIER            | \
93        WAITING_FOR_RWLOCK
94    WAITING_ON_THREAD_QUEUE = \
95        LOCALLY_BLOCKED | WAITING_FOR_RPC_REPLY
96    BLOCKED = \
97        DELAYING                | \
98        WAITING_FOR_TIME        | \
99        WAITING_FOR_PERIOD      | \
100        WAITING_FOR_EVENT       | \
101        WAITING_ON_THREAD_QUEUE | \
102        INTERRUPTIBLE_BY_SIGNAL
103
104    masks = {
105        ALL_SET : 'all-set',
106        READY : 'ready',
107        DORMANT : 'dormant',
108        SUSPENDED : 'suspended',
109        TRANSIENT : 'transient',
110        DELAYING : 'delaying',
111        WAITING_FOR_TIME : 'waiting-for-time',
112        WAITING_FOR_BUFFER : 'waiting-for-buffer',
113        WAITING_FOR_SEGMENT : 'waiting-for-segment',
114        WAITING_FOR_MESSAGE : 'waiting-for-message',
115        WAITING_FOR_EVENT : 'waiting-for-event',
116        WAITING_FOR_SEMAPHORE : 'waiting-for-semaphore',
117        WAITING_FOR_MUTEX : 'waiting-for-mutex',
118        WAITING_FOR_CONDITION_VARIABLE : 'waiting-for-condition-variable',
119        WAITING_FOR_JOIN_AT_EXIT : 'waiting-for-join-at-exit',
120        WAITING_FOR_RPC_REPLY : 'waiting-for-rpc-reply',
121        WAITING_FOR_PERIOD : 'waiting-for-period',
122        WAITING_FOR_SIGNAL : 'waiting-for-signal',
123        WAITING_FOR_BARRIER : 'waiting-for-barrier',
124        WAITING_FOR_RWLOCK : 'waiting-for-rwlock'
125        }
126
127    def __init__(self, s):
128        self.s = s
129
130    def to_string(self):
131        if (self.s & self.LOCALLY_BLOCKED) == self.LOCALLY_BLOCKED:
132            return 'locally-blocked'
133        if (self.s & self.WAITING_ON_THREAD_QUEUE) == self.WAITING_ON_THREAD_QUEUE:
134            return 'waiting-on-thread-queue'
135        if (self.s & self.BLOCKED) == self.BLOCKED:
136            return 'blocked'
137        s = ','
138        for m in self.masks:
139            if (self.s & m) == m:
140                s = self.masks[m] + ','
141        return s[:-1]
142
143class cpu_usage():
144
145    def __init__(self, time_):
146        self.time = time.time(time_)
147
148    def __str__(self):
149        return self.time.tostring()
150
151    def get(self):
152        return self.time.get()
153
154class wait_info():
155
156    def __init__(self, info):
157        self.info = info
158
159    def id(self):
160        return self.info['id']
161
162    def count(self):
163        return self.info['count']
164
165    def return_arg(self):
166        return self.info['return_argument']
167
168    def option(self):
169        return self.info['option']
170
171    def block2n(self):
172        return task_chain(chains.control(self.info['Block2n']))
173
174    def queue(self):
175        return task_chain(chains.control(self.info['queue']))
176
177class registers():
178
179    def __init__(self, regs):
180        self.regs = regs
181
182    def names(self):
183        return [field.name for field in self.regs.type.fields()]
184
185    def get(self, reg):
186        t = str(self.regs[reg].type)
187        if t in ['double']:
188            return float(self.regs[reg])
189        return int(self.regs[reg])
190
191    def format(self, reg):
192        t = self.regs[reg].type
193        if t in ['uint32_t', 'unsigned', 'unsigned long']:
194            return '%08x (%d)' % (val)
195
196class control():
197    '''
198    Thread_Control has the following fields:
199      Object              Objects_Control
200      RBNode              RBTree_Node
201      current_state       States_Control
202      current_priority    Priority_Control
203      real_priority       Priority_Control
204      resource_count      uint32_t
205      Wait                Thread_Wait_information
206      Timer               Watchdog_Control
207      receive_packet      MP_packet_Prefix*                   X
208      lock_mutex          Chain_Control                       X
209      Resource_node       Resource_Node                       X
210      is_global           bool                                X
211      is_preemptible      bool
212      Scheduler           Thread_Scheduler_control
213      rtems_ada_self      void*                               X
214      cpu_time_budget     uint32_t
215      budget_algorithm    Thread_CPU_budget_algorithms
216      budget_callout      Thread_CPU_budget_algorithm_callout
217      cpu_time_used       Thread_CPU_usage_t
218      Start               Thread_Start_information
219      Post_switch_actions Thread_Action_control
220      Registers           Context_Control
221      fp_context          Context_Control_fp*                 X
222      libc_reent          struct _reent*
223      API_Extensions      void*[THREAD_API_LAST + 1]
224      task_variables      rtems_task_variable_t*              X
225      Key_Chain           Chain_Control
226      Life                Thread_Life_control
227      extensions          void*[RTEMS_ZERO_LENGTH_ARRAY]
228
229    where 'X' means the field is condition and may no exist.
230    '''
231
232    def __init__(self, ctrl):
233        if ctrl.type.code == gdb.TYPE_CODE_PTR:
234            self.reference = ctrl
235            self.ctrl = ctrl.dereference()
236        else:
237            self.ctrl = ctrl
238            self.reference = ctrl.address
239        self.object = objects.control(ctrl['Object'])
240        self._executing = percpu.thread_active(self.reference)
241        self._heir = percpu.thread_heir(self.reference)
242
243    def id(self):
244        return self.object.id()
245
246    def name(self):
247        val = self.object.name()
248        if val == "":
249            val = '*'
250        return val
251
252    def executing(self):
253        return self._executing
254
255    def heir(self):
256        return self._heir
257
258    def current_state(self):
259        return state(self.ctrl['current_state']).to_string()
260
261    def current_priority(self):
262        return self.ctrl['current_priority']
263
264    def real_priority(self):
265        return self.ctrl['real_priority']
266
267    def resource_count(self):
268        return self.ctrl['resource_count']
269
270    def cpu_time_budget(self):
271        return self.ctrl['cpu_time_budget']
272
273    def cpu_time_used(self):
274        return cpu_usage(self.ctrl['cpu_time_used'])
275
276    def preemptible(self):
277        return self.ctrl['is_preemptible']
278
279    def cpu_time_budget(self):
280        return self.ctrl['cpu_time_budget']
281
282    def wait_info(self):
283        return wait_info(self.ctrl['Wait'])
284
285    def registers(self):
286        return registers(self.ctrl['Registers'])
287
288    def is_idle(self):
289        return (self.id() & 0xff000000) == 0x90000000
290
291    def brief(self):
292        return "'%s' (c:%d, r:%d)" % \
293            (self.name(), self.current_priority(), self.real_priority())
294
295class queue():
296    """Manage the Thread_queue_Control."""
297
298    def __init__(self, que):
299        if que.type.code == gdb.TYPE_CODE_PTR:
300            self.reference = que
301            self.que = que.dereference()
302        else:
303            self.que = que
304            self.reference = que.address
305
306    def fifo(self):
307        return str(self.que['discipline']) == 'THREAD_QUEUE_DISCIPLINE_FIFO'
308
309    def priority(self):
310        return str(self.que['discipline']) == 'THREAD_QUEUE_DISCIPLINE_PRIORITY'
311
312    def state(self):
313        return state(self.que['state']).to_string()
314
315    def tasks(self):
316        if self.fifo():
317            t = task_chain(chains.control(self.que['Queues']['Fifo']))
318        else:
319            t =  task_tree(rbtrees.control(self.que['Queues']['Priority']))
320        return t
Note: See TracBrowser for help on using the repository browser.