]> git.saurik.com Git - apple/system_cmds.git/blame - KDBG/MachineCPU.hpp
system_cmds-671.10.3.tar.gz
[apple/system_cmds.git] / KDBG / MachineCPU.hpp
CommitLineData
bd6521f0
A
1//
2// MachineCPU.hpp
3// KDBG
4//
5// Created by James McIlree on 10/26/12.
6// Copyright (c) 2014 Apple. All rights reserved.
7//
8
9//
10// Much simplified cpu/thread state model.
11//
12// 1) A thread is *always* on cpu. Always. The only excpetion is during
13// initialization, when the thread on cpu is unknown.
14//
15// 2) There are three states possible: Running, IDLE, INTR.
16// A thread may move from any state to any other state.
17// A thread may not take an INTR while in INTR.
18// It is illegal to context_switch in IDLE or INTR.
19//
20
21enum class kMachineCPUFlag : std::uint32_t {
22 IsStateIdleInitialized = 0x00000001, // Set when the idle state at event[0] has been identified.
23 IsStateINTRInitialized = 0x00000002, // Set when the INTR state at event[0] has been identified.
24 IsStateThreadInitialized = 0x00000004, // Set when the on-cpu thread at event[0] has been identified (may be NULL, for threads not known at the time of event[0])
25 IsStateIdle = 0x00000008, // Set if the cpu is Idle
26 IsStateINTR = 0x00000010, // Set if the cpu is servicing an interrupt
27 IsStateDeactivatedForcedSwitchToIdleThread = 0x00000020, // OSX only; set when the cpu is deactivated and on wake forces a switch to its idle thread without a context switch tracepoint
28 IsIOP = 0x10000000 // Set if the cpu is an IOP
29};
30
31template <typename SIZE>
32class MachineCPU {
33 protected:
34
35 class ThreadOnCPU {
36 protected:
37 MachineThread<SIZE>* _thread;
38 AbsTime _timestamp;
39 public:
40 ThreadOnCPU(MachineThread<SIZE>* thread, bool is_event_zero_init_thread, AbsTime timestamp) :
41 _thread(thread),
42 _timestamp(timestamp)
43 {
44 if (is_event_zero_init_thread)
45 _thread = (MachineThread<SIZE>*)((uintptr_t)_thread | 1);
46 }
47
48 MachineThread<SIZE>* thread() { return (MachineThread<SIZE>*)((uintptr_t)_thread & ~0x1); }
49 AbsTime timestamp() { return _timestamp; }
50 bool is_event_zero_init_thread() { return (uintptr_t)_thread & 0x1; }
51 };
52
53 int32_t _id;
54 uint32_t _flags;
55 std::string _name; // IOP's have names, AP's will be "AP"
56 std::vector<CPUActivity<SIZE>> _timeline;
57
58 // State used only during initialization
59 MachineThread<SIZE>* _thread;
60 AbsTime _begin_idle;
61 AbsTime _begin_intr;
62 std::vector<ThreadOnCPU> _cpu_runq;
63 std::vector<AbsInterval> _cpu_intr;
64 std::vector<AbsInterval> _cpu_idle;
65
66 friend class Machine<SIZE>;
67
68 bool is_running() const { return (_flags & ((uint32_t)kMachineCPUFlag::IsStateIdle | (uint32_t)kMachineCPUFlag::IsStateINTR)) == 0; }
69
70 bool is_idle() const { return (_flags & (uint32_t)kMachineCPUFlag::IsStateIdle) > 0; }
71 void set_idle(AbsTime timestamp);
72 void clear_idle(AbsTime timestamp);
73
74 bool is_deactivate_switch_to_idle_thread() const { return (_flags & (uint32_t)kMachineCPUFlag::IsStateDeactivatedForcedSwitchToIdleThread) > 0; }
75 void set_deactivate_switch_to_idle_thread();
76 void clear_deactivate_switch_to_idle_thread();
77
78 bool is_idle_state_initialized() const { return (_flags & (uint32_t)kMachineCPUFlag::IsStateIdleInitialized) > 0; }
79 void initialize_idle_state(bool value, AbsTime timestamp);
80
81 bool is_intr() const { return (_flags & (uint32_t)kMachineCPUFlag::IsStateINTR) > 0; }
82 void set_intr(AbsTime timestamp);
83 void clear_intr(AbsTime timestamp);
84
85 bool is_intr_state_initialized() const { return (_flags & (uint32_t)kMachineCPUFlag::IsStateINTRInitialized) > 0; }
86 void initialize_intr_state(bool state, AbsTime timestamp);
87
88 void context_switch(MachineThread<SIZE>* to_thread, MachineThread<SIZE>* from_thread, AbsTime timestamp);
89
90 bool is_thread_state_initialized() const { return (_flags & (uint32_t)kMachineCPUFlag::IsStateThreadInitialized) > 0; }
91 void initialize_thread_state(MachineThread<SIZE>* thread, AbsTime timestamp);
92
93 MachineThread<SIZE>* thread() { return _thread; }
94
95 // This is called after all events have been processed, to allow the
96 // cpu timelines to be collapsed and post processed.
97 void post_initialize(AbsInterval events_interval);
98
99 public:
100 MachineCPU(int32_t id, bool is_iop, std::string name) :
101 _id(id),
102 _flags(is_iop ? (uint32_t)kMachineCPUFlag::IsIOP : 0),
103 _name(name),
104 _thread(nullptr),
105 _begin_idle(AbsTime(0)),
106 _begin_intr(AbsTime(0))
107 {
108 }
109
110 int32_t id() const { return _id; }
111 void set_id(int32_t id) { ASSERT(_id = -1, "Attempt to set id twice"); _id = id; }
112
113 bool is_iop() const { return (_flags & (uint32_t)kMachineCPUFlag::IsIOP) > 0; }
114
115 bool is_active() const { return !_timeline.empty(); }
116
117 const char* name() const { return _name.c_str(); }
118
119 const std::vector<CPUActivity<SIZE>>& timeline() const { return _timeline; }
120 const CPUActivity<SIZE>* activity_for_timestamp(AbsTime timestamp) const;
121};