# SPDX-License-Identifier: GPL-2.0
#
# Copyright 2019 Google LLC.

import binascii
import gdb

from linux import constants
from linux import cpus
from linux import rbtree
from linux import utils

timerqueue_node_type = utils.CachedType("struct timerqueue_node").get_type()
hrtimer_type = utils.CachedType("struct hrtimer").get_type()


def ktime_get():
    """Returns the current time, but not very accurately

    We can't read the hardware timer itself to add any nanoseconds
    that need to be added since we last stored the time in the
    timekeeper. But this is probably good enough for debug purposes."""
    tk_core = gdb.parse_and_eval("&tk_core")

    return tk_core['timekeeper']['tkr_mono']['base']


def print_timer(rb_node, idx):
    timerqueue = utils.container_of(rb_node, timerqueue_node_type.pointer(),
                                    "node")
    timer = utils.container_of(timerqueue, hrtimer_type.pointer(), "node")

    function = str(timer['function']).split(" ")[1].strip("<>")
    softexpires = timer['_softexpires']
    expires = timer['node']['expires']
    now = ktime_get()

    text = " #{}: <{}>, {}, ".format(idx, timer, function)
    text += "S:{:02x}\n".format(int(timer['state']))
    text += " # expires at {}-{} nsecs [in {} to {} nsecs]\n".format(
            softexpires, expires, softexpires - now, expires - now)
    return text


def print_active_timers(base):
    curr = base['active']['next']['node']
    curr = curr.address.cast(rbtree.rb_node_type.get_type().pointer())
    idx = 0
    while curr:
        yield print_timer(curr, idx)
        curr = rbtree.rb_next(curr)
        idx += 1


def print_base(base):
    text = " .base:       {}\n".format(base.address)
    text += " .index:      {}\n".format(base['index'])

    text += " .resolution: {} nsecs\n".format(constants.LX_hrtimer_resolution)

    text += " .get_time:   {}\n".format(base['get_time'])
    if constants.LX_CONFIG_HIGH_RES_TIMERS:
        text += "  .offset:     {} nsecs\n".format(base['offset'])
    text += "active timers:\n"
    text += "".join([x for x in print_active_timers(base)])
    return text


def print_cpu(hrtimer_bases, cpu, max_clock_bases):
    cpu_base = cpus.per_cpu(hrtimer_bases, cpu)
    jiffies = gdb.parse_and_eval("jiffies_64")
    tick_sched_ptr = gdb.parse_and_eval("&tick_cpu_sched")
    ts = cpus.per_cpu(tick_sched_ptr, cpu)

    text = "cpu: {}\n".format(cpu)
    for i in xrange(max_clock_bases):
        text += " clock {}:\n".format(i)
        text += print_base(cpu_base['clock_base'][i])

        if constants.LX_CONFIG_HIGH_RES_TIMERS:
            fmts = [("  .{}   : {} nsecs", 'expires_next'),
                    ("  .{}    : {}", 'hres_active'),
                    ("  .{}      : {}", 'nr_events'),
                    ("  .{}     : {}", 'nr_retries'),
                    ("  .{}       : {}", 'nr_hangs'),
                    ("  .{}  : {}", 'max_hang_time')]
            text += "\n".join([s.format(f, cpu_base[f]) for s, f in fmts])
            text += "\n"

        if constants.LX_CONFIG_TICK_ONESHOT:
            fmts = [("  .{}      : {}", 'nohz_mode'),
                    ("  .{}      : {} nsecs", 'last_tick'),
                    ("  .{}   : {}", 'tick_stopped'),
                    ("  .{}   : {}", 'idle_jiffies'),
                    ("  .{}     : {}", 'idle_calls'),
                    ("  .{}    : {}", 'idle_sleeps'),
                    ("  .{} : {} nsecs", 'idle_entrytime'),
                    ("  .{}  : {} nsecs", 'idle_waketime'),
                    ("  .{}  : {} nsecs", 'idle_exittime'),
                    ("  .{} : {} nsecs", 'idle_sleeptime'),
                    ("  .{}: {} nsecs", 'iowait_sleeptime'),
                    ("  .{}   : {}", 'last_jiffies'),
                    ("  .{}     : {}", 'next_timer'),
                    ("  .{}   : {} nsecs", 'idle_expires')]
            text += "\n".join([s.format(f, ts[f]) for s, f in fmts])
            text += "\njiffies: {}\n".format(jiffies)

        text += "\n"

    return text


