Merge pull request #3091 from Subv/hle_request_delat
Kernel/IPC: Add a small delay after each SyncRequest to prevent thread starvation.
This commit is contained in:
commit
2146311ad1
1 changed files with 23 additions and 5 deletions
|
@ -67,13 +67,31 @@ ResultCode ServerSession::HandleSyncRequest(SharedPtr<Thread> thread) {
|
||||||
// If this ServerSession has an associated HLE handler, forward the request to it.
|
// If this ServerSession has an associated HLE handler, forward the request to it.
|
||||||
if (hle_handler != nullptr) {
|
if (hle_handler != nullptr) {
|
||||||
hle_handler->HandleSyncRequest(SharedPtr<ServerSession>(this));
|
hle_handler->HandleSyncRequest(SharedPtr<ServerSession>(this));
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
if (thread->status == THREADSTATUS_RUNNING) {
|
||||||
// Put the thread to sleep until the server replies, it will be awoken in
|
// Put the thread to sleep until the server replies, it will be awoken in
|
||||||
// svcReplyAndReceive.
|
// svcReplyAndReceive for LLE servers.
|
||||||
thread->status = THREADSTATUS_WAIT_IPC;
|
thread->status = THREADSTATUS_WAIT_IPC;
|
||||||
// Add the thread to the list of threads that have issued a sync request with this
|
|
||||||
// server.
|
if (hle_handler != nullptr) {
|
||||||
pending_requesting_threads.push_back(std::move(thread));
|
// For HLE services, we put the request threads to sleep for a short duration to
|
||||||
|
// simulate IPC overhead, but only if the HLE handler didn't put the thread to sleep for
|
||||||
|
// other reasons like an async callback. The IPC overhead is needed to prevent
|
||||||
|
// starvation when a thread only does sync requests to HLE services while a
|
||||||
|
// lower-priority thread is waiting to run.
|
||||||
|
|
||||||
|
// This delay was approximated in a homebrew application by measuring the average time
|
||||||
|
// it takes for svcSendSyncRequest to return when performing the SetLcdForceBlack IPC
|
||||||
|
// request to the GSP:GPU service in a n3DS with firmware 11.6. The measured values have
|
||||||
|
// a high variance and vary between models.
|
||||||
|
static constexpr u64 IPCDelayNanoseconds = 39000;
|
||||||
|
thread->WakeAfterDelay(IPCDelayNanoseconds);
|
||||||
|
} else {
|
||||||
|
// Add the thread to the list of threads that have issued a sync request with this
|
||||||
|
// server.
|
||||||
|
pending_requesting_threads.push_back(std::move(thread));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this ServerSession does not have an HLE implementation, just wake up the threads waiting
|
// If this ServerSession does not have an HLE implementation, just wake up the threads waiting
|
||||||
|
|
Loading…
Reference in a new issue