mirror of
https://github.com/intel/compute-runtime.git
synced 2025-12-18 22:08:53 +08:00
fix: avoid joining thread in deferred deleter
Join thread in DllMain (which we are not aware of) can result in hang occurring in DeferredDeleter, if the library is freed before FreeLibraryAndExitThread call from within the worker thread, the thread gets stuck, thus the main thread is stuck on worker->join(). Related-To: NEO-14121 Signed-off-by: Oskar Hubert Weber <oskar.hubert.weber@intel.com>
This commit is contained in:
committed by
Compute-Runtime-Automation
parent
ee769f5983
commit
1816c8eac4
@@ -27,8 +27,11 @@ void DeferredDeleter::stop() {
|
||||
doWorkInBackground = false;
|
||||
lock.unlock();
|
||||
condition.notify_one();
|
||||
// Wait for the working job to exit
|
||||
worker->join();
|
||||
worker->detach();
|
||||
// Wait for the working job to exit main loop
|
||||
while (!exitedMainLoop) {
|
||||
std::this_thread::yield();
|
||||
}
|
||||
// Delete working thread
|
||||
worker.reset();
|
||||
}
|
||||
@@ -76,6 +79,7 @@ void DeferredDeleter::ensureThread() {
|
||||
if (worker != nullptr) {
|
||||
return;
|
||||
}
|
||||
exitedMainLoop = false;
|
||||
worker = Thread::createFunc(run, reinterpret_cast<void *>(this));
|
||||
}
|
||||
|
||||
@@ -103,6 +107,7 @@ void *DeferredDeleter::run(void *arg) {
|
||||
lock.lock();
|
||||
// Check whether working thread should be stopped
|
||||
} while (!self->shouldStop());
|
||||
self->exitedMainLoop = true;
|
||||
lock.unlock();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ class DeferredDeleter : NEO::NonCopyableAndNonMovableClass {
|
||||
|
||||
static void *run(void *);
|
||||
|
||||
std::atomic<bool> exitedMainLoop = false;
|
||||
std::atomic<bool> doWorkInBackground = false;
|
||||
std::atomic<int> elementsToRelease = 0;
|
||||
std::atomic<int> hostptrsToRelease = 0;
|
||||
|
||||
@@ -24,6 +24,10 @@ void ThreadLinux::join() {
|
||||
pthread_join(threadId, nullptr);
|
||||
}
|
||||
|
||||
void ThreadLinux::detach() {
|
||||
pthread_detach(threadId);
|
||||
}
|
||||
|
||||
void ThreadLinux::yield() {
|
||||
sched_yield();
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ class ThreadLinux : public Thread {
|
||||
public:
|
||||
ThreadLinux(pthread_t threadId);
|
||||
void join() override;
|
||||
void detach() override;
|
||||
void yield() override;
|
||||
~ThreadLinux() override = default;
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ class Thread {
|
||||
public:
|
||||
static decltype(&Thread::create) createFunc;
|
||||
virtual void join() = 0;
|
||||
virtual void detach() = 0;
|
||||
virtual ~Thread() = default;
|
||||
virtual void yield() = 0;
|
||||
};
|
||||
|
||||
@@ -21,7 +21,12 @@ void ThreadWin::join() {
|
||||
thread->join();
|
||||
}
|
||||
|
||||
void ThreadWin::detach() {
|
||||
thread->detach();
|
||||
}
|
||||
|
||||
void ThreadWin::yield() {
|
||||
std::this_thread::yield();
|
||||
}
|
||||
|
||||
} // namespace NEO
|
||||
|
||||
@@ -16,6 +16,7 @@ class ThreadWin : public Thread {
|
||||
public:
|
||||
ThreadWin(std::thread *thread);
|
||||
void join() override;
|
||||
void detach() override;
|
||||
void yield() override;
|
||||
~ThreadWin() override = default;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2024 Intel Corporation
|
||||
* Copyright (C) 2018-2025 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "shared/source/memory_manager/deferrable_allocation_deletion.h"
|
||||
#include "shared/source/memory_manager/deferred_deleter.h"
|
||||
#include "shared/source/os_interface/os_context.h"
|
||||
#include "shared/test/common/helpers/memory_management.h"
|
||||
#include "shared/test/common/libult/ult_command_stream_receiver.h"
|
||||
#include "shared/test/common/mocks/mock_allocation_properties.h"
|
||||
#include "shared/test/common/mocks/mock_device.h"
|
||||
@@ -36,6 +37,7 @@ struct DeferredDeleterPublic : DeferredDeleter {
|
||||
|
||||
struct DeferrableAllocationDeletionTest : ::testing::Test {
|
||||
void SetUp() override {
|
||||
MemoryManagement::fastLeaksDetectionMode = MemoryManagement::LeakDetectionMode::TURN_OFF_LEAK_DETECTION;
|
||||
executionEnvironment = new MockExecutionEnvironment(defaultHwInfo.get(), false, 1u);
|
||||
executionEnvironment->incRefInternal();
|
||||
memoryManager = new MockMemoryManager(*executionEnvironment);
|
||||
|
||||
Reference in New Issue
Block a user