1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
|
/*
* Copyright (C) 2025-2026 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/source/os_interface/linux/external_semaphore_linux.h"
#include "shared/source/os_interface/external_semaphore.h"
#include "shared/source/os_interface/linux/drm_neo.h"
#include "shared/source/os_interface/linux/drm_wrappers.h"
#include "shared/source/os_interface/linux/ioctl_helper.h"
#include "shared/source/os_interface/linux/sys_calls.h"
namespace NEO {
std::unique_ptr<ExternalSemaphore> ExternalSemaphore::create(OSInterface *osInterface, ExternalSemaphore::Type type, void *handle, int fd, const char *name) {
if (!osInterface) {
return nullptr;
}
auto externalSemaphore = ExternalSemaphoreLinux::create(osInterface);
bool result = externalSemaphore->importSemaphore(nullptr, fd, 0, nullptr, type, false);
if (result == false) {
return nullptr;
}
return externalSemaphore;
}
std::unique_ptr<ExternalSemaphoreLinux> ExternalSemaphoreLinux::create(OSInterface *osInterface) {
auto externalSemaphoreLinux = std::make_unique<ExternalSemaphoreLinux>();
externalSemaphoreLinux->osInterface = osInterface;
externalSemaphoreLinux->state = SemaphoreState::Initial;
return externalSemaphoreLinux;
}
bool ExternalSemaphoreLinux::importSemaphore(void *extHandle, int fd, uint32_t flags, const char *name, Type type, bool isNative) {
switch (type) {
case ExternalSemaphore::OpaqueFd:
case ExternalSemaphore::TimelineSemaphoreFd:
break;
default:
DEBUG_BREAK_IF(true);
return false;
}
auto drm = this->osInterface->getDriverModel()->as<Drm>();
struct SyncObjHandle args = {};
args.fd = fd;
args.handle = 0;
auto ioctlHelper = drm->getIoctlHelper();
int ret = ioctlHelper->ioctl(DrmIoctl::syncObjFdToHandle, &args);
if (ret != 0) {
return false;
}
if (fd > 0) {
SysCalls::close(fd);
}
this->syncHandle = args.handle;
this->type = type;
return true;
}
bool ExternalSemaphoreLinux::enqueueWait(uint64_t *fenceValue) {
auto drm = this->osInterface->getDriverModel()->as<Drm>();
auto ioctlHelper = drm->getIoctlHelper();
if (this->type == ExternalSemaphore::TimelineSemaphoreFd) {
struct SyncObjTimelineWait args = {};
args.handles = reinterpret_cast<uintptr_t>(&this->syncHandle);
args.points = reinterpret_cast<uintptr_t>(fenceValue);
args.timeoutNs = 0;
args.countHandles = 1u;
args.flags = 0;
int ret = ioctlHelper->ioctl(DrmIoctl::syncObjTimelineWait, &args);
if (ret != 0) {
return false;
}
} else {
struct SyncObjWait args = {};
args.handles = reinterpret_cast<uintptr_t>(&this->syncHandle);
args.timeoutNs = 0;
args.countHandles = 1u;
args.flags = 0;
int ret = ioctlHelper->ioctl(DrmIoctl::syncObjWait, &args);
if (ret != 0) {
return false;
}
}
this->state = SemaphoreState::Signaled;
return true;
}
bool ExternalSemaphoreLinux::enqueueSignal(uint64_t *fenceValue) {
auto drm = this->osInterface->getDriverModel()->as<Drm>();
auto ioctlHelper = drm->getIoctlHelper();
if (this->type == ExternalSemaphore::TimelineSemaphoreFd) {
struct SyncObjTimelineArray args = {};
args.handles = reinterpret_cast<uintptr_t>(&this->syncHandle);
args.points = reinterpret_cast<uintptr_t>(fenceValue);
args.countHandles = 1u;
int ret = ioctlHelper->ioctl(DrmIoctl::syncObjTimelineSignal, &args);
if (ret != 0) {
return false;
}
} else {
struct SyncObjArray args = {};
args.handles = reinterpret_cast<uintptr_t>(&this->syncHandle);
args.countHandles = 1u;
int ret = ioctlHelper->ioctl(DrmIoctl::syncObjSignal, &args);
if (ret != 0) {
return false;
}
}
return true;
}
ExternalSemaphoreLinux::~ExternalSemaphoreLinux() {
// Safety check: only destroy if we have a valid handle and osInterface
if (syncHandle == 0 || osInterface == nullptr) {
return;
}
auto drm = osInterface->getDriverModel()->as<Drm>();
auto ioctlHelper = drm->getIoctlHelper();
SyncObjDestroy args = {};
args.handle = syncHandle;
// Ignore return value - destructor should not throw
ioctlHelper->ioctl(DrmIoctl::syncObjDestroy, &args);
syncHandle = 0;
}
} // namespace NEO
|