def print_tickdevice(td, cpu):
    dev = td['evtdev']
    text = "Tick Device: mode:     {}\n".format(td['mode'])
    if cpu < 0:
            text += "Broadcast device\n"
    else:
            text += "Per CPU device: {}\n".format(cpu)

    text += "Clock Event Device: "
    if dev == 0:
            text += "<NULL>\n"
            return text

    text += "{}\n".format(dev['name'])
    text += " max_delta_ns:   {}\n".format(dev['max_delta_ns'])
    text += " min_delta_ns:   {}\n".format(dev['min_delta_ns'])
    text += " mult:           {}\n".format(dev['mult'])
    text += " shift:          {}\n".format(dev['shift'])
    text += " mode:           {}\n".format(dev['state_use_accessors'])
    text += " next_event:     {} nsecs\n".format(dev['next_event'])

    text += " set_next_event: {}\n".format(dev['set_next_event'])

    members = [('set_state_shutdown', " shutdown: {}\n"),
               ('set_state_periodic', " periodic: {}\n"),
               ('set_state_oneshot', " oneshot:  {}\n"),
               ('set_state_oneshot_stopped', " oneshot stopped: {}\n"),
               ('tick_resume', " resume:   {}\n")]
    for member, fmt in members:
        if dev[member]:
            text += fmt.format(dev[member])

    text += " event_handler:  {}\n".format(dev['event_handler'])
    text += " retries:        {}\n".format(dev['retries'])

    return text


def pr_cpumask(mask):
    nr_cpu_ids = 1
    if constants.LX_NR_CPUS > 1:
        nr_cpu_ids = gdb.parse_and_eval("nr_cpu_ids")

    inf = gdb.inferiors()[0]
    bits = mask['bits']
    num_bytes = (nr_cpu_ids + 7) / 8
    buf = utils.read_memoryview(inf, bits, num_bytes).tobytes()
    buf = binascii.b2a_hex(buf)

    chunks = []
    i = num_bytes
    while i > 0:
        i -= 1
        start = i * 2
        end = start + 2
        chunks.append(buf[start:end])
        if i != 0 and i % 4 == 0:
            chunks.append(',')

    extra = nr_cpu_ids % 8
    if 0 < extra <= 4:
        chunks[0] = chunks[0][0]  # Cut off the first 0

    return "".join(chunks)


class LxTimerList(gdb.Command):
    """Print /proc/timer_list"""

    def __init__(self):
        super(LxTimerList, self).__init__("lx-timerlist", gdb.COMMAND_DATA)

    def invoke(self, arg, from_tty):
        hrtimer_bases = gdb.parse_and_eval("&hrtimer_bases")
        max_clock_bases = gdb.parse_and_eval("HRTIMER_MAX_CLOCK_BASES")

        text = "Timer List Version: gdb scripts\n"
        text += "HRTIMER_MAX_CLOCK_BASES: {}\n".format(max_clock_bases)
        text += "now at {} nsecs\n".format(ktime_get())

        for cpu in cpus.each_online_cpu():
            text += print_cpu(hrtimer_bases, cpu, max_clock_bases)

        if constants.LX_CONFIG_GENERIC_CLOCKEVENTS:
            if constants.LX_CONFIG_GENERIC_CLOCKEVENTS_BROADCAST:
                bc_dev = gdb.parse_and_eval("&tick_broadcast_device")
                text += print_tickdevice(bc_dev, -1)
                text += "\n"
                mask = gdb.parse_and_eval("tick_broadcast_mask")
                mask = pr_cpumask(mask)
                text += "tick_broadcast_mask: {}\n".format(mask)
                if constants.LX_CONFIG_TICK_ONESHOT:
                    mask = gdb.parse_and_eval("tick_broadcast_oneshot_mask")
                    mask = pr_cpumask(mask)
                    text += "tick_broadcast_oneshot_mask: {}\n".format(mask)
                text += "\n"

            tick_cpu_devices = gdb.parse_and_eval("&tick_cpu_device")
            for cpu in cpus.each_online_cpu():
                tick_dev = cpus.per_cpu(tick_cpu_devices, cpu)
                text += print_tickdevice(tick_dev, cpu)
                text += "\n"

        gdb.write(text)


LxTimerList()
