mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-09 23:59:27 +01:00
CoreTiming: Merge ScheduleEvent variants into one function
Now Core::IsCPUThread() only gets called once when using the AnyThread variant. Also, I think the enum approach makes calling code clearer.
This commit is contained in:
parent
088f7eaa3d
commit
3443a10030
@ -225,8 +225,8 @@ void DoState(PointerWrap& p)
|
|||||||
p.DoMarker("CoreTimingEvents");
|
p.DoMarker("CoreTimingEvents");
|
||||||
}
|
}
|
||||||
|
|
||||||
// This should only be called from the CPU thread, if you are calling it any other thread, you are
|
// This should only be called from the CPU thread. If you are calling
|
||||||
// doing something evil
|
// it from any other thread, you are doing something evil
|
||||||
u64 GetTicks()
|
u64 GetTicks()
|
||||||
{
|
{
|
||||||
u64 ticks = (u64)g_globalTimer;
|
u64 ticks = (u64)g_globalTimer;
|
||||||
@ -243,35 +243,6 @@ u64 GetIdleTicks()
|
|||||||
return (u64)idledCycles;
|
return (u64)idledCycles;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is to be called when outside threads, such as the graphics thread, wants to
|
|
||||||
// schedule things to be executed on the main thread.
|
|
||||||
void ScheduleEvent_Threadsafe(s64 cyclesIntoFuture, int event_type, u64 userdata)
|
|
||||||
{
|
|
||||||
_assert_msg_(POWERPC, !Core::IsCPUThread(), "ScheduleEvent_Threadsafe from wrong thread");
|
|
||||||
if (Core::g_want_determinism)
|
|
||||||
{
|
|
||||||
ERROR_LOG(POWERPC,
|
|
||||||
"Someone scheduled an off-thread \"%s\" event while netplay or movie play/record "
|
|
||||||
"was active. This is likely to cause a desync.",
|
|
||||||
event_types[event_type].name.c_str());
|
|
||||||
}
|
|
||||||
std::lock_guard<std::mutex> lk(tsWriteLock);
|
|
||||||
Event ne;
|
|
||||||
ne.time = g_globalTimer + cyclesIntoFuture;
|
|
||||||
ne.type = event_type;
|
|
||||||
ne.userdata = userdata;
|
|
||||||
tsQueue.Push(ne);
|
|
||||||
}
|
|
||||||
|
|
||||||
// To be used from any thread, including the CPU thread
|
|
||||||
void ScheduleEvent_AnyThread(s64 cyclesIntoFuture, int event_type, u64 userdata)
|
|
||||||
{
|
|
||||||
if (Core::IsCPUThread())
|
|
||||||
ScheduleEvent(cyclesIntoFuture, event_type, userdata);
|
|
||||||
else
|
|
||||||
ScheduleEvent_Threadsafe(cyclesIntoFuture, event_type, userdata);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClearPendingEvents()
|
void ClearPendingEvents()
|
||||||
{
|
{
|
||||||
while (first)
|
while (first)
|
||||||
@ -300,24 +271,49 @@ static void AddEventToQueue(Event* ne)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This must be run ONLY from within the CPU thread
|
void ScheduleEvent(s64 cycles_into_future, int event_type, u64 userdata, FromThread from)
|
||||||
// cyclesIntoFuture may be VERY inaccurate if called from anything else
|
|
||||||
// than Advance
|
|
||||||
void ScheduleEvent(s64 cyclesIntoFuture, int event_type, u64 userdata)
|
|
||||||
{
|
{
|
||||||
_assert_msg_(POWERPC, Core::IsCPUThread() || Core::GetState() == Core::CORE_PAUSE,
|
bool from_cpu_thread;
|
||||||
"ScheduleEvent from wrong thread");
|
if (from == FromThread::ANY)
|
||||||
|
{
|
||||||
|
from_cpu_thread = Core::IsCPUThread();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
from_cpu_thread = from == FromThread::CPU;
|
||||||
|
_assert_msg_(POWERPC, from_cpu_thread == Core::IsCPUThread(),
|
||||||
|
"ScheduleEvent from wrong thread (%s)", from_cpu_thread ? "CPU" : "non-CPU");
|
||||||
|
}
|
||||||
|
|
||||||
Event* ne = GetNewEvent();
|
if (from_cpu_thread)
|
||||||
ne->userdata = userdata;
|
{
|
||||||
ne->type = event_type;
|
Event* ne = GetNewEvent();
|
||||||
ne->time = GetTicks() + cyclesIntoFuture;
|
ne->time = GetTicks() + cycles_into_future;
|
||||||
|
ne->userdata = userdata;
|
||||||
|
ne->type = event_type;
|
||||||
|
|
||||||
// If this event needs to be scheduled before the next advance(), force one early
|
// If this event needs to be scheduled before the next advance(), force one early
|
||||||
if (!globalTimerIsSane)
|
if (!globalTimerIsSane)
|
||||||
ForceExceptionCheck(cyclesIntoFuture);
|
ForceExceptionCheck(cycles_into_future);
|
||||||
|
|
||||||
AddEventToQueue(ne);
|
AddEventToQueue(ne);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Core::g_want_determinism)
|
||||||
|
{
|
||||||
|
ERROR_LOG(POWERPC, "Someone scheduled an off-thread \"%s\" event while netplay or "
|
||||||
|
"movie play/record was active. This is likely to cause a desync.",
|
||||||
|
event_types[event_type].name.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lk(tsWriteLock);
|
||||||
|
Event ne;
|
||||||
|
ne.time = g_globalTimer + cycles_into_future;
|
||||||
|
ne.type = event_type;
|
||||||
|
ne.userdata = userdata;
|
||||||
|
tsQueue.Push(ne);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoveEvent(int event_type)
|
void RemoveEvent(int event_type)
|
||||||
|
@ -48,10 +48,18 @@ void DoState(PointerWrap& p);
|
|||||||
int RegisterEvent(const std::string& name, TimedCallback callback);
|
int RegisterEvent(const std::string& name, TimedCallback callback);
|
||||||
void UnregisterAllEvents();
|
void UnregisterAllEvents();
|
||||||
|
|
||||||
|
enum class FromThread
|
||||||
|
{
|
||||||
|
CPU,
|
||||||
|
NON_CPU,
|
||||||
|
// Don't use ANY unless you're sure you need to call from
|
||||||
|
// both the CPU thread and at least one other thread
|
||||||
|
ANY
|
||||||
|
};
|
||||||
|
|
||||||
// userdata MAY NOT CONTAIN POINTERS. userdata might get written and reloaded from savestates.
|
// userdata MAY NOT CONTAIN POINTERS. userdata might get written and reloaded from savestates.
|
||||||
void ScheduleEvent(s64 cyclesIntoFuture, int event_type, u64 userdata = 0);
|
void ScheduleEvent(s64 cycles_into_future, int event_type, u64 userdata = 0,
|
||||||
void ScheduleEvent_Threadsafe(s64 cyclesIntoFuture, int event_type, u64 userdata = 0);
|
FromThread from = FromThread::CPU);
|
||||||
void ScheduleEvent_AnyThread(s64 cyclesIntoFuture, int event_type, u64 userdata = 0);
|
|
||||||
|
|
||||||
// We only permit one event of each type in the queue at a time.
|
// We only permit one event of each type in the queue at a time.
|
||||||
void RemoveEvent(int event_type);
|
void RemoveEvent(int event_type);
|
||||||
|
@ -465,7 +465,7 @@ static void GenerateDSPInterrupt(u64 DSPIntType, s64 cyclesLate)
|
|||||||
void GenerateDSPInterruptFromDSPEmu(DSPInterruptType type)
|
void GenerateDSPInterruptFromDSPEmu(DSPInterruptType type)
|
||||||
{
|
{
|
||||||
// TODO: Maybe rethink this? The timing is unpredictable.
|
// TODO: Maybe rethink this? The timing is unpredictable.
|
||||||
CoreTiming::ScheduleEvent_AnyThread(0, et_GenerateDSPInterrupt, type);
|
CoreTiming::ScheduleEvent(0, et_GenerateDSPInterrupt, type, CoreTiming::FromThread::ANY);
|
||||||
}
|
}
|
||||||
|
|
||||||
// called whenever SystemTimers thinks the DSP deserves a few more cycles
|
// called whenever SystemTimers thinks the DSP deserves a few more cycles
|
||||||
|
@ -104,13 +104,14 @@ static void ChangeDeviceCallback(u64 userdata, s64 cyclesLate)
|
|||||||
|
|
||||||
void ChangeDevice(const u8 channel, const TEXIDevices device_type, const u8 device_num)
|
void ChangeDevice(const u8 channel, const TEXIDevices device_type, const u8 device_num)
|
||||||
{
|
{
|
||||||
// Called from GUI, so we need to make it thread safe.
|
// Called from GUI, so we need to use FromThread::NON_CPU.
|
||||||
// Let the hardware see no device for 1 second
|
// Let the hardware see no device for 1 second
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(
|
CoreTiming::ScheduleEvent(0, changeDevice,
|
||||||
0, changeDevice, ((u64)channel << 32) | ((u64)EXIDEVICE_NONE << 16) | device_num);
|
((u64)channel << 32) | ((u64)EXIDEVICE_NONE << 16) | device_num,
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(SystemTimers::GetTicksPerSecond(), changeDevice,
|
CoreTiming::FromThread::NON_CPU);
|
||||||
((u64)channel << 32) | ((u64)device_type << 16) |
|
CoreTiming::ScheduleEvent(SystemTimers::GetTicksPerSecond(), changeDevice,
|
||||||
device_num);
|
((u64)channel << 32) | ((u64)device_type << 16) | device_num,
|
||||||
|
CoreTiming::FromThread::NON_CPU);
|
||||||
}
|
}
|
||||||
|
|
||||||
CEXIChannel* GetChannel(u32 index)
|
CEXIChannel* GetChannel(u32 index)
|
||||||
@ -149,14 +150,9 @@ static void UpdateInterruptsCallback(u64 userdata, s64 cycles_late)
|
|||||||
UpdateInterrupts();
|
UpdateInterrupts();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScheduleUpdateInterrupts_Threadsafe(int cycles_late)
|
void ScheduleUpdateInterrupts(CoreTiming::FromThread from, int cycles_late)
|
||||||
{
|
{
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(cycles_late, updateInterrupts, 0);
|
CoreTiming::ScheduleEvent(cycles_late, updateInterrupts, 0, from);
|
||||||
}
|
|
||||||
|
|
||||||
void ScheduleUpdateInterrupts(int cycles_late)
|
|
||||||
{
|
|
||||||
CoreTiming::ScheduleEvent(cycles_late, updateInterrupts, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end of namespace ExpansionInterface
|
} // end of namespace ExpansionInterface
|
||||||
|
@ -10,6 +10,10 @@ class CEXIChannel;
|
|||||||
class IEXIDevice;
|
class IEXIDevice;
|
||||||
class PointerWrap;
|
class PointerWrap;
|
||||||
enum TEXIDevices : int;
|
enum TEXIDevices : int;
|
||||||
|
namespace CoreTiming
|
||||||
|
{
|
||||||
|
enum class FromThread;
|
||||||
|
}
|
||||||
namespace MMIO
|
namespace MMIO
|
||||||
{
|
{
|
||||||
class Mapping;
|
class Mapping;
|
||||||
@ -30,8 +34,7 @@ void PauseAndLock(bool doLock, bool unpauseOnUnlock);
|
|||||||
void RegisterMMIO(MMIO::Mapping* mmio, u32 base);
|
void RegisterMMIO(MMIO::Mapping* mmio, u32 base);
|
||||||
|
|
||||||
void UpdateInterrupts();
|
void UpdateInterrupts();
|
||||||
void ScheduleUpdateInterrupts_Threadsafe(int cycles_late);
|
void ScheduleUpdateInterrupts(CoreTiming::FromThread from, int cycles_late);
|
||||||
void ScheduleUpdateInterrupts(int cycles_late);
|
|
||||||
|
|
||||||
void ChangeDevice(const u8 channel, const TEXIDevices device_type, const u8 device_num);
|
void ChangeDevice(const u8 channel, const TEXIDevices device_type, const u8 device_num);
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/Network.h"
|
#include "Common/Network.h"
|
||||||
#include "Core/ConfigManager.h"
|
#include "Core/ConfigManager.h"
|
||||||
|
#include "Core/CoreTiming.h"
|
||||||
#include "Core/HW/EXI.h"
|
#include "Core/HW/EXI.h"
|
||||||
#include "Core/HW/EXI_DeviceEthernet.h"
|
#include "Core/HW/EXI_DeviceEthernet.h"
|
||||||
#include "Core/HW/Memmap.h"
|
#include "Core/HW/Memmap.h"
|
||||||
@ -406,7 +407,7 @@ void CEXIETHERNET::SendComplete()
|
|||||||
mBbaMem[BBA_IR] |= INT_T;
|
mBbaMem[BBA_IR] |= INT_T;
|
||||||
|
|
||||||
exi_status.interrupt |= exi_status.TRANSFER;
|
exi_status.interrupt |= exi_status.TRANSFER;
|
||||||
ExpansionInterface::ScheduleUpdateInterrupts(0);
|
ExpansionInterface::ScheduleUpdateInterrupts(CoreTiming::FromThread::CPU, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
mBbaMem[BBA_LTPS] = 0;
|
mBbaMem[BBA_LTPS] = 0;
|
||||||
@ -571,7 +572,7 @@ bool CEXIETHERNET::RecvHandlePacket()
|
|||||||
mBbaMem[BBA_IR] |= INT_R;
|
mBbaMem[BBA_IR] |= INT_R;
|
||||||
|
|
||||||
exi_status.interrupt |= exi_status.TRANSFER;
|
exi_status.interrupt |= exi_status.TRANSFER;
|
||||||
ExpansionInterface::ScheduleUpdateInterrupts_Threadsafe(0);
|
ExpansionInterface::ScheduleUpdateInterrupts(CoreTiming::FromThread::NON_CPU, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -179,7 +179,7 @@ void CEXIMic::UpdateNextInterruptTicks()
|
|||||||
{
|
{
|
||||||
int diff = (SystemTimers::GetTicksPerSecond() / sample_rate) * buff_size_samples;
|
int diff = (SystemTimers::GetTicksPerSecond() / sample_rate) * buff_size_samples;
|
||||||
next_int_ticks = CoreTiming::GetTicks() + diff;
|
next_int_ticks = CoreTiming::GetTicks() + diff;
|
||||||
ExpansionInterface::ScheduleUpdateInterrupts(diff);
|
ExpansionInterface::ScheduleUpdateInterrupts(CoreTiming::FromThread::CPU, diff);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CEXIMic::IsInterruptSet()
|
bool CEXIMic::IsInterruptSet()
|
||||||
|
@ -216,10 +216,10 @@ static void IOSNotifyResetButtonCallback(u64 userdata, s64 cyclesLate)
|
|||||||
|
|
||||||
void ResetButton_Tap()
|
void ResetButton_Tap()
|
||||||
{
|
{
|
||||||
CoreTiming::ScheduleEvent_AnyThread(0, toggleResetButton, true);
|
CoreTiming::ScheduleEvent(0, toggleResetButton, true, CoreTiming::FromThread::ANY);
|
||||||
CoreTiming::ScheduleEvent_AnyThread(0, iosNotifyResetButton, 0);
|
CoreTiming::ScheduleEvent(0, iosNotifyResetButton, 0, CoreTiming::FromThread::ANY);
|
||||||
CoreTiming::ScheduleEvent_AnyThread(SystemTimers::GetTicksPerSecond() / 2, toggleResetButton,
|
CoreTiming::ScheduleEvent(SystemTimers::GetTicksPerSecond() / 2, toggleResetButton, false,
|
||||||
false);
|
CoreTiming::FromThread::ANY);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ProcessorInterface
|
} // namespace ProcessorInterface
|
||||||
|
@ -527,24 +527,26 @@ static void ChangeDeviceCallback(u64 userdata, s64 cyclesLate)
|
|||||||
|
|
||||||
void ChangeDevice(SIDevices device, int channel)
|
void ChangeDevice(SIDevices device, int channel)
|
||||||
{
|
{
|
||||||
// Called from GUI, so we need to make it thread safe.
|
// Called from GUI, so we need to use FromThread::NON_CPU.
|
||||||
// Let the hardware see no device for 1 second
|
// Let the hardware see no device for 1 second
|
||||||
// TODO: Calling GetDeviceType here isn't threadsafe.
|
// TODO: Calling GetDeviceType here isn't threadsafe.
|
||||||
if (GetDeviceType(channel) != device)
|
if (GetDeviceType(channel) != device)
|
||||||
{
|
{
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(0, changeDevice, ((u64)channel << 32) | SIDEVICE_NONE);
|
CoreTiming::ScheduleEvent(0, changeDevice, ((u64)channel << 32) | SIDEVICE_NONE,
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(SystemTimers::GetTicksPerSecond(), changeDevice,
|
CoreTiming::FromThread::NON_CPU);
|
||||||
((u64)channel << 32) | device);
|
CoreTiming::ScheduleEvent(SystemTimers::GetTicksPerSecond(), changeDevice,
|
||||||
|
((u64)channel << 32) | device, CoreTiming::FromThread::NON_CPU);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChangeDeviceDeterministic(SIDevices device, int channel)
|
void ChangeDeviceDeterministic(SIDevices device, int channel)
|
||||||
{
|
{
|
||||||
// Called from savestates, so no need to make it thread safe.
|
// Called from savestates, so we don't use FromThread::NON_CPU.
|
||||||
if (GetDeviceType(channel) != device)
|
if (GetDeviceType(channel) != device)
|
||||||
{
|
{
|
||||||
CoreTiming::ScheduleEvent(0, changeDevice, ((u64)channel << 32) | SIDEVICE_NONE);
|
CoreTiming::ScheduleEvent(0, changeDevice, ((u64)channel << 32) | SIDEVICE_NONE);
|
||||||
CoreTiming::ScheduleEvent(500000000, changeDevice, ((u64)channel << 32) | device);
|
CoreTiming::ScheduleEvent(SystemTimers::GetTicksPerSecond(), changeDevice,
|
||||||
|
((u64)channel << 32) | device);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,7 +226,7 @@ void SDIO_EventNotify()
|
|||||||
// TODO: Potential race condition: If IsRunning() becomes false after
|
// TODO: Potential race condition: If IsRunning() becomes false after
|
||||||
// it's checked, an event may be scheduled after CoreTiming shuts down.
|
// it's checked, an event may be scheduled after CoreTiming shuts down.
|
||||||
if (SConfig::GetInstance().bWii && Core::IsRunning())
|
if (SConfig::GetInstance().bWii && Core::IsRunning())
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(0, event_sdio_notify);
|
CoreTiming::ScheduleEvent(0, event_sdio_notify, 0, CoreTiming::FromThread::NON_CPU);
|
||||||
}
|
}
|
||||||
|
|
||||||
int getFreeDeviceId()
|
int getFreeDeviceId()
|
||||||
@ -555,14 +555,9 @@ void EnqueueRequest(u32 address)
|
|||||||
// NOTE: Only call this if you have correctly handled
|
// NOTE: Only call this if you have correctly handled
|
||||||
// CommandAddress+0 and CommandAddress+8.
|
// CommandAddress+0 and CommandAddress+8.
|
||||||
// Please search for examples of this being called elsewhere.
|
// Please search for examples of this being called elsewhere.
|
||||||
void EnqueueReply(u32 address, int cycles_in_future)
|
void EnqueueReply(u32 address, int cycles_in_future, CoreTiming::FromThread from)
|
||||||
{
|
{
|
||||||
CoreTiming::ScheduleEvent(cycles_in_future, event_enqueue, address);
|
CoreTiming::ScheduleEvent(cycles_in_future, event_enqueue, address, from);
|
||||||
}
|
|
||||||
|
|
||||||
void EnqueueReply_Threadsafe(u32 address, int cycles_in_future)
|
|
||||||
{
|
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(cycles_in_future, event_enqueue, address);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnqueueCommandAcknowledgement(u32 address, int cycles_in_future)
|
void EnqueueCommandAcknowledgement(u32 address, int cycles_in_future)
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
|
|
||||||
|
#include "Core/CoreTiming.h"
|
||||||
#include "Core/HW/SystemTimers.h"
|
#include "Core/HW/SystemTimers.h"
|
||||||
|
|
||||||
class IWII_IPC_HLE_Device;
|
class IWII_IPC_HLE_Device;
|
||||||
@ -74,8 +75,8 @@ void UpdateDevices();
|
|||||||
void ExecuteCommand(u32 _Address);
|
void ExecuteCommand(u32 _Address);
|
||||||
|
|
||||||
void EnqueueRequest(u32 address);
|
void EnqueueRequest(u32 address);
|
||||||
void EnqueueReply(u32 address, int cycles_in_future = 0);
|
void EnqueueReply(u32 address, int cycles_in_future = 0,
|
||||||
void EnqueueReply_Threadsafe(u32 address, int cycles_in_future = 0);
|
CoreTiming::FromThread from = CoreTiming::FromThread::CPU);
|
||||||
void EnqueueCommandAcknowledgement(u32 _Address, int cycles_in_future = 0);
|
void EnqueueCommandAcknowledgement(u32 _Address, int cycles_in_future = 0);
|
||||||
|
|
||||||
} // end of namespace WII_IPC_HLE_Interface
|
} // end of namespace WII_IPC_HLE_Interface
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "Common/Thread.h"
|
#include "Common/Thread.h"
|
||||||
#include "Core/Core.h"
|
#include "Core/Core.h"
|
||||||
|
#include "Core/CoreTiming.h"
|
||||||
#include "Core/Debugger/Debugger_SymbolMap.h"
|
#include "Core/Debugger/Debugger_SymbolMap.h"
|
||||||
#include "Core/HW/WII_IPC.h"
|
#include "Core/HW/WII_IPC.h"
|
||||||
#include "Core/IPC_HLE/WII_IPC_HLE.h"
|
#include "Core/IPC_HLE/WII_IPC_HLE.h"
|
||||||
@ -40,7 +41,8 @@ void CWII_IPC_HLE_Device_hid::checkUsbUpdates(CWII_IPC_HLE_Device_hid* hid)
|
|||||||
// Return value
|
// Return value
|
||||||
Memory::Write_U32(0, hid->deviceCommandAddress + 4);
|
Memory::Write_U32(0, hid->deviceCommandAddress + 4);
|
||||||
|
|
||||||
WII_IPC_HLE_Interface::EnqueueReply_Threadsafe(hid->deviceCommandAddress);
|
WII_IPC_HLE_Interface::EnqueueReply(hid->deviceCommandAddress, 0,
|
||||||
|
CoreTiming::FromThread::NON_CPU);
|
||||||
hid->deviceCommandAddress = 0;
|
hid->deviceCommandAddress = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,7 +70,7 @@ void CWII_IPC_HLE_Device_hid::handleUsbUpdates(struct libusb_transfer* transfer)
|
|||||||
// Return value
|
// Return value
|
||||||
Memory::Write_U32(ret, replyAddress + 4);
|
Memory::Write_U32(ret, replyAddress + 4);
|
||||||
|
|
||||||
WII_IPC_HLE_Interface::EnqueueReply_Threadsafe(replyAddress);
|
WII_IPC_HLE_Interface::EnqueueReply(replyAddress, 0, CoreTiming::FromThread::NON_CPU);
|
||||||
// DEBUG_LOG(WII_IPC_HID, "OMG OMG OMG I GOT A CALLBACK, IMMA BE FAMOUS %d %d %d",
|
// 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);
|
// transfer->actual_length, transfer->length, transfer->status);
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ static const int MW_RATE = 600; // Steps per second
|
|||||||
static void MWCallback(u64 userdata, s64 cyclesLate)
|
static void MWCallback(u64 userdata, s64 cyclesLate)
|
||||||
{
|
{
|
||||||
s_memory_watcher->Step();
|
s_memory_watcher->Step();
|
||||||
CoreTiming::ScheduleEvent((SystemTimers::GetTicksPerSecond() / MW_RATE) - cyclesLate, s_event);
|
CoreTiming::ScheduleEvent(SystemTimers::GetTicksPerSecond() / MW_RATE - cyclesLate, s_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryWatcher::Init()
|
void MemoryWatcher::Init()
|
||||||
|
@ -343,7 +343,7 @@ void UpdateInterrupts(u64 userdata)
|
|||||||
void UpdateInterruptsFromVideoBackend(u64 userdata)
|
void UpdateInterruptsFromVideoBackend(u64 userdata)
|
||||||
{
|
{
|
||||||
if (!Fifo::UseDeterministicGPUThread())
|
if (!Fifo::UseDeterministicGPUThread())
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(0, et_UpdateInterrupts, userdata);
|
CoreTiming::ScheduleEvent(0, et_UpdateInterrupts, userdata, CoreTiming::FromThread::NON_CPU);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsInterruptWaiting()
|
bool IsInterruptWaiting()
|
||||||
|
@ -277,10 +277,11 @@ static void RaiseEvent()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
s_event_raised = true;
|
s_event_raised = true;
|
||||||
|
|
||||||
|
CoreTiming::FromThread from = CoreTiming::FromThread::NON_CPU;
|
||||||
if (!SConfig::GetInstance().bCPUThread || Fifo::UseDeterministicGPUThread())
|
if (!SConfig::GetInstance().bCPUThread || Fifo::UseDeterministicGPUThread())
|
||||||
CoreTiming::ScheduleEvent(0, et_SetTokenFinishOnMainThread, 0);
|
from = CoreTiming::FromThread::CPU;
|
||||||
else
|
CoreTiming::ScheduleEvent(0, et_SetTokenFinishOnMainThread, 0, from);
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(0, et_SetTokenFinishOnMainThread, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetToken
|
// SetToken
|
||||||
|
Loading…
x
Reference in New Issue
Block a user