Add facility to run tasks on dedicated threads using the ThreadManager 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.
This commit is contained in:
Henrik Rydgård 2023-01-31 00:42:35 +01:00
parent b04dd81cba
commit 6b0903f566
6 changed files with 26 additions and 7 deletions

View file

@ -213,7 +213,7 @@ public:
}
private:
VulkanContext *vulkan_;
VulkanContext *vulkan_ = nullptr;
Promise<VkShaderModule> *module_ = nullptr;
VkShaderStageFlagBits vkstage_;
bool ok_ = false;

View file

@ -18,11 +18,12 @@ public:
// 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 {

View file

@ -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_;
}

View file

@ -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;
@ -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];

View file

@ -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.

View file

@ -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) {