]> Git Repo - linux.git/blob - scripts/gdb/linux/timerlist.py
Merge tag 'input-for-v6.7-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor...
[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 range(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     if type(buf) is not str:
161         buf=buf.decode()
162
163     chunks = []
164     i = num_bytes
165     while i > 0:
166         i -= 1
167         start = i * 2
168         end = start + 2
169         chunks.append(buf[start:end])
170         if i != 0 and i % 4 == 0:
171             chunks.append(',')
172
173     extra = nr_cpu_ids % 8
174     if 0 < extra <= 4:
175         chunks[0] = chunks[0][0]  # Cut off the first 0
176
177     return "".join(str(chunks))
178
179
180 class LxTimerList(gdb.Command):
181     """Print /proc/timer_list"""
182
183     def __init__(self):
184         super(LxTimerList, self).__init__("lx-timerlist", gdb.COMMAND_DATA)
185
186     def invoke(self, arg, from_tty):
187         hrtimer_bases = gdb.parse_and_eval("&hrtimer_bases")
188         max_clock_bases = gdb.parse_and_eval("HRTIMER_MAX_CLOCK_BASES")
189
190         text = "Timer List Version: gdb scripts\n"
191         text += "HRTIMER_MAX_CLOCK_BASES: {}\n".format(
192             max_clock_bases.type.fields()[max_clock_bases].enumval)
193         text += "now at {} nsecs\n".format(ktime_get())
194
195         for cpu in cpus.each_online_cpu():
196             text += print_cpu(hrtimer_bases, cpu, max_clock_bases)
197
198         if constants.LX_CONFIG_GENERIC_CLOCKEVENTS:
199             if constants.LX_CONFIG_GENERIC_CLOCKEVENTS_BROADCAST:
200                 bc_dev = gdb.parse_and_eval("&tick_broadcast_device")
201                 text += print_tickdevice(bc_dev, -1)
202                 text += "\n"
203                 mask = gdb.parse_and_eval("tick_broadcast_mask")
204                 mask = pr_cpumask(mask)
205                 text += "tick_broadcast_mask: {}\n".format(mask)
206                 if constants.LX_CONFIG_TICK_ONESHOT:
207                     mask = gdb.parse_and_eval("tick_broadcast_oneshot_mask")
208                     mask = pr_cpumask(mask)
209                     text += "tick_broadcast_oneshot_mask: {}\n".format(mask)
210                 text += "\n"
211
212             tick_cpu_devices = gdb.parse_and_eval("&tick_cpu_device")
213             for cpu in cpus.each_online_cpu():
214                 tick_dev = cpus.per_cpu(tick_cpu_devices, cpu)
215                 text += print_tickdevice(tick_dev, cpu)
216                 text += "\n"
217
218         gdb.write(text)
219
220
221 LxTimerList()
This page took 0.042945 seconds and 4 git commands to generate.