Fix VA sharing scenario

- make createGraphicsAllocationFromSharedHandle and
freeGraphicsMemory more threadsafe - there was race condition
where one thread called PRIME_FD_TO_HANDLE ioctl when the other just
closed the last handle with GEM_CLOSE ioctl. This led to situation
where newly acquired handle from PRIME_FD_TO_HANDLE was already invalid
and used in exec.

- adding mutex for the time of accessing shared handles container
 and ioctls (GEM_CLOSE and PRIME_FD_TO_HANDLE) resolves racing problem

Change-Id: I8417a036a1429be8f1ba97e63ebdda2707960564
This commit is contained in:
Hoppe, Mateusz
2018-08-14 13:14:06 +02:00
committed by sys_ocldev
parent 6c521a7936
commit 5be98e2e0f
3 changed files with 102 additions and 11 deletions

View File

@@ -99,6 +99,11 @@ uint32_t DrmMemoryManager::unreference(OCLRT::BufferObject *bo, bool synchronous
;
}
std::unique_lock<std::mutex> lock(mtx, std::defer_lock);
if (bo->isReused) {
lock.lock();
}
uint32_t r = bo->refCount.fetch_sub(1);
if (r == 1) {
@@ -107,12 +112,15 @@ uint32_t DrmMemoryManager::unreference(OCLRT::BufferObject *bo, bool synchronous
auto allocatorType = bo->peekAllocationType();
if (bo->isReused) {
std::lock_guard<decltype(mtx)> lock(mtx);
eraseSharedBufferObject(bo);
}
bo->close();
if (lock) {
lock.unlock();
}
delete bo;
if (address) {
if (unmapSize) {
@@ -344,20 +352,28 @@ BufferObject *DrmMemoryManager::createSharedBufferObject(int boHandle, size_t si
}
GraphicsAllocation *DrmMemoryManager::createGraphicsAllocationFromSharedHandle(osHandle handle, bool requireSpecificBitness, bool reuseBO) {
drm_prime_handle openFd = {0, 0, 0};
openFd.fd = handle;
auto ret = this->drm->ioctl(DRM_IOCTL_PRIME_FD_TO_HANDLE, &openFd);
DEBUG_BREAK_IF(ret != 0);
((void)(ret));
auto boHandle = openFd.handle;
BufferObject *bo = nullptr;
std::unique_lock<std::mutex> lock(mtx, std::defer_lock);
if (reuseBO) {
lock.lock();
}
drm_prime_handle openFd = {0, 0, 0};
openFd.fd = handle;
auto ret = this->drm->ioctl(DRM_IOCTL_PRIME_FD_TO_HANDLE, &openFd);
if (ret != 0) {
int err = errno;
printDebugString(DebugManager.flags.PrintDebugMessages.get(), stderr, "ioctl(PRIME_FD_TO_HANDLE) failed with %d. errno=%d(%s)\n", ret, err, strerror(err));
DEBUG_BREAK_IF(ret != 0);
((void)(ret));
return nullptr;
}
auto boHandle = openFd.handle;
BufferObject *bo = nullptr;
if (reuseBO) {
bo = findAndReferenceSharedBufferObject(boHandle);
}
@@ -373,6 +389,9 @@ GraphicsAllocation *DrmMemoryManager::createGraphicsAllocationFromSharedHandle(o
pushSharedBufferObject(bo);
}
}
if (lock) {
lock.unlock();
}
auto drmAllocation = new DrmAllocation(bo, bo->address, bo->size, handle, MemoryPool::SystemCpuInaccessible);