aboutsummaryrefslogtreecommitdiff
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
authorlizzie <lizzie@eden-emu.dev>2026-04-09 23:46:38 +0200
committercrueter <crueter@eden-emu.dev>2026-04-09 23:46:38 +0200
commitc95cb8f8ec6ce256b75fd85c858c7b80f91e088e (patch)
tree40e5c55bd2bc7b7005e01b37033ec529f9529dda /src/core/hle/kernel
parent3d0eb4b5d71c6e051480408ab4274082c6b232e3 (diff)
[hle] improved flusher that uses jthread (#3837)
not happy with this impl, but I made this a bit quickly to demostrate it can be done better :) Signed-off-by: lizzie <lizzie@eden-emu.dev> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3837 Reviewed-by: MaranBr <maranbr@eden-emu.dev> Reviewed-by: CamilleLaVey <camillelavey99@gmail.com> Co-authored-by: lizzie <lizzie@eden-emu.dev> Co-committed-by: lizzie <lizzie@eden-emu.dev>
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/svc/svc_debug_string.cpp102
1 files changed, 43 insertions, 59 deletions
diff --git a/src/core/hle/kernel/svc/svc_debug_string.cpp b/src/core/hle/kernel/svc/svc_debug_string.cpp
index 92cc334a81..c190fa7a3f 100644
--- a/src/core/hle/kernel/svc/svc_debug_string.cpp
+++ b/src/core/hle/kernel/svc/svc_debug_string.cpp
@@ -6,6 +6,8 @@
#include <condition_variable>
#include <mutex>
+#include <optional>
+#include <stop_token>
#include <thread>
#include "core/core.h"
@@ -18,59 +20,53 @@ namespace Kernel::Svc {
constexpr auto MAX_MSG_TIME = std::chrono::milliseconds(250);
const auto MAX_MSG_SIZE = 0x1000;
-static std::string msg_buffer;
-static std::mutex msg_mutex;
-static std::condition_variable msg_cv;
-static std::chrono::steady_clock::time_point last_msg_time;
-static bool worker_running = true;
-static std::unique_ptr<std::thread> flush_thread;
-static std::once_flag start_flag;
-
-static void FlushDbgLoop() {
- while (true) {
- std::unique_lock lock(msg_mutex);
-
- msg_cv.wait(lock, [] { return !msg_buffer.empty() || !worker_running; });
- if (!worker_running && msg_buffer.empty()) break;
-
- auto timeout = last_msg_time + MAX_MSG_TIME;
- bool woke_early = msg_cv.wait_until(lock, timeout, [] {
- return msg_buffer.size() >= MAX_MSG_SIZE || !worker_running;
- });
-
- if (!woke_early || msg_buffer.size() >= MAX_MSG_SIZE || !worker_running) {
- if (!msg_buffer.empty()) {
- // Remove trailing newline as LOG_INFO adds that anyways
- if (msg_buffer.back() == '\n')
- msg_buffer.pop_back();
-
- LOG_INFO(Debug_Emulated, "\n{}", msg_buffer);
- msg_buffer.clear();
- }
- if (!worker_running) break;
- }
- }
-}
-
/// Used to output a message on a debug hardware unit - does nothing on a retail unit
Result OutputDebugString(Core::System& system, u64 address, u64 len) {
+ static struct DebugFlusher {
+ std::string msg_buffer;
+ std::mutex msg_mutex;
+ std::condition_variable msg_cv;
+ std::chrono::steady_clock::time_point last_msg_time;
+ std::optional<std::jthread> thread;
+ } flusher_data;
R_SUCCEED_IF(len == 0);
-
// Only start the thread the very first time this function is called
- std::call_once(start_flag, [] {
- flush_thread = std::make_unique<std::thread>(FlushDbgLoop);
- });
-
+ if (!flusher_data.thread) {
+ flusher_data.thread.emplace([](std::stop_token stop_token) {
+ while (!stop_token.stop_requested()) {
+ std::unique_lock lock(flusher_data.msg_mutex);
+ flusher_data.msg_cv.wait(lock, [&stop_token] {
+ return !flusher_data.msg_buffer.empty() || stop_token.stop_requested();
+ });
+ if (stop_token.stop_requested() && flusher_data.msg_buffer.empty())
+ break;
+ auto timeout = flusher_data.last_msg_time + MAX_MSG_TIME;
+ bool woke_early = flusher_data.msg_cv.wait_until(lock, timeout, [&stop_token] {
+ return flusher_data.msg_buffer.size() >= MAX_MSG_SIZE || stop_token.stop_requested();
+ });
+ if (!woke_early || flusher_data.msg_buffer.size() >= MAX_MSG_SIZE || stop_token.stop_requested()) {
+ if (!flusher_data.msg_buffer.empty()) {
+ // Remove trailing newline as LOG_INFO adds that anyways
+ if (flusher_data.msg_buffer.back() == '\n')
+ flusher_data.msg_buffer.pop_back();
+
+ LOG_INFO(Debug_Emulated, "\n{}", flusher_data.msg_buffer);
+ flusher_data.msg_buffer.clear();
+ }
+ if (stop_token.stop_requested()) break;
+ }
+ }
+ flusher_data.msg_cv.notify_all();
+ });
+ }
{
- std::lock_guard lock(msg_mutex);
- const auto old_size = msg_buffer.size();
- msg_buffer.resize(old_size + len);
- GetCurrentMemory(system.Kernel()).ReadBlock(address, msg_buffer.data() + old_size, len);
-
- last_msg_time = std::chrono::steady_clock::now();
+ std::lock_guard lock(flusher_data.msg_mutex);
+ const auto old_size = flusher_data.msg_buffer.size();
+ flusher_data.msg_buffer.resize(old_size + len);
+ GetCurrentMemory(system.Kernel()).ReadBlock(address, flusher_data.msg_buffer.data() + old_size, len);
+ flusher_data.last_msg_time = std::chrono::steady_clock::now();
}
-
- msg_cv.notify_one();
+ flusher_data.msg_cv.notify_one();
R_SUCCEED();
}
@@ -82,16 +78,4 @@ Result OutputDebugString64From32(Core::System& system, uint32_t debug_str, uint3
R_RETURN(OutputDebugString(system, debug_str, len));
}
-struct BufferAutoFlush {
- ~BufferAutoFlush() {
- {
- std::lock_guard lock(msg_mutex);
- worker_running = false;
- }
- msg_cv.notify_all();
- if (flush_thread && flush_thread->joinable()) flush_thread->join();
- }
-};
-static BufferAutoFlush auto_flusher;
-
} // namespace Kernel::Svc