From 063ab30e3d6068e2a1490e1b8f90f0a8f0895ee6 Mon Sep 17 00:00:00 2001 From: magumagu Date: Tue, 27 May 2014 20:12:12 -0700 Subject: [PATCH 1/2] IPCHLE: improve HLE timing. This change attempts to make calls to WII_IPC_HLE_Interface::Update() more consistent. We should be calling it whenever there is something we can pop from a queue, and this patch does that. DeviceUpdate() now works independently of Update(): it's now just a periodic timer for devices which need to regularly update state. With this change, we need a non-zero default delay for IPC replies because replies are popped off the queue much more aggressively. This fixes launching channels from the the System Menu. --- Source/Core/Core/HW/SystemTimers.cpp | 2 +- Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp | 56 ++++++++++--------- Source/Core/Core/IPC_HLE/WII_IPC_HLE.h | 3 +- .../Core/IPC_HLE/WII_IPC_HLE_Device_hid.cpp | 13 +---- .../Core/IPC_HLE/WII_IPC_HLE_Device_hid.h | 1 - 5 files changed, 35 insertions(+), 40 deletions(-) diff --git a/Source/Core/Core/HW/SystemTimers.cpp b/Source/Core/Core/HW/SystemTimers.cpp index 41b18ef0fe..95b4684549 100644 --- a/Source/Core/Core/HW/SystemTimers.cpp +++ b/Source/Core/Core/HW/SystemTimers.cpp @@ -165,7 +165,7 @@ void IPC_HLE_UpdateCallback(u64 userdata, int cyclesLate) { if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii) { - WII_IPC_HLE_Interface::Update(); + WII_IPC_HLE_Interface::UpdateDevices(); CoreTiming::ScheduleEvent(IPC_HLE_PERIOD - cyclesLate, et_IPC_HLE); } } diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp index 95c9f7a211..023840df06 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp @@ -76,9 +76,9 @@ IWII_IPC_HLE_Device* es_handles[ES_MAX_COUNT]; typedef std::deque ipc_msg_queue; static ipc_msg_queue request_queue; // ppc -> arm static ipc_msg_queue reply_queue; // arm -> ppc -static std::mutex s_reply_queue; static int enque_reply; +static int enque_request; static u64 last_reply_time; @@ -87,8 +87,14 @@ static u64 last_reply_time; // Please search for examples of this being called elsewhere. void EnqueReplyCallback(u64 userdata, int) { - std::lock_guard lk(s_reply_queue); reply_queue.push_back((u32)userdata); + Update(); +} + +void EnqueRequestCallback(u64 userdata, int) +{ + request_queue.push_back((u32)userdata); + Update(); } void Init() @@ -134,11 +140,13 @@ void Init() g_DeviceMap[i] = new IWII_IPC_HLE_Device(i, "_Unimplemented_Device_"); i++; enque_reply = CoreTiming::RegisterEvent("IPCReply", EnqueReplyCallback); + enque_request = CoreTiming::RegisterEvent("IPCRequest", EnqueRequestCallback); } void Reset(bool _bHard) { CoreTiming::RemoveAllEvents(enque_reply); + CoreTiming::RemoveAllEvents(enque_request); for (IWII_IPC_HLE_Device*& dev : g_FdMap) { @@ -175,12 +183,8 @@ void Reset(bool _bHard) g_DeviceMap.erase(g_DeviceMap.begin(), g_DeviceMap.end()); } request_queue.clear(); + reply_queue.clear(); - // lock due to using reply_queue - { - std::lock_guard lk(s_reply_queue); - reply_queue.clear(); - } last_reply_time = 0; } @@ -264,8 +268,6 @@ IWII_IPC_HLE_Device* CreateFileIO(u32 _DeviceID, const std::string& _rDeviceName void DoState(PointerWrap &p) { - std::lock_guard lk(s_reply_queue); - p.Do(request_queue); p.Do(reply_queue); p.Do(last_reply_time); @@ -537,6 +539,11 @@ void ExecuteCommand(u32 _Address) // Ensure replies happen in order, fairly ugly // Without this, tons of games fail now that DI commands have different reply delays int reply_delay = pDevice ? pDevice->GetCmdDelay(_Address) : 0; + if (!reply_delay) + { + int delay_us = 250; + reply_delay = SystemTimers::GetTicksPerSecond() / 1000000 * delay_us; + } const s64 ticks_til_last_reply = last_reply_time - CoreTiming::GetTicks(); @@ -555,7 +562,7 @@ void ExecuteCommand(u32 _Address) // Happens AS SOON AS IPC gets a new pointer! void EnqRequest(u32 _Address) { - request_queue.push_back(_Address); + CoreTiming::ScheduleEvent(1000, enque_request, _Address); } // Called when IOS module has some reply @@ -567,6 +574,11 @@ void EnqReply(u32 _Address, int cycles_in_future) CoreTiming::ScheduleEvent(cycles_in_future, enque_reply, _Address); } +void EnqReply_Threadsafe(u32 _Address, int cycles_in_future) +{ + CoreTiming::ScheduleEvent_Threadsafe(cycles_in_future, enque_reply, _Address); +} + // This is called every IPC_HLE_PERIOD from SystemTimers.cpp // Takes care of routing ipc <-> ipc HLE void Update() @@ -574,8 +586,6 @@ void Update() if (!WII_IPCInterface::IsReady()) return; - UpdateDevices(); - if (request_queue.size()) { WII_IPCInterface::GenerateAck(request_queue.front()); @@ -583,21 +593,15 @@ void Update() u32 command = request_queue.front(); request_queue.pop_front(); ExecuteCommand(command); - -#if MAX_LOGLEVEL >= DEBUG_LEVEL - Dolphin_Debugger::PrintCallstack(LogTypes::WII_IPC_HLE, LogTypes::LDEBUG); -#endif + return; } - // lock due to using reply_queue + if (reply_queue.size()) { - std::lock_guard lk(s_reply_queue); - if (reply_queue.size()) - { - WII_IPCInterface::GenerateReply(reply_queue.front()); - INFO_LOG(WII_IPC_HLE, "<<-- Reply to IPC Request @ 0x%08x", reply_queue.front()); - reply_queue.pop_front(); - } + WII_IPCInterface::GenerateReply(reply_queue.front()); + INFO_LOG(WII_IPC_HLE, "<<-- Reply to IPC Request @ 0x%08x", reply_queue.front()); + reply_queue.pop_front(); + return; } } @@ -606,9 +610,9 @@ void UpdateDevices() // Check if a hardware device must be updated for (const auto& entry : g_DeviceMap) { - if (entry.second->IsOpened() && entry.second->Update()) + if (entry.second->IsOpened()) { - break; + entry.second->Update(); } } } diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE.h b/Source/Core/Core/IPC_HLE/WII_IPC_HLE.h index 813c1c0250..e672d7ab5b 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE.h +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE.h @@ -29,8 +29,6 @@ namespace WII_IPC_HLE_Interface #define IPC_FIRST_ID 0x00 // First IPC device ID #define IPC_MAX_FILES 0x10 // First IPC file ID -void EnqueReplyCallback(u64 userdata, int =0); - // Init void Init(); @@ -66,5 +64,6 @@ void ExecuteCommand(u32 _Address); void EnqRequest(u32 _Address); void EnqReply(u32 _Address, int cycles_in_future = 0); +void EnqReply_Threadsafe(u32 _Address, int cycles_in_future = 0); } // end of namespace WII_IPC_HLE_Interface diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_hid.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_hid.cpp index 6c7f04aec6..c6e20ed9b4 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_hid.cpp +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_hid.cpp @@ -37,7 +37,7 @@ void CWII_IPC_HLE_Device_hid::checkUsbUpdates(CWII_IPC_HLE_Device_hid* hid) // Return value Memory::Write_U32(0, hid->deviceCommandAddress + 4); - WII_IPC_HLE_Interface::EnqueReplyCallback(hid->deviceCommandAddress); + WII_IPC_HLE_Interface::EnqReply_Threadsafe(hid->deviceCommandAddress); hid->deviceCommandAddress = 0; } } @@ -65,7 +65,7 @@ void CWII_IPC_HLE_Device_hid::handleUsbUpdates(struct libusb_transfer *transfer) // Return value Memory::Write_U32(ret, replyAddress + 4); - WII_IPC_HLE_Interface::EnqueReplyCallback(replyAddress); + WII_IPC_HLE_Interface::EnqReply_Threadsafe(replyAddress); //DEBUG_LOG(WII_IPC_HID, "OMG OMG OMG I GOT A CALLBACK, IMMA BE FAMOUS %d %d %d", transfer->actual_length, transfer->length, transfer->status); } @@ -124,13 +124,6 @@ bool CWII_IPC_HLE_Device_hid::Close(u32 _CommandAddress, bool _bForce) return true; } -u32 CWII_IPC_HLE_Device_hid::Update() -{ - - u32 work_done = 0; - return work_done; -} - bool CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress) { u32 Parameter = Memory::Read_U32(_CommandAddress + 0xC); @@ -256,7 +249,7 @@ bool CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress) // Return value Memory::Write_U32(-1, deviceCommandAddress + 4); - WII_IPC_HLE_Interface::EnqueReplyCallback(deviceCommandAddress); + WII_IPC_HLE_Interface::EnqReply(deviceCommandAddress); deviceCommandAddress = 0; } DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Shutdown) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)", diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_hid.h b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_hid.h index e74da8b81b..4186449a33 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_hid.h +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_hid.h @@ -27,7 +27,6 @@ public: virtual bool Open(u32 _CommandAddress, u32 _Mode) override; virtual bool Close(u32 _CommandAddress, bool _bForce) override; - virtual u32 Update() override; virtual bool IOCtlV(u32 _CommandAddress) override; virtual bool IOCtl(u32 _CommandAddress) override; From 58e9b65f9bc3e053f612c2e085e88b6bd96523c2 Mon Sep 17 00:00:00 2001 From: magumagu Date: Fri, 13 Jun 2014 20:28:06 -0700 Subject: [PATCH 2/2] IPCHLE: clean up spelling. --- Source/Core/Core/HW/WII_IPC.cpp | 2 +- Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp | 33 +++++++++---------- Source/Core/Core/IPC_HLE/WII_IPC_HLE.h | 6 ++-- .../Core/IPC_HLE/WII_IPC_HLE_Device_es.cpp | 2 +- .../Core/IPC_HLE/WII_IPC_HLE_Device_hid.cpp | 6 ++-- .../IPC_HLE/WII_IPC_HLE_Device_sdio_slot0.cpp | 2 +- .../Core/IPC_HLE/WII_IPC_HLE_Device_usb.cpp | 2 +- Source/Core/Core/IPC_HLE/WII_Socket.cpp | 2 +- 8 files changed, 26 insertions(+), 29 deletions(-) diff --git a/Source/Core/Core/HW/WII_IPC.cpp b/Source/Core/Core/HW/WII_IPC.cpp index 93ff9bbade..efbe44d770 100644 --- a/Source/Core/Core/HW/WII_IPC.cpp +++ b/Source/Core/Core/HW/WII_IPC.cpp @@ -158,7 +158,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) MMIO::ComplexWrite([](u32, u32 val) { ctrl.ppc(val); if (ctrl.X1) - WII_IPC_HLE_Interface::EnqRequest(ppc_msg); + WII_IPC_HLE_Interface::EnqueueRequest(ppc_msg); WII_IPC_HLE_Interface::Update(); CoreTiming::ScheduleEvent_Threadsafe(0, updateInterrupts, 0); }) diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp index 023840df06..b52ae01c0b 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp @@ -77,21 +77,18 @@ typedef std::deque ipc_msg_queue; static ipc_msg_queue request_queue; // ppc -> arm static ipc_msg_queue reply_queue; // arm -> ppc -static int enque_reply; -static int enque_request; +static int event_enqueue_reply; +static int event_enqueue_request; static u64 last_reply_time; -// NOTE: Only call this if you have correctly handled -// CommandAddress+0 and CommandAddress+8. -// Please search for examples of this being called elsewhere. -void EnqueReplyCallback(u64 userdata, int) +static void EnqueueReplyCallback(u64 userdata, int) { reply_queue.push_back((u32)userdata); Update(); } -void EnqueRequestCallback(u64 userdata, int) +static void EnqueueRequestCallback(u64 userdata, int) { request_queue.push_back((u32)userdata); Update(); @@ -139,14 +136,14 @@ void Init() g_DeviceMap[i] = new CWII_IPC_HLE_Device_stub(i, "/dev/usb/oh1"); i++; g_DeviceMap[i] = new IWII_IPC_HLE_Device(i, "_Unimplemented_Device_"); i++; - enque_reply = CoreTiming::RegisterEvent("IPCReply", EnqueReplyCallback); - enque_request = CoreTiming::RegisterEvent("IPCRequest", EnqueRequestCallback); + event_enqueue_reply = CoreTiming::RegisterEvent("IPCReply", EnqueueReplyCallback); + event_enqueue_request = CoreTiming::RegisterEvent("IPCRequest", EnqueueRequestCallback); } void Reset(bool _bHard) { - CoreTiming::RemoveAllEvents(enque_reply); - CoreTiming::RemoveAllEvents(enque_request); + CoreTiming::RemoveAllEvents(event_enqueue_reply); + CoreTiming::RemoveAllEvents(event_enqueue_request); for (IWII_IPC_HLE_Device*& dev : g_FdMap) { @@ -555,28 +552,28 @@ void ExecuteCommand(u32 _Address) last_reply_time = CoreTiming::GetTicks() + reply_delay; // Generate a reply to the IPC command - EnqReply(_Address, reply_delay); + EnqueueReply(_Address, reply_delay); } } // Happens AS SOON AS IPC gets a new pointer! -void EnqRequest(u32 _Address) +void EnqueueRequest(u32 address) { - CoreTiming::ScheduleEvent(1000, enque_request, _Address); + CoreTiming::ScheduleEvent(1000, event_enqueue_request, address); } // Called when IOS module has some reply // NOTE: Only call this if you have correctly handled // CommandAddress+0 and CommandAddress+8. // Please search for examples of this being called elsewhere. -void EnqReply(u32 _Address, int cycles_in_future) +void EnqueueReply(u32 address, int cycles_in_future) { - CoreTiming::ScheduleEvent(cycles_in_future, enque_reply, _Address); + CoreTiming::ScheduleEvent(cycles_in_future, event_enqueue_reply, address); } -void EnqReply_Threadsafe(u32 _Address, int cycles_in_future) +void EnqueueReply_Threadsafe(u32 address, int cycles_in_future) { - CoreTiming::ScheduleEvent_Threadsafe(cycles_in_future, enque_reply, _Address); + CoreTiming::ScheduleEvent_Threadsafe(cycles_in_future, event_enqueue_reply, address); } // This is called every IPC_HLE_PERIOD from SystemTimers.cpp diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE.h b/Source/Core/Core/IPC_HLE/WII_IPC_HLE.h index e672d7ab5b..fbb8cfb464 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE.h +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE.h @@ -62,8 +62,8 @@ void UpdateDevices(); void ExecuteCommand(u32 _Address); -void EnqRequest(u32 _Address); -void EnqReply(u32 _Address, int cycles_in_future = 0); -void EnqReply_Threadsafe(u32 _Address, int cycles_in_future = 0); +void EnqueueRequest(u32 address); +void EnqueueReply(u32 address, int cycles_in_future = 0); +void EnqueueReply_Threadsafe(u32 address, int cycles_in_future = 0); } // end of namespace WII_IPC_HLE_Interface diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_es.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_es.cpp index c5fd2871eb..633364d68a 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_es.cpp +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_es.cpp @@ -998,7 +998,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) Memory::Write_U32(IPC_CMD_IOCTLV, _CommandAddress + 8); // Generate a reply to the IPC command - WII_IPC_HLE_Interface::EnqReply(_CommandAddress, 0); + WII_IPC_HLE_Interface::EnqueueReply(_CommandAddress, 0); return false; } diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_hid.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_hid.cpp index c6e20ed9b4..a1bda5250a 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_hid.cpp +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_hid.cpp @@ -37,7 +37,7 @@ void CWII_IPC_HLE_Device_hid::checkUsbUpdates(CWII_IPC_HLE_Device_hid* hid) // Return value Memory::Write_U32(0, hid->deviceCommandAddress + 4); - WII_IPC_HLE_Interface::EnqReply_Threadsafe(hid->deviceCommandAddress); + WII_IPC_HLE_Interface::EnqueueReply_Threadsafe(hid->deviceCommandAddress); hid->deviceCommandAddress = 0; } } @@ -65,7 +65,7 @@ void CWII_IPC_HLE_Device_hid::handleUsbUpdates(struct libusb_transfer *transfer) // Return value Memory::Write_U32(ret, replyAddress + 4); - WII_IPC_HLE_Interface::EnqReply_Threadsafe(replyAddress); + WII_IPC_HLE_Interface::EnqueueReply_Threadsafe(replyAddress); //DEBUG_LOG(WII_IPC_HID, "OMG OMG OMG I GOT A CALLBACK, IMMA BE FAMOUS %d %d %d", transfer->actual_length, transfer->length, transfer->status); } @@ -249,7 +249,7 @@ bool CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress) // Return value Memory::Write_U32(-1, deviceCommandAddress + 4); - WII_IPC_HLE_Interface::EnqReply(deviceCommandAddress); + WII_IPC_HLE_Interface::EnqueueReply(deviceCommandAddress); deviceCommandAddress = 0; } DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Shutdown) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)", diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_sdio_slot0.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_sdio_slot0.cpp index 5eb99b81cc..e096059f8b 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_sdio_slot0.cpp +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_sdio_slot0.cpp @@ -22,7 +22,7 @@ void CWII_IPC_HLE_Device_sdio_slot0::EnqueueReply(u32 CommandAddress, u32 Return Memory::Write_U32(ReturnValue, CommandAddress + 4); - WII_IPC_HLE_Interface::EnqReply(CommandAddress); + WII_IPC_HLE_Interface::EnqueueReply(CommandAddress); } CWII_IPC_HLE_Device_sdio_slot0::CWII_IPC_HLE_Device_sdio_slot0(u32 _DeviceID, const std::string& _rDeviceName) diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb.cpp index de11fd600c..b4b2e81ff7 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb.cpp +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb.cpp @@ -24,7 +24,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::EnqueueReply(u32 CommandAddress) // The original hardware overwrites the command type with the async reply type. Memory::Write_U32(IPC_REP_ASYNC, CommandAddress); - WII_IPC_HLE_Interface::EnqReply(CommandAddress); + WII_IPC_HLE_Interface::EnqueueReply(CommandAddress); } // The device class diff --git a/Source/Core/Core/IPC_HLE/WII_Socket.cpp b/Source/Core/Core/IPC_HLE/WII_Socket.cpp index a7b810be91..e32aea8015 100644 --- a/Source/Core/Core/IPC_HLE/WII_Socket.cpp +++ b/Source/Core/Core/IPC_HLE/WII_Socket.cpp @@ -632,7 +632,7 @@ void WiiSockMan::EnqueueReply(u32 CommandAddress, s32 ReturnValue, IPCCommandTyp // Return value Memory::Write_U32(ReturnValue, CommandAddress + 4); - WII_IPC_HLE_Interface::EnqReply(CommandAddress); + WII_IPC_HLE_Interface::EnqueueReply(CommandAddress); }