]> git.saurik.com Git - apple/system_cmds.git/blame - KDBG/Machine.hpp
system_cmds-671.10.3.tar.gz
[apple/system_cmds.git] / KDBG / Machine.hpp
CommitLineData
bd6521f0
A
1//
2// Machine.hpp
3// KDBG
4//
5// Created by James McIlree on 10/25/12.
6// Copyright (c) 2014 Apple. All rights reserved.
7//
8
9enum class kMachineFlag : std::uint32_t {
10 LostEvents = 0x00000001
11};
12
13template <typename SIZE>
14class Machine {
15 protected:
16 std::vector<MachineCPU<SIZE>> _cpus;
17
18 std::unordered_multimap<pid_t, MachineProcess<SIZE>> _processes_by_pid;
19 std::unordered_multimap<const char*, MachineProcess<SIZE>*, ConstCharHash, ConstCharEqualTo> _processes_by_name;
20 std::vector<MachineProcess<SIZE>*> _processes_by_time;
21
22 std::unordered_multimap<typename SIZE::ptr_t, MachineThread<SIZE> > _threads_by_tid;
23 std::vector<MachineThread<SIZE>*> _threads_by_time;
24
25 std::vector<MachineMachMsg<SIZE>> _mach_msgs;
26 std::unordered_map<uintptr_t, uintptr_t> _mach_msgs_by_event_index;
27 std::unordered_map<typename SIZE::ptr_t, NurseryMachMsg<SIZE>> _mach_msg_nursery;
28
29 //
30 // Vouchers are a bit special. We install pointers to vouchers in
31 // MachineThreads and MachineMachMsg. This means that vouchers cannot
32 // be moved once allocated. We could do two passes to exactly size
33 // the data structures, this should be investigated in the future.
34 //
35 // On create or first observed use, a voucher goes into the nursery.
36 // It stays there until a destroy event, or the end of Machine events.
37 // Once flushed from the nursery, we have a map of addresses, which
38 // points to a vector sorted by time. This allows addr @ time lookups
39 // later.
40 //
41 std::unordered_map<typename SIZE::ptr_t, std::unique_ptr<MachineVoucher<SIZE>>> _voucher_nursery;
42 std::unordered_map<typename SIZE::ptr_t, std::vector<std::unique_ptr<MachineVoucher<SIZE>>>> _vouchers_by_addr;
43
44 std::unordered_map<typename SIZE::ptr_t, IOActivity<SIZE>> _io_by_uid; // uid == unique id, not user id
45 std::vector<IOActivity<SIZE>> _all_io;
46 std::vector<AbsInterval> _all_io_active_intervals;
47
48 MachineProcess<SIZE>* _kernel_task;
49 const KDEvent<SIZE>* _events;
50 uintptr_t _event_count;
51 uint32_t _flags;
52 int32_t _unknown_process_pid; // We need unique negative pid's for previously unknown TID's
53
54 //
55 // Protected initialization code
56 //
57 void raw_initialize(const KDCPUMapEntry* cpumaps,
58 uint32_t cpumap_count,
59 const KDThreadMapEntry<SIZE>* threadmaps,
60 uint32_t threadmap_count,
61 const KDEvent<SIZE>* events,
62 uintptr_t event_count);
63
64 void post_initialize();
65
66 //
67 // Mutable API, for use during construction
68 //
69
70 pid_t next_unknown_pid() { return --_unknown_process_pid; }
71
72 MachineProcess<SIZE>* create_process(pid_t pid, const char* name, AbsTime create_timestamp, kMachineProcessFlag flags);
73 MachineThread<SIZE>* create_thread(MachineProcess<SIZE>* process, typename SIZE::ptr_t tid, MachineVoucher<SIZE>* voucher, AbsTime create_timestamp, kMachineThreadFlag flags);
74 MachineVoucher<SIZE>* create_voucher(typename SIZE::ptr_t address, AbsTime create_timestamp, kMachineVoucherFlag flags, uint32_t content_bytes_capacity);
75
76 void destroy_voucher(typename SIZE::ptr_t address, AbsTime timestamp);
77
78 void set_flags(kMachineFlag flag) { _flags |= (uint32_t)flag; }
79
80 void set_process_name(MachineProcess<SIZE>* process, const char* name);
81
82 MachineProcess<SIZE>* mutable_process(pid_t pid, AbsTime time) { return const_cast<MachineProcess<SIZE>*>(process(pid, time)); }
83 MachineThread<SIZE>* mutable_thread(typename SIZE::ptr_t tid, AbsTime time) { return const_cast<MachineThread<SIZE>*>(thread(tid, time)); }
84
85 MachineProcess<SIZE>* youngest_mutable_process(pid_t pid);
86 MachineThread<SIZE>* youngest_mutable_thread(typename SIZE::ptr_t tid);
87
88 MachineVoucher<SIZE>* process_event_voucher_lookup(typename SIZE::ptr_t address, uint32_t msgh_bits);
89 MachineThread<SIZE>* process_event_tid_lookup(typename SIZE::ptr_t tid, AbsTime now);
90
91 MachineVoucher<SIZE>* thread_forwarding_voucher_lookup(const MachineVoucher<SIZE>* original_thread_voucher);
92
93 void begin_io(MachineThread<SIZE>* thread, AbsTime time, typename SIZE::ptr_t uid, typename SIZE::ptr_t size);
94 void end_io(AbsTime time, typename SIZE::ptr_t uid);
95
96 bool process_event(const KDEvent<SIZE>& event);
97 void process_trequested_task(pid_t pid, typename SIZE::ptr_t trequested_0, typename SIZE::ptr_t trequested_1);
98 void process_trequested_thread(typename SIZE::ptr_t tid, typename SIZE::ptr_t trequested_0, typename SIZE::ptr_t trequested_1);
99
100 void initialize_cpu_idle_intr_states();
101
102 public:
103 static MachineVoucher<SIZE> UnsetVoucher;
104 static MachineVoucher<SIZE> NullVoucher;
105
106 Machine(KDCPUMapEntry* cpumaps, uint32_t cpumap_count, KDThreadMapEntry<SIZE>* threadmaps, uint32_t threadmap_count, KDEvent<SIZE>* events, uintptr_t event_count);
107 // Destructive, mutates parent!
108 Machine(Machine<SIZE>& parent, KDEvent<SIZE>* events, uintptr_t event_count);
109 Machine(const TraceFile& file);
110
111 bool lost_events() const { return (_flags & (uint32_t)kMachineFlag::LostEvents) > 0; }
112
113 const MachineProcess<SIZE>* process(pid_t pid, AbsTime time) const;
114 const MachineThread<SIZE>* thread(typename SIZE::ptr_t tid, AbsTime time) const;
115 const MachineVoucher<SIZE>* voucher(typename SIZE::ptr_t address, AbsTime time) const;
116 const MachineMachMsg<SIZE>* mach_msg(uintptr_t event_index) const;
117
118 const std::vector<const MachineProcess<SIZE>*>& processes() const;
119 const std::vector<const MachineThread<SIZE>*>& threads() const;
120 const std::vector<const MachineCPU<SIZE>>& cpus() const;
121
122 const KDEvent<SIZE>* events() const { return _events; }
123 uintptr_t event_count() const { return _event_count; }
124
125 AbsInterval timespan() const;
126
127 // Returns the number of cpus that have timeline data.
128 // (IOW, typically the number of AP(s) on a machine, but might be less if you've disabled some so they generate no trace data)
129 uint32_t active_cpus() const;
130
131 // If summary_cpu == NULL , all cpus are matched.
132 CPUSummary<SIZE> summary_for_timespan(AbsInterval timespan, const MachineCPU<SIZE>* summary_cpu) const;
133
134 // This attempts to analyze various pieces of data and guess
135 // if the Machine represents an ios device or not.
136 bool is_ios() const;
137
138 DEBUG_ONLY(void validate() const;)
139};
140
141template <typename SIZE> MachineVoucher<SIZE> Machine<SIZE>::UnsetVoucher(SIZE::PTRMAX, AbsInterval(AbsTime(0),AbsTime(UINT64_MAX)), kMachineVoucherFlag::IsUnsetVoucher, 0);
142template <typename SIZE> MachineVoucher<SIZE> Machine<SIZE>::NullVoucher(0, AbsInterval(AbsTime(0),AbsTime(UINT64_MAX)), kMachineVoucherFlag::IsNullVoucher, 0);
143