~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/scripts/gdb/linux/timerlist.py

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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()

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php