Skip to content

Commit

Permalink
Add facility to run tasks on dedicated threads using the ThreadManage…
Browse files Browse the repository at this point in the history
…r interface.

Useful for things that should be run ASAP even if the threadpool is full,
at a small extra cost. (Not recommended for very small tasks).

Considering using this to resolve the deadlocks in #16802.
  • Loading branch information
hrydgard committed Jan 31, 2023
1 parent b04dd81 commit 6b0903f
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 7 deletions.
2 changes: 1 addition & 1 deletion Common/GPU/Vulkan/thin3d_vulkan.cpp
Expand Up @@ -213,7 +213,7 @@ class VKShaderModule : public ShaderModule {
}

private:
VulkanContext *vulkan_;
VulkanContext *vulkan_ = nullptr;
Promise<VkShaderModule> *module_ = nullptr;
VkShaderStageFlagBits vkstage_;
bool ok_ = false;
Expand Down
5 changes: 3 additions & 2 deletions Common/Net/HTTPHeaders.h
Expand Up @@ -18,11 +18,12 @@ class RequestHeader {
// Public variables since it doesn't make sense
// to bother with accessors for all these.
int status = 100;
// Intentional misspelling.
char *referer = nullptr;

char *referer = nullptr; // Intentional misspelling.
char *user_agent = nullptr;
char *resource = nullptr;
char *params = nullptr;

int content_length = -1;
std::unordered_map<std::string, std::string> other;
enum RequestType {
Expand Down
2 changes: 1 addition & 1 deletion Common/Net/HTTPServer.cpp
Expand Up @@ -81,7 +81,7 @@ Request::~Request() {
}
delete in_;
if (!out_->Empty()) {
ERROR_LOG(IO, "Output not empty - connection abort?");
ERROR_LOG(IO, "Output not empty - connection abort? (%s)", this->header_.resource);
}
delete out_;
}
Expand Down
12 changes: 12 additions & 0 deletions Common/Thread/ThreadManager.cpp
Expand Up @@ -217,6 +217,16 @@ void ThreadManager::Init(int numRealCores, int numLogicalCoresPerCpu) {
}

void ThreadManager::EnqueueTask(Task *task) {
if (task->Type() == TaskType::DEDICATED_THREAD) {
std::thread th([=](Task *task) {
SetCurrentThreadName("DedicatedThreadTask");
task->Run();
task->Release();
}, task);
th.detach();
return;
}

_assert_msg_(IsInitialized(), "ThreadManager not initialized");

int minThread;
Expand Down Expand Up @@ -270,6 +280,8 @@ void ThreadManager::EnqueueTask(Task *task) {
}

void ThreadManager::EnqueueTaskOnThread(int threadNum, Task *task) {
_assert_msg_(task->Type() != TaskType::DEDICATED_THREAD, "Dedicated thread tasks can't be put on specific threads");

_assert_msg_(threadNum >= 0 && threadNum < (int)global_->threads_.size(), "Bad threadnum or not initialized");
ThreadContext *thread = global_->threads_[threadNum];

Expand Down
1 change: 1 addition & 0 deletions Common/Thread/ThreadManager.h
Expand Up @@ -8,6 +8,7 @@
enum class TaskType {
CPU_COMPUTE,
IO_BLOCKING,
DEDICATED_THREAD, // These can never get stuck in queue behind others, but are more expensive to launch. Cannot use I/O.
};

// Implement this to make something that you can run on the thread manager.
Expand Down
11 changes: 8 additions & 3 deletions GPU/Vulkan/ShaderManagerVulkan.cpp
Expand Up @@ -98,12 +98,17 @@ static Promise<VkShaderModule> *CompileShaderModuleAsync(VulkanContext *vulkan,

#if defined(_DEBUG)
// Don't parallelize in debug mode, pathological behavior due to mutex locks in allocator which is HEAVILY used by glslang.
return Promise<VkShaderModule>::AlreadyDone(compile());
bool singleThreaded = true;
#else
return Promise<VkShaderModule>::Spawn(&g_threadManager, compile, TaskType::CPU_COMPUTE);
bool singleThreaded = false;
#endif
}

if (singleThreaded) {
return Promise<VkShaderModule>::AlreadyDone(compile());
} else {
return Promise<VkShaderModule>::Spawn(&g_threadManager, compile, TaskType::CPU_COMPUTE);
}
}

VulkanFragmentShader::VulkanFragmentShader(VulkanContext *vulkan, FShaderID id, FragmentShaderFlags flags, const char *code)
: vulkan_(vulkan), id_(id), flags_(flags) {
Expand Down

0 comments on commit 6b0903f

Please sign in to comment.