]>
Commit | Line | Data |
---|---|---|
bd6521f0 A |
1 | // |
2 | // MachineProcess.mutable-impl.hpp | |
3 | // KDBG | |
4 | // | |
5 | // Created by James McIlree on 10/30/12. | |
6 | // Copyright (c) 2014 Apple. All rights reserved. | |
7 | // | |
8 | ||
9 | #include "KDebug.h" | |
10 | ||
11 | template <typename SIZE> | |
12 | void MachineProcess<SIZE>::set_exit_by_syscall(AbsTime timestamp, int32_t exit_status) { | |
13 | ASSERT(!is_exiting(), "Attempt to exit after process is already exiting"); | |
14 | ASSERT(_exit_initiated_timestamp == 0, "Sanity"); | |
15 | ASSERT(!is_kernel(), "Kernel process is attempting to exit"); | |
16 | ||
17 | _exit_status = exit_status; | |
18 | _exit_initiated_timestamp = timestamp; | |
19 | ||
20 | set_flags(kMachineProcessFlag::IsExitBySyscall); | |
21 | } | |
22 | ||
23 | template <typename SIZE> | |
24 | void MachineProcess<SIZE>::set_exit_by_jetsam(AbsTime timestamp) { | |
25 | ASSERT(!is_exiting(), "Attempt to exit after process is already exiting"); | |
26 | ASSERT(_exit_initiated_timestamp == 0, "Sanity"); | |
27 | ASSERT(!is_kernel(), "Kernel process is attempting to exit"); | |
28 | ||
29 | _exit_initiated_timestamp = timestamp; | |
30 | ||
31 | set_flags(kMachineProcessFlag::IsExitByJetsam); | |
32 | } | |
33 | ||
34 | template <typename SIZE> | |
35 | void MachineProcess<SIZE>::set_exit_by_exec(AbsTime timestamp) { | |
36 | ASSERT(!is_exiting(), "Attempt to exit after process is already exiting"); | |
37 | ASSERT(_exit_initiated_timestamp == 0, "Sanity"); | |
38 | ASSERT(!is_kernel(), "Kernel process is attempting to exit"); | |
39 | ||
40 | _exit_initiated_timestamp = timestamp; | |
41 | set_flags(kMachineProcessFlag::IsExitByExec); | |
42 | ||
43 | for (MachineThread<SIZE>* thread : _threads_by_time) { | |
44 | if (!thread->is_trace_terminated()) { | |
45 | thread->set_trace_terminated(timestamp); | |
46 | } | |
47 | } | |
48 | ||
49 | set_trace_terminated(timestamp); | |
50 | } | |
51 | ||
52 | template <typename SIZE> | |
53 | void MachineProcess<SIZE>::set_trace_terminated(AbsTime timestamp){ | |
54 | ASSERT(is_exiting(), "Attempting to set trace terminated without precursor exit event"); | |
55 | ASSERT(!is_kernel(), "Kernel process is attempting to set trace terminated"); | |
56 | ||
57 | DEBUG_ONLY({ | |
58 | for (MachineThread<SIZE>* thread : _threads_by_time) { | |
59 | ASSERT(thread->is_trace_terminated(), "Setting process as trace terminated when it still has live threads"); | |
60 | } | |
61 | }) | |
62 | ||
63 | _timespan.set_max(timestamp + AbsTime(1)); | |
64 | set_flags(kMachineProcessFlag::IsTraceTerminated); | |
65 | } | |
66 | ||
67 | template <typename SIZE> | |
68 | void MachineProcess<SIZE>::set_apptype(uint32_t type) { | |
69 | ASSERT(type >= TASK_APPTYPE_NONE && type <= TASK_APPTYPE_APP_TAL, "Out of range"); | |
70 | ASSERT(_apptype == -1 || _apptype == type, "Attempt to set apptype more than once, or to change an inherited apptype"); | |
71 | ASSERT(!is_kernel(), "Kernel is attempting to set apptype"); | |
72 | ASSERT(!is_exiting(), "Setting apptype after exit"); | |
73 | ||
74 | _apptype = type; | |
75 | } | |
76 | ||
77 | template <typename SIZE> | |
78 | void MachineProcess<SIZE>::set_apptype_from_trequested(uint32_t type) { | |
79 | ASSERT(type >= TASK_APPTYPE_NONE && type <= TASK_APPTYPE_APP_TAL, "Out of range"); | |
80 | ASSERT(_apptype == -1 || _apptype == type, "trequested apptype does not match set apptype"); | |
81 | ||
82 | _apptype = type; | |
83 | } | |
84 | ||
85 | template <typename SIZE> | |
86 | void MachineProcess<SIZE>::set_name(const char* name) { | |
87 | ASSERT(name, "Sanity"); | |
88 | ASSERT(strlen(name) < sizeof(_name) - 1, "Sanity"); | |
89 | ||
90 | strlcpy(_name, name, sizeof(_name)); | |
91 | } | |
92 | ||
93 | template <typename SIZE> | |
94 | void MachineProcess<SIZE>::clear_fork_exec_in_progress() { | |
95 | ASSERT(!is_unknown(), "Sanity"); | |
96 | ASSERT(!is_kernel(), "Sanity"); | |
97 | ASSERT(!is_exiting(), "Sanity"); | |
98 | ASSERT(!is_exec_in_progress(), "Sanity"); | |
99 | ASSERT(is_fork_exec_in_progress(), "Sanity"); | |
100 | ||
101 | clear_flags(kMachineProcessFlag::IsForkExecInProgress); | |
102 | } | |
103 | ||
104 | template <typename SIZE> | |
105 | void MachineProcess<SIZE>::clear_exec_in_progress() { | |
106 | ASSERT(!is_unknown(), "Sanity"); | |
107 | ASSERT(!is_kernel(), "Sanity"); | |
108 | ASSERT(!is_exiting(), "Sanity"); | |
109 | ASSERT(!is_fork_exec_in_progress(), "Sanity"); | |
110 | ASSERT(is_exec_in_progress(), "Sanity"); | |
111 | ||
112 | clear_flags(kMachineProcessFlag::IsExecInProgress); | |
113 | } | |
114 | ||
115 | template <typename SIZE> | |
116 | void MachineProcess<SIZE>::add_thread(MachineThread<SIZE>* thread) { | |
117 | ASSERT(thread, "Sanity"); | |
118 | ASSERT(&thread->process() == this, "Sanity"); | |
119 | ASSERT(!thread->is_trace_terminated(), "Attempt to add thread that is already terminated"); | |
120 | ASSERT(thread->timespan().location() >= _timespan.location(), "Attempt to add thread that started before this process"); | |
121 | ASSERT(!is_exiting(), "Adding thread to process that has exited"); | |
122 | ||
123 | // 6/20/2014, reworking time handling, is this still true? | |
124 | // | |
125 | // Process/thread created by a previous machine state will violate these | |
126 | // rules, during initialization. However, only threads created in that | |
127 | // form will be so tagged, and so we can exclude them from this assert. | |
128 | // | |
129 | // ASSERT(!is_exited() || thread->is_created_by_previous_machine_state(), "Adding thread to process that has marked itself as exited"); | |
130 | ||
131 | DEBUG_ONLY({ | |
132 | // At this point, the threads vector is not sorted. | |
133 | // We have to look at everything :-(. | |
134 | for (MachineThread<SIZE>* process_thread : _threads_by_time) { | |
135 | if (process_thread->tid() == thread->tid()) { | |
136 | ASSERT(!process_thread->timespan().intersects(thread->timespan()), "Overlapping duplicate threads"); | |
137 | } | |
138 | } | |
139 | }) | |
140 | ||
141 | _threads_by_time.push_back(thread); | |
142 | } | |
143 | ||
144 | template <typename SIZE> | |
145 | void MachineProcess<SIZE>::post_initialize(AbsTime last_machine_timestamp) { | |
146 | // | |
147 | // For processes that are still alive at the post_initialize phase, | |
148 | // we want to extend their timespan(s) to the end of the machine state, | |
149 | // so they can be looked up by pid/name. | |
150 | // | |
151 | if (!is_trace_terminated()) { | |
152 | ASSERT(_timespan.length() == 0, "Should not have timespan set"); | |
153 | ||
154 | // Time in a range is always half open. [ 10, 11 ) means 10 is included, | |
155 | // but 11 is not. In order to include a given timestamp, we must use | |
156 | // a value one greater. | |
157 | AbsTime half_open_timestamp = last_machine_timestamp + AbsTime(1); | |
158 | ||
159 | _timespan.set_max(half_open_timestamp); | |
160 | } | |
161 | ||
162 | std::sort(_threads_by_time.begin(), _threads_by_time.end(), thread_by_time_sort<SIZE>); | |
163 | } |