0001
0002
0003
0004
0005 import binascii
0006 import gdb
0007
0008 from linux import constants
0009 from linux import cpus
0010 from linux import rbtree
0011 from linux import utils
0012
0013 timerqueue_node_type = utils.CachedType("struct timerqueue_node").get_type()
0014 hrtimer_type = utils.CachedType("struct hrtimer").get_type()
0015
0016
0017 def ktime_get():
0018 """Returns the current time, but not very accurately
0019
0020 We can't read the hardware timer itself to add any nanoseconds
0021 that need to be added since we last stored the time in the
0022 timekeeper. But this is probably good enough for debug purposes."""
0023 tk_core = gdb.parse_and_eval("&tk_core")
0024
0025 return tk_core['timekeeper']['tkr_mono']['base']
0026
0027
0028 def print_timer(rb_node, idx):
0029 timerqueue = utils.container_of(rb_node, timerqueue_node_type.pointer(),
0030 "node")
0031 timer = utils.container_of(timerqueue, hrtimer_type.pointer(), "node")
0032
0033 function = str(timer['function']).split(" ")[1].strip("<>")
0034 softexpires = timer['_softexpires']
0035 expires = timer['node']['expires']
0036 now = ktime_get()
0037
0038 text = " #{}: <{}>, {}, ".format(idx, timer, function)
0039 text += "S:{:02x}\n".format(int(timer['state']))
0040 text += " # expires at {}-{} nsecs [in {} to {} nsecs]\n".format(
0041 softexpires, expires, softexpires - now, expires - now)
0042 return text
0043
0044
0045 def print_active_timers(base):
0046 curr = base['active']['next']['node']
0047 curr = curr.address.cast(rbtree.rb_node_type.get_type().pointer())
0048 idx = 0
0049 while curr:
0050 yield print_timer(curr, idx)
0051 curr = rbtree.rb_next(curr)
0052 idx += 1
0053
0054
0055 def print_base(base):
0056 text = " .base: {}\n".format(base.address)
0057 text += " .index: {}\n".format(base['index'])
0058
0059 text += " .resolution: {} nsecs\n".format(constants.LX_hrtimer_resolution)
0060
0061 text += " .get_time: {}\n".format(base['get_time'])
0062 if constants.LX_CONFIG_HIGH_RES_TIMERS:
0063 text += " .offset: {} nsecs\n".format(base['offset'])
0064 text += "active timers:\n"
0065 text += "".join([x for x in print_active_timers(base)])
0066 return text
0067
0068
0069 def print_cpu(hrtimer_bases, cpu, max_clock_bases):
0070 cpu_base = cpus.per_cpu(hrtimer_bases, cpu)
0071 jiffies = gdb.parse_and_eval("jiffies_64")
0072 tick_sched_ptr = gdb.parse_and_eval("&tick_cpu_sched")
0073 ts = cpus.per_cpu(tick_sched_ptr, cpu)
0074
0075 text = "cpu: {}\n".format(cpu)
0076 for i in xrange(max_clock_bases):
0077 text += " clock {}:\n".format(i)
0078 text += print_base(cpu_base['clock_base'][i])
0079
0080 if constants.LX_CONFIG_HIGH_RES_TIMERS:
0081 fmts = [(" .{} : {} nsecs", 'expires_next'),
0082 (" .{} : {}", 'hres_active'),
0083 (" .{} : {}", 'nr_events'),
0084 (" .{} : {}", 'nr_retries'),
0085 (" .{} : {}", 'nr_hangs'),
0086 (" .{} : {}", 'max_hang_time')]
0087 text += "\n".join([s.format(f, cpu_base[f]) for s, f in fmts])
0088 text += "\n"
0089
0090 if constants.LX_CONFIG_TICK_ONESHOT:
0091 fmts = [(" .{} : {}", 'nohz_mode'),
0092 (" .{} : {} nsecs", 'last_tick'),
0093 (" .{} : {}", 'tick_stopped'),
0094 (" .{} : {}", 'idle_jiffies'),
0095 (" .{} : {}", 'idle_calls'),
0096 (" .{} : {}", 'idle_sleeps'),
0097 (" .{} : {} nsecs", 'idle_entrytime'),
0098 (" .{} : {} nsecs", 'idle_waketime'),
0099 (" .{} : {} nsecs", 'idle_exittime'),
0100 (" .{} : {} nsecs", 'idle_sleeptime'),
0101 (" .{}: {} nsecs", 'iowait_sleeptime'),
0102 (" .{} : {}", 'last_jiffies'),
0103 (" .{} : {}", 'next_timer'),
0104 (" .{} : {} nsecs", 'idle_expires')]
0105 text += "\n".join([s.format(f, ts[f]) for s, f in fmts])
0106 text += "\njiffies: {}\n".format(jiffies)
0107
0108 text += "\n"
0109
0110 return text
0111
0112
0113 def print_tickdevice(td, cpu):
0114 dev = td['evtdev']
0115 text = "Tick Device: mode: {}\n".format(td['mode'])
0116 if cpu < 0:
0117 text += "Broadcast device\n"
0118 else:
0119 text += "Per CPU device: {}\n".format(cpu)
0120
0121 text += "Clock Event Device: "
0122 if dev == 0:
0123 text += "<NULL>\n"
0124 return text
0125
0126 text += "{}\n".format(dev['name'])
0127 text += " max_delta_ns: {}\n".format(dev['max_delta_ns'])
0128 text += " min_delta_ns: {}\n".format(dev['min_delta_ns'])
0129 text += " mult: {}\n".format(dev['mult'])
0130 text += " shift: {}\n".format(dev['shift'])
0131 text += " mode: {}\n".format(dev['state_use_accessors'])
0132 text += " next_event: {} nsecs\n".format(dev['next_event'])
0133
0134 text += " set_next_event: {}\n".format(dev['set_next_event'])
0135
0136 members = [('set_state_shutdown', " shutdown: {}\n"),
0137 ('set_state_periodic', " periodic: {}\n"),
0138 ('set_state_oneshot', " oneshot: {}\n"),
0139 ('set_state_oneshot_stopped', " oneshot stopped: {}\n"),
0140 ('tick_resume', " resume: {}\n")]
0141 for member, fmt in members:
0142 if dev[member]:
0143 text += fmt.format(dev[member])
0144
0145 text += " event_handler: {}\n".format(dev['event_handler'])
0146 text += " retries: {}\n".format(dev['retries'])
0147
0148 return text
0149
0150
0151 def pr_cpumask(mask):
0152 nr_cpu_ids = 1
0153 if constants.LX_NR_CPUS > 1:
0154 nr_cpu_ids = gdb.parse_and_eval("nr_cpu_ids")
0155
0156 inf = gdb.inferiors()[0]
0157 bits = mask['bits']
0158 num_bytes = (nr_cpu_ids + 7) / 8
0159 buf = utils.read_memoryview(inf, bits, num_bytes).tobytes()
0160 buf = binascii.b2a_hex(buf)
0161
0162 chunks = []
0163 i = num_bytes
0164 while i > 0:
0165 i -= 1
0166 start = i * 2
0167 end = start + 2
0168 chunks.append(buf[start:end])
0169 if i != 0 and i % 4 == 0:
0170 chunks.append(',')
0171
0172 extra = nr_cpu_ids % 8
0173 if 0 < extra <= 4:
0174 chunks[0] = chunks[0][0]
0175
0176 return "".join(chunks)
0177
0178
0179 class LxTimerList(gdb.Command):
0180 """Print /proc/timer_list"""
0181
0182 def __init__(self):
0183 super(LxTimerList, self).__init__("lx-timerlist", gdb.COMMAND_DATA)
0184
0185 def invoke(self, arg, from_tty):
0186 hrtimer_bases = gdb.parse_and_eval("&hrtimer_bases")
0187 max_clock_bases = gdb.parse_and_eval("HRTIMER_MAX_CLOCK_BASES")
0188
0189 text = "Timer List Version: gdb scripts\n"
0190 text += "HRTIMER_MAX_CLOCK_BASES: {}\n".format(max_clock_bases)
0191 text += "now at {} nsecs\n".format(ktime_get())
0192
0193 for cpu in cpus.each_online_cpu():
0194 text += print_cpu(hrtimer_bases, cpu, max_clock_bases)
0195
0196 if constants.LX_CONFIG_GENERIC_CLOCKEVENTS:
0197 if constants.LX_CONFIG_GENERIC_CLOCKEVENTS_BROADCAST:
0198 bc_dev = gdb.parse_and_eval("&tick_broadcast_device")
0199 text += print_tickdevice(bc_dev, -1)
0200 text += "\n"
0201 mask = gdb.parse_and_eval("tick_broadcast_mask")
0202 mask = pr_cpumask(mask)
0203 text += "tick_broadcast_mask: {}\n".format(mask)
0204 if constants.LX_CONFIG_TICK_ONESHOT:
0205 mask = gdb.parse_and_eval("tick_broadcast_oneshot_mask")
0206 mask = pr_cpumask(mask)
0207 text += "tick_broadcast_oneshot_mask: {}\n".format(mask)
0208 text += "\n"
0209
0210 tick_cpu_devices = gdb.parse_and_eval("&tick_cpu_device")
0211 for cpu in cpus.each_online_cpu():
0212 tick_dev = cpus.per_cpu(tick_cpu_devices, cpu)
0213 text += print_tickdevice(tick_dev, cpu)
0214 text += "\n"
0215
0216 gdb.write(text)
0217
0218
0219 LxTimerList()