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:
Jaroslaw Chodor 2023-03-03 11:24:48 +00:00 committed by Compute-Runtime-Automation
parent 5b2e1f619c
commit f7cf09d195
3 changed files with 18 additions and 7 deletions

View File

@ -473,7 +473,10 @@ CIF::RAII::UPtr_t<IGC::FclOclTranslationCtxTagOCL> CompilerInterface::createFclT
}
if (fclBaseTranslationCtx == nullptr) {
fclBaseTranslationCtx = deviceCtx->CreateTranslationCtx(inType, outType);
auto ulock = this->lock();
if (fclBaseTranslationCtx == nullptr) {
fclBaseTranslationCtx = deviceCtx->CreateTranslationCtx(inType, outType);
}
}
return deviceCtx->CreateTranslationCtx(inType, outType);

View File

@ -21,6 +21,7 @@ namespace NEO {
class MockCompilerInterface : public CompilerInterface {
public:
using CompilerInterface::fclBaseTranslationCtx;
using CompilerInterface::fclDeviceContexts;
using CompilerInterface::initialize;
using CompilerInterface::isCompilerAvailable;

View File

@ -684,20 +684,25 @@ struct MockCompilerDeviceCtx : DeviceCtxBase {
template <typename DeviceCtx, typename MockDeviceCtx>
struct LockListener {
LockListener(NEO::Device *device)
: device(device) {
LockListener(NEO::Device *device, bool createDeviceCtxOnLock = true)
: device(device), createDeviceCtxOnLock(createDeviceCtxOnLock) {
}
static void listener(MockCompilerInterface &compInt) {
auto data = (LockListener *)compInt.lockListenerData;
auto deviceCtx = CIF::RAII::UPtr(new MockDeviceCtx);
EXPECT_TRUE(compInt.getDeviceContexts<DeviceCtx>().empty());
compInt.setDeviceCtx(*data->device, deviceCtx.get());
data->createdDeviceCtx = deviceCtx.get();
data->lockCount += 1;
if (data->createDeviceCtxOnLock && compInt.getDeviceContexts<DeviceCtx>().empty()) {
auto deviceCtx = CIF::RAII::UPtr(new MockDeviceCtx);
compInt.setDeviceCtx(*data->device, deviceCtx.get());
data->createdDeviceCtx = deviceCtx.get();
}
}
NEO::Device *device = nullptr;
MockDeviceCtx *createdDeviceCtx = nullptr;
bool createDeviceCtxOnLock = false;
int lockCount = 0;
};
struct WasLockedListener {
@ -768,7 +773,9 @@ TEST_F(CompilerInterfaceTest, GivenSimultaneousRequestForNewFclTranslationContex
this->pCompilerInterface->lockListenerData = &listenerData;
this->pCompilerInterface->lockListener = ListenerT::listener;
EXPECT_EQ(0, listenerData.lockCount);
auto ret = this->pCompilerInterface->createFclTranslationCtx(*device, IGC::CodeType::oclC, IGC::CodeType::spirV);
EXPECT_EQ(2, listenerData.lockCount);
EXPECT_NE(nullptr, ret.get());
ASSERT_EQ(1U, this->pCompilerInterface->getFclDeviceContexts().size());
ASSERT_NE(this->pCompilerInterface->getFclDeviceContexts().end(),