diff options
Diffstat (limited to 'src/syncobject.cpp')
| -rw-r--r-- | src/syncobject.cpp | 487 |
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; -} |
