]> Git Repo - J-linux.git/blob - scripts/gdb/linux/timerlist.py
scripts/gdb: fix lx-timerlist for struct timequeue_head change
[J-linux.git] / scripts / gdb / linux / timerlist.py
1 # SPDX-License-Identifier: GPL-2.0
2 #
3 # Copyright 2019 Google LLC.
4
5 import binascii
6 import gdb
7
8 from linux import constants
9 from linux import cpus
10 from linux import rbtree
11 from linux import utils
12
13 timerqueue_node_type = utils.CachedType("struct timerqueue_node").get_type()
14 hrtimer_type = utils.CachedType("struct hrtimer").get_type()
15
16
17 def ktime_get():
18     """Returns the current time, but not very accurately
19
20     We can't read the hardware timer itself to add any nanoseconds
21     that need to be added since we last stored the time in the
22     timekeeper. But this is probably good enough for debug purposes."""
23     tk_core = gdb.parse_and_eval("&tk_core")
24
25     return tk_core['timekeeper']['tkr_mono']['base']
26
27
28 def print_timer(rb_node, idx):
29     timerqueue = utils.container_of(rb_node, timerqueue_node_type.pointer(),
30                                     "node")
31     timer = utils.container_of(timerqueue, hrtimer_type.pointer(), "node")
32
33     function = str(timer['function']).split(" ")[1].strip("<>")
34     softexpires = timer['_softexpires']
35     expires = timer['node']['expires']
36     now = ktime_get()
37
38     text = " #{}: <{}>, {}, ".format(idx, timer, function)
39     text += "S:{:02x}\n".format(int(timer['state']))
40     text += " # expires at {}-{} nsecs [in {} to {} nsecs]\n".format(
41             softexpires, expires, softexpires - now, expires - now)
42     return text
43
44
45 def print_active_timers(base):
46     curr = base['active']['rb_root']['rb_leftmost']
47     idx = 0
48     while curr:
49         yield print_timer(curr, idx)
50         curr = rbtree.rb_next(curr)
51         idx += 1
52
53
54 def print_base(base):
55     text = " .base:       {}\n".format(base.address)
56     text += " .index:      {}\n".format(base['index'])
57
58     text += " .resolution: {} nsecs\n".format(constants.LX_hrtimer_resolution)
59
60     text += " .get_time:   {}\n".format(base['get_time'])
61     if constants.LX_CONFIG_HIGH_RES_TIMERS:
62         text += "  .offset:     {} nsecs\n".format(base['offset'])
63     text += "active timers:\n"
64     text += "".join([x for x in print_active_timers(base)])
65     return text
66
67
68 def print_cpu(hrtimer_bases, cpu, max_clock_bases):
69     cpu_base = cpus.per_cpu(hrtimer_bases, cpu)
70     jiffies = gdb.parse_and_eval("jiffies_64")
71     tick_sched_ptr = gdb.parse_and_eval("&tick_cpu_sched")
72     ts = cpus.per_cpu(tick_sched_ptr, cpu)
73
74     text = "cpu: {}\n".format(cpu)
75     for i in xrange(max_clock_bases):
76         text += " clock {}:\n".format(i)
77         text += print_base(cpu_base['clock_base'][i])
78
79         if constants.LX_CONFIG_HIGH_RES_TIMERS:
80             fmts = [("  .{}   : {} nsecs", 'expires_next'),
81                     ("  .{}    : {}", 'hres_active'),
82                     ("  .{}      : {}", 'nr_events'),
83                     ("  .{}     : {}", 'nr_retries'),
84                     ("  .{}       : {}", 'nr_hangs'),
85                     ("  .{}  : {}", 'max_hang_time')]
86             text += "\n".join([s.format(f, cpu_base[f]) for s, f in fmts])
87             text += "\n"
88
89         if constants.LX_CONFIG_TICK_ONESHOT:
90             fmts = [("  .{}      : {}", 'nohz_mode'),
91                     ("  .{}      : {} nsecs", 'last_tick'),
92                     ("  .{}   : {}", 'tick_stopped'),
93                     ("  .{}   : {}", 'idle_jiffies'),
94                     ("  .{}     : {}", 'idle_calls'),
95                     ("  .{}    : {}", 'idle_sleeps'),
96                     ("  .{} : {} nsecs", 'idle_entrytime'),
97                     ("  .{}  : {} nsecs", 'idle_waketime'),
98                     ("  .{}  : {} nsecs", 'idle_exittime'),
99                     ("  .{} : {} nsecs", 'idle_sleeptime'),
100                     ("  .{}: {} nsecs", 'iowait_sleeptime'),
101                     ("  .{}   : {}", 'last_jiffies'),
102                     ("  .{}     : {}", 'next_timer'),
103                     ("  .{}   : {} nsecs", 'idle_expires')]
104             text += "\n".join([s.format(f, ts[f]) for s, f in fmts])
105             text += "\njiffies: {}\n".format(jiffies)
106
107         text += "\n"
108
109     return text
110
111
112 def print_tickdevice(td, cpu):
113     dev = td['evtdev']
114     text = "Tick Device: mode:     {}\n".format(td['mode'])
115     if cpu < 0:
116             text += "Broadcast device\n"
117     else:
118             text += "Per CPU device: {}\n".format(cpu)
119
120     text += "Clock Event Device: "
121     if dev == 0:
122             text += "<NULL>\n"
123             return text
124
125     text += "{}\n".format(dev['name'])
126     text += " max_delta_ns:   {}\n".format(dev['max_delta_ns'])
127     text += " min_delta_ns:   {}\n".format(dev['min_delta_ns'])
128     text += " mult:           {}\n".format(dev['mult'])
129     text += " shift:          {}\n".format(dev['shift'])
130     text += " mode:           {}\n".format(dev['state_use_accessors'])
131     text += " next_event:     {} nsecs\n".format(dev['next_event'])
132
133     text += " set_next_event: {}\n".format(dev['set_next_event'])
134
135     members = [('set_state_shutdown', " shutdown: {}\n"),
136                ('set_state_periodic', " periodic: {}\n"),
137                ('set_state_oneshot', " oneshot:  {}\n"),
138                ('set_state_oneshot_stopped', " oneshot stopped: {}\n"),
139                ('tick_resume', " resume:   {}\n")]
140     for member, fmt in members:
141         if dev[member]:
142             text += fmt.format(dev[member])
143
144     text += " event_handler:  {}\n".format(dev['event_handler'])
145     text += " retries:        {}\n".format(dev['retries'])
146
147     return text
148
149
150 def pr_cpumask(mask):
151     nr_cpu_ids = 1
152     if constants.LX_NR_CPUS > 1:
153         nr_cpu_ids = gdb.parse_and_eval("nr_cpu_ids")
154
155     inf = gdb.inferiors()[0]
156     bits = mask['bits']
157     num_bytes = (nr_cpu_ids + 7) / 8
158     buf = utils.read_memoryview(inf, bits, num_bytes).tobytes()
159     buf = binascii.b2a_hex(buf)
160
161     chunks = []
162     i = num_bytes
163     while i > 0:
164         i -= 1
165         start = i * 2
166         end = start + 2
167         chunks.append(buf[start:end])
168         if i != 0 and i % 4 == 0:
169             chunks.append(',')
170
171     extra = nr_cpu_ids % 8
172     if 0 < extra <= 4:
173         chunks[0] = chunks[0][0]  # Cut off the first 0
174
175     return "".join(chunks)
176
177
178 class LxTimerList(gdb.Command):
179     """Print /proc/timer_list"""
180
181     def __init__(self):
182         super(LxTimerList, self).__init__("lx-timerlist", gdb.COMMAND_DATA)
183
184     def invoke(self, arg, from_tty):
185         hrtimer_bases = gdb.parse_and_eval("&hrtimer_bases")
186         max_clock_bases = gdb.parse_and_eval("HRTIMER_MAX_CLOCK_BASES")
187
188         text = "Timer List Version: gdb scripts\n"
189         text += "HRTIMER_MAX_CLOCK_BASES: {}\n".format(max_clock_bases)
190         text += "now at {} nsecs\n".format(ktime_get())
191
192         for cpu in cpus.each_online_cpu():
193             text += print_cpu(hrtimer_bases, cpu, max_clock_bases)
194
195         if constants.LX_CONFIG_GENERIC_CLOCKEVENTS:
196             if constants.LX_CONFIG_GENERIC_CLOCKEVENTS_BROADCAST:
197                 bc_dev = gdb.parse_and_eval("&tick_broadcast_device")
198                 text += print_tickdevice(bc_dev, -1)
199                 text += "\n"
200                 mask = gdb.parse_and_eval("tick_broadcast_mask")
201                 mask = pr_cpumask(mask)
202                 text += "tick_broadcast_mask: {}\n".format(mask)
203                 if constants.LX_CONFIG_TICK_ONESHOT:
204                     mask = gdb.parse_and_eval("tick_broadcast_oneshot_mask")
205                     mask = pr_cpumask(mask)
206                     text += "tick_broadcast_oneshot_mask: {}\n".format(mask)
207                 text += "\n"
208
209             tick_cpu_devices = gdb.parse_and_eval("&tick_cpu_device")
210             for cpu in cpus.each_online_cpu():
211                 tick_dev = cpus.per_cpu(tick_cpu_devices, cpu)
212                 text += print_tickdevice(tick_dev, cpu)
213                 text += "\n"
214
215         gdb.write(text)
216
217
218 LxTimerList()
This page took 0.041106 seconds and 4 git commands to generate.