diff --git a/rpcs3/Emu/Cell/Modules/cellAudio.cpp b/rpcs3/Emu/Cell/Modules/cellAudio.cpp index 3e5484d749..a4a35a50a7 100644 --- a/rpcs3/Emu/Cell/Modules/cellAudio.cpp +++ b/rpcs3/Emu/Cell/Modules/cellAudio.cpp @@ -8,8 +8,6 @@ #include "Emu/Audio/AudioThread.h" #include "cellAudio.h" -#include - LOG_CHANNEL(cellAudio); template <> @@ -40,22 +38,7 @@ void fmt_class_string::format(std::string& out, u64 arg) }); } -void audio_config::on_init(const std::shared_ptr& _this) -{ - m_buffer.set(vm::alloc(AUDIO_PORT_OFFSET * AUDIO_PORT_COUNT, vm::main)); - m_indexes.set(vm::alloc(sizeof(u64) * AUDIO_PORT_COUNT, vm::main)); - - for (u32 i = 0; i < AUDIO_PORT_COUNT; i++) - { - ports[i].number = i; - ports[i].addr = m_buffer + AUDIO_PORT_OFFSET * i; - ports[i].index = m_indexes + i; - } - - old_thread::on_init(_this); -} - -void audio_config::on_task() +std::pair audio_thread::operator()() { thread_ctrl::set_native_priority(1); @@ -76,11 +59,11 @@ void audio_config::on_task() const auto audio = Emu.GetCallbacks().get_audio(); audio->Open(buf8ch, buf_sz); - while (fxm::check() && !Emu.IsStopped()) + while (fxm::check() == this && !Emu.IsStopped()) { if (Emu.IsPaused()) { - std::this_thread::sleep_for(1ms); // hack + thread_ctrl::wait_for(1000); // hack continue; } @@ -94,7 +77,7 @@ void audio_config::on_task() const u64 expected_time = m_counter * AUDIO_SAMPLES * 1000000 / 48000; if (expected_time >= time_pos) { - std::this_thread::sleep_for(1ms); // hack + thread_ctrl::wait_for(1000); // hack continue; } @@ -342,17 +325,24 @@ void audio_config::on_task() cellAudio.trace("Audio perf: (access=%d, AddData=%d, events=%d, dump=%d)", stamp1 - stamp0, stamp2 - stamp1, stamp3 - stamp2, get_system_time() - stamp3); } + + return {m_buffer.addr(), m_indexes.addr()}; } error_code cellAudioInit() { cellAudio.warning("cellAudioInit()"); + const auto buf = vm::cast(vm::alloc(AUDIO_PORT_OFFSET * AUDIO_PORT_COUNT, vm::main)); + const auto ind = vm::cast(vm::alloc(sizeof(u64) * AUDIO_PORT_COUNT, vm::main)); + // Start audio thread - const auto g_audio = fxm::make(); + const auto g_audio = fxm::make("Audio Thread", buf, ind); if (!g_audio) { + vm::dealloc(buf); + vm::dealloc(ind); return CELL_AUDIO_ERROR_ALREADY_INIT; } @@ -371,6 +361,10 @@ error_code cellAudioQuit() return CELL_AUDIO_ERROR_NOT_INIT; } + // Join and dealloc + auto [buf, ind] = g_audio->operator()(); + vm::dealloc(buf); + vm::dealloc(ind); return CELL_OK; } diff --git a/rpcs3/Emu/Cell/Modules/cellAudio.h b/rpcs3/Emu/Cell/Modules/cellAudio.h index db30ea9228..4314e6b433 100644 --- a/rpcs3/Emu/Cell/Modules/cellAudio.h +++ b/rpcs3/Emu/Cell/Modules/cellAudio.h @@ -2,8 +2,6 @@ #include "Utilities/Thread.h" - - // Error codes enum CellAudioError : u32 { @@ -85,8 +83,6 @@ enum : u32 AUDIO_SAMPLES = CELL_AUDIO_BLOCK_SAMPLES, }; -extern u64 get_system_time(); - enum class audio_port_state : u32 { closed, @@ -96,7 +92,7 @@ enum class audio_port_state : u32 struct audio_port { - atomic_t state{ audio_port_state::closed }; + atomic_t state = audio_port_state::closed; u32 number; vm::ptr addr{}; @@ -119,36 +115,36 @@ struct audio_port atomic_t level_set; }; -class audio_config final : public old_thread +class audio_thread { - void on_task() override; - - std::string get_name() const override { return "Audio Thread"; } - - vm::ptr m_buffer = vm::null; - vm::ptr m_indexes = vm::null; + vm::ptr m_buffer; + vm::ptr m_indexes; u64 m_counter{}; public: - void on_init(const std::shared_ptr&) override; - const u64 start_time = get_system_time(); std::array ports; std::vector keys; - semaphore<> mutex; + shared_mutex mutex; - audio_config() = default; - - ~audio_config() + audio_thread(vm::ptr buf, vm::ptr ind) + : m_buffer(buf) + , m_indexes(ind) { - vm::dealloc_verbose_nothrow(m_buffer.addr()); - vm::dealloc_verbose_nothrow(m_indexes.addr()); + for (u32 i = 0; i < AUDIO_PORT_COUNT; i++) + { + ports[i].number = i; + ports[i].addr = m_buffer + AUDIO_PORT_OFFSET * i; + ports[i].index = m_indexes + i; + } } + std::pair operator()(); + audio_port* open_port() { for (u32 i = 0; i < AUDIO_PORT_COUNT; i++) @@ -162,3 +158,5 @@ public: return nullptr; } }; + +using audio_config = named_thread; diff --git a/rpcs3/Emu/Cell/Modules/cellCamera.cpp b/rpcs3/Emu/Cell/Modules/cellCamera.cpp index a2fd4bbdd3..840143e00c 100644 --- a/rpcs3/Emu/Cell/Modules/cellCamera.cpp +++ b/rpcs3/Emu/Cell/Modules/cellCamera.cpp @@ -7,8 +7,6 @@ #include "Emu/Io/PadHandler.h" #include "Emu/System.h" -#include - LOG_CHANNEL(cellCamera); // ************** @@ -284,7 +282,7 @@ s32 cellCameraInit() } // Start camera thread - const auto g_camera = fxm::make(); + const auto g_camera = fxm::make("Camera Thread"); if (!g_camera) { @@ -356,6 +354,13 @@ s32 cellCameraEnd() return CELL_OK; } + const auto g_camera = fxm::withdraw(); + + if (!g_camera) + { + return CELL_CAMERA_ERROR_NOT_INIT; + } + // TODO: My tests hinted to this behavior, but I'm not sure, so I'll leave this commented //s32 res = cellCameraClose(0); //if (res != CELL_OK) @@ -363,11 +368,8 @@ s32 cellCameraEnd() // return res; //} - if (!fxm::remove()) - { - return CELL_CAMERA_ERROR_NOT_INIT; - } - + // Join thread + g_camera->operator()(); return CELL_OK; } @@ -1154,19 +1156,19 @@ DECLARE(ppu_module_manager::cellCamera)("cellCamera", []() // camera_thread members -void camera_thread::on_task() +void camera_context::operator()() { - while (fxm::check() && !Emu.IsStopped()) + while (fxm::check() == this && !Emu.IsStopped()) { - std::chrono::steady_clock::time_point frame_start = std::chrono::steady_clock::now(); + const u64 frame_start = get_system_time(); if (Emu.IsPaused()) { - std::this_thread::sleep_for(1ms); // hack + thread_ctrl::wait_for(1000); // hack continue; } - std::lock_guard lock(mutex_notify_data_map); + std::unique_lock lock(mutex_notify_data_map); for (auto const& notify_data_entry : notify_data_map) { @@ -1180,8 +1182,8 @@ void camera_thread::on_task() { if (auto queue = lv2_event_queue::find(key)) { - u64 data2{ 0 }; - u64 data3{ 0 }; + u64 data2 = 0; + u64 data3 = 0; if (read_mode.load() == CELL_CAMERA_READ_DIRECT) { @@ -1205,29 +1207,22 @@ void camera_thread::on_task() } } } - } - const std::chrono::microseconds frame_target_time{ static_cast(1000000.0 / info.framerate) }; + lock.unlock(); - std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); - - std::chrono::microseconds frame_processing_time = std::chrono::duration_cast(now - frame_start); - - if (frame_processing_time < frame_target_time) + for (const u64 frame_target_time = 1000000u / info.framerate;;) { - std::chrono::microseconds frame_idle_time = frame_target_time - frame_processing_time; - std::this_thread::sleep_for(frame_idle_time); + const u64 time_passed = get_system_time() - frame_start; + if (time_passed >= frame_target_time) + break; + + thread_ctrl::wait_for(frame_target_time - time_passed); } } } -void camera_thread::on_init(const std::shared_ptr& _this) -{ - old_thread::on_init(_this); -} - -void camera_thread::send_attach_state(bool attached) +void camera_context::send_attach_state(bool attached) { std::lock_guard lock(mutex_notify_data_map); @@ -1255,7 +1250,7 @@ void camera_thread::send_attach_state(bool attached) } } -void camera_thread::set_attr(s32 attrib, u32 arg1, u32 arg2) +void camera_context::set_attr(s32 attrib, u32 arg1, u32 arg2) { if (attrib == CELL_CAMERA_READMODE) { @@ -1271,7 +1266,7 @@ void camera_thread::set_attr(s32 attrib, u32 arg1, u32 arg2) attr[attrib] = {arg1, arg2}; } -void camera_thread::add_queue(u64 key, u64 source, u64 flag) +void camera_context::add_queue(u64 key, u64 source, u64 flag) { std::lock_guard lock(mutex); { @@ -1284,7 +1279,7 @@ void camera_thread::add_queue(u64 key, u64 source, u64 flag) send_attach_state(true); } -void camera_thread::remove_queue(u64 key) +void camera_context::remove_queue(u64 key) { std::lock_guard lock(mutex); { diff --git a/rpcs3/Emu/Cell/Modules/cellCamera.h b/rpcs3/Emu/Cell/Modules/cellCamera.h index 7aa5dc6dc8..9af50a5707 100644 --- a/rpcs3/Emu/Cell/Modules/cellCamera.h +++ b/rpcs3/Emu/Cell/Modules/cellCamera.h @@ -351,21 +351,16 @@ struct CellCameraReadEx vm::bptr pbuf; }; -class camera_thread final : public old_thread +class camera_context { -private: struct notify_event_data { u64 source; u64 flag; }; - void on_task() override; - - std::string get_name() const override { return "Camera Thread"; } - public: - void on_init(const std::shared_ptr&) override; + void operator()(); void send_attach_state(bool attached); void set_attr(s32 attrib, u32 arg1, u32 arg2); @@ -385,11 +380,11 @@ public: std::map notify_data_map; - semaphore<> mutex; - semaphore<> mutex_notify_data_map; + shared_mutex mutex; + shared_mutex mutex_notify_data_map; Timer timer; - atomic_t read_mode{0}; + atomic_t read_mode{CELL_CAMERA_READ_FUNCCALL}; atomic_t is_streaming{false}; atomic_t is_attached{false}; atomic_t is_open{false}; @@ -404,11 +399,10 @@ public: lv2_memory_container container; atomic_t frame_num; - - camera_thread() : read_mode(CELL_CAMERA_READ_FUNCCALL) {} - ~camera_thread() = default; }; +using camera_thread = named_thread; + /// Shared data between cellGem and cellCamera struct gem_camera_shared { diff --git a/rpcs3/Emu/Cell/Modules/cellMic.cpp b/rpcs3/Emu/Cell/Modules/cellMic.cpp index de904932f7..8fb5a40ab0 100644 --- a/rpcs3/Emu/Cell/Modules/cellMic.cpp +++ b/rpcs3/Emu/Cell/Modules/cellMic.cpp @@ -5,38 +5,24 @@ #include "cellMic.h" #include #include -#include LOG_CHANNEL(cellMic); -void mic_thread::on_init(const std::shared_ptr& _this) +void mic_context::operator()() { - old_thread::on_init(_this); -} - -void mic_thread::on_task() -{ - while (micInited && !Emu.IsStopped()) + while (fxm::check() == this && !Emu.IsStopped()) { + thread_ctrl::wait_for(1000); + if (Emu.IsPaused()) - { - std::this_thread::sleep_for(1ms); // hack from cellAudio continue; - } + if (!micOpened || !micStarted) continue; - // If event queue is not set, then we can't send any events - if (eventQueueKey == 0) - continue; - - std::this_thread::sleep_for(1s); - - // Make sure the mic thread wasn't stopped while we were sleeping - if (!micInited) - break; - auto micQueue = lv2_event_queue::find(eventQueueKey); + if (!micQueue) + continue; micQueue->send(0, CELL_MIC_DATA, 0, 0); } @@ -47,8 +33,8 @@ void mic_thread::on_task() s32 cellMicInit() { cellMic.notice("cellMicInit()"); - const auto micThread = fxm::make(); - micInited = true; + + const auto micThread = fxm::make("Mic Thread"); if (!micThread) return CELL_MIC_ERROR_ALREADY_INIT; @@ -58,11 +44,13 @@ s32 cellMicInit() s32 cellMicEnd() { cellMic.notice("cellMicEnd()"); - micInited = false; + const auto micThread = fxm::withdraw(); if (!micThread) return CELL_MIC_ERROR_NOT_INIT; + // Join + micThread->operator()(); return CELL_OK; } @@ -479,8 +467,8 @@ s32 cellMicGetDeviceIdentifier() return CELL_OK; } -DECLARE(ppu_module_manager::cellMic) -("cellMic", []() { +DECLARE(ppu_module_manager::cellMic)("cellMic", []() +{ REG_FUNC(cellMic, cellMicInit); REG_FUNC(cellMic, cellMicEnd); REG_FUNC(cellMic, cellMicOpen); diff --git a/rpcs3/Emu/Cell/Modules/cellMic.h b/rpcs3/Emu/Cell/Modules/cellMic.h index cb26fe7436..da77ce4f9f 100644 --- a/rpcs3/Emu/Cell/Modules/cellMic.h +++ b/rpcs3/Emu/Cell/Modules/cellMic.h @@ -52,15 +52,11 @@ enum CellMicCommand // TODO: generate this from input from an actual microphone const u32 bufferSize = 1; -bool micInited = false; - -class mic_thread final : public old_thread +class mic_context { -private: - void on_task() override; - std::string get_name() const override { return "Mic Thread"; } public: - void on_init(const std::shared_ptr&) override; + void operator()(); + // Default value of 48000 for no particular reason u32 DspFrequency = 48000; // DSP is the default type u32 rawFrequency = 48000; @@ -76,9 +72,6 @@ public: f32 signalStateGainControl; f32 signalStateMicSignalLevel; // value is in decibels f32 signalStateSpeakerSignalLevel; // value is in decibels - mic_thread() = default; - ~mic_thread() - { - micInited = false; - } }; + +using mic_thread = named_thread;