1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 02:32:36 +01:00

Improve cellMic and sys_usbd thread scheduling

This commit is contained in:
RipleyTom 2023-04-01 22:51:00 +02:00 committed by Megamouse
parent ec3114d6d8
commit 0e8b0e414a
4 changed files with 42 additions and 50 deletions

View File

@ -70,74 +70,64 @@ void fmt_class_string<CellMicInErrorDsp>::format(std::string& out, u64 arg)
void mic_context::operator()()
{
// Timestep in microseconds
constexpr u64 TIMESTEP = 256ull * 1'000'000ull / 48000ull;
u64 timeout = 0;
u64 oldvalue = 0;
while (thread_ctrl::state() != thread_state::aborting)
{
// The time between processing is copied from audio thread
// Might be inaccurate for mic thread
if (Emu.IsPaused())
if (timeout != 0)
{
thread_ctrl::wait_for(1000); // hack
continue;
thread_ctrl::wait_on(wakey, oldvalue, timeout);
oldvalue = wakey;
}
const u64 stamp0 = get_guest_system_time();
const u64 time_pos = stamp0 - start_time - Emu.GetPauseTime();
std::lock_guard lock(mutex);
const u64 expected_time = m_counter * 256 * 1000000 / 48000;
if (expected_time >= time_pos)
if (std::none_of(mic_list.begin(), mic_list.end(), [](const microphone_device& dev) { return dev.is_registered(); }))
{
thread_ctrl::wait_for(1000); // hack
timeout = umax;
continue;
}
m_counter++;
// Process signals
const auto process_signals = [this]() -> bool
else
{
std::lock_guard lock(mutex);
timeout = TIMESTEP - (std::chrono::duration_cast<std::chrono::microseconds>(steady_clock::now().time_since_epoch()).count() % TIMESTEP);
}
if (std::none_of(mic_list.begin(), mic_list.end(), [](const microphone_device& dev) { return dev.is_registered(); }))
{
return false;
}
for (auto& mic_entry : mic_list)
{
mic_entry.update_audio();
}
auto mic_queue = lv2_event_queue::find(event_queue_key);
if (!mic_queue)
{
return true;
}
for (usz dev_num = 0; dev_num < mic_list.size(); dev_num++)
{
microphone_device& device = ::at32(mic_list, dev_num);
if (device.has_data())
{
mic_queue->send(event_queue_source, CELLMIC_DATA, dev_num, 0);
}
}
return true;
};
// Get mic input and sleep if mics are idle
if (!process_signals())
for (auto& mic_entry : mic_list)
{
thread_ctrl::wait_for(100000);
mic_entry.update_audio();
}
auto mic_queue = lv2_event_queue::find(event_queue_key);
if (!mic_queue)
continue;
for (usz dev_num = 0; dev_num < mic_list.size(); dev_num++)
{
microphone_device& device = ::at32(mic_list, dev_num);
if (device.has_data())
{
mic_queue->send(event_queue_source, CELLMIC_DATA, dev_num, 0);
}
}
}
// Cleanup
std::lock_guard lock(mutex);
for (auto& mic_entry : mic_list)
{
mic_entry.close_microphone();
}
}
void mic_context::wake_up()
{
wakey++;
wakey.notify_one();
}
void mic_context::load_config_and_init()
{
mic_list = {};
@ -214,6 +204,8 @@ u32 mic_context::register_device(const std::string& device_name)
break;
}
wake_up();
return ::narrow<u32>(index);
}

View File

@ -356,6 +356,7 @@ class mic_context
public:
void operator()();
void load_config_and_init();
void wake_up();
// Returns index of registered device
u32 register_device(const std::string& name);
@ -373,8 +374,7 @@ public:
static constexpr auto thread_name = "Microphone Thread"sv;
protected:
const u64 start_time = get_guest_system_time();
u64 m_counter = 0;
atomic_t<u64> wakey = 0;
// u32 signalStateLocalTalk = 9; // value is in range 0-10. 10 indicates talking, 0 indicating none.
// u32 signalStateFarTalk = 0; // value is in range 0-10. 10 indicates talking from far away, 0 indicating none.

View File

@ -398,7 +398,7 @@ void usb_handler_thread::operator()()
if (handled_devices.empty())
thread_ctrl::wait_for(500'000);
else
std::this_thread::yield();
thread_ctrl::wait_for(1'000);
}
}

View File

@ -487,7 +487,7 @@ void usb_device_usio::interrupt_transfer(u32 buf_size, u8* buf, u32 endpoint, Us
transfer->fake = true;
transfer->expected_result = HC_CC_NOERR;
// The latency varies per operation but it doesn't seem to matter for this device so let's go fast!
transfer->expected_time = get_timestamp();
transfer->expected_time = get_timestamp() + 1'000;
is_used = true;