xref: /xnu-11417.121.6/tools/lldbmacros/memorystatus.py (revision a1e26a70f38d1d7daa7b49b258e2f8538ad81650)
1from core.cvalue import sizeof, value
2from enum import Enum
3from memory import GetLedgerEntryWithName, Memstats
4from process import GetProcName, GetProcPID, GetTaskFromProc, GetTaskSummary, ledger_limit_infinity
5from scheduler import GetRecentTimestamp
6from utils import Cast
7from xnu import header, kern, lldb_command, unsigned
8from xnudefines import JETSAM_PRIORITY_MAX, P_MEMSTAT_FROZEN
9
10
11# Macro: showmemorystatus
12
13class PControlAction(Enum):
14    # See proc_internal.h
15    NONE = 0
16    THROTTLE = 1
17    SUSPEND = 2
18    KILL = 3
19
20class RelaunchProbability(Enum):
21    # See kern_memorystatus.h
22    LOW = 1
23    MED = 2
24    HIGH = 4
25
26def CalculateLedgerPeak(phys_footprint_entry):
27    """
28    Internal function to calculate ledger peak value for the given phys footprint entry
29    params: phys_footprint_entry - value representing struct ledger_entry *
30    return: value - representing the ledger peak for the given phys footprint entry
31    """
32    return max(phys_footprint_entry['balance'], phys_footprint_entry.get('interval_max', 0))
33
34@header(f'{"cur_pri": <12s} '
35        f'{"name": <32s} '
36        f'{"pid": >8s} '
37        f'{"req_pri": >12s} '
38        f'{"ast_pri": >12s} '
39        f'{"state": >12s} '
40        f'{"dirty": >12s} '
41        f'{"relaunch": >10s} '
42        f'{"pcontrol": >10s} '
43        f'{"paction": >10s} '
44        f'{"footprint": >12s} '
45        f'{"max_footprint": >13s} '
46        f'{"limit": >12s}')
47def GetMemoryStatusNode(proc):
48    """
49    Internal function to get memorystatus information from the given proc
50    params: proc - value representing struct proc *
51    return: str - formatted output information for proc object
52    """
53
54    task_val = GetTaskFromProc(proc)
55    if task_val is None:
56        return ''
57
58    task_ledgerp = task_val.ledger
59    ledger_template = kern.globals.task_ledger_template
60
61    task_physmem_footprint_ledger_entry = GetLedgerEntryWithName(ledger_template, task_ledgerp, 'phys_mem')
62    task_iokit_footprint_ledger_entry = GetLedgerEntryWithName(ledger_template, task_ledgerp, 'iokit_mapped')
63    task_phys_footprint_ledger_entry = GetLedgerEntryWithName(ledger_template, task_ledgerp, 'phys_footprint')
64    page_size = kern.globals.page_size
65
66    phys_mem_footprint = task_physmem_footprint_ledger_entry['balance'] // 1024
67    iokit_footprint = task_iokit_footprint_ledger_entry['balance'] // 1024
68    phys_footprint = task_phys_footprint_ledger_entry['balance'] // 1024
69    if task_phys_footprint_ledger_entry['limit'] == ledger_limit_infinity:
70        phys_footprint_limit = '-'
71    else:
72        phys_footprint_limit = str(task_phys_footprint_ledger_entry['limit'] // 1024)
73    ledger_peak = CalculateLedgerPeak(task_phys_footprint_ledger_entry) // 1024
74    phys_footprint_spike = ledger_peak // 1024
75    phys_footprint_lifetime_max = task_phys_footprint_ledger_entry['lifetime_max'] // 1024
76
77    if proc.p_memstat_relaunch_flags != 0:
78        relaunch_flags = RelaunchProbability(int(proc.p_memstat_relaunch_flags)).name
79    else:
80        relaunch_flags = '-'
81
82    if proc.p_pcaction != 0:
83        pc_control = PControlAction(proc.p_pcaction & 0xff).name
84        pc_action = PControlAction((proc.p_pcaction & 0xff00) >> 16).name
85    else:
86        pc_control = '-'
87        pc_action = '-'
88
89    return (f'{proc.p_memstat_effectivepriority:<12d} '
90            f'{GetProcName(proc):<32s} '
91            f'{GetProcPID(proc):>8d} '
92            f'{proc.p_memstat_requestedpriority:>12d} '
93            f'{proc.p_memstat_assertionpriority:>12d} '
94            f'{proc.p_memstat_state:#12x} '
95            f'{proc.p_memstat_dirty:#12x} '
96            f'{relaunch_flags:>10s} '
97            f'{pc_control:>10s} '
98            f'{pc_action:>10s} '
99            f'{phys_footprint:>12d} '
100            f'{phys_footprint_lifetime_max:>13d} '
101            f'{phys_footprint_limit:>12s}')
102
103@lldb_command('showmemorystatus')
104def ShowMemoryStatus(cmd_args=None):
105    """
106    Routine to display each entry in jetsam list with a summary of pressure statistics
107    Usage: showmemorystatus
108    """
109    bucket_index = 0
110    print(GetMemoryStatusNode.header)
111    while bucket_index <= JETSAM_PRIORITY_MAX:
112        current_bucket = kern.globals.memstat_bucket[bucket_index]
113        current_list = current_bucket.list
114        current_proc = Cast(current_list.tqh_first, 'proc *')
115        while unsigned(current_proc) != 0:
116            print(GetMemoryStatusNode(current_proc))
117            current_proc = current_proc.p_memstat_list.tqe_next
118        bucket_index += 1
119
120# EndMacro: showmemorystatus
121