summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/syncobject.cpp487
1 files changed, 197 insertions, 290 deletions
diff --git a/src/syncobject.cpp b/src/syncobject.cpp
index 6614a9d..f2d3bbc 100644
--- a/src/syncobject.cpp
+++ b/src/syncobject.cpp
@@ -5,20 +5,20 @@
#include "drm++/ioctl.hpp"
#include <cstddef>
-#include <functional>
#include <optional>
+#include <span>
#include <stdexcept>
#include <vector>
-#include <unistd.h>
#include <drm.h>
+#include <unistd.h>
using namespace drm;
using namespace drm::syncobj;
-/* Binary Sync Objects */
+/* Base sync object class */
-SyncObject::SyncObject(int fd, bool signaled) : m_fd(fd) {
+SyncObjectBase::SyncObjectBase(int fd, bool signaled) : m_fd(fd) {
drm_syncobj_create args{
.flags = signaled ? DRM_SYNCOBJ_CREATE_SIGNALED : 0U
};
@@ -27,7 +27,7 @@ SyncObject::SyncObject(int fd, bool signaled) : m_fd(fd) {
this->m_handle = args.handle;
}
-SyncObject::SyncObject(int fd, int syncobj_fd, bool close) : m_fd(fd) {
+SyncObjectBase::SyncObjectBase(int fd, int syncobj_fd, bool close) : m_fd(fd) {
try {
drm_syncobj_handle args{
.fd = syncobj_fd
@@ -48,7 +48,7 @@ SyncObject::SyncObject(int fd, int syncobj_fd, bool close) : m_fd(fd) {
}
}
-int SyncObject::exportFd() const {
+int SyncObjectBase::exportFd() const {
drm_syncobj_handle args{
.handle = this->m_handle,
};
@@ -57,305 +57,241 @@ int SyncObject::exportFd() const {
return args.fd;
}
-void SyncObject::importSyncFile(int syncfile_fd, bool close) const {
+void SyncObjectBase::destruct() noexcept {
+ if (this->m_fd < 0) {
+ return;
+ }
+
+ drm_syncobj_destroy args{
+ .handle = this->m_handle
+ };
try {
- drm_syncobj_handle args{
- .handle = this->m_handle,
- .flags = DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE,
- .fd = syncfile_fd
- };
- ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, args);
- } catch (...) {
+ ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_DESTROY, args);
+ } catch(...) {
+ (void) 0; // not much we can do about the leak
+ }
+
+ this->m_fd = -1;
+}
+
+/* Importing/exporting sync fiels */
+
+namespace {
+ void importSyncFile(int fd, u32 syncobj, int syncfile_fd, u64 point, bool close) {
+ try {
+ drm_syncobj_handle args{
+ .handle = syncobj,
+ .flags = DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE
+ | (point != 0 ? DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_TIMELINE : 0U),
+ .fd = syncfile_fd,
+ .point = point
+ };
+ ioctl::perform(fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, args);
+ } catch (...) {
+ if (close) {
+ ::close(syncfile_fd);
+ }
+
+ throw;
+ }
+
if (close) {
::close(syncfile_fd);
}
-
- throw;
}
+ int exportSyncFile(int fd, u32 syncobj, u64 point) {
+ drm_syncobj_handle args{
+ .handle = syncobj,
+ .flags = DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE
+ | (point != 0 ? DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_TIMELINE : 0U),
+ .point = point
+ };
+ ioctl::perform(fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, args);
- if (close) {
- ::close(syncfile_fd);
+ return args.fd;
}
}
+void SyncObject::importSyncFile(int syncfile_fd, bool close) const {
+ ::importSyncFile(this->m_fd, this->m_handle, syncfile_fd, 0, close);
+}
int SyncObject::exportSyncFile() const {
- drm_syncobj_handle args{
- .handle = this->m_handle,
- .flags = DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE
- };
- ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, args);
+ return ::exportSyncFile(this->m_fd, this->m_handle, 0);
+}
+void TimelineSyncObject::importSyncFile(int syncfile_fd, u64 point, bool close) const {
+ ::importSyncFile(this->m_fd, this->m_handle, syncfile_fd, point, close);
+}
+int TimelineSyncObject::exportSyncFile(u64 point) const {
+ return ::exportSyncFile(this->m_fd, this->m_handle, point);
+}
- return args.fd;
+/* Transfer operations */
+
+namespace {
+ void transfer(int fd, u32 src, u32 dst, u64 srcPoint, u64 dstPoint) {
+ drm_syncobj_transfer args{
+ .src_handle = src,
+ .dst_handle = dst,
+ .src_point = srcPoint,
+ .dst_point = dstPoint
+ };
+ ioctl::perform(fd, DRM_IOCTL_SYNCOBJ_TRANSFER, args);
+ }
}
void SyncObject::transfer(const SyncObject& dest) const {
- drm_syncobj_transfer args{
- .src_handle = this->m_handle,
- .dst_handle = dest.m_handle
- };
- ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_TRANSFER, args);
+ ::transfer(this->m_fd, this->m_handle, dest.m_handle, 0, 0);
}
-
void SyncObject::transfer(const TimelineSyncObject& dest, u64 destPoint) const {
- drm_syncobj_transfer args{
- .src_handle = this->m_handle,
- .dst_handle = dest.handle(),
- .dst_point = destPoint
- };
- ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_TRANSFER, args);
+ ::transfer(this->m_fd, this->m_handle, dest.m_handle, 0, destPoint);
}
-
-void SyncObject::signal() const {
- drm_syncobj_array args{
- .handles = reinterpret_cast<u64>(&this->m_handle),
- .count_handles = 1
- };
- ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_SIGNAL, args);
+void TimelineSyncObject::transfer(const TimelineSyncObject& dest,
+ u64 srcPoint, u64 destPoint) const {
+ ::transfer(this->m_fd, this->m_handle, dest.m_handle, srcPoint, destPoint);
}
-
-void SyncObject::reset() const {
- drm_syncobj_array args{
- .handles = reinterpret_cast<u64>(&this->m_handle),
- .count_handles = 1
- };
- ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_RESET, args);
+void TimelineSyncObject::transfer(const SyncObject& dest, u64 srcPoint) const {
+ ::transfer(this->m_fd, this->m_handle, dest.m_handle, srcPoint, 0);
}
-void SyncObject::wait(
- s64 timeout,
- WaitMode waitMode,
- std::optional<u64> deadlineHint
-) const {
- drm_syncobj_wait args{
- .handles = reinterpret_cast<u64>(&this->m_handle),
- .timeout_nsec = timeout,
- .count_handles = 1,
- .flags = (waitMode == WaitMode::WaitEmpty ? DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT : 0U) |
- (waitMode == WaitMode::WaitAvailable ? DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE : 0U) |
- (deadlineHint.has_value() ? DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE : 0U),
- .deadline_nsec = deadlineHint.value_or(0)
- };
- ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_WAIT, args);
+/* Registering eventfds */
+
+namespace {
+ void registerEventFd(int fd, u32 syncobj, int eventfd_fd, u64 point, bool waitAvailable) {
+ drm_syncobj_eventfd args{
+ .handle = syncobj,
+ .flags = waitAvailable ? DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE : 0U,
+ .point = point,
+ .fd = eventfd_fd
+ };
+ ioctl::perform(fd, DRM_IOCTL_SYNCOBJ_EVENTFD, args);
+ }
}
void SyncObject::registerEventFd(int eventfd_fd, bool waitAvailable) const {
- drm_syncobj_eventfd args{
- .handle = this->m_handle,
- .flags = waitAvailable ? DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE : 0U,
- .fd = eventfd_fd
- };
- ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_EVENTFD, args);
+ ::registerEventFd(this->m_fd, this->m_handle, eventfd_fd, 0, waitAvailable);
}
-
-void SyncObject::destruct() noexcept {
- if (this->m_fd < 0) {
- return;
- }
-
- drm_syncobj_destroy args{
- .handle = this->m_handle
- };
- try {
- ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_DESTROY, args);
- } catch(...) {
- (void) 0; // not much we can do about the leak
- }
-
- this->m_fd = -1;
+void TimelineSyncObject::registerEventFd(int eventfd_fd, u64 point, bool waitAvailable) const {
+ ::registerEventFd(this->m_fd, this->m_handle, eventfd_fd, point, waitAvailable);
}
-/* Timeline Sync Objects */
+/* Binary signal & reset operations */
-TimelineSyncObject::TimelineSyncObject(int fd) : m_fd(fd) {
- drm_syncobj_create args{
- .flags = 0U
- };
- ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_CREATE, args);
-
- this->m_handle = args.handle;
-}
-
-TimelineSyncObject::TimelineSyncObject(int fd, int syncobj_fd, bool close) : m_fd(fd) {
- try {
- drm_syncobj_handle args{
- .fd = syncobj_fd
+namespace {
+ template<unsigned long OP>
+ void signal(int fd, std::span<const u32> syncobjs) {
+ drm_syncobj_array args{
+ .handles = reinterpret_cast<u64>(syncobjs.data()),
+ .count_handles = static_cast<u32>(syncobjs.size())
};
- ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, args);
+ ioctl::perform(fd, OP, args);
+ }
+ template<unsigned long OP>
+ void signalBulk(const std::vector<ref<const SyncObject>>& syncobjs) {
+ if (syncobjs.empty()) {
+ return;
+ }
- this->m_handle = args.handle;
- } catch (...) {
- if (close) {
- ::close(syncobj_fd);
+ std::vector<u32> handles(syncobjs.size());
+ for (size_t i = 0; i < syncobjs.size(); ++i) {
+ handles.at(i) = syncobjs.at(i).get().handle();
}
- throw;
- }
-
- if (close) {
- ::close(syncobj_fd);
+ ::signal<OP>(syncobjs.front().get().fd(), handles);
}
}
-int TimelineSyncObject::exportFd() const {
- drm_syncobj_handle args{
- .handle = this->m_handle,
- };
- ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, args);
-
- return args.fd;
+void SyncObject::signal() const {
+ ::signal<DRM_IOCTL_SYNCOBJ_SIGNAL>(this->m_fd, std::span(&this->m_handle, 1));
+}
+void SyncObject::reset() const {
+ ::signal<DRM_IOCTL_SYNCOBJ_RESET>(this->m_fd, std::span(&this->m_handle, 1));
+}
+void syncobj::signal(const std::vector<ref<const SyncObject>>& objs) {
+ ::signalBulk<DRM_IOCTL_SYNCOBJ_SIGNAL>(objs);
+}
+void syncobj::reset(const std::vector<ref<const SyncObject>>& objs) {
+ ::signalBulk<DRM_IOCTL_SYNCOBJ_RESET>(objs);
}
-void TimelineSyncObject::importSyncFile(int syncfile_fd, u64 point, bool close) const {
- try {
- drm_syncobj_handle args{
- .handle = this->m_handle,
- .flags = DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE
- | DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_TIMELINE,
- .fd = syncfile_fd,
- .point = point
+/* Timeline signal & query operations */
+
+namespace {
+ template<unsigned long OP>
+ void signal(int fd, std::span<const u32> syncobjs, std::span<u64> points, bool lastSubmitted) {
+ drm_syncobj_timeline_array args{
+ .handles = reinterpret_cast<u64>(syncobjs.data()),
+ .points = reinterpret_cast<u64>(points.data()),
+ .count_handles = static_cast<u32>(syncobjs.size()),
+ .flags = lastSubmitted ? DRM_SYNCOBJ_QUERY_FLAGS_LAST_SUBMITTED : 0U
};
- ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, args);
- } catch (...) {
- if (close) {
- ::close(syncfile_fd);
+ ioctl::perform(fd, OP, args);
+ }
+ template<unsigned long OP>
+ void signalBulk(const std::vector<ref<const TimelineSyncObject>>& syncobjs,
+ std::span<u64> points, bool lastSubmitted) {
+ if (syncobjs.empty()) {
+ return;
}
- throw;
- }
+ if (syncobjs.size() != points.size()) {
+ throw std::invalid_argument("syncobjs and points must have the same size");
+ }
- if (close) {
- ::close(syncfile_fd);
+ std::vector<u32> handles(syncobjs.size());
+ for (size_t i = 0; i < syncobjs.size(); ++i) {
+ handles.at(i) = syncobjs.at(i).get().handle();
+ }
+
+ ::signal<OP>(syncobjs.front().get().fd(), handles, points, lastSubmitted);
}
}
-int TimelineSyncObject::exportSyncFile(u64 point) const {
- drm_syncobj_handle args{
- .handle = this->m_handle,
- .flags = DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE
- | DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_TIMELINE,
- .point = point
- };
- ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, args);
-
- return args.fd;
+void TimelineSyncObject::signal(u64 point) const {
+ ::signal<DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL>(this->m_fd,
+ std::span(&this->m_handle, 1), std::span(&point, 1), false);
}
-
-void TimelineSyncObject::transfer(
- const TimelineSyncObject& dest,
- u64 srcPoint,
- u64 destPoint
-) const {
- drm_syncobj_transfer args{
- .src_handle = this->m_handle,
- .dst_handle = dest.m_handle,
- .src_point = srcPoint,
- .dst_point = destPoint
- };
- ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_TRANSFER, args);
+u64 TimelineSyncObject::query(bool lastSubmitted) const {
+ u64 point{};
+ ::signal<DRM_IOCTL_SYNCOBJ_QUERY>(this->m_fd,
+ std::span(&this->m_handle, 1), std::span(&point, 1), lastSubmitted);
+ return point;
}
-
-void TimelineSyncObject::transfer(const SyncObject& dest, u64 srcPoint) const {
- drm_syncobj_transfer args{
- .src_handle = this->m_handle,
- .dst_handle = dest.handle(),
- .src_point = srcPoint
- };
- ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_TRANSFER, args);
+void syncobj::signal(
+ const std::vector<ref<const TimelineSyncObject>>& objs,
+ std::vector<u64> points
+) {
+ ::signalBulk<DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL>(objs, points, false);
}
-
-void TimelineSyncObject::signal(u64 point) const {
- drm_syncobj_timeline_array args{
- .handles = reinterpret_cast<u64>(&this->m_handle),
- .points = reinterpret_cast<u64>(&point),
- .count_handles = 1
- };
- ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL, args);
+std::vector<u64> syncobj::query(
+ const std::vector<ref<const TimelineSyncObject>>& objs,
+ bool lastSubmitted
+) {
+ std::vector<u64> points(objs.size());
+ ::signalBulk<DRM_IOCTL_SYNCOBJ_QUERY>(objs, points, lastSubmitted);
+ return points;
}
-void TimelineSyncObject::wait(
+/* Wait operations */
+
+void SyncObject::wait(
s64 timeout,
- u64 point,
- bool waitAvailable,
+ WaitMode waitMode,
std::optional<u64> deadlineHint
) const {
- drm_syncobj_timeline_wait args{
+ drm_syncobj_wait args{
.handles = reinterpret_cast<u64>(&this->m_handle),
- .points = reinterpret_cast<u64>(&point),
.timeout_nsec = timeout,
.count_handles = 1,
- .flags = (waitAvailable ? DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE : 0U) |
+ .flags = (waitMode == WaitMode::WaitEmpty ? DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT : 0U) |
+ (waitMode == WaitMode::WaitAvailable ? DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE : 0U) |
(deadlineHint.has_value() ? DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE : 0U),
.deadline_nsec = deadlineHint.value_or(0)
};
ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_WAIT, args);
}
-u64 TimelineSyncObject::query(bool lastSubmitted) const {
- u64 point{};
-
- drm_syncobj_timeline_array args{
- .handles = reinterpret_cast<u64>(&this->m_handle),
- .points = reinterpret_cast<u64>(&point),
- .count_handles = 1,
- .flags = lastSubmitted ? DRM_SYNCOBJ_QUERY_FLAGS_LAST_SUBMITTED : 0U
- };
- ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_QUERY, args);
-
- return point;
-}
-
-void TimelineSyncObject::registerEventFd(
- int eventfd_fd,
- u64 point,
- bool waitAvailable
-) const {
- drm_syncobj_eventfd args{
- .handle = this->m_handle,
- .flags = waitAvailable ? DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE : 0U,
- .point = point,
- .fd = eventfd_fd
- };
- ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_EVENTFD, args);
-}
-
-/* Bulk Operations */
-
-void syncobj::signal(const std::vector<std::reference_wrapper<SyncObject>>& objs) {
- if (objs.empty()) {
- return;
- }
-
- std::vector<u32> handles(objs.size());
- for (size_t i = 0; i < objs.size(); ++i) {
- handles.at(i) = objs.at(i).get().handle();
- }
-
- drm_syncobj_array args{
- .handles = reinterpret_cast<u64>(handles.data()),
- .count_handles = static_cast<u32>(handles.size())
- };
- ioctl::perform(objs.front().get().fd(), DRM_IOCTL_SYNCOBJ_SIGNAL, args);
-}
-
-void syncobj::reset(const std::vector<std::reference_wrapper<SyncObject>>& objs) {
- if (objs.empty()) {
- return;
- }
-
- std::vector<u32> handles(objs.size());
- for (size_t i = 0; i < objs.size(); ++i) {
- handles.at(i) = objs.at(i).get().handle();
- }
-
- drm_syncobj_array args{
- .handles = reinterpret_cast<u64>(handles.data()),
- .count_handles = static_cast<u32>(handles.size())
- };
- ioctl::perform(objs.front().get().fd(), DRM_IOCTL_SYNCOBJ_RESET, args);
-}
-
-SyncObject& syncobj::wait(
- const std::vector<std::reference_wrapper<SyncObject>>& objs,
+const SyncObject& syncobj::wait(
+ const std::vector<ref<const SyncObject>>& objs,
s64 timeout,
bool waitAll,
WaitMode waitMode,
@@ -385,29 +321,26 @@ SyncObject& syncobj::wait(
return objs.at(args.first_signaled).get();
}
-void syncobj::signal(
- const std::vector<std::reference_wrapper<TimelineSyncObject>>& objs,
- const std::vector<u64>& points
-) {
- if (objs.empty()) {
- return;
- }
-
- std::vector<u32> handles(objs.size());
- for (size_t i = 0; i < objs.size(); ++i) {
- handles.at(i) = objs.at(i).get().handle();
- }
-
- drm_syncobj_timeline_array args{
- .handles = reinterpret_cast<u64>(handles.data()),
- .points = reinterpret_cast<u64>(points.data()),
- .count_handles = static_cast<u32>(handles.size())
+void TimelineSyncObject::wait(
+ s64 timeout,
+ u64 point,
+ bool waitAvailable,
+ std::optional<u64> deadlineHint
+) const {
+ drm_syncobj_timeline_wait args{
+ .handles = reinterpret_cast<u64>(&this->m_handle),
+ .points = reinterpret_cast<u64>(&point),
+ .timeout_nsec = timeout,
+ .count_handles = 1,
+ .flags = (waitAvailable ? DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE : 0U) |
+ (deadlineHint.has_value() ? DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE : 0U),
+ .deadline_nsec = deadlineHint.value_or(0)
};
- ioctl::perform(objs.front().get().fd(), DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL, args);
+ ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_WAIT, args);
}
void syncobj::wait(
- const std::vector<std::reference_wrapper<TimelineSyncObject>>& objs,
+ const std::vector<ref<const TimelineSyncObject>>& objs,
const std::vector<u64>& points,
s64 timeout,
bool waitAll,
@@ -435,29 +368,3 @@ void syncobj::wait(
};
ioctl::perform(objs.front().get().fd(), DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT, args);
}
-
-std::vector<u64> syncobj::query(
- const std::vector<std::reference_wrapper<TimelineSyncObject>>& objs,
- bool lastSubmitted
-) {
- if (objs.empty()) {
- return {};
- }
-
- std::vector<u32> handles(objs.size());
- for (size_t i = 0; i < objs.size(); ++i) {
- handles.at(i) = objs.at(i).get().handle();
- }
-
- std::vector<u64> points(objs.size());
-
- drm_syncobj_timeline_array args{
- .handles = reinterpret_cast<u64>(handles.data()),
- .points = reinterpret_cast<u64>(points.data()),
- .count_handles = static_cast<u32>(handles.size()),
- .flags = lastSubmitted ? DRM_SYNCOBJ_QUERY_FLAGS_LAST_SUBMITTED : 0U
- };
- ioctl::perform(objs.front().get().fd(), DRM_IOCTL_SYNCOBJ_QUERY, args);
-
- return points;
-}