Skip to content

Commit 6a6252d

Browse files
author
Baraldi, Giovanni
authored
SWDEV-489158: Fix for exit thread safety (#61)
* SWDEV-489158: Fix for exit thread safety * Fixed exit thread logic * Force CI to rerun * Remove .vscode * Fix thread safety bug * Addressed some comments * Formatting --------- Co-authored-by: Giovanni Baraldi <gbaraldi@amd.com> [ROCm/rocprofiler-sdk commit: f4984f9]
1 parent 82ca852 commit 6a6252d

File tree

4 files changed

+64
-28
lines changed

4 files changed

+64
-28
lines changed

samples/counter_collection/callback_client.cpp

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@ start()
5959

6060
namespace
6161
{
62+
struct tool_data_t
63+
{
64+
std::mutex mut{};
65+
std::ostream* output_stream{nullptr};
66+
};
67+
6268
rocprofiler_context_id_t&
6369
get_client_ctx()
6470
{
@@ -70,8 +76,8 @@ void
7076
record_callback(rocprofiler_dispatch_counting_service_data_t dispatch_data,
7177
rocprofiler_record_counter_t* record_data,
7278
size_t record_count,
73-
rocprofiler_user_data_t user_data,
74-
void* callback_data_args)
79+
rocprofiler_user_data_t /* user_data */,
80+
void* callback_data_args)
7581
{
7682
std::stringstream ss;
7783
ss << "Dispatch_Id=" << dispatch_data.dispatch_info.dispatch_id
@@ -81,11 +87,11 @@ record_callback(rocprofiler_dispatch_counting_service_data_t dispatch_data,
8187
ss << "(Id: " << record_data[i].id << " Value [D]: " << record_data[i].counter_value
8288
<< "),";
8389

84-
auto* output_stream = static_cast<std::ostream*>(callback_data_args);
85-
if(!output_stream) throw std::runtime_error{"nullptr to output stream"};
86-
*output_stream << "[" << __FUNCTION__ << "] " << ss.str() << "\n";
90+
auto* tool = static_cast<tool_data_t*>(callback_data_args);
91+
if(!tool || !tool->output_stream) throw std::runtime_error{"nullptr to output stream"};
8792

88-
(void) user_data;
93+
auto _lk = std::unique_lock{tool->mut};
94+
*tool->output_stream << "[" << __FUNCTION__ << "] " << ss.str() << "\n";
8995
}
9096

9197
/**
@@ -197,12 +203,20 @@ tool_init(rocprofiler_client_finalize_t, void* user_data)
197203
void
198204
tool_fini(void* user_data)
199205
{
206+
assert(user_data);
200207
std::clog << "In tool fini\n";
201208
rocprofiler_stop_context(get_client_ctx());
209+
auto* tool_data = static_cast<tool_data_t*>(user_data);
210+
211+
{
212+
auto _lk = std::unique_lock{tool_data->mut};
213+
auto* output_stream = tool_data->output_stream;
202214

203-
auto* output_stream = static_cast<std::ostream*>(user_data);
204-
*output_stream << std::flush;
205-
if(output_stream != &std::cout && output_stream != &std::cerr) delete output_stream;
215+
*output_stream << std::flush;
216+
if(output_stream != &std::cout && output_stream != &std::cerr) delete output_stream;
217+
}
218+
219+
delete tool_data;
206220
}
207221
} // namespace
208222

@@ -227,22 +241,23 @@ rocprofiler_configure(uint32_t version,
227241

228242
std::clog << info.str() << std::endl;
229243

230-
std::ostream* output_stream = nullptr;
231-
std::string filename = "counter_collection.log";
244+
auto* tool_data = new tool_data_t{};
245+
246+
std::string filename = "counter_collection.log";
232247
if(auto* outfile = getenv("ROCPROFILER_SAMPLE_OUTPUT_FILE"); outfile) filename = outfile;
233248
if(filename == "stdout")
234-
output_stream = &std::cout;
249+
tool_data->output_stream = &std::cout;
235250
else if(filename == "stderr")
236-
output_stream = &std::cerr;
251+
tool_data->output_stream = &std::cerr;
237252
else
238-
output_stream = new std::ofstream{filename};
253+
tool_data->output_stream = new std::ofstream{filename};
239254

240255
// create configure data
241256
static auto cfg =
242257
rocprofiler_tool_configure_result_t{sizeof(rocprofiler_tool_configure_result_t),
243258
&tool_init,
244259
&tool_fini,
245-
static_cast<void*>(output_stream)};
260+
static_cast<void*>(tool_data)};
246261

247262
// return pointer to configure data
248263
return &cfg;

source/lib/output/format_path.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
#include <cstring>
4444
#include <ctime>
4545
#include <fstream>
46+
#include <limits>
47+
#include <locale>
4648
#include <regex>
4749
#include <set>
4850
#include <sstream>
@@ -66,6 +68,17 @@ const auto env_regexes =
6668
// - %q{USER} Compatibility with NVIDIA
6769
//
6870

71+
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77704
72+
// NOLINTBEGIN
73+
[[maybe_unused]] volatile bool _initLocale = []() {
74+
const std::ctype<char>& ct(std::use_facet<std::ctype<char>>(std::locale()));
75+
for(size_t i = 0; i <= std::numeric_limits<unsigned char>::max(); i++)
76+
ct.narrow(static_cast<char>(i), '\0');
77+
ct.narrow(0, 0, 0, 0);
78+
return true;
79+
}();
80+
// NOLINTEND
81+
6982
std::string
7083
format_path_impl(std::string _fpath, const std::vector<output_key>& _keys)
7184
{

source/lib/rocprofiler-sdk/counters/sample_consumer.hpp

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,21 +44,23 @@ class consumer_thread_t
4444

4545
void start()
4646
{
47-
{
48-
std::unique_lock<std::mutex> lk(mut);
49-
if(valid.exchange(true)) return;
50-
}
47+
std::unique_lock<std::mutex> lk(mut);
48+
49+
if(valid.exchange(true)) return;
50+
exited.store(false);
51+
5152
consumer = std::thread{&consumer_thread_t::consumer_loop, this};
5253
}
5354

5455
void exit()
5556
{
56-
{
57-
std::unique_lock<std::mutex> lk(mut);
58-
if(!valid.exchange(false)) return;
59-
cv.notify_one();
60-
}
61-
consumer.join();
57+
std::unique_lock<std::mutex> lk(mut);
58+
59+
valid.store(false);
60+
cv.notify_all();
61+
62+
if(!exited) cv.wait(lk, [&] { return exited.load(); });
63+
if(consumer.joinable()) consumer.join();
6264
}
6365

6466
void add(DataType&& params)
@@ -74,7 +76,7 @@ class consumer_thread_t
7476

7577
buffer.at(write_ptr % buffer.size()) = std::move(params);
7678
write_ptr.fetch_add(1);
77-
cv.notify_one();
79+
cv.notify_all();
7880
}
7981

8082
protected:
@@ -86,7 +88,12 @@ class consumer_thread_t
8688
{
8789
std::unique_lock<std::mutex> lk(mut);
8890
cv.wait(lk, [&] { return read_ptr != write_ptr || !valid; });
89-
if(!valid && read_ptr == write_ptr) return;
91+
if(!valid && read_ptr == write_ptr)
92+
{
93+
exited.store(true);
94+
cv.notify_all();
95+
return;
96+
}
9097
}
9198

9299
auto retrieved = std::move(buffer.at(read_ptr % buffer.size()));
@@ -97,6 +104,7 @@ class consumer_thread_t
97104

98105
consume_func_t consume_fn;
99106
std::atomic<bool> valid{false};
107+
std::atomic<bool> exited{true};
100108
std::mutex mut;
101109
std::atomic<size_t> write_ptr{0};
102110
std::atomic<size_t> read_ptr{0};

tests/rocprofv3/tracing-plus-counter-collection/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ set(cc-tracing-env "${PRELOAD_ENV}")
3030

3131
set_tests_properties(
3232
rocprofv3-test-tracing-plus-counter-collection-execute
33-
PROPERTIES TIMEOUT 45 LABELS "integration-tests;application-replay" ENVIRONMENT
33+
PROPERTIES TIMEOUT 90 LABELS "integration-tests;application-replay" ENVIRONMENT
3434
"${cc-tracing-env}" FAIL_REGULAR_EXPRESSION
3535
"${ROCPROFILER_DEFAULT_FAIL_REGEX}")
3636

0 commit comments

Comments
 (0)