forked from Xilinx/XRT
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSmiWatchMode.cpp
More file actions
149 lines (131 loc) · 4.3 KB
/
SmiWatchMode.cpp
File metadata and controls
149 lines (131 loc) · 4.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// SPDX-License-Identifier: Apache-2.0
// Copyright (C) 2025 Advanced Micro Devices, Inc. All rights reserved.
// ------ I N C L U D E F I L E S -------------------------------------------
// Local - Include Files
#include "SmiWatchMode.h"
#include "XBUtilitiesCore.h"
#include "core/common/query_requests.h"
#include "core/common/time.h"
// 3rd Party Library - Include Files
#include <algorithm>
#include <atomic>
#include <chrono>
#include <csignal>
#include <iomanip>
#include <sstream>
#include <thread>
// ------ S T A T I C V A R I A B L E S -------------------------------------
namespace signal_handler {
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) - Required for signal handling
std::atomic<bool> watch_interrupted{false};
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) - Required for signal handling
void (*old_signal_handler)(int) = nullptr;
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) - Required for signal handling
bool signal_handler_set = false;
void watch(int signal) {
if (signal == SIGINT) {
watch_interrupted = true;
}
}
/**
* @brief Set up SIGINT signal handler for watch mode interruption
*
* - Saves the current SIGINT handler for restoration later
* - Installs custom handler that sets atomic interrupt flag
* - Uses thread-safe signal handling
*
* @note Must be paired with restore() call
* @note Uses standard signal() function for cross-platform compatibility
*/
void setup() {
if (!signal_handler_set) {
old_signal_handler = signal(SIGINT, watch);
signal_handler_set = true;
}
}
/**
* @brief Restore the original SIGINT signal handler
*
* - Restores the signal handler that was active before setup()
* - Clears internal state flags
* - Safe to call multiple times or without prior setup
*
* @note Should be called before exiting watch mode
*/
void restore() {
if (signal_handler_set) {
static_cast<void>(signal(SIGINT, old_signal_handler));
signal_handler_set = false;
}
}
/**
* @brief Reset the interrupt flag to allow new watch mode session
*
* This method provides controlled access to reset the interrupt state
* without exposing the internal variable directly.
*/
void reset_interrupt() {
watch_interrupted = false;
}
/**
* @brief Check if watch mode is still active
*
* @return true if watch mode should continue, false if interrupted
*
* This method provides controlled read access to the interrupt state
* with inverted logic for more intuitive usage in while loops.
*/
bool active() {
return !watch_interrupted;
}
} // namespace signal_handler
bool
smi_watch_mode::
parse_watch_mode_options(const std::vector<std::string>& elements_filter)
{
return std::any_of(elements_filter.begin(), elements_filter.end(),
[](const std::string& filter) {
return filter == "watch";
});
}
void
smi_watch_mode::
run_watch_mode(const xrt_core::device* device,
std::ostream& output,
const ReportGenerator& report_generator,
unsigned refresh_interval_seconds,
bool refresh_terminal)
{
if (!report_generator) {
output << "Error: Invalid report generator provided to watch mode\n";
return;
}
// Set up signal handler for Ctrl+C
signal_handler::setup();
signal_handler::reset_interrupt();
bool first_iteration = true;
while (signal_handler::active()) {
if (!first_iteration && refresh_interval_seconds > 0)
std::this_thread::sleep_for(std::chrono::seconds(refresh_interval_seconds));
first_iteration = false;
try {
if (refresh_terminal && !XBUtilities::is_escape_codes_disabled())
output << "\033[2J\033[H";
output << report_generator(device);
output.flush();
}
catch (const std::exception& e) {
output << "Error generating report: " << e.what() << "\n";
output.flush();
signal_handler::restore();
return;
}
}
output << "\n\nWatch mode interrupted by user.\n";
signal_handler::restore();
}
smi_debug_buffer::
smi_debug_buffer(uint64_t abs_offset, bool b_wait, size_t size)
: buffer(size),
log_buffer{abs_offset, buffer.data(), size, b_wait}
{}