fix(ocl) fixing race condition in createFclTranslationCtx
In rare case of multiple threads trying to set fclBaseTranslationCtx, there was a potential for use after free (double delete) on std::unique_ptr::reset. Resolves: NEO-7767 Signed-off-by: Jaroslaw Chodor <jaroslaw.chodor@intel.com>
This commit is contained in:
parent
5b2e1f619c
commit
f7cf09d195
|
@ -472,9 +472,12 @@ CIF::RAII::UPtr_t<IGC::FclOclTranslationCtxTagOCL> CompilerInterface::createFclT
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fclBaseTranslationCtx == nullptr) {
|
||||||
|
auto ulock = this->lock();
|
||||||
if (fclBaseTranslationCtx == nullptr) {
|
if (fclBaseTranslationCtx == nullptr) {
|
||||||
fclBaseTranslationCtx = deviceCtx->CreateTranslationCtx(inType, outType);
|
fclBaseTranslationCtx = deviceCtx->CreateTranslationCtx(inType, outType);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return deviceCtx->CreateTranslationCtx(inType, outType);
|
return deviceCtx->CreateTranslationCtx(inType, outType);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ namespace NEO {
|
||||||
|
|
||||||
class MockCompilerInterface : public CompilerInterface {
|
class MockCompilerInterface : public CompilerInterface {
|
||||||
public:
|
public:
|
||||||
|
using CompilerInterface::fclBaseTranslationCtx;
|
||||||
using CompilerInterface::fclDeviceContexts;
|
using CompilerInterface::fclDeviceContexts;
|
||||||
using CompilerInterface::initialize;
|
using CompilerInterface::initialize;
|
||||||
using CompilerInterface::isCompilerAvailable;
|
using CompilerInterface::isCompilerAvailable;
|
||||||
|
|
|
@ -684,20 +684,25 @@ struct MockCompilerDeviceCtx : DeviceCtxBase {
|
||||||
|
|
||||||
template <typename DeviceCtx, typename MockDeviceCtx>
|
template <typename DeviceCtx, typename MockDeviceCtx>
|
||||||
struct LockListener {
|
struct LockListener {
|
||||||
LockListener(NEO::Device *device)
|
LockListener(NEO::Device *device, bool createDeviceCtxOnLock = true)
|
||||||
: device(device) {
|
: device(device), createDeviceCtxOnLock(createDeviceCtxOnLock) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void listener(MockCompilerInterface &compInt) {
|
static void listener(MockCompilerInterface &compInt) {
|
||||||
auto data = (LockListener *)compInt.lockListenerData;
|
auto data = (LockListener *)compInt.lockListenerData;
|
||||||
|
data->lockCount += 1;
|
||||||
|
if (data->createDeviceCtxOnLock && compInt.getDeviceContexts<DeviceCtx>().empty()) {
|
||||||
|
|
||||||
auto deviceCtx = CIF::RAII::UPtr(new MockDeviceCtx);
|
auto deviceCtx = CIF::RAII::UPtr(new MockDeviceCtx);
|
||||||
EXPECT_TRUE(compInt.getDeviceContexts<DeviceCtx>().empty());
|
|
||||||
compInt.setDeviceCtx(*data->device, deviceCtx.get());
|
compInt.setDeviceCtx(*data->device, deviceCtx.get());
|
||||||
data->createdDeviceCtx = deviceCtx.get();
|
data->createdDeviceCtx = deviceCtx.get();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NEO::Device *device = nullptr;
|
NEO::Device *device = nullptr;
|
||||||
MockDeviceCtx *createdDeviceCtx = nullptr;
|
MockDeviceCtx *createdDeviceCtx = nullptr;
|
||||||
|
bool createDeviceCtxOnLock = false;
|
||||||
|
int lockCount = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WasLockedListener {
|
struct WasLockedListener {
|
||||||
|
@ -768,7 +773,9 @@ TEST_F(CompilerInterfaceTest, GivenSimultaneousRequestForNewFclTranslationContex
|
||||||
this->pCompilerInterface->lockListenerData = &listenerData;
|
this->pCompilerInterface->lockListenerData = &listenerData;
|
||||||
this->pCompilerInterface->lockListener = ListenerT::listener;
|
this->pCompilerInterface->lockListener = ListenerT::listener;
|
||||||
|
|
||||||
|
EXPECT_EQ(0, listenerData.lockCount);
|
||||||
auto ret = this->pCompilerInterface->createFclTranslationCtx(*device, IGC::CodeType::oclC, IGC::CodeType::spirV);
|
auto ret = this->pCompilerInterface->createFclTranslationCtx(*device, IGC::CodeType::oclC, IGC::CodeType::spirV);
|
||||||
|
EXPECT_EQ(2, listenerData.lockCount);
|
||||||
EXPECT_NE(nullptr, ret.get());
|
EXPECT_NE(nullptr, ret.get());
|
||||||
ASSERT_EQ(1U, this->pCompilerInterface->getFclDeviceContexts().size());
|
ASSERT_EQ(1U, this->pCompilerInterface->getFclDeviceContexts().size());
|
||||||
ASSERT_NE(this->pCompilerInterface->getFclDeviceContexts().end(),
|
ASSERT_NE(this->pCompilerInterface->getFclDeviceContexts().end(),
|
||||||
|
|
Loading…
Reference in New Issue