xref: /xnu-12377.41.6/tools/lldbmacros/taskinfo.py (revision bbb1b6f9e71b8cdde6e5cd6f4841f207dee3d828)
1from core.cvalue import sizeof, value
2from scheduler import GetRecentTimestamp
3from xnu import ArgumentError, lldb_command, kern
4
5# Macro: showtasksuspendstats
6
7def ShowTaskSuspendStats(task: value):
8    """
9    Routine to print out a summary of suspension statistics for a given task
10        params:
11            task - core.value : a object of type 'task *'
12        returns:
13            None
14    """
15    stats = task.t_suspend_stats
16    count = stats.tss_count
17    suspended = bool(task.suspend_count > 0)
18    recent_time = GetRecentTimestamp()
19    duration_sec = kern.GetNanotimeFromAbstime(stats.tss_duration) / 1e9
20    last_start_sec = kern.GetNanotimeFromAbstime(stats.tss_last_start - recent_time) / 1e9
21    last_end_sec = kern.GetNanotimeFromAbstime(stats.tss_last_end - recent_time) / 1e9
22    header_fmt = '{:<20s} {:<20s} {:<20s} {:<20s} {:<20s} {:<20s}'
23    header = header_fmt.format('task', 'suspended', 'total_suspensions', 'total_duration(s)', 'last_start_ago(s)', 'last_end_ago(s)')
24    print(header)
25    print(f'{task: <#020x} {str(suspended).lower():<20s} {count:<20d} {duration_sec:<20f} {last_start_sec:<20f} {last_end_sec:<20f}')
26
27@lldb_command('showtasksuspendstats')
28def ShowTaskSuspendStatsMacro(cmd_args=None, cmd_options={}):
29    """
30    Display suspension statistics for a given task
31        Usage: showtasksuspendstats <task addr>  (ex. showtasksuspendstats 0x00ataskptr00 )
32    """
33    if cmd_args is None or len(cmd_args) != 1:
34        raise ArgumentError("Invalid argument")
35    task = kern.GetValueFromAddress(cmd_args[0], 'task *')
36    ShowTaskSuspendStats(task)
37
38# EndMacro
39# Macro: showtasksuspenders
40
41def ShowTaskSuspendSources(task: value):
42    '''
43    Print task suspension events for a given task
44        params:
45            task - core.value : an object of type `task_t`
46    '''
47    sources = task.t_suspend_sources
48    header_fmt = '{:<20s} {:<20s} {:<20s} {:<20s}'
49    header = header_fmt.format('procname', 'pid', 'tid', 'time_ago(s)')
50    print(header)
51    source_count = sizeof(sources) // sizeof(sources[0])
52    for i in range(source_count):
53        source = sources[i]
54        recent_time = GetRecentTimestamp()
55        time_ago_sec = kern.GetNanotimeFromAbstime(source.tss_time - recent_time) / 1e9 if source.tss_time != 0 else -1.0
56        procname = str(source.tss_procname) if str(source.tss_procname) != '' else 'nil'
57        print(f'{procname:<20s} {source.tss_pid:<20d} {source.tss_tid:<20d} {time_ago_sec:<20.3f}')
58
59
60@lldb_command('showtasksuspendsources')
61def ShowTaskSuspendSourcesMacro(cmd_args=None, cmd_options={}):
62    '''
63    Show info on the most recent suspenders for a given task
64        Usage showtasksuspenders <task addr> (ex. showtasksuspenders 0x00ataskptr00 )
65    '''
66    if cmd_args is None or len(cmd_args) != 1:
67        raise ArgumentError("Invalid argument")
68    task = kern.GetValueFromAddress(cmd_args[0], 'task *')
69    ShowTaskSuspendSources(task)
70
71# EndMacro
72