mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Added ThreadPriorityBoost setting
This commit is contained in:
parent
6f92c8ef22
commit
b3b54d5fbd
6
DDrawCompat/Config/Config.cpp
Normal file
6
DDrawCompat/Config/Config.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
#include <Config/Config.h>
|
||||
|
||||
namespace Config
|
||||
{
|
||||
Settings::ThreadPriorityBoost threadPriorityBoost;
|
||||
}
|
@ -1,10 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <Config/Settings/ThreadPriorityBoost.h>
|
||||
|
||||
namespace Config
|
||||
{
|
||||
const unsigned delayedFlipModeTimeout = 200;
|
||||
const unsigned evictionTimeout = 200;
|
||||
const unsigned maxPaletteUpdatesPerMs = 5;
|
||||
const unsigned maxUserModeDisplayDrivers = 3;
|
||||
const unsigned threadSwitchCycleTime = 3 * 1000 * 1000;
|
||||
|
||||
extern Settings::ThreadPriorityBoost threadPriorityBoost;
|
||||
}
|
||||
|
35
DDrawCompat/Config/EnumSetting.cpp
Normal file
35
DDrawCompat/Config/EnumSetting.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include <Config/Parser.h>
|
||||
#include <Config/EnumSetting.h>
|
||||
|
||||
namespace Config
|
||||
{
|
||||
EnumSetting::EnumSetting(const std::string& name, unsigned default, const std::vector<std::string>& enumNames)
|
||||
: Setting(name)
|
||||
, m_default(default)
|
||||
, m_value(default)
|
||||
, m_enumNames(enumNames)
|
||||
{
|
||||
}
|
||||
|
||||
std::string EnumSetting::getValueStr() const
|
||||
{
|
||||
return m_enumNames[m_value];
|
||||
}
|
||||
|
||||
void EnumSetting::resetValue()
|
||||
{
|
||||
m_value = m_default;
|
||||
}
|
||||
|
||||
void EnumSetting::setValue(const std::string& value)
|
||||
{
|
||||
auto it = std::find(m_enumNames.begin(), m_enumNames.end(), value);
|
||||
if (it == m_enumNames.end())
|
||||
{
|
||||
throw ParsingError("invalid value: '" + value + "'");
|
||||
}
|
||||
m_value = it - m_enumNames.begin();
|
||||
}
|
||||
}
|
26
DDrawCompat/Config/EnumSetting.h
Normal file
26
DDrawCompat/Config/EnumSetting.h
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <Config/Setting.h>
|
||||
|
||||
namespace Config
|
||||
{
|
||||
class EnumSetting : public Setting
|
||||
{
|
||||
public:
|
||||
unsigned get() const { return m_value; }
|
||||
|
||||
protected:
|
||||
EnumSetting(const std::string& name, unsigned default, const std::vector<std::string>& enumNames);
|
||||
|
||||
private:
|
||||
std::string getValueStr() const override;
|
||||
void resetValue() override;
|
||||
void setValue(const std::string& value) override;
|
||||
|
||||
unsigned m_default;
|
||||
unsigned m_value;
|
||||
const std::vector<std::string> m_enumNames;
|
||||
};
|
||||
}
|
@ -1,17 +1,27 @@
|
||||
#include <fstream>
|
||||
#include <locale>
|
||||
#include <map>
|
||||
|
||||
#include <Common/Log.h>
|
||||
#include <Common/Path.h>
|
||||
#include <Config/Parser.h>
|
||||
#include <Config/Setting.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
void setConfig(const std::string& name, const std::string& value);
|
||||
void setConfig(const std::string& name, const std::string& value, const std::string& source);
|
||||
std::string tolower(const std::string& str);
|
||||
std::string trim(const std::string& str);
|
||||
|
||||
void loadConfigFile(const std::string& type, const std::filesystem::path& path)
|
||||
auto& getSettings()
|
||||
{
|
||||
Compat::Log() << "Loading " << type << " config file: " << path.u8string();
|
||||
static std::map<std::string, Config::Setting&> settings;
|
||||
return settings;
|
||||
}
|
||||
|
||||
void loadConfigFile(const std::string& source, const std::filesystem::path& path)
|
||||
{
|
||||
Compat::Log() << "Loading " << source << " config file: " << path.u8string();
|
||||
std::ifstream f(path);
|
||||
if (!f.is_open())
|
||||
{
|
||||
@ -42,7 +52,7 @@ namespace
|
||||
throw Config::ParsingError("missing '=' separator");
|
||||
}
|
||||
|
||||
setConfig(trim(line.substr(0, pos)), trim(line.substr(pos + 1)));
|
||||
setConfig(trim(line.substr(0, pos)), trim(line.substr(pos + 1)), source);
|
||||
}
|
||||
catch (const Config::ParsingError& error)
|
||||
{
|
||||
@ -51,14 +61,38 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
void setConfig(const std::string& name, const std::string& /*value*/)
|
||||
void setConfig(const std::string& name, const std::string& value, const std::string& source)
|
||||
{
|
||||
if (name.empty())
|
||||
{
|
||||
throw Config::ParsingError("missing setting name before '='");
|
||||
}
|
||||
|
||||
throw Config::ParsingError("unknown setting: '" + name + "'");
|
||||
auto it = std::find_if(getSettings().cbegin(), getSettings().cend(), [&](const auto& v) {
|
||||
return 0 == _stricmp(v.first.c_str(), name.c_str()); });
|
||||
if (it == getSettings().end())
|
||||
{
|
||||
throw Config::ParsingError("unknown setting: '" + name + "'");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
it->second.set(tolower(value), source);
|
||||
}
|
||||
catch (const Config::ParsingError& error)
|
||||
{
|
||||
throw Config::ParsingError(it->second.getName() + ": " + error.what());
|
||||
}
|
||||
}
|
||||
|
||||
std::string tolower(const std::string& str)
|
||||
{
|
||||
std::string result(str);
|
||||
for (auto& c : result)
|
||||
{
|
||||
c = std::tolower(c, std::locale());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string trim(const std::string& str)
|
||||
@ -85,6 +119,10 @@ namespace Config
|
||||
{
|
||||
void loadAllConfigFiles(const std::filesystem::path& processPath)
|
||||
{
|
||||
for (auto& setting : getSettings()) {
|
||||
setting.second.reset();
|
||||
}
|
||||
|
||||
loadConfigFile("global", Compat::getEnvPath("PROGRAMDATA") / "DDrawCompat" / "DDrawCompat.ini");
|
||||
loadConfigFile("user", Compat::getEnvPath("LOCALAPPDATA") / "DDrawCompat" / "DDrawCompat.ini");
|
||||
loadConfigFile("directory", Compat::replaceFilename(processPath, "DDrawCompat.ini"));
|
||||
@ -96,6 +134,36 @@ namespace Config
|
||||
}
|
||||
processConfigPath.replace_filename(L"DDrawCompat-" + processConfigPath.filename().native() + L".ini");
|
||||
loadConfigFile("process", processConfigPath);
|
||||
|
||||
std::size_t maxNameLength = 0;
|
||||
std::size_t maxSourceLength = 0;
|
||||
for (const auto& setting : getSettings())
|
||||
{
|
||||
if (setting.second.getName().length() > maxNameLength)
|
||||
{
|
||||
maxNameLength = setting.second.getName().length();
|
||||
}
|
||||
if (setting.second.getSource().length() > maxSourceLength)
|
||||
{
|
||||
maxSourceLength = setting.second.getSource().length();
|
||||
}
|
||||
}
|
||||
|
||||
Compat::Log() << "Final configuration:";
|
||||
for (const auto& setting : getSettings())
|
||||
{
|
||||
std::string name(setting.second.getName());
|
||||
name.insert(name.end(), maxNameLength - name.length(), ' ');
|
||||
std::string source(setting.second.getSource());
|
||||
source.insert(source.end(), maxSourceLength - source.length(), ' ');
|
||||
Compat::Log() << " [" << source << "] " << name << " = " << setting.second.getValueAsString();
|
||||
}
|
||||
}
|
||||
|
||||
void registerSetting(Setting& setting)
|
||||
{
|
||||
const auto& name = setting.getName();
|
||||
getSettings().emplace(name, setting);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,8 +11,11 @@ namespace Config
|
||||
ParsingError(const std::string& error) : runtime_error(error) {}
|
||||
};
|
||||
|
||||
class Setting;
|
||||
|
||||
namespace Parser
|
||||
{
|
||||
void loadAllConfigFiles(const std::filesystem::path& processPath);
|
||||
void registerSetting(Setting& setting);
|
||||
}
|
||||
}
|
||||
|
30
DDrawCompat/Config/Setting.cpp
Normal file
30
DDrawCompat/Config/Setting.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
#include <Config/Parser.h>
|
||||
#include <Config/Setting.h>
|
||||
|
||||
namespace Config
|
||||
{
|
||||
Setting::Setting(const std::string& name)
|
||||
: m_name(name)
|
||||
{
|
||||
Parser::registerSetting(*this);
|
||||
}
|
||||
|
||||
void Setting::reset()
|
||||
{
|
||||
resetValue();
|
||||
m_source = "default";
|
||||
}
|
||||
|
||||
void Setting::set(const std::string& value, const std::string& source)
|
||||
{
|
||||
if ("default" == value)
|
||||
{
|
||||
resetValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
setValue(value);
|
||||
}
|
||||
m_source = source;
|
||||
}
|
||||
}
|
32
DDrawCompat/Config/Setting.h
Normal file
32
DDrawCompat/Config/Setting.h
Normal file
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Config
|
||||
{
|
||||
class Setting
|
||||
{
|
||||
public:
|
||||
Setting(const std::string& name);
|
||||
|
||||
Setting(const Setting&) = delete;
|
||||
Setting(Setting&&) = delete;
|
||||
Setting& operator=(const Setting&) = delete;
|
||||
Setting& operator=(Setting&&) = delete;
|
||||
|
||||
const std::string& getName() const { return m_name; }
|
||||
const std::string& getSource() const { return m_source; }
|
||||
std::string getValueAsString() const { return getValueStr(); }
|
||||
|
||||
void reset();
|
||||
void set(const std::string& value, const std::string& source);
|
||||
|
||||
private:
|
||||
virtual std::string getValueStr() const = 0;
|
||||
virtual void resetValue() = 0;
|
||||
virtual void setValue(const std::string& value) = 0;
|
||||
|
||||
std::string m_name;
|
||||
std::string m_source;
|
||||
};
|
||||
}
|
20
DDrawCompat/Config/Settings/ThreadPriorityBoost.h
Normal file
20
DDrawCompat/Config/Settings/ThreadPriorityBoost.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <Config/EnumSetting.h>
|
||||
|
||||
namespace Config
|
||||
{
|
||||
namespace Settings
|
||||
{
|
||||
class ThreadPriorityBoost : public EnumSetting
|
||||
{
|
||||
public:
|
||||
enum Value { OFF, ON, MAIN, APP };
|
||||
|
||||
ThreadPriorityBoost()
|
||||
: EnumSetting("ThreadPriorityBoost", OFF, { "off", "on", "main", "app" })
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -178,7 +178,10 @@
|
||||
<ClInclude Include="Common\ScopedCriticalSection.h" />
|
||||
<ClInclude Include="Common\Time.h" />
|
||||
<ClInclude Include="Config\Config.h" />
|
||||
<ClInclude Include="Config\EnumSetting.h" />
|
||||
<ClInclude Include="Config\Parser.h" />
|
||||
<ClInclude Include="Config\Setting.h" />
|
||||
<ClInclude Include="Config\Settings\ThreadPriorityBoost.h" />
|
||||
<ClInclude Include="D3dDdi\Adapter.h" />
|
||||
<ClInclude Include="D3dDdi\AdapterCallbacks.h" />
|
||||
<ClInclude Include="D3dDdi\AdapterFuncs.h" />
|
||||
@ -265,14 +268,17 @@
|
||||
<ClInclude Include="Win32\MemoryManagement.h" />
|
||||
<ClInclude Include="Win32\MsgHooks.h" />
|
||||
<ClInclude Include="Win32\Registry.h" />
|
||||
<ClInclude Include="Win32\WaitFunctions.h" />
|
||||
<ClInclude Include="Win32\Thread.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Common\Log.cpp" />
|
||||
<ClCompile Include="Common\Hook.cpp" />
|
||||
<ClCompile Include="Common\Path.cpp" />
|
||||
<ClCompile Include="Common\Time.cpp" />
|
||||
<ClCompile Include="Config\Config.cpp" />
|
||||
<ClCompile Include="Config\EnumSetting.cpp" />
|
||||
<ClCompile Include="Config\Parser.cpp" />
|
||||
<ClCompile Include="Config\Setting.cpp" />
|
||||
<ClCompile Include="D3dDdi\Adapter.cpp" />
|
||||
<ClCompile Include="D3dDdi\AdapterCallbacks.cpp" />
|
||||
<ClCompile Include="D3dDdi\AdapterFuncs.cpp" />
|
||||
@ -341,7 +347,7 @@
|
||||
<ClCompile Include="Win32\MemoryManagement.cpp" />
|
||||
<ClCompile Include="Win32\MsgHooks.cpp" />
|
||||
<ClCompile Include="Win32\Registry.cpp" />
|
||||
<ClCompile Include="Win32\WaitFunctions.cpp" />
|
||||
<ClCompile Include="Win32\Thread.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="DDrawCompat.rc" />
|
||||
|
@ -82,6 +82,9 @@
|
||||
<Filter Include="Source Files\Config">
|
||||
<UniqueIdentifier>{9d313de7-b8ca-49d0-84d2-217f2818d9d3}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\Config\Settings">
|
||||
<UniqueIdentifier>{bdde0d15-27ab-43a7-9c0a-294df6a52bad}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Gdi\Gdi.h">
|
||||
@ -327,9 +330,6 @@
|
||||
<ClInclude Include="DDraw\Log.h">
|
||||
<Filter>Header Files\DDraw</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Win32\WaitFunctions.h">
|
||||
<Filter>Header Files\Win32</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Direct3d\Direct3dMaterial.h">
|
||||
<Filter>Header Files\Direct3d</Filter>
|
||||
</ClInclude>
|
||||
@ -396,6 +396,18 @@
|
||||
<ClInclude Include="Config\Parser.h">
|
||||
<Filter>Header Files\Config</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Config\Setting.h">
|
||||
<Filter>Header Files\Config</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Config\EnumSetting.h">
|
||||
<Filter>Header Files\Config</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Config\Settings\ThreadPriorityBoost.h">
|
||||
<Filter>Header Files\Config\Settings</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Win32\Thread.h">
|
||||
<Filter>Header Files\Win32</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Gdi\Gdi.cpp">
|
||||
@ -563,9 +575,6 @@
|
||||
<ClCompile Include="DDraw\Log.cpp">
|
||||
<Filter>Source Files\DDraw</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Win32\WaitFunctions.cpp">
|
||||
<Filter>Source Files\Win32</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Direct3d\Direct3dMaterial.cpp">
|
||||
<Filter>Source Files\Direct3d</Filter>
|
||||
</ClCompile>
|
||||
@ -620,6 +629,18 @@
|
||||
<ClCompile Include="Config\Parser.cpp">
|
||||
<Filter>Source Files\Config</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Config\Config.cpp">
|
||||
<Filter>Source Files\Config</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Config\Setting.cpp">
|
||||
<Filter>Source Files\Config</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Config\EnumSetting.cpp">
|
||||
<Filter>Source Files\Config</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Win32\Thread.cpp">
|
||||
<Filter>Source Files\Win32</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="DDrawCompat.rc">
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <Common/Log.h>
|
||||
#include <Common/Path.h>
|
||||
#include <Common/Time.h>
|
||||
#include <Config/Config.h>
|
||||
#include <Config/Parser.h>
|
||||
#include <D3dDdi/Hooks.h>
|
||||
#include <DDraw/DirectDraw.h>
|
||||
@ -22,7 +23,7 @@
|
||||
#include <Win32/MemoryManagement.h>
|
||||
#include <Win32/MsgHooks.h>
|
||||
#include <Win32/Registry.h>
|
||||
#include <Win32/WaitFunctions.h>
|
||||
#include <Win32/Thread.h>
|
||||
|
||||
HRESULT WINAPI SetAppCompatData(DWORD, DWORD);
|
||||
|
||||
@ -60,8 +61,6 @@ namespace
|
||||
Win32::Registry::installHooks();
|
||||
Compat::Log() << "Installing Direct3D driver hooks";
|
||||
D3dDdi::installHooks();
|
||||
Compat::Log() << "Installing Win32 hooks";
|
||||
Win32::WaitFunctions::installHooks();
|
||||
Gdi::VirtualScreen::init();
|
||||
|
||||
CompatPtr<IDirectDraw> dd;
|
||||
@ -206,19 +205,19 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||
|
||||
Dll::g_jmpTargetProcs = Dll::g_origProcs;
|
||||
|
||||
VISIT_PUBLIC_DDRAW_PROCS(HOOK_DDRAW_PROC)
|
||||
VISIT_PUBLIC_DDRAW_PROCS(HOOK_DDRAW_PROC);
|
||||
|
||||
Win32::MemoryManagement::installHooks();
|
||||
Win32::MsgHooks::installHooks();
|
||||
Win32::Thread::installHooks();
|
||||
Compat::closeDbgEng();
|
||||
|
||||
const BOOL disablePriorityBoost = TRUE;
|
||||
SetProcessPriorityBoost(GetCurrentProcess(), disablePriorityBoost);
|
||||
SetProcessAffinityMask(GetCurrentProcess(), 1);
|
||||
timeBeginPeriod(1);
|
||||
setDpiAwareness();
|
||||
SetThemeAppProperties(0);
|
||||
|
||||
Win32::MemoryManagement::installHooks();
|
||||
Win32::MsgHooks::installHooks();
|
||||
Time::init();
|
||||
Compat::closeDbgEng();
|
||||
Win32::Thread::applyConfig();
|
||||
|
||||
const DWORD disableMaxWindowedMode = 12;
|
||||
CALL_ORIG_PROC(SetAppCompatData)(disableMaxWindowedMode, 0);
|
||||
|
60
DDrawCompat/Win32/Thread.cpp
Normal file
60
DDrawCompat/Win32/Thread.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
#include <Windows.h>
|
||||
|
||||
#include <Common/Hook.h>
|
||||
#include <Common/Log.h>
|
||||
#include <Config/Config.h>
|
||||
#include <Win32/Thread.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
BOOL WINAPI setProcessPriorityBoost(HANDLE hProcess, BOOL bDisablePriorityBoost)
|
||||
{
|
||||
LOG_FUNC("SetProcessPriorityBoost", hProcess, bDisablePriorityBoost);
|
||||
if (Config::Settings::ThreadPriorityBoost::APP != Config::threadPriorityBoost.get())
|
||||
{
|
||||
return LOG_RESULT(TRUE);
|
||||
}
|
||||
return LOG_RESULT(CALL_ORIG_FUNC(SetProcessPriorityBoost)(hProcess, bDisablePriorityBoost));
|
||||
}
|
||||
|
||||
BOOL WINAPI setThreadPriorityBoost(HANDLE hThread, BOOL bDisablePriorityBoost)
|
||||
{
|
||||
LOG_FUNC("SetThreadPriorityBoost", hThread, bDisablePriorityBoost);
|
||||
if (Config::Settings::ThreadPriorityBoost::APP != Config::threadPriorityBoost.get())
|
||||
{
|
||||
return LOG_RESULT(TRUE);
|
||||
}
|
||||
return LOG_RESULT(CALL_ORIG_FUNC(SetThreadPriorityBoost)(hThread, bDisablePriorityBoost));
|
||||
}
|
||||
}
|
||||
|
||||
namespace Win32
|
||||
{
|
||||
namespace Thread
|
||||
{
|
||||
void applyConfig()
|
||||
{
|
||||
switch (Config::threadPriorityBoost.get())
|
||||
{
|
||||
case Config::Settings::ThreadPriorityBoost::OFF:
|
||||
CALL_ORIG_FUNC(SetProcessPriorityBoost)(GetCurrentProcess(), TRUE);
|
||||
break;
|
||||
|
||||
case Config::Settings::ThreadPriorityBoost::ON:
|
||||
CALL_ORIG_FUNC(SetProcessPriorityBoost)(GetCurrentProcess(), FALSE);
|
||||
break;
|
||||
|
||||
case Config::Settings::ThreadPriorityBoost::MAIN:
|
||||
CALL_ORIG_FUNC(SetProcessPriorityBoost)(GetCurrentProcess(), TRUE);
|
||||
CALL_ORIG_FUNC(SetThreadPriorityBoost)(GetCurrentThread(), FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void installHooks()
|
||||
{
|
||||
HOOK_FUNCTION(kernel32, SetProcessPriorityBoost, setProcessPriorityBoost);
|
||||
HOOK_FUNCTION(kernel32, SetThreadPriorityBoost, setThreadPriorityBoost);
|
||||
}
|
||||
}
|
||||
}
|
@ -2,8 +2,9 @@
|
||||
|
||||
namespace Win32
|
||||
{
|
||||
namespace WaitFunctions
|
||||
namespace Thread
|
||||
{
|
||||
void applyConfig();
|
||||
void installHooks();
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
#include <Windows.h>
|
||||
#include <timeapi.h>
|
||||
|
||||
#include <Common/Hook.h>
|
||||
#include <Common/Time.h>
|
||||
#include <Config/Config.h>
|
||||
#include <Win32/WaitFunctions.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
void mitigateBusyWaiting()
|
||||
{
|
||||
thread_local ULONG64 ctLastThreadSwitch = Time::queryThreadCycleTime();
|
||||
ULONG64 ctNow = Time::queryThreadCycleTime();
|
||||
if (ctNow - ctLastThreadSwitch >= Config::threadSwitchCycleTime)
|
||||
{
|
||||
Sleep(0);
|
||||
ctLastThreadSwitch = ctNow;
|
||||
}
|
||||
}
|
||||
|
||||
template <auto func, typename Result, typename... Params>
|
||||
Result WINAPI mitigatedBusyWaitingFunc(Params... params)
|
||||
{
|
||||
mitigateBusyWaiting();
|
||||
return Compat::g_origFuncPtr<func>(params...);
|
||||
}
|
||||
}
|
||||
|
||||
#define MITIGATE_BUSY_WAITING(module, func) \
|
||||
Compat::hookFunction<&func>(#module, #func, &mitigatedBusyWaitingFunc<&func>)
|
||||
|
||||
namespace Win32
|
||||
{
|
||||
namespace WaitFunctions
|
||||
{
|
||||
void installHooks()
|
||||
{
|
||||
MITIGATE_BUSY_WAITING(user32, GetMessageA);
|
||||
MITIGATE_BUSY_WAITING(user32, GetMessageW);
|
||||
MITIGATE_BUSY_WAITING(kernel32, GetTickCount);
|
||||
MITIGATE_BUSY_WAITING(user32, MsgWaitForMultipleObjects);
|
||||
MITIGATE_BUSY_WAITING(user32, MsgWaitForMultipleObjectsEx);
|
||||
MITIGATE_BUSY_WAITING(user32, PeekMessageA);
|
||||
MITIGATE_BUSY_WAITING(user32, PeekMessageW);
|
||||
MITIGATE_BUSY_WAITING(kernel32, SignalObjectAndWait);
|
||||
MITIGATE_BUSY_WAITING(winmm, timeGetTime);
|
||||
MITIGATE_BUSY_WAITING(kernel32, WaitForSingleObjectEx);
|
||||
MITIGATE_BUSY_WAITING(kernel32, WaitForMultipleObjectsEx);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user