| 190 | } |
| 191 | |
| 192 | static void UpdateProcessEvents( |
| 193 | PMTraceConsumer* pmConsumer, |
| 194 | std::vector<ProcessEvent>* processEvents) |
| 195 | { |
| 196 | std::vector<ProcessEvent> newProcessEvents; |
| 197 | pmConsumer->DequeueProcessEvents(newProcessEvents); |
| 198 | |
| 199 | if (!newProcessEvents.empty()) { |
| 200 | processEvents->insert(processEvents->end(), newProcessEvents.begin(), newProcessEvents.end()); |
| 201 | newProcessEvents.clear(); |
| 202 | newProcessEvents.shrink_to_fit(); |
| 203 | |
| 204 | std::sort(processEvents->begin(), processEvents->end(), [](ProcessEvent const& a, ProcessEvent const& b) { return a.QpcTime < b.QpcTime; }); |
| 205 | } |
| 206 | |
| 207 | // Check if any realtime processes terminated and create process events for them. |
| 208 | // |
| 209 | // We assume that the process terminated now, which is wrong but conservative and functionally |
| 210 | // ok because no other process should start with the same PID as long as we're still holding a |
| 211 | // handle to it. |
| 212 | for (auto& pair : gProcesses) { |
| 213 | auto processId = pair.first; |
| 214 | auto processInfo = &pair.second; |
| 215 | |
| 216 | DWORD exitCode = 0; |
| 217 | if (processInfo->mHandle != NULL && GetExitCodeProcess(processInfo->mHandle, &exitCode) && exitCode != STILL_ACTIVE) { |
| 218 | uint64_t qpc = 0; |
| 219 | QueryPerformanceCounter((LARGE_INTEGER*) &qpc); |
| 220 | |
| 221 | ProcessEvent e; |
| 222 | e.ImageFileName = processInfo->mModuleName; |
| 223 | e.QpcTime = qpc; |
| 224 | e.ProcessId = processId; |
| 225 | e.IsStartEvent = false; |
| 226 | processEvents->push_back(e); |
| 227 | |
| 228 | CloseHandle(processInfo->mHandle); |
| 229 | processInfo->mHandle = NULL; |
| 230 | } |
| 231 | } |
| 232 | } |
| 233 | |
| 234 | static void UpdateAverage(float* avg, double value) |
| 235 | { |