]> Git Repo - J-linux.git/blob - scripts/gdb/linux/timerlist.py
Merge tag 'hid-for-linus-2024101301' of git://git.kernel.org/pub/scm/linux/kernel...
[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 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             TS_FLAG_STOPPED = 1 << 1
91             TS_FLAG_NOHZ = 1 << 4
92             text += f"  .{'nohz':15s}: {int(bool(ts['flags'] & TS_FLAG_NOHZ))}\n"
93             text += f"  .{'last_tick':15s}: {ts['last_tick']}\n"
94             text += f"  .{'tick_stopped':15s}: {int(bool(ts['flags'] & TS_FLAG_STOPPED))}\n"
95             text += f"  .{'idle_jiffies':15s}: {ts['idle_jiffies']}\n"
96             text += f"  .{'idle_calls':15s}: {ts['idle_calls']}\n"
97             text += f"  .{'idle_sleeps':15s}: {ts['idle_sleeps']}\n"
98             text += f"  .{'idle_entrytime':15s}: {ts['idle_entrytime']} nsecs\n"
99             text += f"  .{'idle_waketime':15s}: {ts['idle_waketime']} nsecs\n"
100             text += f"  .{'idle_exittime':15s}: {ts['idle_exittime']} nsecs\n"
101             text += f"  .{'idle_sleeptime':15s}: {ts['idle_sleeptime']} nsecs\n"
102             text += f"  .{'iowait_sleeptime':15s}: {ts['iowait_sleeptime']} nsecs\n"
103             text += f"  .{'last_jiffies':15s}: {ts['last_jiffies']}\n"
104             text += f"  .{'next_timer':15s}: {ts['next_timer']}\n"
105             text += f"  .{'idle_expires':15s}: {ts['idle_expires']} nsecs\n"
106             text += "\njiffies: {}\n".format(jiffies)
107
108         text += "\n"
109
110     return text
111
112
113 def print_tickdevice(td, cpu):
114     dev = td['evtdev']
115     text = "Tick Device: mode:     {}\n".format(td['mode'])
116     if cpu < 0:
117             text += "Broadcast device\n"
118     else:
119             text += "Per CPU device: {}\n".format(cpu)
120
121     text += "Clock Event Device: "
122     if dev == 0:
123             text += "<NULL>\n"
124             return text
125
126     text += "{}\n".format(dev['name'])
127     text += " max_delta_ns:   {}\n".format(dev['max_delta_ns'])
128     text += " min_delta_ns:   {}\n".format(dev['min_delta_ns'])
129     text += " mult:           {}\n".format(dev['mult'])
130     text += " shift:          {}\n".format(dev['shift'])
131     text += " mode:           {}\n".format(dev['state_use_accessors'])
132     text += " next_event:     {} nsecs\n".format(dev['next_event'])
133
134     text += " set_next_event: {}\n".format(dev['set_next_event'])
135
136     members = [('set_state_shutdown', " shutdown: {}\n"),
137                ('set_state_periodic', " periodic: {}\n"),
138                ('set_state_oneshot', " oneshot:  {}\n"),
139                ('set_state_oneshot_stopped', " oneshot stopped: {}\n"),
140                ('tick_resume', " resume:   {}\n")]
141     for member, fmt in members:
142         if dev[member]:
143             text += fmt.format(dev[member])
144
145     text += " event_handler:  {}\n".format(dev['event_handler'])
146     text += " retries:        {}\n".format(dev['retries'])
147
148     return text
149
150
151 def pr_cpumask(mask):
152     nr_cpu_ids = 1
153     if constants.LX_NR_CPUS > 1:
154         nr_cpu_ids = gdb.parse_and_eval("nr_cpu_ids")
155
156     inf = gdb.inferiors()[0]
157     bits = mask['bits']
158     num_bytes = (nr_cpu_ids + 7) / 8
159     buf = utils.read_memoryview(inf, bits, num_bytes).tobytes()
160     buf = binascii.b2a_hex(buf)
161     if type(buf) is not str:
162         buf=buf.decode()
163
164     chunks = []
165     i = num_bytes
166     while i > 0:
167         i -= 1
168         start = i * 2
169         end = start + 2
170         chunks.append(buf[start:end])
171         if i != 0 and i % 4 == 0:
172             chunks.append(',')
173
174     extra = nr_cpu_ids % 8
175     if 0 < extra <= 4:
176         chunks[0] = chunks[0][0]  # Cut off the first 0
177
178     return "".join(str(chunks))
179
180
181 class LxTimerList(gdb.Command):
182     """Print /proc/timer_list"""
183
184     def __init__(self):
185         super(LxTimerList, self).__init__("lx-timerlist", gdb.COMMAND_DATA)
186
187     def invoke(self, arg, from_tty):
188         hrtimer_bases = gdb.parse_and_eval("&hrtimer_bases")
189         max_clock_bases = gdb.parse_and_eval("HRTIMER_MAX_CLOCK_BASES")
190
191         text = "Timer List Version: gdb scripts\n"
192         text += "HRTIMER_MAX_CLOCK_BASES: {}\n".format(
193             max_clock_bases.type.fields()[max_clock_bases].enumval)
194         text += "now at {} nsecs\n".format(ktime_get())
195
196         for cpu in cpus.each_online_cpu():
197             text += print_cpu(hrtimer_bases, cpu, max_clock_bases)
198
199         if constants.LX_CONFIG_GENERIC_CLOCKEVENTS:
200             if constants.LX_CONFIG_GENERIC_CLOCKEVENTS_BROADCAST:
201                 bc_dev = gdb.parse_and_eval("&tick_broadcast_device")
202                 text += print_tickdevice(bc_dev, -1)
203                 text += "\n"
204                 mask = gdb.parse_and_eval("tick_broadcast_mask")
205                 mask = pr_cpumask(mask)
206                 text += "tick_broadcast_mask: {}\n".format(mask)
207                 if constants.LX_CONFIG_TICK_ONESHOT:
208                     mask = gdb.parse_and_eval("tick_broadcast_oneshot_mask")
209                     mask = pr_cpumask(mask)
210                     text += "tick_broadcast_oneshot_mask: {}\n".format(mask)
211                 text += "\n"
212
213             tick_cpu_devices = gdb.parse_and_eval("&tick_cpu_device")
214             for cpu in cpus.each_online_cpu():
215                 tick_dev = cpus.per_cpu(tick_cpu_devices, cpu)
216                 text += print_tickdevice(tick_dev, cpu)
217                 text += "\n"
218
219         gdb.write(text)
220
221
222 LxTimerList()
This page took 0.039275 seconds and 4 git commands to generate.