Message ID | 20211128235752.10836-18-laurent.pinchart@ideasonboard.com |
---|---|
State | Superseded |
Headers | show |
Series |
|
Related | show |
Hi Laurent, On Mon, Nov 29, 2021 at 8:58 AM Laurent Pinchart <laurent.pinchart@ideasonboard.com> wrote: > > Now that we have a UniqueFD class, the name FileDescriptor is ambiguous. > Rename it to SharedFD. > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Hirokazu Honda <hiroh@chromium.org> > --- > include/libcamera/base/file.h | 4 +- > include/libcamera/base/meson.build | 2 +- > .../base/{file_descriptor.h => shared_fd.h} | 20 +- > include/libcamera/framebuffer.h | 4 +- > .../libcamera/internal/ipa_data_serializer.h | 40 +-- > include/libcamera/internal/ipc_pipe.h | 8 +- > include/libcamera/ipa/core.mojom | 6 +- > include/libcamera/ipa/raspberrypi.mojom | 2 +- > src/android/camera_device.cpp | 2 +- > src/ipa/raspberrypi/raspberrypi.cpp | 4 +- > src/libcamera/base/file.cpp | 6 +- > src/libcamera/base/file_descriptor.cpp | 266 ------------------ > src/libcamera/base/meson.build | 2 +- > src/libcamera/base/shared_fd.cpp | 262 +++++++++++++++++ > src/libcamera/framebuffer.cpp | 6 +- > src/libcamera/ipa_data_serializer.cpp | 100 +++---- > src/libcamera/ipc_pipe.cpp | 4 +- > .../pipeline/raspberrypi/raspberrypi.cpp | 6 +- > src/libcamera/v4l2_videodevice.cpp | 6 +- > src/v4l2/v4l2_camera.h | 2 +- > test/meson.build | 2 +- > .../ipa_data_serializer_test.cpp | 14 +- > test/{file-descriptor.cpp => shared-fd.cpp} | 46 +-- > .../module_ipa_proxy.cpp.tmpl | 2 +- > .../module_ipa_proxy.h.tmpl | 2 +- > .../libcamera_templates/proxy_functions.tmpl | 2 +- > .../libcamera_templates/serializer.tmpl | 22 +- > .../generators/mojom_libcamera_generator.py | 6 +- > 28 files changed, 422 insertions(+), 426 deletions(-) > rename include/libcamera/base/{file_descriptor.h => shared_fd.h} (55%) > delete mode 100644 src/libcamera/base/file_descriptor.cpp > create mode 100644 src/libcamera/base/shared_fd.cpp > rename test/{file-descriptor.cpp => shared-fd.cpp} (80%) > > diff --git a/include/libcamera/base/file.h b/include/libcamera/base/file.h > index 47769da7abc2..691b52d6ab2d 100644 > --- a/include/libcamera/base/file.h > +++ b/include/libcamera/base/file.h > @@ -21,7 +21,7 @@ > > namespace libcamera { > > -class FileDescriptor; > +class SharedFD; > > class File > { > @@ -69,7 +69,7 @@ public: > bool unmap(uint8_t *addr); > > static bool exists(const std::string &name); > - static ino_t inode(const FileDescriptor &fd); > + static ino_t inode(const SharedFD &fd); > > private: > LIBCAMERA_DISABLE_COPY(File) > diff --git a/include/libcamera/base/meson.build b/include/libcamera/base/meson.build > index cca374a769cc..112420dab225 100644 > --- a/include/libcamera/base/meson.build > +++ b/include/libcamera/base/meson.build > @@ -11,13 +11,13 @@ libcamera_base_headers = files([ > 'event_dispatcher_poll.h', > 'event_notifier.h', > 'file.h', > - 'file_descriptor.h', > 'flags.h', > 'log.h', > 'message.h', > 'object.h', > 'private.h', > 'semaphore.h', > + 'shared_fd.h', > 'signal.h', > 'span.h', > 'thread.h', > diff --git a/include/libcamera/base/file_descriptor.h b/include/libcamera/base/shared_fd.h > similarity index 55% > rename from include/libcamera/base/file_descriptor.h > rename to include/libcamera/base/shared_fd.h > index 12a43f95d414..a786885ceb32 100644 > --- a/include/libcamera/base/file_descriptor.h > +++ b/include/libcamera/base/shared_fd.h > @@ -2,7 +2,7 @@ > /* > * Copyright (C) 2019, Google Inc. > * > - * file_descriptor.h - File descriptor wrapper > + * shared_fd.h - File descriptor wrapper with shared ownership > */ > > #pragma once > @@ -13,18 +13,18 @@ namespace libcamera { > > class UniqueFD; > > -class FileDescriptor final > +class SharedFD final > { > public: > - explicit FileDescriptor(const int &fd = -1); > - explicit FileDescriptor(int &&fd); > - explicit FileDescriptor(UniqueFD fd); > - FileDescriptor(const FileDescriptor &other); > - FileDescriptor(FileDescriptor &&other); > - ~FileDescriptor(); > + explicit SharedFD(const int &fd = -1); > + explicit SharedFD(int &&fd); > + explicit SharedFD(UniqueFD fd); > + SharedFD(const SharedFD &other); > + SharedFD(SharedFD &&other); > + ~SharedFD(); > > - FileDescriptor &operator=(const FileDescriptor &other); > - FileDescriptor &operator=(FileDescriptor &&other); > + SharedFD &operator=(const SharedFD &other); > + SharedFD &operator=(SharedFD &&other); > > bool isValid() const { return fd_ != nullptr; } > int fd() const { return fd_ ? fd_->fd() : -1; } > diff --git a/include/libcamera/framebuffer.h b/include/libcamera/framebuffer.h > index 2fbea9c5be16..357bbe189551 100644 > --- a/include/libcamera/framebuffer.h > +++ b/include/libcamera/framebuffer.h > @@ -13,7 +13,7 @@ > #include <vector> > > #include <libcamera/base/class.h> > -#include <libcamera/base/file_descriptor.h> > +#include <libcamera/base/shared_fd.h> > #include <libcamera/base/span.h> > > namespace libcamera { > @@ -51,7 +51,7 @@ class FrameBuffer final : public Extensible > public: > struct Plane { > static constexpr unsigned int kInvalidOffset = std::numeric_limits<unsigned int>::max(); > - FileDescriptor fd; > + SharedFD fd; > unsigned int offset = kInvalidOffset; > unsigned int length; > }; > diff --git a/include/libcamera/internal/ipa_data_serializer.h b/include/libcamera/internal/ipa_data_serializer.h > index c2f602d5b7de..a87449c9be48 100644 > --- a/include/libcamera/internal/ipa_data_serializer.h > +++ b/include/libcamera/internal/ipa_data_serializer.h > @@ -66,7 +66,7 @@ template<typename T> > class IPADataSerializer > { > public: > - static std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > + static std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > serialize(const T &data, ControlSerializer *cs = nullptr); > > static T deserialize(const std::vector<uint8_t> &data, > @@ -76,12 +76,12 @@ public: > ControlSerializer *cs = nullptr); > > static T deserialize(const std::vector<uint8_t> &data, > - const std::vector<FileDescriptor> &fds, > + const std::vector<SharedFD> &fds, > ControlSerializer *cs = nullptr); > static T deserialize(std::vector<uint8_t>::const_iterator dataBegin, > std::vector<uint8_t>::const_iterator dataEnd, > - std::vector<FileDescriptor>::const_iterator fdsBegin, > - std::vector<FileDescriptor>::const_iterator fdsEnd, > + std::vector<SharedFD>::const_iterator fdsBegin, > + std::vector<SharedFD>::const_iterator fdsEnd, > ControlSerializer *cs = nullptr); > }; > > @@ -104,11 +104,11 @@ template<typename V> > class IPADataSerializer<std::vector<V>> > { > public: > - static std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > + static std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > serialize(const std::vector<V> &data, ControlSerializer *cs = nullptr) > { > std::vector<uint8_t> dataVec; > - std::vector<FileDescriptor> fdsVec; > + std::vector<SharedFD> fdsVec; > > /* Serialize the length. */ > uint32_t vecLen = data.size(); > @@ -117,7 +117,7 @@ public: > /* Serialize the members. */ > for (auto const &it : data) { > std::vector<uint8_t> dvec; > - std::vector<FileDescriptor> fvec; > + std::vector<SharedFD> fvec; > > std::tie(dvec, fvec) = > IPADataSerializer<V>::serialize(it, cs); > @@ -141,11 +141,11 @@ public: > std::vector<uint8_t>::const_iterator dataEnd, > ControlSerializer *cs = nullptr) > { > - std::vector<FileDescriptor> fds; > + std::vector<SharedFD> fds; > return deserialize(dataBegin, dataEnd, fds.cbegin(), fds.end(), cs); > } > > - static std::vector<V> deserialize(std::vector<uint8_t> &data, std::vector<FileDescriptor> &fds, > + static std::vector<V> deserialize(std::vector<uint8_t> &data, std::vector<SharedFD> &fds, > ControlSerializer *cs = nullptr) > { > return deserialize(data.cbegin(), data.end(), fds.cbegin(), fds.end(), cs); > @@ -153,15 +153,15 @@ public: > > static std::vector<V> deserialize(std::vector<uint8_t>::const_iterator dataBegin, > std::vector<uint8_t>::const_iterator dataEnd, > - std::vector<FileDescriptor>::const_iterator fdsBegin, > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, > + std::vector<SharedFD>::const_iterator fdsBegin, > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, > ControlSerializer *cs = nullptr) > { > uint32_t vecLen = readPOD<uint32_t>(dataBegin, 0, dataEnd); > std::vector<V> ret(vecLen); > > std::vector<uint8_t>::const_iterator dataIter = dataBegin + 4; > - std::vector<FileDescriptor>::const_iterator fdIter = fdsBegin; > + std::vector<SharedFD>::const_iterator fdIter = fdsBegin; > for (uint32_t i = 0; i < vecLen; i++) { > uint32_t sizeofData = readPOD<uint32_t>(dataIter, 0, dataEnd); > uint32_t sizeofFds = readPOD<uint32_t>(dataIter, 4, dataEnd); > @@ -201,11 +201,11 @@ template<typename K, typename V> > class IPADataSerializer<std::map<K, V>> > { > public: > - static std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > + static std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > serialize(const std::map<K, V> &data, ControlSerializer *cs = nullptr) > { > std::vector<uint8_t> dataVec; > - std::vector<FileDescriptor> fdsVec; > + std::vector<SharedFD> fdsVec; > > /* Serialize the length. */ > uint32_t mapLen = data.size(); > @@ -214,7 +214,7 @@ public: > /* Serialize the members. */ > for (auto const &it : data) { > std::vector<uint8_t> dvec; > - std::vector<FileDescriptor> fvec; > + std::vector<SharedFD> fvec; > > std::tie(dvec, fvec) = > IPADataSerializer<K>::serialize(it.first, cs); > @@ -247,11 +247,11 @@ public: > std::vector<uint8_t>::const_iterator dataEnd, > ControlSerializer *cs = nullptr) > { > - std::vector<FileDescriptor> fds; > + std::vector<SharedFD> fds; > return deserialize(dataBegin, dataEnd, fds.cbegin(), fds.end(), cs); > } > > - static std::map<K, V> deserialize(std::vector<uint8_t> &data, std::vector<FileDescriptor> &fds, > + static std::map<K, V> deserialize(std::vector<uint8_t> &data, std::vector<SharedFD> &fds, > ControlSerializer *cs = nullptr) > { > return deserialize(data.cbegin(), data.end(), fds.cbegin(), fds.end(), cs); > @@ -259,8 +259,8 @@ public: > > static std::map<K, V> deserialize(std::vector<uint8_t>::const_iterator dataBegin, > std::vector<uint8_t>::const_iterator dataEnd, > - std::vector<FileDescriptor>::const_iterator fdsBegin, > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, > + std::vector<SharedFD>::const_iterator fdsBegin, > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, > ControlSerializer *cs = nullptr) > { > std::map<K, V> ret; > @@ -268,7 +268,7 @@ public: > uint32_t mapLen = readPOD<uint32_t>(dataBegin, 0, dataEnd); > > std::vector<uint8_t>::const_iterator dataIter = dataBegin + 4; > - std::vector<FileDescriptor>::const_iterator fdIter = fdsBegin; > + std::vector<SharedFD>::const_iterator fdIter = fdsBegin; > for (uint32_t i = 0; i < mapLen; i++) { > uint32_t sizeofData = readPOD<uint32_t>(dataIter, 0, dataEnd); > uint32_t sizeofFds = readPOD<uint32_t>(dataIter, 4, dataEnd); > diff --git a/include/libcamera/internal/ipc_pipe.h b/include/libcamera/internal/ipc_pipe.h > index 986f8d886fa6..ab5dd67c3813 100644 > --- a/include/libcamera/internal/ipc_pipe.h > +++ b/include/libcamera/internal/ipc_pipe.h > @@ -9,7 +9,7 @@ > > #include <vector> > > -#include <libcamera/base/file_descriptor.h> > +#include <libcamera/base/shared_fd.h> > #include <libcamera/base/signal.h> > > #include "libcamera/internal/ipc_unixsocket.h" > @@ -33,17 +33,17 @@ public: > > Header &header() { return header_; } > std::vector<uint8_t> &data() { return data_; } > - std::vector<FileDescriptor> &fds() { return fds_; } > + std::vector<SharedFD> &fds() { return fds_; } > > const Header &header() const { return header_; } > const std::vector<uint8_t> &data() const { return data_; } > - const std::vector<FileDescriptor> &fds() const { return fds_; } > + const std::vector<SharedFD> &fds() const { return fds_; } > > private: > Header header_; > > std::vector<uint8_t> data_; > - std::vector<FileDescriptor> fds_; > + std::vector<SharedFD> fds_; > }; > > class IPCPipe > diff --git a/include/libcamera/ipa/core.mojom b/include/libcamera/ipa/core.mojom > index f7eff0c7ab8c..74f3339e56f2 100644 > --- a/include/libcamera/ipa/core.mojom > +++ b/include/libcamera/ipa/core.mojom > @@ -32,7 +32,7 @@ module libcamera; > * - This attribute instructs the build system that a (de)serializer is > * available for the type and there's no need to generate one > * - hasFd - struct fields or empty structs only > - * - Designate that this field or empty struct contains a FileDescriptor > + * - Designate that this field or empty struct contains a SharedFD > * > * Rules: > * - If the type is defined in a libcamera C++ header *and* a (de)serializer is > @@ -60,7 +60,7 @@ module libcamera; > * - In mojom, reference the type as FrameBuffer.Plane and only as map/array > * member > * - [skipHeader] and [skipSerdes] only work here in core.mojom > - * - If a field in a struct has a FileDescriptor, but is not explicitly > + * - If a field in a struct has a SharedFD, but is not explicitly > * defined so in mojom, then the field must be marked with the [hasFd] > * attribute > * > @@ -71,7 +71,7 @@ module libcamera; > */ > [skipSerdes, skipHeader] struct ControlInfoMap {}; > [skipSerdes, skipHeader] struct ControlList {}; > -[skipSerdes, skipHeader] struct FileDescriptor {}; > +[skipSerdes, skipHeader] struct SharedFD {}; > > [skipHeader] struct Point { > int32 x; > diff --git a/include/libcamera/ipa/raspberrypi.mojom b/include/libcamera/ipa/raspberrypi.mojom > index e453d46cb14f..acd3cafe6c91 100644 > --- a/include/libcamera/ipa/raspberrypi.mojom > +++ b/include/libcamera/ipa/raspberrypi.mojom > @@ -35,7 +35,7 @@ struct ISPConfig { > > struct IPAConfig { > uint32 transform; > - libcamera.FileDescriptor lsTableHandle; > + libcamera.SharedFD lsTableHandle; > }; > > struct StartConfig { > diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp > index f2e0bdbdbbf6..1938b10509fa 100644 > --- a/src/android/camera_device.cpp > +++ b/src/android/camera_device.cpp > @@ -725,7 +725,7 @@ CameraDevice::createFrameBuffer(const buffer_handle_t camera3buffer, > > std::vector<FrameBuffer::Plane> planes(buf.numPlanes()); > for (size_t i = 0; i < buf.numPlanes(); ++i) { > - FileDescriptor fd{ camera3buffer->data[i] }; > + SharedFD fd{ camera3buffer->data[i] }; > if (!fd.isValid()) { > LOG(HAL, Fatal) << "No valid fd"; > return nullptr; > diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp > index c6aec09046f7..aaf629eeb3fc 100644 > --- a/src/ipa/raspberrypi/raspberrypi.cpp > +++ b/src/ipa/raspberrypi/raspberrypi.cpp > @@ -15,8 +15,8 @@ > > #include <linux/bcm2835-isp.h> > > -#include <libcamera/base/file_descriptor.h> > #include <libcamera/base/log.h> > +#include <libcamera/base/shared_fd.h> > #include <libcamera/base/span.h> > > #include <libcamera/control_ids.h> > @@ -164,7 +164,7 @@ private: > bool processPending_; > > /* LS table allocation passed in from the pipeline handler. */ > - FileDescriptor lsTableHandle_; > + SharedFD lsTableHandle_; > void *lsTable_; > > /* Distinguish the first camera start from others. */ > diff --git a/src/libcamera/base/file.cpp b/src/libcamera/base/file.cpp > index 66c73c406198..3ca9839bb989 100644 > --- a/src/libcamera/base/file.cpp > +++ b/src/libcamera/base/file.cpp > @@ -14,8 +14,8 @@ > #include <sys/types.h> > #include <unistd.h> > > -#include <libcamera/base/file_descriptor.h> > #include <libcamera/base/log.h> > +#include <libcamera/base/shared_fd.h> > > /** > * \file base/file.h > @@ -473,11 +473,11 @@ bool File::exists(const std::string &name) > } > > /** > - * \brief Retrieve the inode of a FileDescriptor > + * \brief Retrieve the inode of a SharedFD > * > * \return The file descriptor inode on success, or 0 on error > */ > -ino_t File::inode(const FileDescriptor &fd) > +ino_t File::inode(const SharedFD &fd) > { > if (!fd.isValid()) > return 0; > diff --git a/src/libcamera/base/file_descriptor.cpp b/src/libcamera/base/file_descriptor.cpp > deleted file mode 100644 > index a83bf52c31e6..000000000000 > --- a/src/libcamera/base/file_descriptor.cpp > +++ /dev/null > @@ -1,266 +0,0 @@ > -/* SPDX-License-Identifier: LGPL-2.1-or-later */ > -/* > - * Copyright (C) 2019, Google Inc. > - * > - * file_descriptor.cpp - File descriptor wrapper > - */ > - > -#include <libcamera/base/file_descriptor.h> > - > -#include <string.h> > -#include <sys/types.h> > -#include <unistd.h> > -#include <utility> > - > -#include <libcamera/base/log.h> > -#include <libcamera/base/unique_fd.h> > - > -/** > - * \file base/file_descriptor.h > - * \brief File descriptor wrapper > - */ > - > -namespace libcamera { > - > -LOG_DEFINE_CATEGORY(FileDescriptor) > - > -/** > - * \class FileDescriptor > - * \brief RAII-style wrapper for file descriptors > - * > - * The FileDescriptor class provides RAII-style lifetime management of file > - * descriptors with an efficient mechanism for ownership sharing. At its core, > - * an internal Descriptor object wraps a file descriptor (expressed as a signed > - * integer) with an RAII-style interface. The Descriptor is then implicitly > - * shared with all FileDescriptor instances constructed as copies. > - * > - * When constructed from a numerical file descriptor, the FileDescriptor > - * instance either duplicates or takes over the file descriptor: > - * > - * - The FileDescriptor(const int &) constructor duplicates the numerical file > - * descriptor and wraps the duplicate in a Descriptor. The caller is > - * responsible for closing the original file descriptor, and the value > - * returned by fd() will be different from the value passed to the > - * constructor. > - * > - * - The FileDescriptor(int &&) constructor takes over the numerical file > - * descriptor and wraps it in a Descriptor. The caller shall not touch the > - * original file descriptor once the function returns, and the value returned > - * by fd() will be identical to the value passed to the constructor. > - * > - * The copy constructor and assignment operator create copies that share the > - * Descriptor, while the move versions of those functions additionally make the > - * other FileDescriptor invalid. When the last FileDescriptor that references a > - * Descriptor is destroyed, the file descriptor is closed. > - * > - * The numerical file descriptor is available through the fd() function. All > - * FileDescriptor instances created as copies of a FileDescriptor will report > - * the same fd() value. Callers can perform operations on the fd(), but shall > - * never close it manually. > - */ > - > -/** > - * \brief Create a FileDescriptor copying a given \a fd > - * \param[in] fd File descriptor > - * > - * Construct a FileDescriptor from a numerical file descriptor by duplicating > - * the \a fd, and take ownership of the copy. The original \a fd is left > - * untouched, and the caller is responsible for closing it when appropriate. > - * The duplicated file descriptor will be closed automatically when all > - * FileDescriptor instances that reference it are destroyed. > - * > - * If the \a fd is negative, the FileDescriptor is constructed as invalid and > - * the fd() function will return -1. > - */ > -FileDescriptor::FileDescriptor(const int &fd) > -{ > - if (fd < 0) > - return; > - > - fd_ = std::make_shared<Descriptor>(fd, true); > - if (fd_->fd() < 0) > - fd_.reset(); > -} > - > -/** > - * \brief Create a FileDescriptor taking ownership of a given \a fd > - * \param[in] fd File descriptor > - * > - * Construct a FileDescriptor from a numerical file descriptor by taking > - * ownership of the \a fd. The original \a fd is set to -1 and shall not be > - * touched by the caller anymore. In particular, the caller shall not close the > - * original \a fd manually. The duplicated file descriptor will be closed > - * automatically when all FileDescriptor instances that reference it are > - * destroyed. > - * > - * If the \a fd is negative, the FileDescriptor is constructed as invalid and > - * the fd() function will return -1. > - */ > -FileDescriptor::FileDescriptor(int &&fd) > -{ > - if (fd < 0) > - return; > - > - fd_ = std::make_shared<Descriptor>(fd, false); > - /* > - * The Descriptor constructor can't have failed here, as it took over > - * the fd without duplicating it. Just set the original fd to -1 to > - * implement move semantics. > - */ > - fd = -1; > -} > - > -/** > - * \brief Create a FileDescriptor taking ownership of a given UniqueFD \a fd > - * \param[in] fd UniqueFD > - * > - * Construct a FileDescriptor from UniqueFD by taking ownership of the \a fd. > - * The original \a fd becomes invalid. > - */ > -FileDescriptor::FileDescriptor(UniqueFD fd) > - : FileDescriptor(fd.release()) > -{ > -} > - > -/** > - * \brief Copy constructor, create a FileDescriptor from a copy of \a other > - * \param[in] other The other FileDescriptor > - * > - * Copying a FileDescriptor implicitly shares ownership of the wrapped file > - * descriptor. The original FileDescriptor is left untouched, and the caller is > - * responsible for destroying it when appropriate. The wrapped file descriptor > - * will be closed automatically when all FileDescriptor instances that > - * reference it are destroyed. > - */ > -FileDescriptor::FileDescriptor(const FileDescriptor &other) > - : fd_(other.fd_) > -{ > -} > - > -/** > - * \brief Move constructor, create a FileDescriptor by taking over \a other > - * \param[in] other The other FileDescriptor > - * > - * Moving a FileDescriptor moves the reference to the wrapped descriptor owned > - * by \a other to the new FileDescriptor. The \a other FileDescriptor is > - * invalidated and its fd() function will return -1. The wrapped file descriptor > - * will be closed automatically when all FileDescriptor instances that > - * reference it are destroyed. > - */ > -FileDescriptor::FileDescriptor(FileDescriptor &&other) > - : fd_(std::move(other.fd_)) > -{ > -} > - > -/** > - * \brief Destroy the FileDescriptor instance > - * > - * Destroying a FileDescriptor instance releases its reference to the wrapped > - * descriptor, if any. When the last instance that references a wrapped > - * descriptor is destroyed, the file descriptor is automatically closed. > - */ > -FileDescriptor::~FileDescriptor() > -{ > -} > - > -/** > - * \brief Copy assignment operator, replace the wrapped file descriptor with a > - * copy of \a other > - * \param[in] other The other FileDescriptor > - * > - * Copying a FileDescriptor creates a new reference to the wrapped file > - * descriptor owner by \a other. If \a other is invalid, *this will also be > - * invalid. The original FileDescriptor is left untouched, and the caller is > - * responsible for destroying it when appropriate. The wrapped file descriptor > - * will be closed automatically when all FileDescriptor instances that > - * reference it are destroyed. > - * > - * \return A reference to this FileDescriptor > - */ > -FileDescriptor &FileDescriptor::operator=(const FileDescriptor &other) > -{ > - fd_ = other.fd_; > - > - return *this; > -} > - > -/** > - * \brief Move assignment operator, replace the wrapped file descriptor by > - * taking over \a other > - * \param[in] other The other FileDescriptor > - * > - * Moving a FileDescriptor moves the reference to the wrapped descriptor owned > - * by \a other to the new FileDescriptor. If \a other is invalid, *this will > - * also be invalid. The \a other FileDescriptor is invalidated and its fd() > - * function will return -1. The wrapped file descriptor will be closed > - * automatically when all FileDescriptor instances that reference it are > - * destroyed. > - * > - * \return A reference to this FileDescriptor > - */ > -FileDescriptor &FileDescriptor::operator=(FileDescriptor &&other) > -{ > - fd_ = std::move(other.fd_); > - > - return *this; > -} > - > -/** > - * \fn FileDescriptor::isValid() > - * \brief Check if the FileDescriptor instance is valid > - * \return True if the FileDescriptor is valid, false otherwise > - */ > - > -/** > - * \fn FileDescriptor::fd() > - * \brief Retrieve the numerical file descriptor > - * \return The numerical file descriptor, which may be -1 if the FileDescriptor > - * instance is invalid > - */ > - > -/** > - * \brief Duplicate a FileDescriptor > - * > - * Duplicating a FileDescriptor creates a duplicate of the wrapped file > - * descriptor and returns a UniqueFD that owns the duplicate. The fd() function > - * of the original and the get() function of the duplicate will return different > - * values. The duplicate instance will not be affected by destruction of the > - * original instance or its copies. > - * > - * \return A UniqueFD owning a duplicate of the original file descriptor > - */ > -UniqueFD FileDescriptor::dup() const > -{ > - int dupFd = ::dup(fd()); > - if (dupFd == -1) { > - int ret = -errno; > - LOG(FileDescriptor, Error) > - << "Failed to dup() fd: " << strerror(-ret); > - } > - > - return UniqueFD(dupFd); > -} > - > -FileDescriptor::Descriptor::Descriptor(int fd, bool duplicate) > -{ > - if (!duplicate) { > - fd_ = fd; > - return; > - } > - > - /* Failing to dup() a fd should not happen and is fatal. */ > - fd_ = ::dup(fd); > - if (fd_ == -1) { > - int ret = -errno; > - LOG(FileDescriptor, Fatal) > - << "Failed to dup() fd: " << strerror(-ret); > - } > -} > - > -FileDescriptor::Descriptor::~Descriptor() > -{ > - if (fd_ != -1) > - close(fd_); > -} > - > -} /* namespace libcamera */ > diff --git a/src/libcamera/base/meson.build b/src/libcamera/base/meson.build > index b0d85bc19245..ccb746c27466 100644 > --- a/src/libcamera/base/meson.build > +++ b/src/libcamera/base/meson.build > @@ -8,12 +8,12 @@ libcamera_base_sources = files([ > 'event_dispatcher_poll.cpp', > 'event_notifier.cpp', > 'file.cpp', > - 'file_descriptor.cpp', > 'flags.cpp', > 'log.cpp', > 'message.cpp', > 'object.cpp', > 'semaphore.cpp', > + 'shared_fd.cpp', > 'signal.cpp', > 'thread.cpp', > 'timer.cpp', > diff --git a/src/libcamera/base/shared_fd.cpp b/src/libcamera/base/shared_fd.cpp > new file mode 100644 > index 000000000000..05b6892f7e19 > --- /dev/null > +++ b/src/libcamera/base/shared_fd.cpp > @@ -0,0 +1,262 @@ > +/* SPDX-License-Identifier: LGPL-2.1-or-later */ > +/* > + * Copyright (C) 2019, Google Inc. > + * > + * shared_fd.cpp - File descriptor wrapper with shared ownership > + */ > + > +#include <libcamera/base/shared_fd.h> > + > +#include <string.h> > +#include <sys/types.h> > +#include <unistd.h> > +#include <utility> > + > +#include <libcamera/base/log.h> > +#include <libcamera/base/unique_fd.h> > + > +/** > + * \file base/shared_fd.h > + * \brief File descriptor wrapper > + */ > + > +namespace libcamera { > + > +LOG_DEFINE_CATEGORY(SharedFD) > + > +/** > + * \class SharedFD > + * \brief RAII-style wrapper for file descriptors > + * > + * The SharedFD class provides RAII-style lifetime management of file > + * descriptors with an efficient mechanism for ownership sharing. At its core, > + * an internal Descriptor object wraps a file descriptor (expressed as a signed > + * integer) with an RAII-style interface. The Descriptor is then implicitly > + * shared with all SharedFD instances constructed as copies. > + * > + * When constructed from a numerical file descriptor, the SharedFD instance > + * either duplicates or takes over the file descriptor: > + * > + * - The SharedFD(const int &) constructor duplicates the numerical file > + * descriptor and wraps the duplicate in a Descriptor. The caller is > + * responsible for closing the original file descriptor, and the value > + * returned by fd() will be different from the value passed to the > + * constructor. > + * > + * - The SharedFD(int &&) constructor takes over the numerical file descriptor > + * and wraps it in a Descriptor. The caller shall not touch the original file > + * descriptor once the function returns, and the value returned by fd() will > + * be identical to the value passed to the constructor. > + * > + * The copy constructor and assignment operator create copies that share the > + * Descriptor, while the move versions of those functions additionally make the > + * other SharedFD invalid. When the last SharedFD that references a Descriptor > + * is destroyed, the file descriptor is closed. > + * > + * The numerical file descriptor is available through the fd() function. All > + * SharedFD instances created as copies of a SharedFD will report the same fd() > + * value. Callers can perform operations on the fd(), but shall never close it > + * manually. > + */ > + > +/** > + * \brief Create a SharedFD copying a given \a fd > + * \param[in] fd File descriptor > + * > + * Construct a SharedFD from a numerical file descriptor by duplicating the > + * \a fd, and take ownership of the copy. The original \a fd is left untouched, > + * and the caller is responsible for closing it when appropriate. The duplicated > + * file descriptor will be closed automatically when all SharedFD instances that > + * reference it are destroyed. > + * > + * If the \a fd is negative, the SharedFD is constructed as invalid and the fd() > + * function will return -1. > + */ > +SharedFD::SharedFD(const int &fd) > +{ > + if (fd < 0) > + return; > + > + fd_ = std::make_shared<Descriptor>(fd, true); > + if (fd_->fd() < 0) > + fd_.reset(); > +} > + > +/** > + * \brief Create a SharedFD taking ownership of a given \a fd > + * \param[in] fd File descriptor > + * > + * Construct a SharedFD from a numerical file descriptor by taking ownership of > + * the \a fd. The original \a fd is set to -1 and shall not be touched by the > + * caller anymore. In particular, the caller shall not close the original \a fd > + * manually. The duplicated file descriptor will be closed automatically when > + * all SharedFD instances that reference it are destroyed. > + * > + * If the \a fd is negative, the SharedFD is constructed as invalid and the fd() > + * function will return -1. > + */ > +SharedFD::SharedFD(int &&fd) > +{ > + if (fd < 0) > + return; > + > + fd_ = std::make_shared<Descriptor>(fd, false); > + /* > + * The Descriptor constructor can't have failed here, as it took over > + * the fd without duplicating it. Just set the original fd to -1 to > + * implement move semantics. > + */ > + fd = -1; > +} > + > +/** > + * \brief Create a SharedFD taking ownership of a given UniqueFD \a fd > + * \param[in] fd UniqueFD > + * > + * Construct a SharedFD from UniqueFD by taking ownership of the \a fd. The > + * original \a fd becomes invalid. > + */ > +SharedFD::SharedFD(UniqueFD fd) > + : SharedFD(fd.release()) > +{ > +} > + > +/** > + * \brief Copy constructor, create a SharedFD from a copy of \a other > + * \param[in] other The other SharedFD > + * > + * Copying a SharedFD implicitly shares ownership of the wrapped file > + * descriptor. The original SharedFD is left untouched, and the caller is > + * responsible for destroying it when appropriate. The wrapped file descriptor > + * will be closed automatically when all SharedFD instances that reference it > + * are destroyed. > + */ > +SharedFD::SharedFD(const SharedFD &other) > + : fd_(other.fd_) > +{ > +} > + > +/** > + * \brief Move constructor, create a SharedFD by taking over \a other > + * \param[in] other The other SharedFD > + * > + * Moving a SharedFD moves the reference to the wrapped descriptor owned by > + * \a other to the new SharedFD. The \a other SharedFD is invalidated and its > + * fd() function will return -1. The wrapped file descriptor will be closed > + * automatically when all SharedFD instances that reference it are destroyed. > + */ > +SharedFD::SharedFD(SharedFD &&other) > + : fd_(std::move(other.fd_)) > +{ > +} > + > +/** > + * \brief Destroy the SharedFD instance > + * > + * Destroying a SharedFD instance releases its reference to the wrapped > + * descriptor, if any. When the last instance that references a wrapped > + * descriptor is destroyed, the file descriptor is automatically closed. > + */ > +SharedFD::~SharedFD() > +{ > +} > + > +/** > + * \brief Copy assignment operator, replace the wrapped file descriptor with a > + * copy of \a other > + * \param[in] other The other SharedFD > + * > + * Copying a SharedFD creates a new reference to the wrapped file descriptor > + * owner by \a other. If \a other is invalid, *this will also be invalid. The > + * original SharedFD is left untouched, and the caller is responsible for > + * destroying it when appropriate. The wrapped file descriptor will be closed > + * automatically when all SharedFD instances that reference it are destroyed. > + * > + * \return A reference to this SharedFD > + */ > +SharedFD &SharedFD::operator=(const SharedFD &other) > +{ > + fd_ = other.fd_; > + > + return *this; > +} > + > +/** > + * \brief Move assignment operator, replace the wrapped file descriptor by > + * taking over \a other > + * \param[in] other The other SharedFD > + * > + * Moving a SharedFD moves the reference to the wrapped descriptor owned by > + * \a other to the new SharedFD. If \a other is invalid, *this will also be > + * invalid. The \a other SharedFD is invalidated and its fd() function will > + * return -1. The wrapped file descriptor will be closed automatically when > + * all SharedFD instances that reference it are destroyed. > + * > + * \return A reference to this SharedFD > + */ > +SharedFD &SharedFD::operator=(SharedFD &&other) > +{ > + fd_ = std::move(other.fd_); > + > + return *this; > +} > + > +/** > + * \fn SharedFD::isValid() > + * \brief Check if the SharedFD instance is valid > + * \return True if the SharedFD is valid, false otherwise > + */ > + > +/** > + * \fn SharedFD::fd() > + * \brief Retrieve the numerical file descriptor > + * \return The numerical file descriptor, which may be -1 if the SharedFD > + * instance is invalid > + */ > + > +/** > + * \brief Duplicate a SharedFD > + * > + * Duplicating a SharedFD creates a duplicate of the wrapped file descriptor and > + * returns a UniqueFD that owns the duplicate. The fd() function of the original > + * and the get() function of the duplicate will return different values. The > + * duplicate instance will not be affected by destruction of the original > + * instance or its copies. > + * > + * \return A UniqueFD owning a duplicate of the original file descriptor > + */ > +UniqueFD SharedFD::dup() const > +{ > + int dupFd = ::dup(fd()); > + if (dupFd == -1) { > + int ret = -errno; > + LOG(SharedFD, Error) > + << "Failed to dup() fd: " << strerror(-ret); > + } > + > + return UniqueFD(dupFd); > +} > + > +SharedFD::Descriptor::Descriptor(int fd, bool duplicate) > +{ > + if (!duplicate) { > + fd_ = fd; > + return; > + } > + > + /* Failing to dup() a fd should not happen and is fatal. */ > + fd_ = ::dup(fd); > + if (fd_ == -1) { > + int ret = -errno; > + LOG(SharedFD, Fatal) > + << "Failed to dup() fd: " << strerror(-ret); > + } > +} > + > +SharedFD::Descriptor::~Descriptor() > +{ > + if (fd_ != -1) > + close(fd_); > +} > + > +} /* namespace libcamera */ > diff --git a/src/libcamera/framebuffer.cpp b/src/libcamera/framebuffer.cpp > index f5bcf107d7aa..0a5bf7fdbeb7 100644 > --- a/src/libcamera/framebuffer.cpp > +++ b/src/libcamera/framebuffer.cpp > @@ -180,9 +180,9 @@ FrameBuffer::Private::Private() > * offset and length. > * > * To support DMA access, planes are associated with dmabuf objects represented > - * by FileDescriptor handles. The Plane class doesn't handle mapping of the > - * memory to the CPU, but applications and IPAs may use the dmabuf file > - * descriptors to map the plane memory with mmap() and access its contents. > + * by SharedFD handles. The Plane class doesn't handle mapping of the memory to > + * the CPU, but applications and IPAs may use the dmabuf file descriptors to map > + * the plane memory with mmap() and access its contents. > * > * \todo Specify how an application shall decide whether to use a single or > * multiple dmabufs, based on the camera requirements. > diff --git a/src/libcamera/ipa_data_serializer.cpp b/src/libcamera/ipa_data_serializer.cpp > index 82ec9b20a411..0a259305afa2 100644 > --- a/src/libcamera/ipa_data_serializer.cpp > +++ b/src/libcamera/ipa_data_serializer.cpp > @@ -31,7 +31,7 @@ LOG_DEFINE_CATEGORY(IPADataSerializer) > * > * \todo Harden the vector and map deserializer > * > - * \todo For FileDescriptors, instead of storing a validity flag, store an > + * \todo For SharedFDs, instead of storing a validity flag, store an > * index into the fd array. This will allow us to use views instead of copying. > */ > > @@ -112,7 +112,7 @@ namespace { > * \param[in] cs ControlSerializer > * > * This version of deserialize() can be used if the object type \a T and its > - * members don't have any FileDescriptor. > + * members don't have any SharedFD. > * > * \a cs is only necessary if the object type \a T or its members contain > * ControlList or ControlInfoMap. > @@ -132,7 +132,7 @@ namespace { > * \param[in] cs ControlSerializer > * > * This version of deserialize() can be used if the object type \a T and its > - * members don't have any FileDescriptor. > + * members don't have any SharedFD. > * > * \a cs is only necessary if the object type \a T or its members contain > * ControlList or ControlInfoMap. > @@ -143,7 +143,7 @@ namespace { > /** > * \fn template<typename T> IPADataSerializer<T>::deserialize( > * const std::vector<uint8_t> &data, > - * const std::vector<FileDescriptor> &fds, > + * const std::vector<SharedFD> &fds, > * ControlSerializer *cs = nullptr) > * \brief Deserialize byte vector and fd vector into an object > * \tparam T Type of object to deserialize to > @@ -152,7 +152,7 @@ namespace { > * \param[in] cs ControlSerializer > * > * This version of deserialize() (or the iterator version) must be used if > - * the object type \a T or its members contain FileDescriptor. > + * the object type \a T or its members contain SharedFD. > * > * \a cs is only necessary if the object type \a T or its members contain > * ControlList or ControlInfoMap. > @@ -164,8 +164,8 @@ namespace { > * \fn template<typename T> IPADataSerializer::deserialize( > * std::vector<uint8_t>::const_iterator dataBegin, > * std::vector<uint8_t>::const_iterator dataEnd, > - * std::vector<FileDescriptor>::const_iterator fdsBegin, > - * std::vector<FileDescriptor>::const_iterator fdsEnd, > + * std::vector<SharedFD>::const_iterator fdsBegin, > + * std::vector<SharedFD>::const_iterator fdsEnd, > * ControlSerializer *cs = nullptr) > * \brief Deserialize byte vector and fd vector into an object > * \tparam T Type of object to deserialize to > @@ -176,7 +176,7 @@ namespace { > * \param[in] cs ControlSerializer > * > * This version of deserialize() (or the vector version) must be used if > - * the object type \a T or its members contain FileDescriptor. > + * the object type \a T or its members contain SharedFD. > * > * \a cs is only necessary if the object type \a T or its members contain > * ControlList or ControlInfoMap. > @@ -189,7 +189,7 @@ namespace { > #define DEFINE_POD_SERIALIZER(type) \ > \ > template<> \ > -std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> \ > +std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> \ > IPADataSerializer<type>::serialize(const type &data, \ > [[maybe_unused]] ControlSerializer *cs) \ > { \ > @@ -217,7 +217,7 @@ type IPADataSerializer<type>::deserialize(const std::vector<uint8_t> &data, \ > \ > template<> \ > type IPADataSerializer<type>::deserialize(const std::vector<uint8_t> &data, \ > - [[maybe_unused]] const std::vector<FileDescriptor> &fds, \ > + [[maybe_unused]] const std::vector<SharedFD> &fds, \ > ControlSerializer *cs) \ > { \ > return deserialize(data.cbegin(), data.end(), cs); \ > @@ -226,8 +226,8 @@ type IPADataSerializer<type>::deserialize(const std::vector<uint8_t> &data, \ > template<> \ > type IPADataSerializer<type>::deserialize(std::vector<uint8_t>::const_iterator dataBegin, \ > std::vector<uint8_t>::const_iterator dataEnd, \ > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsBegin, \ > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, \ > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsBegin, \ > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, \ > ControlSerializer *cs) \ > { \ > return deserialize(dataBegin, dataEnd, cs); \ > @@ -251,7 +251,7 @@ DEFINE_POD_SERIALIZER(double) > * function parameter serdes). > */ > template<> > -std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > +std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > IPADataSerializer<std::string>::serialize(const std::string &data, > [[maybe_unused]] ControlSerializer *cs) > { > @@ -278,7 +278,7 @@ IPADataSerializer<std::string>::deserialize(std::vector<uint8_t>::const_iterator > template<> > std::string > IPADataSerializer<std::string>::deserialize(const std::vector<uint8_t> &data, > - [[maybe_unused]] const std::vector<FileDescriptor> &fds, > + [[maybe_unused]] const std::vector<SharedFD> &fds, > [[maybe_unused]] ControlSerializer *cs) > { > return { data.cbegin(), data.cend() }; > @@ -288,8 +288,8 @@ template<> > std::string > IPADataSerializer<std::string>::deserialize(std::vector<uint8_t>::const_iterator dataBegin, > std::vector<uint8_t>::const_iterator dataEnd, > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsBegin, > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsBegin, > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, > [[maybe_unused]] ControlSerializer *cs) > { > return { dataBegin, dataEnd }; > @@ -307,7 +307,7 @@ IPADataSerializer<std::string>::deserialize(std::vector<uint8_t>::const_iterator > * be used. The serialized ControlInfoMap will have zero length. > */ > template<> > -std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > +std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > IPADataSerializer<ControlList>::serialize(const ControlList &data, ControlSerializer *cs) > { > if (!cs) > @@ -407,7 +407,7 @@ IPADataSerializer<ControlList>::deserialize(const std::vector<uint8_t> &data, > template<> > ControlList > IPADataSerializer<ControlList>::deserialize(const std::vector<uint8_t> &data, > - [[maybe_unused]] const std::vector<FileDescriptor> &fds, > + [[maybe_unused]] const std::vector<SharedFD> &fds, > ControlSerializer *cs) > { > return deserialize(data.cbegin(), data.end(), cs); > @@ -417,8 +417,8 @@ template<> > ControlList > IPADataSerializer<ControlList>::deserialize(std::vector<uint8_t>::const_iterator dataBegin, > std::vector<uint8_t>::const_iterator dataEnd, > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsBegin, > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsBegin, > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, > ControlSerializer *cs) > { > return deserialize(dataBegin, dataEnd, cs); > @@ -431,7 +431,7 @@ IPADataSerializer<ControlList>::deserialize(std::vector<uint8_t>::const_iterator > * X bytes - Serialized ControlInfoMap (using ControlSerializer) > */ > template<> > -std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > +std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > IPADataSerializer<ControlInfoMap>::serialize(const ControlInfoMap &map, > ControlSerializer *cs) > { > @@ -493,7 +493,7 @@ IPADataSerializer<ControlInfoMap>::deserialize(const std::vector<uint8_t> &data, > template<> > ControlInfoMap > IPADataSerializer<ControlInfoMap>::deserialize(const std::vector<uint8_t> &data, > - [[maybe_unused]] const std::vector<FileDescriptor> &fds, > + [[maybe_unused]] const std::vector<SharedFD> &fds, > ControlSerializer *cs) > { > return deserialize(data.cbegin(), data.end(), cs); > @@ -503,30 +503,30 @@ template<> > ControlInfoMap > IPADataSerializer<ControlInfoMap>::deserialize(std::vector<uint8_t>::const_iterator dataBegin, > std::vector<uint8_t>::const_iterator dataEnd, > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsBegin, > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsBegin, > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, > ControlSerializer *cs) > { > return deserialize(dataBegin, dataEnd, cs); > } > > /* > - * FileDescriptors are serialized into four bytes that tells if the > - * FileDescriptor is valid or not. If it is valid, then for serialization > - * the fd will be written to the fd vector, or for deserialization the > - * fd vector const_iterator will be valid. > + * SharedFD instances are serialized into four bytes that tells if the SharedFD > + * is valid or not. If it is valid, then for serialization the fd will be > + * written to the fd vector, or for deserialization the fd vector const_iterator > + * will be valid. > * > * This validity is necessary so that we don't send -1 fd over sendmsg(). It > * also allows us to simply send the entire fd vector into the deserializer > * and it will be recursively consumed as necessary. > */ > template<> > -std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > -IPADataSerializer<FileDescriptor>::serialize(const FileDescriptor &data, > - [[maybe_unused]] ControlSerializer *cs) > +std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > +IPADataSerializer<SharedFD>::serialize(const SharedFD &data, > + [[maybe_unused]] ControlSerializer *cs) > { > std::vector<uint8_t> dataVec; > - std::vector<FileDescriptor> fdVec; > + std::vector<SharedFD> fdVec; > > /* > * Store as uint32_t to prepare for conversion from validity flag > @@ -542,11 +542,11 @@ IPADataSerializer<FileDescriptor>::serialize(const FileDescriptor &data, > } > > template<> > -FileDescriptor IPADataSerializer<FileDescriptor>::deserialize([[maybe_unused]] std::vector<uint8_t>::const_iterator dataBegin, > - [[maybe_unused]] std::vector<uint8_t>::const_iterator dataEnd, > - std::vector<FileDescriptor>::const_iterator fdsBegin, > - std::vector<FileDescriptor>::const_iterator fdsEnd, > - [[maybe_unused]] ControlSerializer *cs) > +SharedFD IPADataSerializer<SharedFD>::deserialize([[maybe_unused]] std::vector<uint8_t>::const_iterator dataBegin, > + [[maybe_unused]] std::vector<uint8_t>::const_iterator dataEnd, > + std::vector<SharedFD>::const_iterator fdsBegin, > + std::vector<SharedFD>::const_iterator fdsEnd, > + [[maybe_unused]] ControlSerializer *cs) > { > ASSERT(std::distance(dataBegin, dataEnd) >= 4); > > @@ -554,13 +554,13 @@ FileDescriptor IPADataSerializer<FileDescriptor>::deserialize([[maybe_unused]] s > > ASSERT(!(valid && std::distance(fdsBegin, fdsEnd) < 1)); > > - return valid ? *fdsBegin : FileDescriptor(); > + return valid ? *fdsBegin : SharedFD(); > } > > template<> > -FileDescriptor IPADataSerializer<FileDescriptor>::deserialize(const std::vector<uint8_t> &data, > - const std::vector<FileDescriptor> &fds, > - [[maybe_unused]] ControlSerializer *cs) > +SharedFD IPADataSerializer<SharedFD>::deserialize(const std::vector<uint8_t> &data, > + const std::vector<SharedFD> &fds, > + [[maybe_unused]] ControlSerializer *cs) > { > return deserialize(data.cbegin(), data.end(), fds.cbegin(), fds.end()); > } > @@ -568,22 +568,22 @@ FileDescriptor IPADataSerializer<FileDescriptor>::deserialize(const std::vector< > /* > * FrameBuffer::Plane is serialized as: > * > - * 4 byte - FileDescriptor > + * 4 byte - SharedFD > * 4 bytes - uint32_t Offset > * 4 bytes - uint32_t Length > */ > template<> > -std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > +std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > IPADataSerializer<FrameBuffer::Plane>::serialize(const FrameBuffer::Plane &data, > [[maybe_unused]] ControlSerializer *cs) > { > std::vector<uint8_t> dataVec; > - std::vector<FileDescriptor> fdsVec; > + std::vector<SharedFD> fdsVec; > > std::vector<uint8_t> fdBuf; > - std::vector<FileDescriptor> fdFds; > + std::vector<SharedFD> fdFds; > std::tie(fdBuf, fdFds) = > - IPADataSerializer<FileDescriptor>::serialize(data.fd); > + IPADataSerializer<SharedFD>::serialize(data.fd); > dataVec.insert(dataVec.end(), fdBuf.begin(), fdBuf.end()); > fdsVec.insert(fdsVec.end(), fdFds.begin(), fdFds.end()); > > @@ -597,13 +597,13 @@ template<> > FrameBuffer::Plane > IPADataSerializer<FrameBuffer::Plane>::deserialize(std::vector<uint8_t>::const_iterator dataBegin, > std::vector<uint8_t>::const_iterator dataEnd, > - std::vector<FileDescriptor>::const_iterator fdsBegin, > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, > + std::vector<SharedFD>::const_iterator fdsBegin, > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, > [[maybe_unused]] ControlSerializer *cs) > { > FrameBuffer::Plane ret; > > - ret.fd = IPADataSerializer<FileDescriptor>::deserialize(dataBegin, dataBegin + 4, > + ret.fd = IPADataSerializer<SharedFD>::deserialize(dataBegin, dataBegin + 4, > fdsBegin, fdsBegin + 1); > ret.offset = readPOD<uint32_t>(dataBegin, 4, dataEnd); > ret.length = readPOD<uint32_t>(dataBegin, 8, dataEnd); > @@ -614,7 +614,7 @@ IPADataSerializer<FrameBuffer::Plane>::deserialize(std::vector<uint8_t>::const_i > template<> > FrameBuffer::Plane > IPADataSerializer<FrameBuffer::Plane>::deserialize(const std::vector<uint8_t> &data, > - const std::vector<FileDescriptor> &fds, > + const std::vector<SharedFD> &fds, > ControlSerializer *cs) > { > return deserialize(data.cbegin(), data.end(), fds.cbegin(), fds.end(), cs); > diff --git a/src/libcamera/ipc_pipe.cpp b/src/libcamera/ipc_pipe.cpp > index ad870fd4137f..3b47032de0a2 100644 > --- a/src/libcamera/ipc_pipe.cpp > +++ b/src/libcamera/ipc_pipe.cpp > @@ -87,7 +87,7 @@ IPCMessage::IPCMessage(IPCUnixSocket::Payload &payload) > data_ = std::vector<uint8_t>(payload.data.begin() + sizeof(header_), > payload.data.end()); > for (int32_t &fd : payload.fds) > - fds_.push_back(FileDescriptor(std::move(fd))); > + fds_.push_back(SharedFD(std::move(fd))); > } > > /** > @@ -112,7 +112,7 @@ IPCUnixSocket::Payload IPCMessage::payload() const > data_.data(), data_.size()); > } > > - for (const FileDescriptor &fd : fds_) > + for (const SharedFD &fd : fds_) > payload.fds.push_back(fd.fd()); > > return payload; > diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp > index ffa51a0c65ca..ea8243912a29 100644 > --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp > +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp > @@ -12,7 +12,7 @@ > #include <queue> > #include <unordered_set> > > -#include <libcamera/base/file_descriptor.h> > +#include <libcamera/base/shared_fd.h> > > #include <libcamera/camera.h> > #include <libcamera/control_ids.h> > @@ -228,7 +228,7 @@ public: > > /* DMAHEAP allocation helper. */ > RPi::DmaHeap dmaHeap_; > - FileDescriptor lsTable_; > + SharedFD lsTable_; > > std::unique_ptr<DelayedControls> delayedCtrls_; > bool sensorMetadata_; > @@ -1365,7 +1365,7 @@ int RPiCameraData::configureIPA(const CameraConfiguration *config) > if (!fd.isValid()) > return -ENOMEM; > > - lsTable_ = FileDescriptor(std::move(fd)); > + lsTable_ = SharedFD(std::move(fd)); > > /* Allow the IPA to mmap the LS table via the file descriptor. */ > /* > diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp > index 3966483a365f..97d431071def 100644 > --- a/src/libcamera/v4l2_videodevice.cpp > +++ b/src/libcamera/v4l2_videodevice.cpp > @@ -22,8 +22,8 @@ > #include <linux/version.h> > > #include <libcamera/base/event_notifier.h> > -#include <libcamera/base/file_descriptor.h> > #include <libcamera/base/log.h> > +#include <libcamera/base/shared_fd.h> > #include <libcamera/base/unique_fd.h> > #include <libcamera/base/utils.h> > > @@ -1325,7 +1325,7 @@ std::unique_ptr<FrameBuffer> V4L2VideoDevice::createBuffer(unsigned int index) > return nullptr; > > FrameBuffer::Plane plane; > - plane.fd = FileDescriptor(std::move(fd)); > + plane.fd = SharedFD(std::move(fd)); > /* > * V4L2 API doesn't provide dmabuf offset information of plane. > * Set 0 as a placeholder offset. > @@ -1354,7 +1354,7 @@ std::unique_ptr<FrameBuffer> V4L2VideoDevice::createBuffer(unsigned int index) > ASSERT(numPlanes == 1u); > > planes.resize(formatInfo_->numPlanes()); > - const FileDescriptor &fd = planes[0].fd; > + const SharedFD &fd = planes[0].fd; > size_t offset = 0; > > for (auto [i, plane] : utils::enumerate(planes)) { > diff --git a/src/v4l2/v4l2_camera.h b/src/v4l2/v4l2_camera.h > index 9817fd393d59..586347829845 100644 > --- a/src/v4l2/v4l2_camera.h > +++ b/src/v4l2/v4l2_camera.h > @@ -11,8 +11,8 @@ > #include <mutex> > #include <utility> > > -#include <libcamera/base/file_descriptor.h> > #include <libcamera/base/semaphore.h> > +#include <libcamera/base/shared_fd.h> > > #include <libcamera/camera.h> > #include <libcamera/framebuffer.h> > diff --git a/test/meson.build b/test/meson.build > index 42dfbc1f8ee9..daaa3862cdd6 100644 > --- a/test/meson.build > +++ b/test/meson.build > @@ -40,7 +40,6 @@ internal_tests = [ > ['event-dispatcher', 'event-dispatcher.cpp'], > ['event-thread', 'event-thread.cpp'], > ['file', 'file.cpp'], > - ['file-descriptor', 'file-descriptor.cpp'], > ['flags', 'flags.cpp'], > ['hotplug-cameras', 'hotplug-cameras.cpp'], > ['mapped-buffer', 'mapped-buffer.cpp'], > @@ -49,6 +48,7 @@ internal_tests = [ > ['object-delete', 'object-delete.cpp'], > ['object-invoke', 'object-invoke.cpp'], > ['pixel-format', 'pixel-format.cpp'], > + ['shared-fd', 'shared-fd.cpp'], > ['signal-threads', 'signal-threads.cpp'], > ['threads', 'threads.cpp'], > ['timer', 'timer.cpp'], > diff --git a/test/serialization/ipa_data_serializer_test.cpp b/test/serialization/ipa_data_serializer_test.cpp > index 5fcdcb8eae92..d2050a868b38 100644 > --- a/test/serialization/ipa_data_serializer_test.cpp > +++ b/test/serialization/ipa_data_serializer_test.cpp > @@ -53,7 +53,7 @@ template<typename T> > int testPodSerdes(T in) > { > std::vector<uint8_t> buf; > - std::vector<FileDescriptor> fds; > + std::vector<SharedFD> fds; > > std::tie(buf, fds) = IPADataSerializer<T>::serialize(in); > T out = IPADataSerializer<T>::deserialize(buf, fds); > @@ -72,7 +72,7 @@ int testVectorSerdes(const std::vector<T> &in, > ControlSerializer *cs = nullptr) > { > std::vector<uint8_t> buf; > - std::vector<FileDescriptor> fds; > + std::vector<SharedFD> fds; > > std::tie(buf, fds) = IPADataSerializer<std::vector<T>>::serialize(in, cs); > std::vector<T> out = IPADataSerializer<std::vector<T>>::deserialize(buf, fds, cs); > @@ -92,7 +92,7 @@ int testMapSerdes(const std::map<K, V> &in, > ControlSerializer *cs = nullptr) > { > std::vector<uint8_t> buf; > - std::vector<FileDescriptor> fds; > + std::vector<SharedFD> fds; > > std::tie(buf, fds) = IPADataSerializer<std::map<K, V>>::serialize(in, cs); > std::map<K, V> out = IPADataSerializer<std::map<K, V>>::deserialize(buf, fds, cs); > @@ -198,7 +198,7 @@ private: > ControlSerializer cs(ControlSerializer::Role::Proxy); > > /* > - * We don't test FileDescriptor serdes because it dup()s, so we > + * We don't test SharedFD serdes because it dup()s, so we > * can't check for equality. > */ > std::vector<uint8_t> vecUint8 = { 1, 2, 3, 4, 5, 6 }; > @@ -219,7 +219,7 @@ private: > }; > > std::vector<uint8_t> buf; > - std::vector<FileDescriptor> fds; > + std::vector<SharedFD> fds; > > if (testVectorSerdes(vecUint8) != TestPass) > return TestFail; > @@ -291,7 +291,7 @@ private: > { { "a", { 1, 2, 3 } }, { "b", { 4, 5, 6 } }, { "c", { 7, 8, 9 } } }; > > std::vector<uint8_t> buf; > - std::vector<FileDescriptor> fds; > + std::vector<SharedFD> fds; > > if (testMapSerdes(mapUintStr) != TestPass) > return TestFail; > @@ -359,7 +359,7 @@ private: > std::string strEmpty = ""; > > std::vector<uint8_t> buf; > - std::vector<FileDescriptor> fds; > + std::vector<SharedFD> fds; > > if (testPodSerdes(u32min) != TestPass) > return TestFail; > diff --git a/test/file-descriptor.cpp b/test/shared-fd.cpp > similarity index 80% > rename from test/file-descriptor.cpp > rename to test/shared-fd.cpp > index 76badc4c5fad..60e5d0aaa395 100644 > --- a/test/file-descriptor.cpp > +++ b/test/shared-fd.cpp > @@ -2,7 +2,7 @@ > /* > * Copyright (C) 2019, Google Inc. > * > - * file_descriptor.cpp - FileDescriptor test > + * shared_fd.cpp - SharedFD test > */ > > #include <fcntl.h> > @@ -11,7 +11,7 @@ > #include <sys/types.h> > #include <unistd.h> > > -#include <libcamera/base/file_descriptor.h> > +#include <libcamera/base/shared_fd.h> > #include <libcamera/base/utils.h> > > #include "test.h" > @@ -19,7 +19,7 @@ > using namespace libcamera; > using namespace std; > > -class FileDescriptorTest : public Test > +class SharedFDTest : public Test > { > protected: > int init() > @@ -43,8 +43,8 @@ protected: > > int run() > { > - /* Test creating empty FileDescriptor. */ > - desc1_ = new FileDescriptor(); > + /* Test creating empty SharedFD. */ > + desc1_ = new SharedFD(); > > if (desc1_->fd() != -1) { > std::cout << "Failed fd numerical check (default constructor)" > @@ -56,10 +56,10 @@ protected: > desc1_ = nullptr; > > /* > - * Test creating FileDescriptor by copying numerical file > + * Test creating SharedFD by copying numerical file > * descriptor. > */ > - desc1_ = new FileDescriptor(fd_); > + desc1_ = new SharedFD(fd_); > if (desc1_->fd() == fd_) { > std::cout << "Failed fd numerical check (lvalue ref constructor)" > << std::endl; > @@ -84,13 +84,13 @@ protected: > } > > /* > - * Test creating FileDescriptor by taking ownership of > + * Test creating SharedFD by taking ownership of > * numerical file descriptor. > */ > int dupFd = dup(fd_); > int dupFdCopy = dupFd; > > - desc1_ = new FileDescriptor(std::move(dupFd)); > + desc1_ = new SharedFD(std::move(dupFd)); > if (desc1_->fd() != dupFdCopy) { > std::cout << "Failed fd numerical check (rvalue ref constructor)" > << std::endl; > @@ -114,9 +114,9 @@ protected: > return TestFail; > } > > - /* Test creating FileDescriptor from other FileDescriptor. */ > - desc1_ = new FileDescriptor(fd_); > - desc2_ = new FileDescriptor(*desc1_); > + /* Test creating SharedFD from other SharedFD. */ > + desc1_ = new SharedFD(fd_); > + desc2_ = new SharedFD(*desc1_); > > if (desc1_->fd() == fd_ || desc2_->fd() == fd_ || desc1_->fd() != desc2_->fd()) { > std::cout << "Failed fd numerical check (copy constructor)" > @@ -142,10 +142,10 @@ protected: > delete desc2_; > desc2_ = nullptr; > > - /* Test creating FileDescriptor by taking over other FileDescriptor. */ > - desc1_ = new FileDescriptor(fd_); > + /* Test creating SharedFD by taking over other SharedFD. */ > + desc1_ = new SharedFD(fd_); > fd = desc1_->fd(); > - desc2_ = new FileDescriptor(std::move(*desc1_)); > + desc2_ = new SharedFD(std::move(*desc1_)); > > if (desc1_->fd() != -1 || desc2_->fd() != fd) { > std::cout << "Failed fd numerical check (move constructor)" > @@ -164,9 +164,9 @@ protected: > delete desc2_; > desc2_ = nullptr; > > - /* Test creating FileDescriptor by copy assignment. */ > - desc1_ = new FileDescriptor(); > - desc2_ = new FileDescriptor(fd_); > + /* Test creating SharedFD by copy assignment. */ > + desc1_ = new SharedFD(); > + desc2_ = new SharedFD(fd_); > > fd = desc2_->fd(); > *desc1_ = *desc2_; > @@ -188,9 +188,9 @@ protected: > delete desc2_; > desc2_ = nullptr; > > - /* Test creating FileDescriptor by move assignment. */ > - desc1_ = new FileDescriptor(); > - desc2_ = new FileDescriptor(fd_); > + /* Test creating SharedFD by move assignment. */ > + desc1_ = new SharedFD(); > + desc2_ = new SharedFD(fd_); > > fd = desc2_->fd(); > *desc1_ = std::move(*desc2_); > @@ -237,7 +237,7 @@ private: > > int fd_; > ino_t inodeNr_; > - FileDescriptor *desc1_, *desc2_; > + SharedFD *desc1_, *desc2_; > }; > > -TEST_REGISTER(FileDescriptorTest) > +TEST_REGISTER(SharedFDTest) > diff --git a/utils/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl b/utils/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl > index d856339aa9ee..c37c4941b528 100644 > --- a/utils/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl > +++ b/utils/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl > @@ -237,7 +237,7 @@ void {{proxy_name}}::recvMessage(const IPCMessage &data) > void {{proxy_name}}::{{method.mojom_name}}IPC( > std::vector<uint8_t>::const_iterator data, > size_t dataSize, > - [[maybe_unused]] const std::vector<FileDescriptor> &fds) > + [[maybe_unused]] const std::vector<SharedFD> &fds) > { > {%- for param in method.parameters %} > {{param|name}} {{param.mojom_name}}; > diff --git a/utils/ipc/generators/libcamera_templates/module_ipa_proxy.h.tmpl b/utils/ipc/generators/libcamera_templates/module_ipa_proxy.h.tmpl > index ce396c183d0c..c308dd10c7e5 100644 > --- a/utils/ipc/generators/libcamera_templates/module_ipa_proxy.h.tmpl > +++ b/utils/ipc/generators/libcamera_templates/module_ipa_proxy.h.tmpl > @@ -64,7 +64,7 @@ private: > void {{method.mojom_name}}IPC( > std::vector<uint8_t>::const_iterator data, > size_t dataSize, > - const std::vector<FileDescriptor> &fds); > + const std::vector<SharedFD> &fds); > {% endfor %} > > /* Helper class to invoke async functions in another thread. */ > diff --git a/utils/ipc/generators/libcamera_templates/proxy_functions.tmpl b/utils/ipc/generators/libcamera_templates/proxy_functions.tmpl > index ebcd2aaaafae..bac826a74c2d 100644 > --- a/utils/ipc/generators/libcamera_templates/proxy_functions.tmpl > +++ b/utils/ipc/generators/libcamera_templates/proxy_functions.tmpl > @@ -54,7 +54,7 @@ > {%- for param in params %} > std::vector<uint8_t> {{param.mojom_name}}Buf; > {%- if param|has_fd %} > - std::vector<FileDescriptor> {{param.mojom_name}}Fds; > + std::vector<SharedFD> {{param.mojom_name}}Fds; > std::tie({{param.mojom_name}}Buf, {{param.mojom_name}}Fds) = > {%- else %} > std::tie({{param.mojom_name}}Buf, std::ignore) = > diff --git a/utils/ipc/generators/libcamera_templates/serializer.tmpl b/utils/ipc/generators/libcamera_templates/serializer.tmpl > index b8ef8e7b974e..77bae36fe6b7 100644 > --- a/utils/ipc/generators/libcamera_templates/serializer.tmpl > +++ b/utils/ipc/generators/libcamera_templates/serializer.tmpl > @@ -40,7 +40,7 @@ > retData.insert(retData.end(), {{field.mojom_name}}.begin(), {{field.mojom_name}}.end()); > {%- elif field|is_fd %} > std::vector<uint8_t> {{field.mojom_name}}; > - std::vector<FileDescriptor> {{field.mojom_name}}Fds; > + std::vector<SharedFD> {{field.mojom_name}}Fds; > std::tie({{field.mojom_name}}, {{field.mojom_name}}Fds) = > IPADataSerializer<{{field|name}}>::serialize(data.{{field.mojom_name}}); > retData.insert(retData.end(), {{field.mojom_name}}.begin(), {{field.mojom_name}}.end()); > @@ -58,7 +58,7 @@ > {%- elif field|is_plain_struct or field|is_array or field|is_map or field|is_str %} > std::vector<uint8_t> {{field.mojom_name}}; > {%- if field|has_fd %} > - std::vector<FileDescriptor> {{field.mojom_name}}Fds; > + std::vector<SharedFD> {{field.mojom_name}}Fds; > std::tie({{field.mojom_name}}, {{field.mojom_name}}Fds) = > {%- else %} > std::tie({{field.mojom_name}}, std::ignore) = > @@ -177,7 +177,7 @@ > # \a struct. > #} > {%- macro serializer(struct, namespace) %} > - static std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > + static std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > serialize(const {{struct|name_full}} &data, > {%- if struct|needs_control_serializer %} > ControlSerializer *cs) > @@ -187,7 +187,7 @@ > { > std::vector<uint8_t> retData; > {%- if struct|has_fd %} > - std::vector<FileDescriptor> retFds; > + std::vector<SharedFD> retFds; > {%- endif %} > {%- for field in struct.fields %} > {{serializer_field(field, namespace, loop)}} > @@ -210,7 +210,7 @@ > {%- macro deserializer_fd(struct, namespace) %} > static {{struct|name_full}} > deserialize(std::vector<uint8_t> &data, > - std::vector<FileDescriptor> &fds, > + std::vector<SharedFD> &fds, > {%- if struct|needs_control_serializer %} > ControlSerializer *cs) > {%- else %} > @@ -224,8 +224,8 @@ > static {{struct|name_full}} > deserialize(std::vector<uint8_t>::const_iterator dataBegin, > std::vector<uint8_t>::const_iterator dataEnd, > - std::vector<FileDescriptor>::const_iterator fdsBegin, > - std::vector<FileDescriptor>::const_iterator fdsEnd, > + std::vector<SharedFD>::const_iterator fdsBegin, > + std::vector<SharedFD>::const_iterator fdsEnd, > {%- if struct|needs_control_serializer %} > ControlSerializer *cs) > {%- else %} > @@ -234,7 +234,7 @@ > { > {{struct|name_full}} ret; > std::vector<uint8_t>::const_iterator m = dataBegin; > - std::vector<FileDescriptor>::const_iterator n = fdsBegin; > + std::vector<SharedFD>::const_iterator n = fdsBegin; > > size_t dataSize = std::distance(dataBegin, dataEnd); > [[maybe_unused]] size_t fdsSize = std::distance(fdsBegin, fdsEnd); > @@ -255,7 +255,7 @@ > {%- macro deserializer_fd_simple(struct, namespace) %} > static {{struct|name_full}} > deserialize(std::vector<uint8_t> &data, > - [[maybe_unused]] std::vector<FileDescriptor> &fds, > + [[maybe_unused]] std::vector<SharedFD> &fds, > ControlSerializer *cs = nullptr) > { > return IPADataSerializer<{{struct|name_full}}>::deserialize(data.cbegin(), data.cend(), cs); > @@ -264,8 +264,8 @@ > static {{struct|name_full}} > deserialize(std::vector<uint8_t>::const_iterator dataBegin, > std::vector<uint8_t>::const_iterator dataEnd, > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsBegin, > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsBegin, > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, > ControlSerializer *cs = nullptr) > { > return IPADataSerializer<{{struct|name_full}}>::deserialize(dataBegin, dataEnd, cs); > diff --git a/utils/ipc/generators/mojom_libcamera_generator.py b/utils/ipc/generators/mojom_libcamera_generator.py > index c609f4e5c062..753bfc734e56 100644 > --- a/utils/ipc/generators/mojom_libcamera_generator.py > +++ b/utils/ipc/generators/mojom_libcamera_generator.py > @@ -77,7 +77,7 @@ def GetDefaultValue(element): > if mojom.IsEnumKind(element.kind): > return f'static_cast<{element.kind.mojom_name}>(0)' > if isinstance(element.kind, mojom.Struct) and \ > - element.kind.mojom_name == 'FileDescriptor': > + element.kind.mojom_name == 'SharedFD': > return '-1' > return '' > > @@ -140,7 +140,7 @@ def HasFd(element): > types = GetAllTypes(element) > else: > types = GetAllTypes(element.kind) > - return "FileDescriptor" in types or (attrs is not None and "hasFd" in attrs) > + return "SharedFD" in types or (attrs is not None and "hasFd" in attrs) > > def WithDefaultValues(element): > return [x for x in element if HasDefaultValue(x)] > @@ -221,7 +221,7 @@ def IsEnum(element): > return mojom.IsEnumKind(element.kind) > > def IsFd(element): > - return mojom.IsStructKind(element.kind) and element.kind.mojom_name == "FileDescriptor" > + return mojom.IsStructKind(element.kind) and element.kind.mojom_name == "SharedFD" > > def IsMap(element): > return mojom.IsMapKind(element.kind) > -- > Regards, > > Laurent Pinchart >
Hi Laurent On Mon, Nov 29, 2021 at 01:57:52AM +0200, Laurent Pinchart wrote: > Now that we have a UniqueFD class, the name FileDescriptor is ambiguous. > Rename it to SharedFD. > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> makes sense! Thanks j > --- > include/libcamera/base/file.h | 4 +- > include/libcamera/base/meson.build | 2 +- > .../base/{file_descriptor.h => shared_fd.h} | 20 +- > include/libcamera/framebuffer.h | 4 +- > .../libcamera/internal/ipa_data_serializer.h | 40 +-- > include/libcamera/internal/ipc_pipe.h | 8 +- > include/libcamera/ipa/core.mojom | 6 +- > include/libcamera/ipa/raspberrypi.mojom | 2 +- > src/android/camera_device.cpp | 2 +- > src/ipa/raspberrypi/raspberrypi.cpp | 4 +- > src/libcamera/base/file.cpp | 6 +- > src/libcamera/base/file_descriptor.cpp | 266 ------------------ > src/libcamera/base/meson.build | 2 +- > src/libcamera/base/shared_fd.cpp | 262 +++++++++++++++++ > src/libcamera/framebuffer.cpp | 6 +- > src/libcamera/ipa_data_serializer.cpp | 100 +++---- > src/libcamera/ipc_pipe.cpp | 4 +- > .../pipeline/raspberrypi/raspberrypi.cpp | 6 +- > src/libcamera/v4l2_videodevice.cpp | 6 +- > src/v4l2/v4l2_camera.h | 2 +- > test/meson.build | 2 +- > .../ipa_data_serializer_test.cpp | 14 +- > test/{file-descriptor.cpp => shared-fd.cpp} | 46 +-- > .../module_ipa_proxy.cpp.tmpl | 2 +- > .../module_ipa_proxy.h.tmpl | 2 +- > .../libcamera_templates/proxy_functions.tmpl | 2 +- > .../libcamera_templates/serializer.tmpl | 22 +- > .../generators/mojom_libcamera_generator.py | 6 +- > 28 files changed, 422 insertions(+), 426 deletions(-) > rename include/libcamera/base/{file_descriptor.h => shared_fd.h} (55%) > delete mode 100644 src/libcamera/base/file_descriptor.cpp > create mode 100644 src/libcamera/base/shared_fd.cpp > rename test/{file-descriptor.cpp => shared-fd.cpp} (80%) > > diff --git a/include/libcamera/base/file.h b/include/libcamera/base/file.h > index 47769da7abc2..691b52d6ab2d 100644 > --- a/include/libcamera/base/file.h > +++ b/include/libcamera/base/file.h > @@ -21,7 +21,7 @@ > > namespace libcamera { > > -class FileDescriptor; > +class SharedFD; > > class File > { > @@ -69,7 +69,7 @@ public: > bool unmap(uint8_t *addr); > > static bool exists(const std::string &name); > - static ino_t inode(const FileDescriptor &fd); > + static ino_t inode(const SharedFD &fd); > > private: > LIBCAMERA_DISABLE_COPY(File) > diff --git a/include/libcamera/base/meson.build b/include/libcamera/base/meson.build > index cca374a769cc..112420dab225 100644 > --- a/include/libcamera/base/meson.build > +++ b/include/libcamera/base/meson.build > @@ -11,13 +11,13 @@ libcamera_base_headers = files([ > 'event_dispatcher_poll.h', > 'event_notifier.h', > 'file.h', > - 'file_descriptor.h', > 'flags.h', > 'log.h', > 'message.h', > 'object.h', > 'private.h', > 'semaphore.h', > + 'shared_fd.h', > 'signal.h', > 'span.h', > 'thread.h', > diff --git a/include/libcamera/base/file_descriptor.h b/include/libcamera/base/shared_fd.h > similarity index 55% > rename from include/libcamera/base/file_descriptor.h > rename to include/libcamera/base/shared_fd.h > index 12a43f95d414..a786885ceb32 100644 > --- a/include/libcamera/base/file_descriptor.h > +++ b/include/libcamera/base/shared_fd.h > @@ -2,7 +2,7 @@ > /* > * Copyright (C) 2019, Google Inc. > * > - * file_descriptor.h - File descriptor wrapper > + * shared_fd.h - File descriptor wrapper with shared ownership > */ > > #pragma once > @@ -13,18 +13,18 @@ namespace libcamera { > > class UniqueFD; > > -class FileDescriptor final > +class SharedFD final > { > public: > - explicit FileDescriptor(const int &fd = -1); > - explicit FileDescriptor(int &&fd); > - explicit FileDescriptor(UniqueFD fd); > - FileDescriptor(const FileDescriptor &other); > - FileDescriptor(FileDescriptor &&other); > - ~FileDescriptor(); > + explicit SharedFD(const int &fd = -1); > + explicit SharedFD(int &&fd); > + explicit SharedFD(UniqueFD fd); > + SharedFD(const SharedFD &other); > + SharedFD(SharedFD &&other); > + ~SharedFD(); > > - FileDescriptor &operator=(const FileDescriptor &other); > - FileDescriptor &operator=(FileDescriptor &&other); > + SharedFD &operator=(const SharedFD &other); > + SharedFD &operator=(SharedFD &&other); > > bool isValid() const { return fd_ != nullptr; } > int fd() const { return fd_ ? fd_->fd() : -1; } > diff --git a/include/libcamera/framebuffer.h b/include/libcamera/framebuffer.h > index 2fbea9c5be16..357bbe189551 100644 > --- a/include/libcamera/framebuffer.h > +++ b/include/libcamera/framebuffer.h > @@ -13,7 +13,7 @@ > #include <vector> > > #include <libcamera/base/class.h> > -#include <libcamera/base/file_descriptor.h> > +#include <libcamera/base/shared_fd.h> > #include <libcamera/base/span.h> > > namespace libcamera { > @@ -51,7 +51,7 @@ class FrameBuffer final : public Extensible > public: > struct Plane { > static constexpr unsigned int kInvalidOffset = std::numeric_limits<unsigned int>::max(); > - FileDescriptor fd; > + SharedFD fd; > unsigned int offset = kInvalidOffset; > unsigned int length; > }; > diff --git a/include/libcamera/internal/ipa_data_serializer.h b/include/libcamera/internal/ipa_data_serializer.h > index c2f602d5b7de..a87449c9be48 100644 > --- a/include/libcamera/internal/ipa_data_serializer.h > +++ b/include/libcamera/internal/ipa_data_serializer.h > @@ -66,7 +66,7 @@ template<typename T> > class IPADataSerializer > { > public: > - static std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > + static std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > serialize(const T &data, ControlSerializer *cs = nullptr); > > static T deserialize(const std::vector<uint8_t> &data, > @@ -76,12 +76,12 @@ public: > ControlSerializer *cs = nullptr); > > static T deserialize(const std::vector<uint8_t> &data, > - const std::vector<FileDescriptor> &fds, > + const std::vector<SharedFD> &fds, > ControlSerializer *cs = nullptr); > static T deserialize(std::vector<uint8_t>::const_iterator dataBegin, > std::vector<uint8_t>::const_iterator dataEnd, > - std::vector<FileDescriptor>::const_iterator fdsBegin, > - std::vector<FileDescriptor>::const_iterator fdsEnd, > + std::vector<SharedFD>::const_iterator fdsBegin, > + std::vector<SharedFD>::const_iterator fdsEnd, > ControlSerializer *cs = nullptr); > }; > > @@ -104,11 +104,11 @@ template<typename V> > class IPADataSerializer<std::vector<V>> > { > public: > - static std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > + static std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > serialize(const std::vector<V> &data, ControlSerializer *cs = nullptr) > { > std::vector<uint8_t> dataVec; > - std::vector<FileDescriptor> fdsVec; > + std::vector<SharedFD> fdsVec; > > /* Serialize the length. */ > uint32_t vecLen = data.size(); > @@ -117,7 +117,7 @@ public: > /* Serialize the members. */ > for (auto const &it : data) { > std::vector<uint8_t> dvec; > - std::vector<FileDescriptor> fvec; > + std::vector<SharedFD> fvec; > > std::tie(dvec, fvec) = > IPADataSerializer<V>::serialize(it, cs); > @@ -141,11 +141,11 @@ public: > std::vector<uint8_t>::const_iterator dataEnd, > ControlSerializer *cs = nullptr) > { > - std::vector<FileDescriptor> fds; > + std::vector<SharedFD> fds; > return deserialize(dataBegin, dataEnd, fds.cbegin(), fds.end(), cs); > } > > - static std::vector<V> deserialize(std::vector<uint8_t> &data, std::vector<FileDescriptor> &fds, > + static std::vector<V> deserialize(std::vector<uint8_t> &data, std::vector<SharedFD> &fds, > ControlSerializer *cs = nullptr) > { > return deserialize(data.cbegin(), data.end(), fds.cbegin(), fds.end(), cs); > @@ -153,15 +153,15 @@ public: > > static std::vector<V> deserialize(std::vector<uint8_t>::const_iterator dataBegin, > std::vector<uint8_t>::const_iterator dataEnd, > - std::vector<FileDescriptor>::const_iterator fdsBegin, > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, > + std::vector<SharedFD>::const_iterator fdsBegin, > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, > ControlSerializer *cs = nullptr) > { > uint32_t vecLen = readPOD<uint32_t>(dataBegin, 0, dataEnd); > std::vector<V> ret(vecLen); > > std::vector<uint8_t>::const_iterator dataIter = dataBegin + 4; > - std::vector<FileDescriptor>::const_iterator fdIter = fdsBegin; > + std::vector<SharedFD>::const_iterator fdIter = fdsBegin; > for (uint32_t i = 0; i < vecLen; i++) { > uint32_t sizeofData = readPOD<uint32_t>(dataIter, 0, dataEnd); > uint32_t sizeofFds = readPOD<uint32_t>(dataIter, 4, dataEnd); > @@ -201,11 +201,11 @@ template<typename K, typename V> > class IPADataSerializer<std::map<K, V>> > { > public: > - static std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > + static std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > serialize(const std::map<K, V> &data, ControlSerializer *cs = nullptr) > { > std::vector<uint8_t> dataVec; > - std::vector<FileDescriptor> fdsVec; > + std::vector<SharedFD> fdsVec; > > /* Serialize the length. */ > uint32_t mapLen = data.size(); > @@ -214,7 +214,7 @@ public: > /* Serialize the members. */ > for (auto const &it : data) { > std::vector<uint8_t> dvec; > - std::vector<FileDescriptor> fvec; > + std::vector<SharedFD> fvec; > > std::tie(dvec, fvec) = > IPADataSerializer<K>::serialize(it.first, cs); > @@ -247,11 +247,11 @@ public: > std::vector<uint8_t>::const_iterator dataEnd, > ControlSerializer *cs = nullptr) > { > - std::vector<FileDescriptor> fds; > + std::vector<SharedFD> fds; > return deserialize(dataBegin, dataEnd, fds.cbegin(), fds.end(), cs); > } > > - static std::map<K, V> deserialize(std::vector<uint8_t> &data, std::vector<FileDescriptor> &fds, > + static std::map<K, V> deserialize(std::vector<uint8_t> &data, std::vector<SharedFD> &fds, > ControlSerializer *cs = nullptr) > { > return deserialize(data.cbegin(), data.end(), fds.cbegin(), fds.end(), cs); > @@ -259,8 +259,8 @@ public: > > static std::map<K, V> deserialize(std::vector<uint8_t>::const_iterator dataBegin, > std::vector<uint8_t>::const_iterator dataEnd, > - std::vector<FileDescriptor>::const_iterator fdsBegin, > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, > + std::vector<SharedFD>::const_iterator fdsBegin, > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, > ControlSerializer *cs = nullptr) > { > std::map<K, V> ret; > @@ -268,7 +268,7 @@ public: > uint32_t mapLen = readPOD<uint32_t>(dataBegin, 0, dataEnd); > > std::vector<uint8_t>::const_iterator dataIter = dataBegin + 4; > - std::vector<FileDescriptor>::const_iterator fdIter = fdsBegin; > + std::vector<SharedFD>::const_iterator fdIter = fdsBegin; > for (uint32_t i = 0; i < mapLen; i++) { > uint32_t sizeofData = readPOD<uint32_t>(dataIter, 0, dataEnd); > uint32_t sizeofFds = readPOD<uint32_t>(dataIter, 4, dataEnd); > diff --git a/include/libcamera/internal/ipc_pipe.h b/include/libcamera/internal/ipc_pipe.h > index 986f8d886fa6..ab5dd67c3813 100644 > --- a/include/libcamera/internal/ipc_pipe.h > +++ b/include/libcamera/internal/ipc_pipe.h > @@ -9,7 +9,7 @@ > > #include <vector> > > -#include <libcamera/base/file_descriptor.h> > +#include <libcamera/base/shared_fd.h> > #include <libcamera/base/signal.h> > > #include "libcamera/internal/ipc_unixsocket.h" > @@ -33,17 +33,17 @@ public: > > Header &header() { return header_; } > std::vector<uint8_t> &data() { return data_; } > - std::vector<FileDescriptor> &fds() { return fds_; } > + std::vector<SharedFD> &fds() { return fds_; } > > const Header &header() const { return header_; } > const std::vector<uint8_t> &data() const { return data_; } > - const std::vector<FileDescriptor> &fds() const { return fds_; } > + const std::vector<SharedFD> &fds() const { return fds_; } > > private: > Header header_; > > std::vector<uint8_t> data_; > - std::vector<FileDescriptor> fds_; > + std::vector<SharedFD> fds_; > }; > > class IPCPipe > diff --git a/include/libcamera/ipa/core.mojom b/include/libcamera/ipa/core.mojom > index f7eff0c7ab8c..74f3339e56f2 100644 > --- a/include/libcamera/ipa/core.mojom > +++ b/include/libcamera/ipa/core.mojom > @@ -32,7 +32,7 @@ module libcamera; > * - This attribute instructs the build system that a (de)serializer is > * available for the type and there's no need to generate one > * - hasFd - struct fields or empty structs only > - * - Designate that this field or empty struct contains a FileDescriptor > + * - Designate that this field or empty struct contains a SharedFD > * > * Rules: > * - If the type is defined in a libcamera C++ header *and* a (de)serializer is > @@ -60,7 +60,7 @@ module libcamera; > * - In mojom, reference the type as FrameBuffer.Plane and only as map/array > * member > * - [skipHeader] and [skipSerdes] only work here in core.mojom > - * - If a field in a struct has a FileDescriptor, but is not explicitly > + * - If a field in a struct has a SharedFD, but is not explicitly > * defined so in mojom, then the field must be marked with the [hasFd] > * attribute > * > @@ -71,7 +71,7 @@ module libcamera; > */ > [skipSerdes, skipHeader] struct ControlInfoMap {}; > [skipSerdes, skipHeader] struct ControlList {}; > -[skipSerdes, skipHeader] struct FileDescriptor {}; > +[skipSerdes, skipHeader] struct SharedFD {}; > > [skipHeader] struct Point { > int32 x; > diff --git a/include/libcamera/ipa/raspberrypi.mojom b/include/libcamera/ipa/raspberrypi.mojom > index e453d46cb14f..acd3cafe6c91 100644 > --- a/include/libcamera/ipa/raspberrypi.mojom > +++ b/include/libcamera/ipa/raspberrypi.mojom > @@ -35,7 +35,7 @@ struct ISPConfig { > > struct IPAConfig { > uint32 transform; > - libcamera.FileDescriptor lsTableHandle; > + libcamera.SharedFD lsTableHandle; > }; > > struct StartConfig { > diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp > index f2e0bdbdbbf6..1938b10509fa 100644 > --- a/src/android/camera_device.cpp > +++ b/src/android/camera_device.cpp > @@ -725,7 +725,7 @@ CameraDevice::createFrameBuffer(const buffer_handle_t camera3buffer, > > std::vector<FrameBuffer::Plane> planes(buf.numPlanes()); > for (size_t i = 0; i < buf.numPlanes(); ++i) { > - FileDescriptor fd{ camera3buffer->data[i] }; > + SharedFD fd{ camera3buffer->data[i] }; > if (!fd.isValid()) { > LOG(HAL, Fatal) << "No valid fd"; > return nullptr; > diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp > index c6aec09046f7..aaf629eeb3fc 100644 > --- a/src/ipa/raspberrypi/raspberrypi.cpp > +++ b/src/ipa/raspberrypi/raspberrypi.cpp > @@ -15,8 +15,8 @@ > > #include <linux/bcm2835-isp.h> > > -#include <libcamera/base/file_descriptor.h> > #include <libcamera/base/log.h> > +#include <libcamera/base/shared_fd.h> > #include <libcamera/base/span.h> > > #include <libcamera/control_ids.h> > @@ -164,7 +164,7 @@ private: > bool processPending_; > > /* LS table allocation passed in from the pipeline handler. */ > - FileDescriptor lsTableHandle_; > + SharedFD lsTableHandle_; > void *lsTable_; > > /* Distinguish the first camera start from others. */ > diff --git a/src/libcamera/base/file.cpp b/src/libcamera/base/file.cpp > index 66c73c406198..3ca9839bb989 100644 > --- a/src/libcamera/base/file.cpp > +++ b/src/libcamera/base/file.cpp > @@ -14,8 +14,8 @@ > #include <sys/types.h> > #include <unistd.h> > > -#include <libcamera/base/file_descriptor.h> > #include <libcamera/base/log.h> > +#include <libcamera/base/shared_fd.h> > > /** > * \file base/file.h > @@ -473,11 +473,11 @@ bool File::exists(const std::string &name) > } > > /** > - * \brief Retrieve the inode of a FileDescriptor > + * \brief Retrieve the inode of a SharedFD > * > * \return The file descriptor inode on success, or 0 on error > */ > -ino_t File::inode(const FileDescriptor &fd) > +ino_t File::inode(const SharedFD &fd) > { > if (!fd.isValid()) > return 0; > diff --git a/src/libcamera/base/file_descriptor.cpp b/src/libcamera/base/file_descriptor.cpp > deleted file mode 100644 > index a83bf52c31e6..000000000000 > --- a/src/libcamera/base/file_descriptor.cpp > +++ /dev/null > @@ -1,266 +0,0 @@ > -/* SPDX-License-Identifier: LGPL-2.1-or-later */ > -/* > - * Copyright (C) 2019, Google Inc. > - * > - * file_descriptor.cpp - File descriptor wrapper > - */ > - > -#include <libcamera/base/file_descriptor.h> > - > -#include <string.h> > -#include <sys/types.h> > -#include <unistd.h> > -#include <utility> > - > -#include <libcamera/base/log.h> > -#include <libcamera/base/unique_fd.h> > - > -/** > - * \file base/file_descriptor.h > - * \brief File descriptor wrapper > - */ > - > -namespace libcamera { > - > -LOG_DEFINE_CATEGORY(FileDescriptor) > - > -/** > - * \class FileDescriptor > - * \brief RAII-style wrapper for file descriptors > - * > - * The FileDescriptor class provides RAII-style lifetime management of file > - * descriptors with an efficient mechanism for ownership sharing. At its core, > - * an internal Descriptor object wraps a file descriptor (expressed as a signed > - * integer) with an RAII-style interface. The Descriptor is then implicitly > - * shared with all FileDescriptor instances constructed as copies. > - * > - * When constructed from a numerical file descriptor, the FileDescriptor > - * instance either duplicates or takes over the file descriptor: > - * > - * - The FileDescriptor(const int &) constructor duplicates the numerical file > - * descriptor and wraps the duplicate in a Descriptor. The caller is > - * responsible for closing the original file descriptor, and the value > - * returned by fd() will be different from the value passed to the > - * constructor. > - * > - * - The FileDescriptor(int &&) constructor takes over the numerical file > - * descriptor and wraps it in a Descriptor. The caller shall not touch the > - * original file descriptor once the function returns, and the value returned > - * by fd() will be identical to the value passed to the constructor. > - * > - * The copy constructor and assignment operator create copies that share the > - * Descriptor, while the move versions of those functions additionally make the > - * other FileDescriptor invalid. When the last FileDescriptor that references a > - * Descriptor is destroyed, the file descriptor is closed. > - * > - * The numerical file descriptor is available through the fd() function. All > - * FileDescriptor instances created as copies of a FileDescriptor will report > - * the same fd() value. Callers can perform operations on the fd(), but shall > - * never close it manually. > - */ > - > -/** > - * \brief Create a FileDescriptor copying a given \a fd > - * \param[in] fd File descriptor > - * > - * Construct a FileDescriptor from a numerical file descriptor by duplicating > - * the \a fd, and take ownership of the copy. The original \a fd is left > - * untouched, and the caller is responsible for closing it when appropriate. > - * The duplicated file descriptor will be closed automatically when all > - * FileDescriptor instances that reference it are destroyed. > - * > - * If the \a fd is negative, the FileDescriptor is constructed as invalid and > - * the fd() function will return -1. > - */ > -FileDescriptor::FileDescriptor(const int &fd) > -{ > - if (fd < 0) > - return; > - > - fd_ = std::make_shared<Descriptor>(fd, true); > - if (fd_->fd() < 0) > - fd_.reset(); > -} > - > -/** > - * \brief Create a FileDescriptor taking ownership of a given \a fd > - * \param[in] fd File descriptor > - * > - * Construct a FileDescriptor from a numerical file descriptor by taking > - * ownership of the \a fd. The original \a fd is set to -1 and shall not be > - * touched by the caller anymore. In particular, the caller shall not close the > - * original \a fd manually. The duplicated file descriptor will be closed > - * automatically when all FileDescriptor instances that reference it are > - * destroyed. > - * > - * If the \a fd is negative, the FileDescriptor is constructed as invalid and > - * the fd() function will return -1. > - */ > -FileDescriptor::FileDescriptor(int &&fd) > -{ > - if (fd < 0) > - return; > - > - fd_ = std::make_shared<Descriptor>(fd, false); > - /* > - * The Descriptor constructor can't have failed here, as it took over > - * the fd without duplicating it. Just set the original fd to -1 to > - * implement move semantics. > - */ > - fd = -1; > -} > - > -/** > - * \brief Create a FileDescriptor taking ownership of a given UniqueFD \a fd > - * \param[in] fd UniqueFD > - * > - * Construct a FileDescriptor from UniqueFD by taking ownership of the \a fd. > - * The original \a fd becomes invalid. > - */ > -FileDescriptor::FileDescriptor(UniqueFD fd) > - : FileDescriptor(fd.release()) > -{ > -} > - > -/** > - * \brief Copy constructor, create a FileDescriptor from a copy of \a other > - * \param[in] other The other FileDescriptor > - * > - * Copying a FileDescriptor implicitly shares ownership of the wrapped file > - * descriptor. The original FileDescriptor is left untouched, and the caller is > - * responsible for destroying it when appropriate. The wrapped file descriptor > - * will be closed automatically when all FileDescriptor instances that > - * reference it are destroyed. > - */ > -FileDescriptor::FileDescriptor(const FileDescriptor &other) > - : fd_(other.fd_) > -{ > -} > - > -/** > - * \brief Move constructor, create a FileDescriptor by taking over \a other > - * \param[in] other The other FileDescriptor > - * > - * Moving a FileDescriptor moves the reference to the wrapped descriptor owned > - * by \a other to the new FileDescriptor. The \a other FileDescriptor is > - * invalidated and its fd() function will return -1. The wrapped file descriptor > - * will be closed automatically when all FileDescriptor instances that > - * reference it are destroyed. > - */ > -FileDescriptor::FileDescriptor(FileDescriptor &&other) > - : fd_(std::move(other.fd_)) > -{ > -} > - > -/** > - * \brief Destroy the FileDescriptor instance > - * > - * Destroying a FileDescriptor instance releases its reference to the wrapped > - * descriptor, if any. When the last instance that references a wrapped > - * descriptor is destroyed, the file descriptor is automatically closed. > - */ > -FileDescriptor::~FileDescriptor() > -{ > -} > - > -/** > - * \brief Copy assignment operator, replace the wrapped file descriptor with a > - * copy of \a other > - * \param[in] other The other FileDescriptor > - * > - * Copying a FileDescriptor creates a new reference to the wrapped file > - * descriptor owner by \a other. If \a other is invalid, *this will also be > - * invalid. The original FileDescriptor is left untouched, and the caller is > - * responsible for destroying it when appropriate. The wrapped file descriptor > - * will be closed automatically when all FileDescriptor instances that > - * reference it are destroyed. > - * > - * \return A reference to this FileDescriptor > - */ > -FileDescriptor &FileDescriptor::operator=(const FileDescriptor &other) > -{ > - fd_ = other.fd_; > - > - return *this; > -} > - > -/** > - * \brief Move assignment operator, replace the wrapped file descriptor by > - * taking over \a other > - * \param[in] other The other FileDescriptor > - * > - * Moving a FileDescriptor moves the reference to the wrapped descriptor owned > - * by \a other to the new FileDescriptor. If \a other is invalid, *this will > - * also be invalid. The \a other FileDescriptor is invalidated and its fd() > - * function will return -1. The wrapped file descriptor will be closed > - * automatically when all FileDescriptor instances that reference it are > - * destroyed. > - * > - * \return A reference to this FileDescriptor > - */ > -FileDescriptor &FileDescriptor::operator=(FileDescriptor &&other) > -{ > - fd_ = std::move(other.fd_); > - > - return *this; > -} > - > -/** > - * \fn FileDescriptor::isValid() > - * \brief Check if the FileDescriptor instance is valid > - * \return True if the FileDescriptor is valid, false otherwise > - */ > - > -/** > - * \fn FileDescriptor::fd() > - * \brief Retrieve the numerical file descriptor > - * \return The numerical file descriptor, which may be -1 if the FileDescriptor > - * instance is invalid > - */ > - > -/** > - * \brief Duplicate a FileDescriptor > - * > - * Duplicating a FileDescriptor creates a duplicate of the wrapped file > - * descriptor and returns a UniqueFD that owns the duplicate. The fd() function > - * of the original and the get() function of the duplicate will return different > - * values. The duplicate instance will not be affected by destruction of the > - * original instance or its copies. > - * > - * \return A UniqueFD owning a duplicate of the original file descriptor > - */ > -UniqueFD FileDescriptor::dup() const > -{ > - int dupFd = ::dup(fd()); > - if (dupFd == -1) { > - int ret = -errno; > - LOG(FileDescriptor, Error) > - << "Failed to dup() fd: " << strerror(-ret); > - } > - > - return UniqueFD(dupFd); > -} > - > -FileDescriptor::Descriptor::Descriptor(int fd, bool duplicate) > -{ > - if (!duplicate) { > - fd_ = fd; > - return; > - } > - > - /* Failing to dup() a fd should not happen and is fatal. */ > - fd_ = ::dup(fd); > - if (fd_ == -1) { > - int ret = -errno; > - LOG(FileDescriptor, Fatal) > - << "Failed to dup() fd: " << strerror(-ret); > - } > -} > - > -FileDescriptor::Descriptor::~Descriptor() > -{ > - if (fd_ != -1) > - close(fd_); > -} > - > -} /* namespace libcamera */ > diff --git a/src/libcamera/base/meson.build b/src/libcamera/base/meson.build > index b0d85bc19245..ccb746c27466 100644 > --- a/src/libcamera/base/meson.build > +++ b/src/libcamera/base/meson.build > @@ -8,12 +8,12 @@ libcamera_base_sources = files([ > 'event_dispatcher_poll.cpp', > 'event_notifier.cpp', > 'file.cpp', > - 'file_descriptor.cpp', > 'flags.cpp', > 'log.cpp', > 'message.cpp', > 'object.cpp', > 'semaphore.cpp', > + 'shared_fd.cpp', > 'signal.cpp', > 'thread.cpp', > 'timer.cpp', > diff --git a/src/libcamera/base/shared_fd.cpp b/src/libcamera/base/shared_fd.cpp > new file mode 100644 > index 000000000000..05b6892f7e19 > --- /dev/null > +++ b/src/libcamera/base/shared_fd.cpp > @@ -0,0 +1,262 @@ > +/* SPDX-License-Identifier: LGPL-2.1-or-later */ > +/* > + * Copyright (C) 2019, Google Inc. > + * > + * shared_fd.cpp - File descriptor wrapper with shared ownership > + */ > + > +#include <libcamera/base/shared_fd.h> > + > +#include <string.h> > +#include <sys/types.h> > +#include <unistd.h> > +#include <utility> > + > +#include <libcamera/base/log.h> > +#include <libcamera/base/unique_fd.h> > + > +/** > + * \file base/shared_fd.h > + * \brief File descriptor wrapper > + */ > + > +namespace libcamera { > + > +LOG_DEFINE_CATEGORY(SharedFD) > + > +/** > + * \class SharedFD > + * \brief RAII-style wrapper for file descriptors > + * > + * The SharedFD class provides RAII-style lifetime management of file > + * descriptors with an efficient mechanism for ownership sharing. At its core, > + * an internal Descriptor object wraps a file descriptor (expressed as a signed > + * integer) with an RAII-style interface. The Descriptor is then implicitly > + * shared with all SharedFD instances constructed as copies. > + * > + * When constructed from a numerical file descriptor, the SharedFD instance > + * either duplicates or takes over the file descriptor: > + * > + * - The SharedFD(const int &) constructor duplicates the numerical file > + * descriptor and wraps the duplicate in a Descriptor. The caller is > + * responsible for closing the original file descriptor, and the value > + * returned by fd() will be different from the value passed to the > + * constructor. > + * > + * - The SharedFD(int &&) constructor takes over the numerical file descriptor > + * and wraps it in a Descriptor. The caller shall not touch the original file > + * descriptor once the function returns, and the value returned by fd() will > + * be identical to the value passed to the constructor. > + * > + * The copy constructor and assignment operator create copies that share the > + * Descriptor, while the move versions of those functions additionally make the > + * other SharedFD invalid. When the last SharedFD that references a Descriptor > + * is destroyed, the file descriptor is closed. > + * > + * The numerical file descriptor is available through the fd() function. All > + * SharedFD instances created as copies of a SharedFD will report the same fd() > + * value. Callers can perform operations on the fd(), but shall never close it > + * manually. > + */ > + > +/** > + * \brief Create a SharedFD copying a given \a fd > + * \param[in] fd File descriptor > + * > + * Construct a SharedFD from a numerical file descriptor by duplicating the > + * \a fd, and take ownership of the copy. The original \a fd is left untouched, > + * and the caller is responsible for closing it when appropriate. The duplicated > + * file descriptor will be closed automatically when all SharedFD instances that > + * reference it are destroyed. > + * > + * If the \a fd is negative, the SharedFD is constructed as invalid and the fd() > + * function will return -1. > + */ > +SharedFD::SharedFD(const int &fd) > +{ > + if (fd < 0) > + return; > + > + fd_ = std::make_shared<Descriptor>(fd, true); > + if (fd_->fd() < 0) > + fd_.reset(); > +} > + > +/** > + * \brief Create a SharedFD taking ownership of a given \a fd > + * \param[in] fd File descriptor > + * > + * Construct a SharedFD from a numerical file descriptor by taking ownership of > + * the \a fd. The original \a fd is set to -1 and shall not be touched by the > + * caller anymore. In particular, the caller shall not close the original \a fd > + * manually. The duplicated file descriptor will be closed automatically when > + * all SharedFD instances that reference it are destroyed. > + * > + * If the \a fd is negative, the SharedFD is constructed as invalid and the fd() > + * function will return -1. > + */ > +SharedFD::SharedFD(int &&fd) > +{ > + if (fd < 0) > + return; > + > + fd_ = std::make_shared<Descriptor>(fd, false); > + /* > + * The Descriptor constructor can't have failed here, as it took over > + * the fd without duplicating it. Just set the original fd to -1 to > + * implement move semantics. > + */ > + fd = -1; > +} > + > +/** > + * \brief Create a SharedFD taking ownership of a given UniqueFD \a fd > + * \param[in] fd UniqueFD > + * > + * Construct a SharedFD from UniqueFD by taking ownership of the \a fd. The > + * original \a fd becomes invalid. > + */ > +SharedFD::SharedFD(UniqueFD fd) > + : SharedFD(fd.release()) > +{ > +} > + > +/** > + * \brief Copy constructor, create a SharedFD from a copy of \a other > + * \param[in] other The other SharedFD > + * > + * Copying a SharedFD implicitly shares ownership of the wrapped file > + * descriptor. The original SharedFD is left untouched, and the caller is > + * responsible for destroying it when appropriate. The wrapped file descriptor > + * will be closed automatically when all SharedFD instances that reference it > + * are destroyed. > + */ > +SharedFD::SharedFD(const SharedFD &other) > + : fd_(other.fd_) > +{ > +} > + > +/** > + * \brief Move constructor, create a SharedFD by taking over \a other > + * \param[in] other The other SharedFD > + * > + * Moving a SharedFD moves the reference to the wrapped descriptor owned by > + * \a other to the new SharedFD. The \a other SharedFD is invalidated and its > + * fd() function will return -1. The wrapped file descriptor will be closed > + * automatically when all SharedFD instances that reference it are destroyed. > + */ > +SharedFD::SharedFD(SharedFD &&other) > + : fd_(std::move(other.fd_)) > +{ > +} > + > +/** > + * \brief Destroy the SharedFD instance > + * > + * Destroying a SharedFD instance releases its reference to the wrapped > + * descriptor, if any. When the last instance that references a wrapped > + * descriptor is destroyed, the file descriptor is automatically closed. > + */ > +SharedFD::~SharedFD() > +{ > +} > + > +/** > + * \brief Copy assignment operator, replace the wrapped file descriptor with a > + * copy of \a other > + * \param[in] other The other SharedFD > + * > + * Copying a SharedFD creates a new reference to the wrapped file descriptor > + * owner by \a other. If \a other is invalid, *this will also be invalid. The > + * original SharedFD is left untouched, and the caller is responsible for > + * destroying it when appropriate. The wrapped file descriptor will be closed > + * automatically when all SharedFD instances that reference it are destroyed. > + * > + * \return A reference to this SharedFD > + */ > +SharedFD &SharedFD::operator=(const SharedFD &other) > +{ > + fd_ = other.fd_; > + > + return *this; > +} > + > +/** > + * \brief Move assignment operator, replace the wrapped file descriptor by > + * taking over \a other > + * \param[in] other The other SharedFD > + * > + * Moving a SharedFD moves the reference to the wrapped descriptor owned by > + * \a other to the new SharedFD. If \a other is invalid, *this will also be > + * invalid. The \a other SharedFD is invalidated and its fd() function will > + * return -1. The wrapped file descriptor will be closed automatically when > + * all SharedFD instances that reference it are destroyed. > + * > + * \return A reference to this SharedFD > + */ > +SharedFD &SharedFD::operator=(SharedFD &&other) > +{ > + fd_ = std::move(other.fd_); > + > + return *this; > +} > + > +/** > + * \fn SharedFD::isValid() > + * \brief Check if the SharedFD instance is valid > + * \return True if the SharedFD is valid, false otherwise > + */ > + > +/** > + * \fn SharedFD::fd() > + * \brief Retrieve the numerical file descriptor > + * \return The numerical file descriptor, which may be -1 if the SharedFD > + * instance is invalid > + */ > + > +/** > + * \brief Duplicate a SharedFD > + * > + * Duplicating a SharedFD creates a duplicate of the wrapped file descriptor and > + * returns a UniqueFD that owns the duplicate. The fd() function of the original > + * and the get() function of the duplicate will return different values. The > + * duplicate instance will not be affected by destruction of the original > + * instance or its copies. > + * > + * \return A UniqueFD owning a duplicate of the original file descriptor > + */ > +UniqueFD SharedFD::dup() const > +{ > + int dupFd = ::dup(fd()); > + if (dupFd == -1) { > + int ret = -errno; > + LOG(SharedFD, Error) > + << "Failed to dup() fd: " << strerror(-ret); > + } > + > + return UniqueFD(dupFd); > +} > + > +SharedFD::Descriptor::Descriptor(int fd, bool duplicate) > +{ > + if (!duplicate) { > + fd_ = fd; > + return; > + } > + > + /* Failing to dup() a fd should not happen and is fatal. */ > + fd_ = ::dup(fd); > + if (fd_ == -1) { > + int ret = -errno; > + LOG(SharedFD, Fatal) > + << "Failed to dup() fd: " << strerror(-ret); > + } > +} > + > +SharedFD::Descriptor::~Descriptor() > +{ > + if (fd_ != -1) > + close(fd_); > +} > + > +} /* namespace libcamera */ > diff --git a/src/libcamera/framebuffer.cpp b/src/libcamera/framebuffer.cpp > index f5bcf107d7aa..0a5bf7fdbeb7 100644 > --- a/src/libcamera/framebuffer.cpp > +++ b/src/libcamera/framebuffer.cpp > @@ -180,9 +180,9 @@ FrameBuffer::Private::Private() > * offset and length. > * > * To support DMA access, planes are associated with dmabuf objects represented > - * by FileDescriptor handles. The Plane class doesn't handle mapping of the > - * memory to the CPU, but applications and IPAs may use the dmabuf file > - * descriptors to map the plane memory with mmap() and access its contents. > + * by SharedFD handles. The Plane class doesn't handle mapping of the memory to > + * the CPU, but applications and IPAs may use the dmabuf file descriptors to map > + * the plane memory with mmap() and access its contents. > * > * \todo Specify how an application shall decide whether to use a single or > * multiple dmabufs, based on the camera requirements. > diff --git a/src/libcamera/ipa_data_serializer.cpp b/src/libcamera/ipa_data_serializer.cpp > index 82ec9b20a411..0a259305afa2 100644 > --- a/src/libcamera/ipa_data_serializer.cpp > +++ b/src/libcamera/ipa_data_serializer.cpp > @@ -31,7 +31,7 @@ LOG_DEFINE_CATEGORY(IPADataSerializer) > * > * \todo Harden the vector and map deserializer > * > - * \todo For FileDescriptors, instead of storing a validity flag, store an > + * \todo For SharedFDs, instead of storing a validity flag, store an > * index into the fd array. This will allow us to use views instead of copying. > */ > > @@ -112,7 +112,7 @@ namespace { > * \param[in] cs ControlSerializer > * > * This version of deserialize() can be used if the object type \a T and its > - * members don't have any FileDescriptor. > + * members don't have any SharedFD. > * > * \a cs is only necessary if the object type \a T or its members contain > * ControlList or ControlInfoMap. > @@ -132,7 +132,7 @@ namespace { > * \param[in] cs ControlSerializer > * > * This version of deserialize() can be used if the object type \a T and its > - * members don't have any FileDescriptor. > + * members don't have any SharedFD. > * > * \a cs is only necessary if the object type \a T or its members contain > * ControlList or ControlInfoMap. > @@ -143,7 +143,7 @@ namespace { > /** > * \fn template<typename T> IPADataSerializer<T>::deserialize( > * const std::vector<uint8_t> &data, > - * const std::vector<FileDescriptor> &fds, > + * const std::vector<SharedFD> &fds, > * ControlSerializer *cs = nullptr) > * \brief Deserialize byte vector and fd vector into an object > * \tparam T Type of object to deserialize to > @@ -152,7 +152,7 @@ namespace { > * \param[in] cs ControlSerializer > * > * This version of deserialize() (or the iterator version) must be used if > - * the object type \a T or its members contain FileDescriptor. > + * the object type \a T or its members contain SharedFD. > * > * \a cs is only necessary if the object type \a T or its members contain > * ControlList or ControlInfoMap. > @@ -164,8 +164,8 @@ namespace { > * \fn template<typename T> IPADataSerializer::deserialize( > * std::vector<uint8_t>::const_iterator dataBegin, > * std::vector<uint8_t>::const_iterator dataEnd, > - * std::vector<FileDescriptor>::const_iterator fdsBegin, > - * std::vector<FileDescriptor>::const_iterator fdsEnd, > + * std::vector<SharedFD>::const_iterator fdsBegin, > + * std::vector<SharedFD>::const_iterator fdsEnd, > * ControlSerializer *cs = nullptr) > * \brief Deserialize byte vector and fd vector into an object > * \tparam T Type of object to deserialize to > @@ -176,7 +176,7 @@ namespace { > * \param[in] cs ControlSerializer > * > * This version of deserialize() (or the vector version) must be used if > - * the object type \a T or its members contain FileDescriptor. > + * the object type \a T or its members contain SharedFD. > * > * \a cs is only necessary if the object type \a T or its members contain > * ControlList or ControlInfoMap. > @@ -189,7 +189,7 @@ namespace { > #define DEFINE_POD_SERIALIZER(type) \ > \ > template<> \ > -std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> \ > +std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> \ > IPADataSerializer<type>::serialize(const type &data, \ > [[maybe_unused]] ControlSerializer *cs) \ > { \ > @@ -217,7 +217,7 @@ type IPADataSerializer<type>::deserialize(const std::vector<uint8_t> &data, \ > \ > template<> \ > type IPADataSerializer<type>::deserialize(const std::vector<uint8_t> &data, \ > - [[maybe_unused]] const std::vector<FileDescriptor> &fds, \ > + [[maybe_unused]] const std::vector<SharedFD> &fds, \ > ControlSerializer *cs) \ > { \ > return deserialize(data.cbegin(), data.end(), cs); \ > @@ -226,8 +226,8 @@ type IPADataSerializer<type>::deserialize(const std::vector<uint8_t> &data, \ > template<> \ > type IPADataSerializer<type>::deserialize(std::vector<uint8_t>::const_iterator dataBegin, \ > std::vector<uint8_t>::const_iterator dataEnd, \ > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsBegin, \ > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, \ > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsBegin, \ > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, \ > ControlSerializer *cs) \ > { \ > return deserialize(dataBegin, dataEnd, cs); \ > @@ -251,7 +251,7 @@ DEFINE_POD_SERIALIZER(double) > * function parameter serdes). > */ > template<> > -std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > +std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > IPADataSerializer<std::string>::serialize(const std::string &data, > [[maybe_unused]] ControlSerializer *cs) > { > @@ -278,7 +278,7 @@ IPADataSerializer<std::string>::deserialize(std::vector<uint8_t>::const_iterator > template<> > std::string > IPADataSerializer<std::string>::deserialize(const std::vector<uint8_t> &data, > - [[maybe_unused]] const std::vector<FileDescriptor> &fds, > + [[maybe_unused]] const std::vector<SharedFD> &fds, > [[maybe_unused]] ControlSerializer *cs) > { > return { data.cbegin(), data.cend() }; > @@ -288,8 +288,8 @@ template<> > std::string > IPADataSerializer<std::string>::deserialize(std::vector<uint8_t>::const_iterator dataBegin, > std::vector<uint8_t>::const_iterator dataEnd, > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsBegin, > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsBegin, > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, > [[maybe_unused]] ControlSerializer *cs) > { > return { dataBegin, dataEnd }; > @@ -307,7 +307,7 @@ IPADataSerializer<std::string>::deserialize(std::vector<uint8_t>::const_iterator > * be used. The serialized ControlInfoMap will have zero length. > */ > template<> > -std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > +std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > IPADataSerializer<ControlList>::serialize(const ControlList &data, ControlSerializer *cs) > { > if (!cs) > @@ -407,7 +407,7 @@ IPADataSerializer<ControlList>::deserialize(const std::vector<uint8_t> &data, > template<> > ControlList > IPADataSerializer<ControlList>::deserialize(const std::vector<uint8_t> &data, > - [[maybe_unused]] const std::vector<FileDescriptor> &fds, > + [[maybe_unused]] const std::vector<SharedFD> &fds, > ControlSerializer *cs) > { > return deserialize(data.cbegin(), data.end(), cs); > @@ -417,8 +417,8 @@ template<> > ControlList > IPADataSerializer<ControlList>::deserialize(std::vector<uint8_t>::const_iterator dataBegin, > std::vector<uint8_t>::const_iterator dataEnd, > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsBegin, > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsBegin, > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, > ControlSerializer *cs) > { > return deserialize(dataBegin, dataEnd, cs); > @@ -431,7 +431,7 @@ IPADataSerializer<ControlList>::deserialize(std::vector<uint8_t>::const_iterator > * X bytes - Serialized ControlInfoMap (using ControlSerializer) > */ > template<> > -std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > +std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > IPADataSerializer<ControlInfoMap>::serialize(const ControlInfoMap &map, > ControlSerializer *cs) > { > @@ -493,7 +493,7 @@ IPADataSerializer<ControlInfoMap>::deserialize(const std::vector<uint8_t> &data, > template<> > ControlInfoMap > IPADataSerializer<ControlInfoMap>::deserialize(const std::vector<uint8_t> &data, > - [[maybe_unused]] const std::vector<FileDescriptor> &fds, > + [[maybe_unused]] const std::vector<SharedFD> &fds, > ControlSerializer *cs) > { > return deserialize(data.cbegin(), data.end(), cs); > @@ -503,30 +503,30 @@ template<> > ControlInfoMap > IPADataSerializer<ControlInfoMap>::deserialize(std::vector<uint8_t>::const_iterator dataBegin, > std::vector<uint8_t>::const_iterator dataEnd, > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsBegin, > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsBegin, > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, > ControlSerializer *cs) > { > return deserialize(dataBegin, dataEnd, cs); > } > > /* > - * FileDescriptors are serialized into four bytes that tells if the > - * FileDescriptor is valid or not. If it is valid, then for serialization > - * the fd will be written to the fd vector, or for deserialization the > - * fd vector const_iterator will be valid. > + * SharedFD instances are serialized into four bytes that tells if the SharedFD > + * is valid or not. If it is valid, then for serialization the fd will be > + * written to the fd vector, or for deserialization the fd vector const_iterator > + * will be valid. > * > * This validity is necessary so that we don't send -1 fd over sendmsg(). It > * also allows us to simply send the entire fd vector into the deserializer > * and it will be recursively consumed as necessary. > */ > template<> > -std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > -IPADataSerializer<FileDescriptor>::serialize(const FileDescriptor &data, > - [[maybe_unused]] ControlSerializer *cs) > +std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > +IPADataSerializer<SharedFD>::serialize(const SharedFD &data, > + [[maybe_unused]] ControlSerializer *cs) > { > std::vector<uint8_t> dataVec; > - std::vector<FileDescriptor> fdVec; > + std::vector<SharedFD> fdVec; > > /* > * Store as uint32_t to prepare for conversion from validity flag > @@ -542,11 +542,11 @@ IPADataSerializer<FileDescriptor>::serialize(const FileDescriptor &data, > } > > template<> > -FileDescriptor IPADataSerializer<FileDescriptor>::deserialize([[maybe_unused]] std::vector<uint8_t>::const_iterator dataBegin, > - [[maybe_unused]] std::vector<uint8_t>::const_iterator dataEnd, > - std::vector<FileDescriptor>::const_iterator fdsBegin, > - std::vector<FileDescriptor>::const_iterator fdsEnd, > - [[maybe_unused]] ControlSerializer *cs) > +SharedFD IPADataSerializer<SharedFD>::deserialize([[maybe_unused]] std::vector<uint8_t>::const_iterator dataBegin, > + [[maybe_unused]] std::vector<uint8_t>::const_iterator dataEnd, > + std::vector<SharedFD>::const_iterator fdsBegin, > + std::vector<SharedFD>::const_iterator fdsEnd, > + [[maybe_unused]] ControlSerializer *cs) > { > ASSERT(std::distance(dataBegin, dataEnd) >= 4); > > @@ -554,13 +554,13 @@ FileDescriptor IPADataSerializer<FileDescriptor>::deserialize([[maybe_unused]] s > > ASSERT(!(valid && std::distance(fdsBegin, fdsEnd) < 1)); > > - return valid ? *fdsBegin : FileDescriptor(); > + return valid ? *fdsBegin : SharedFD(); > } > > template<> > -FileDescriptor IPADataSerializer<FileDescriptor>::deserialize(const std::vector<uint8_t> &data, > - const std::vector<FileDescriptor> &fds, > - [[maybe_unused]] ControlSerializer *cs) > +SharedFD IPADataSerializer<SharedFD>::deserialize(const std::vector<uint8_t> &data, > + const std::vector<SharedFD> &fds, > + [[maybe_unused]] ControlSerializer *cs) > { > return deserialize(data.cbegin(), data.end(), fds.cbegin(), fds.end()); > } > @@ -568,22 +568,22 @@ FileDescriptor IPADataSerializer<FileDescriptor>::deserialize(const std::vector< > /* > * FrameBuffer::Plane is serialized as: > * > - * 4 byte - FileDescriptor > + * 4 byte - SharedFD > * 4 bytes - uint32_t Offset > * 4 bytes - uint32_t Length > */ > template<> > -std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > +std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > IPADataSerializer<FrameBuffer::Plane>::serialize(const FrameBuffer::Plane &data, > [[maybe_unused]] ControlSerializer *cs) > { > std::vector<uint8_t> dataVec; > - std::vector<FileDescriptor> fdsVec; > + std::vector<SharedFD> fdsVec; > > std::vector<uint8_t> fdBuf; > - std::vector<FileDescriptor> fdFds; > + std::vector<SharedFD> fdFds; > std::tie(fdBuf, fdFds) = > - IPADataSerializer<FileDescriptor>::serialize(data.fd); > + IPADataSerializer<SharedFD>::serialize(data.fd); > dataVec.insert(dataVec.end(), fdBuf.begin(), fdBuf.end()); > fdsVec.insert(fdsVec.end(), fdFds.begin(), fdFds.end()); > > @@ -597,13 +597,13 @@ template<> > FrameBuffer::Plane > IPADataSerializer<FrameBuffer::Plane>::deserialize(std::vector<uint8_t>::const_iterator dataBegin, > std::vector<uint8_t>::const_iterator dataEnd, > - std::vector<FileDescriptor>::const_iterator fdsBegin, > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, > + std::vector<SharedFD>::const_iterator fdsBegin, > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, > [[maybe_unused]] ControlSerializer *cs) > { > FrameBuffer::Plane ret; > > - ret.fd = IPADataSerializer<FileDescriptor>::deserialize(dataBegin, dataBegin + 4, > + ret.fd = IPADataSerializer<SharedFD>::deserialize(dataBegin, dataBegin + 4, > fdsBegin, fdsBegin + 1); > ret.offset = readPOD<uint32_t>(dataBegin, 4, dataEnd); > ret.length = readPOD<uint32_t>(dataBegin, 8, dataEnd); > @@ -614,7 +614,7 @@ IPADataSerializer<FrameBuffer::Plane>::deserialize(std::vector<uint8_t>::const_i > template<> > FrameBuffer::Plane > IPADataSerializer<FrameBuffer::Plane>::deserialize(const std::vector<uint8_t> &data, > - const std::vector<FileDescriptor> &fds, > + const std::vector<SharedFD> &fds, > ControlSerializer *cs) > { > return deserialize(data.cbegin(), data.end(), fds.cbegin(), fds.end(), cs); > diff --git a/src/libcamera/ipc_pipe.cpp b/src/libcamera/ipc_pipe.cpp > index ad870fd4137f..3b47032de0a2 100644 > --- a/src/libcamera/ipc_pipe.cpp > +++ b/src/libcamera/ipc_pipe.cpp > @@ -87,7 +87,7 @@ IPCMessage::IPCMessage(IPCUnixSocket::Payload &payload) > data_ = std::vector<uint8_t>(payload.data.begin() + sizeof(header_), > payload.data.end()); > for (int32_t &fd : payload.fds) > - fds_.push_back(FileDescriptor(std::move(fd))); > + fds_.push_back(SharedFD(std::move(fd))); > } > > /** > @@ -112,7 +112,7 @@ IPCUnixSocket::Payload IPCMessage::payload() const > data_.data(), data_.size()); > } > > - for (const FileDescriptor &fd : fds_) > + for (const SharedFD &fd : fds_) > payload.fds.push_back(fd.fd()); > > return payload; > diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp > index ffa51a0c65ca..ea8243912a29 100644 > --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp > +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp > @@ -12,7 +12,7 @@ > #include <queue> > #include <unordered_set> > > -#include <libcamera/base/file_descriptor.h> > +#include <libcamera/base/shared_fd.h> > > #include <libcamera/camera.h> > #include <libcamera/control_ids.h> > @@ -228,7 +228,7 @@ public: > > /* DMAHEAP allocation helper. */ > RPi::DmaHeap dmaHeap_; > - FileDescriptor lsTable_; > + SharedFD lsTable_; > > std::unique_ptr<DelayedControls> delayedCtrls_; > bool sensorMetadata_; > @@ -1365,7 +1365,7 @@ int RPiCameraData::configureIPA(const CameraConfiguration *config) > if (!fd.isValid()) > return -ENOMEM; > > - lsTable_ = FileDescriptor(std::move(fd)); > + lsTable_ = SharedFD(std::move(fd)); > > /* Allow the IPA to mmap the LS table via the file descriptor. */ > /* > diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp > index 3966483a365f..97d431071def 100644 > --- a/src/libcamera/v4l2_videodevice.cpp > +++ b/src/libcamera/v4l2_videodevice.cpp > @@ -22,8 +22,8 @@ > #include <linux/version.h> > > #include <libcamera/base/event_notifier.h> > -#include <libcamera/base/file_descriptor.h> > #include <libcamera/base/log.h> > +#include <libcamera/base/shared_fd.h> > #include <libcamera/base/unique_fd.h> > #include <libcamera/base/utils.h> > > @@ -1325,7 +1325,7 @@ std::unique_ptr<FrameBuffer> V4L2VideoDevice::createBuffer(unsigned int index) > return nullptr; > > FrameBuffer::Plane plane; > - plane.fd = FileDescriptor(std::move(fd)); > + plane.fd = SharedFD(std::move(fd)); > /* > * V4L2 API doesn't provide dmabuf offset information of plane. > * Set 0 as a placeholder offset. > @@ -1354,7 +1354,7 @@ std::unique_ptr<FrameBuffer> V4L2VideoDevice::createBuffer(unsigned int index) > ASSERT(numPlanes == 1u); > > planes.resize(formatInfo_->numPlanes()); > - const FileDescriptor &fd = planes[0].fd; > + const SharedFD &fd = planes[0].fd; > size_t offset = 0; > > for (auto [i, plane] : utils::enumerate(planes)) { > diff --git a/src/v4l2/v4l2_camera.h b/src/v4l2/v4l2_camera.h > index 9817fd393d59..586347829845 100644 > --- a/src/v4l2/v4l2_camera.h > +++ b/src/v4l2/v4l2_camera.h > @@ -11,8 +11,8 @@ > #include <mutex> > #include <utility> > > -#include <libcamera/base/file_descriptor.h> > #include <libcamera/base/semaphore.h> > +#include <libcamera/base/shared_fd.h> > > #include <libcamera/camera.h> > #include <libcamera/framebuffer.h> > diff --git a/test/meson.build b/test/meson.build > index 42dfbc1f8ee9..daaa3862cdd6 100644 > --- a/test/meson.build > +++ b/test/meson.build > @@ -40,7 +40,6 @@ internal_tests = [ > ['event-dispatcher', 'event-dispatcher.cpp'], > ['event-thread', 'event-thread.cpp'], > ['file', 'file.cpp'], > - ['file-descriptor', 'file-descriptor.cpp'], > ['flags', 'flags.cpp'], > ['hotplug-cameras', 'hotplug-cameras.cpp'], > ['mapped-buffer', 'mapped-buffer.cpp'], > @@ -49,6 +48,7 @@ internal_tests = [ > ['object-delete', 'object-delete.cpp'], > ['object-invoke', 'object-invoke.cpp'], > ['pixel-format', 'pixel-format.cpp'], > + ['shared-fd', 'shared-fd.cpp'], > ['signal-threads', 'signal-threads.cpp'], > ['threads', 'threads.cpp'], > ['timer', 'timer.cpp'], > diff --git a/test/serialization/ipa_data_serializer_test.cpp b/test/serialization/ipa_data_serializer_test.cpp > index 5fcdcb8eae92..d2050a868b38 100644 > --- a/test/serialization/ipa_data_serializer_test.cpp > +++ b/test/serialization/ipa_data_serializer_test.cpp > @@ -53,7 +53,7 @@ template<typename T> > int testPodSerdes(T in) > { > std::vector<uint8_t> buf; > - std::vector<FileDescriptor> fds; > + std::vector<SharedFD> fds; > > std::tie(buf, fds) = IPADataSerializer<T>::serialize(in); > T out = IPADataSerializer<T>::deserialize(buf, fds); > @@ -72,7 +72,7 @@ int testVectorSerdes(const std::vector<T> &in, > ControlSerializer *cs = nullptr) > { > std::vector<uint8_t> buf; > - std::vector<FileDescriptor> fds; > + std::vector<SharedFD> fds; > > std::tie(buf, fds) = IPADataSerializer<std::vector<T>>::serialize(in, cs); > std::vector<T> out = IPADataSerializer<std::vector<T>>::deserialize(buf, fds, cs); > @@ -92,7 +92,7 @@ int testMapSerdes(const std::map<K, V> &in, > ControlSerializer *cs = nullptr) > { > std::vector<uint8_t> buf; > - std::vector<FileDescriptor> fds; > + std::vector<SharedFD> fds; > > std::tie(buf, fds) = IPADataSerializer<std::map<K, V>>::serialize(in, cs); > std::map<K, V> out = IPADataSerializer<std::map<K, V>>::deserialize(buf, fds, cs); > @@ -198,7 +198,7 @@ private: > ControlSerializer cs(ControlSerializer::Role::Proxy); > > /* > - * We don't test FileDescriptor serdes because it dup()s, so we > + * We don't test SharedFD serdes because it dup()s, so we > * can't check for equality. > */ > std::vector<uint8_t> vecUint8 = { 1, 2, 3, 4, 5, 6 }; > @@ -219,7 +219,7 @@ private: > }; > > std::vector<uint8_t> buf; > - std::vector<FileDescriptor> fds; > + std::vector<SharedFD> fds; > > if (testVectorSerdes(vecUint8) != TestPass) > return TestFail; > @@ -291,7 +291,7 @@ private: > { { "a", { 1, 2, 3 } }, { "b", { 4, 5, 6 } }, { "c", { 7, 8, 9 } } }; > > std::vector<uint8_t> buf; > - std::vector<FileDescriptor> fds; > + std::vector<SharedFD> fds; > > if (testMapSerdes(mapUintStr) != TestPass) > return TestFail; > @@ -359,7 +359,7 @@ private: > std::string strEmpty = ""; > > std::vector<uint8_t> buf; > - std::vector<FileDescriptor> fds; > + std::vector<SharedFD> fds; > > if (testPodSerdes(u32min) != TestPass) > return TestFail; > diff --git a/test/file-descriptor.cpp b/test/shared-fd.cpp > similarity index 80% > rename from test/file-descriptor.cpp > rename to test/shared-fd.cpp > index 76badc4c5fad..60e5d0aaa395 100644 > --- a/test/file-descriptor.cpp > +++ b/test/shared-fd.cpp > @@ -2,7 +2,7 @@ > /* > * Copyright (C) 2019, Google Inc. > * > - * file_descriptor.cpp - FileDescriptor test > + * shared_fd.cpp - SharedFD test > */ > > #include <fcntl.h> > @@ -11,7 +11,7 @@ > #include <sys/types.h> > #include <unistd.h> > > -#include <libcamera/base/file_descriptor.h> > +#include <libcamera/base/shared_fd.h> > #include <libcamera/base/utils.h> > > #include "test.h" > @@ -19,7 +19,7 @@ > using namespace libcamera; > using namespace std; > > -class FileDescriptorTest : public Test > +class SharedFDTest : public Test > { > protected: > int init() > @@ -43,8 +43,8 @@ protected: > > int run() > { > - /* Test creating empty FileDescriptor. */ > - desc1_ = new FileDescriptor(); > + /* Test creating empty SharedFD. */ > + desc1_ = new SharedFD(); > > if (desc1_->fd() != -1) { > std::cout << "Failed fd numerical check (default constructor)" > @@ -56,10 +56,10 @@ protected: > desc1_ = nullptr; > > /* > - * Test creating FileDescriptor by copying numerical file > + * Test creating SharedFD by copying numerical file > * descriptor. > */ > - desc1_ = new FileDescriptor(fd_); > + desc1_ = new SharedFD(fd_); > if (desc1_->fd() == fd_) { > std::cout << "Failed fd numerical check (lvalue ref constructor)" > << std::endl; > @@ -84,13 +84,13 @@ protected: > } > > /* > - * Test creating FileDescriptor by taking ownership of > + * Test creating SharedFD by taking ownership of > * numerical file descriptor. > */ > int dupFd = dup(fd_); > int dupFdCopy = dupFd; > > - desc1_ = new FileDescriptor(std::move(dupFd)); > + desc1_ = new SharedFD(std::move(dupFd)); > if (desc1_->fd() != dupFdCopy) { > std::cout << "Failed fd numerical check (rvalue ref constructor)" > << std::endl; > @@ -114,9 +114,9 @@ protected: > return TestFail; > } > > - /* Test creating FileDescriptor from other FileDescriptor. */ > - desc1_ = new FileDescriptor(fd_); > - desc2_ = new FileDescriptor(*desc1_); > + /* Test creating SharedFD from other SharedFD. */ > + desc1_ = new SharedFD(fd_); > + desc2_ = new SharedFD(*desc1_); > > if (desc1_->fd() == fd_ || desc2_->fd() == fd_ || desc1_->fd() != desc2_->fd()) { > std::cout << "Failed fd numerical check (copy constructor)" > @@ -142,10 +142,10 @@ protected: > delete desc2_; > desc2_ = nullptr; > > - /* Test creating FileDescriptor by taking over other FileDescriptor. */ > - desc1_ = new FileDescriptor(fd_); > + /* Test creating SharedFD by taking over other SharedFD. */ > + desc1_ = new SharedFD(fd_); > fd = desc1_->fd(); > - desc2_ = new FileDescriptor(std::move(*desc1_)); > + desc2_ = new SharedFD(std::move(*desc1_)); > > if (desc1_->fd() != -1 || desc2_->fd() != fd) { > std::cout << "Failed fd numerical check (move constructor)" > @@ -164,9 +164,9 @@ protected: > delete desc2_; > desc2_ = nullptr; > > - /* Test creating FileDescriptor by copy assignment. */ > - desc1_ = new FileDescriptor(); > - desc2_ = new FileDescriptor(fd_); > + /* Test creating SharedFD by copy assignment. */ > + desc1_ = new SharedFD(); > + desc2_ = new SharedFD(fd_); > > fd = desc2_->fd(); > *desc1_ = *desc2_; > @@ -188,9 +188,9 @@ protected: > delete desc2_; > desc2_ = nullptr; > > - /* Test creating FileDescriptor by move assignment. */ > - desc1_ = new FileDescriptor(); > - desc2_ = new FileDescriptor(fd_); > + /* Test creating SharedFD by move assignment. */ > + desc1_ = new SharedFD(); > + desc2_ = new SharedFD(fd_); > > fd = desc2_->fd(); > *desc1_ = std::move(*desc2_); > @@ -237,7 +237,7 @@ private: > > int fd_; > ino_t inodeNr_; > - FileDescriptor *desc1_, *desc2_; > + SharedFD *desc1_, *desc2_; > }; > > -TEST_REGISTER(FileDescriptorTest) > +TEST_REGISTER(SharedFDTest) > diff --git a/utils/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl b/utils/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl > index d856339aa9ee..c37c4941b528 100644 > --- a/utils/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl > +++ b/utils/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl > @@ -237,7 +237,7 @@ void {{proxy_name}}::recvMessage(const IPCMessage &data) > void {{proxy_name}}::{{method.mojom_name}}IPC( > std::vector<uint8_t>::const_iterator data, > size_t dataSize, > - [[maybe_unused]] const std::vector<FileDescriptor> &fds) > + [[maybe_unused]] const std::vector<SharedFD> &fds) > { > {%- for param in method.parameters %} > {{param|name}} {{param.mojom_name}}; > diff --git a/utils/ipc/generators/libcamera_templates/module_ipa_proxy.h.tmpl b/utils/ipc/generators/libcamera_templates/module_ipa_proxy.h.tmpl > index ce396c183d0c..c308dd10c7e5 100644 > --- a/utils/ipc/generators/libcamera_templates/module_ipa_proxy.h.tmpl > +++ b/utils/ipc/generators/libcamera_templates/module_ipa_proxy.h.tmpl > @@ -64,7 +64,7 @@ private: > void {{method.mojom_name}}IPC( > std::vector<uint8_t>::const_iterator data, > size_t dataSize, > - const std::vector<FileDescriptor> &fds); > + const std::vector<SharedFD> &fds); > {% endfor %} > > /* Helper class to invoke async functions in another thread. */ > diff --git a/utils/ipc/generators/libcamera_templates/proxy_functions.tmpl b/utils/ipc/generators/libcamera_templates/proxy_functions.tmpl > index ebcd2aaaafae..bac826a74c2d 100644 > --- a/utils/ipc/generators/libcamera_templates/proxy_functions.tmpl > +++ b/utils/ipc/generators/libcamera_templates/proxy_functions.tmpl > @@ -54,7 +54,7 @@ > {%- for param in params %} > std::vector<uint8_t> {{param.mojom_name}}Buf; > {%- if param|has_fd %} > - std::vector<FileDescriptor> {{param.mojom_name}}Fds; > + std::vector<SharedFD> {{param.mojom_name}}Fds; > std::tie({{param.mojom_name}}Buf, {{param.mojom_name}}Fds) = > {%- else %} > std::tie({{param.mojom_name}}Buf, std::ignore) = > diff --git a/utils/ipc/generators/libcamera_templates/serializer.tmpl b/utils/ipc/generators/libcamera_templates/serializer.tmpl > index b8ef8e7b974e..77bae36fe6b7 100644 > --- a/utils/ipc/generators/libcamera_templates/serializer.tmpl > +++ b/utils/ipc/generators/libcamera_templates/serializer.tmpl > @@ -40,7 +40,7 @@ > retData.insert(retData.end(), {{field.mojom_name}}.begin(), {{field.mojom_name}}.end()); > {%- elif field|is_fd %} > std::vector<uint8_t> {{field.mojom_name}}; > - std::vector<FileDescriptor> {{field.mojom_name}}Fds; > + std::vector<SharedFD> {{field.mojom_name}}Fds; > std::tie({{field.mojom_name}}, {{field.mojom_name}}Fds) = > IPADataSerializer<{{field|name}}>::serialize(data.{{field.mojom_name}}); > retData.insert(retData.end(), {{field.mojom_name}}.begin(), {{field.mojom_name}}.end()); > @@ -58,7 +58,7 @@ > {%- elif field|is_plain_struct or field|is_array or field|is_map or field|is_str %} > std::vector<uint8_t> {{field.mojom_name}}; > {%- if field|has_fd %} > - std::vector<FileDescriptor> {{field.mojom_name}}Fds; > + std::vector<SharedFD> {{field.mojom_name}}Fds; > std::tie({{field.mojom_name}}, {{field.mojom_name}}Fds) = > {%- else %} > std::tie({{field.mojom_name}}, std::ignore) = > @@ -177,7 +177,7 @@ > # \a struct. > #} > {%- macro serializer(struct, namespace) %} > - static std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > + static std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > serialize(const {{struct|name_full}} &data, > {%- if struct|needs_control_serializer %} > ControlSerializer *cs) > @@ -187,7 +187,7 @@ > { > std::vector<uint8_t> retData; > {%- if struct|has_fd %} > - std::vector<FileDescriptor> retFds; > + std::vector<SharedFD> retFds; > {%- endif %} > {%- for field in struct.fields %} > {{serializer_field(field, namespace, loop)}} > @@ -210,7 +210,7 @@ > {%- macro deserializer_fd(struct, namespace) %} > static {{struct|name_full}} > deserialize(std::vector<uint8_t> &data, > - std::vector<FileDescriptor> &fds, > + std::vector<SharedFD> &fds, > {%- if struct|needs_control_serializer %} > ControlSerializer *cs) > {%- else %} > @@ -224,8 +224,8 @@ > static {{struct|name_full}} > deserialize(std::vector<uint8_t>::const_iterator dataBegin, > std::vector<uint8_t>::const_iterator dataEnd, > - std::vector<FileDescriptor>::const_iterator fdsBegin, > - std::vector<FileDescriptor>::const_iterator fdsEnd, > + std::vector<SharedFD>::const_iterator fdsBegin, > + std::vector<SharedFD>::const_iterator fdsEnd, > {%- if struct|needs_control_serializer %} > ControlSerializer *cs) > {%- else %} > @@ -234,7 +234,7 @@ > { > {{struct|name_full}} ret; > std::vector<uint8_t>::const_iterator m = dataBegin; > - std::vector<FileDescriptor>::const_iterator n = fdsBegin; > + std::vector<SharedFD>::const_iterator n = fdsBegin; > > size_t dataSize = std::distance(dataBegin, dataEnd); > [[maybe_unused]] size_t fdsSize = std::distance(fdsBegin, fdsEnd); > @@ -255,7 +255,7 @@ > {%- macro deserializer_fd_simple(struct, namespace) %} > static {{struct|name_full}} > deserialize(std::vector<uint8_t> &data, > - [[maybe_unused]] std::vector<FileDescriptor> &fds, > + [[maybe_unused]] std::vector<SharedFD> &fds, > ControlSerializer *cs = nullptr) > { > return IPADataSerializer<{{struct|name_full}}>::deserialize(data.cbegin(), data.cend(), cs); > @@ -264,8 +264,8 @@ > static {{struct|name_full}} > deserialize(std::vector<uint8_t>::const_iterator dataBegin, > std::vector<uint8_t>::const_iterator dataEnd, > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsBegin, > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsBegin, > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, > ControlSerializer *cs = nullptr) > { > return IPADataSerializer<{{struct|name_full}}>::deserialize(dataBegin, dataEnd, cs); > diff --git a/utils/ipc/generators/mojom_libcamera_generator.py b/utils/ipc/generators/mojom_libcamera_generator.py > index c609f4e5c062..753bfc734e56 100644 > --- a/utils/ipc/generators/mojom_libcamera_generator.py > +++ b/utils/ipc/generators/mojom_libcamera_generator.py > @@ -77,7 +77,7 @@ def GetDefaultValue(element): > if mojom.IsEnumKind(element.kind): > return f'static_cast<{element.kind.mojom_name}>(0)' > if isinstance(element.kind, mojom.Struct) and \ > - element.kind.mojom_name == 'FileDescriptor': > + element.kind.mojom_name == 'SharedFD': > return '-1' > return '' > > @@ -140,7 +140,7 @@ def HasFd(element): > types = GetAllTypes(element) > else: > types = GetAllTypes(element.kind) > - return "FileDescriptor" in types or (attrs is not None and "hasFd" in attrs) > + return "SharedFD" in types or (attrs is not None and "hasFd" in attrs) > > def WithDefaultValues(element): > return [x for x in element if HasDefaultValue(x)] > @@ -221,7 +221,7 @@ def IsEnum(element): > return mojom.IsEnumKind(element.kind) > > def IsFd(element): > - return mojom.IsStructKind(element.kind) and element.kind.mojom_name == "FileDescriptor" > + return mojom.IsStructKind(element.kind) and element.kind.mojom_name == "SharedFD" > > def IsMap(element): > return mojom.IsMapKind(element.kind) > -- > Regards, > > Laurent Pinchart >
Hi Jacopo, On Mon, Nov 29, 2021 at 05:00:55PM +0100, Jacopo Mondi wrote: > On Mon, Nov 29, 2021 at 01:57:52AM +0200, Laurent Pinchart wrote: > > Now that we have a UniqueFD class, the name FileDescriptor is ambiguous. > > Rename it to SharedFD. > > > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > > makes sense! Does this mean Rb ? :-) > > --- > > include/libcamera/base/file.h | 4 +- > > include/libcamera/base/meson.build | 2 +- > > .../base/{file_descriptor.h => shared_fd.h} | 20 +- > > include/libcamera/framebuffer.h | 4 +- > > .../libcamera/internal/ipa_data_serializer.h | 40 +-- > > include/libcamera/internal/ipc_pipe.h | 8 +- > > include/libcamera/ipa/core.mojom | 6 +- > > include/libcamera/ipa/raspberrypi.mojom | 2 +- > > src/android/camera_device.cpp | 2 +- > > src/ipa/raspberrypi/raspberrypi.cpp | 4 +- > > src/libcamera/base/file.cpp | 6 +- > > src/libcamera/base/file_descriptor.cpp | 266 ------------------ > > src/libcamera/base/meson.build | 2 +- > > src/libcamera/base/shared_fd.cpp | 262 +++++++++++++++++ > > src/libcamera/framebuffer.cpp | 6 +- > > src/libcamera/ipa_data_serializer.cpp | 100 +++---- > > src/libcamera/ipc_pipe.cpp | 4 +- > > .../pipeline/raspberrypi/raspberrypi.cpp | 6 +- > > src/libcamera/v4l2_videodevice.cpp | 6 +- > > src/v4l2/v4l2_camera.h | 2 +- > > test/meson.build | 2 +- > > .../ipa_data_serializer_test.cpp | 14 +- > > test/{file-descriptor.cpp => shared-fd.cpp} | 46 +-- > > .../module_ipa_proxy.cpp.tmpl | 2 +- > > .../module_ipa_proxy.h.tmpl | 2 +- > > .../libcamera_templates/proxy_functions.tmpl | 2 +- > > .../libcamera_templates/serializer.tmpl | 22 +- > > .../generators/mojom_libcamera_generator.py | 6 +- > > 28 files changed, 422 insertions(+), 426 deletions(-) > > rename include/libcamera/base/{file_descriptor.h => shared_fd.h} (55%) > > delete mode 100644 src/libcamera/base/file_descriptor.cpp > > create mode 100644 src/libcamera/base/shared_fd.cpp > > rename test/{file-descriptor.cpp => shared-fd.cpp} (80%) > > > > diff --git a/include/libcamera/base/file.h b/include/libcamera/base/file.h > > index 47769da7abc2..691b52d6ab2d 100644 > > --- a/include/libcamera/base/file.h > > +++ b/include/libcamera/base/file.h > > @@ -21,7 +21,7 @@ > > > > namespace libcamera { > > > > -class FileDescriptor; > > +class SharedFD; > > > > class File > > { > > @@ -69,7 +69,7 @@ public: > > bool unmap(uint8_t *addr); > > > > static bool exists(const std::string &name); > > - static ino_t inode(const FileDescriptor &fd); > > + static ino_t inode(const SharedFD &fd); > > > > private: > > LIBCAMERA_DISABLE_COPY(File) > > diff --git a/include/libcamera/base/meson.build b/include/libcamera/base/meson.build > > index cca374a769cc..112420dab225 100644 > > --- a/include/libcamera/base/meson.build > > +++ b/include/libcamera/base/meson.build > > @@ -11,13 +11,13 @@ libcamera_base_headers = files([ > > 'event_dispatcher_poll.h', > > 'event_notifier.h', > > 'file.h', > > - 'file_descriptor.h', > > 'flags.h', > > 'log.h', > > 'message.h', > > 'object.h', > > 'private.h', > > 'semaphore.h', > > + 'shared_fd.h', > > 'signal.h', > > 'span.h', > > 'thread.h', > > diff --git a/include/libcamera/base/file_descriptor.h b/include/libcamera/base/shared_fd.h > > similarity index 55% > > rename from include/libcamera/base/file_descriptor.h > > rename to include/libcamera/base/shared_fd.h > > index 12a43f95d414..a786885ceb32 100644 > > --- a/include/libcamera/base/file_descriptor.h > > +++ b/include/libcamera/base/shared_fd.h > > @@ -2,7 +2,7 @@ > > /* > > * Copyright (C) 2019, Google Inc. > > * > > - * file_descriptor.h - File descriptor wrapper > > + * shared_fd.h - File descriptor wrapper with shared ownership > > */ > > > > #pragma once > > @@ -13,18 +13,18 @@ namespace libcamera { > > > > class UniqueFD; > > > > -class FileDescriptor final > > +class SharedFD final > > { > > public: > > - explicit FileDescriptor(const int &fd = -1); > > - explicit FileDescriptor(int &&fd); > > - explicit FileDescriptor(UniqueFD fd); > > - FileDescriptor(const FileDescriptor &other); > > - FileDescriptor(FileDescriptor &&other); > > - ~FileDescriptor(); > > + explicit SharedFD(const int &fd = -1); > > + explicit SharedFD(int &&fd); > > + explicit SharedFD(UniqueFD fd); > > + SharedFD(const SharedFD &other); > > + SharedFD(SharedFD &&other); > > + ~SharedFD(); > > > > - FileDescriptor &operator=(const FileDescriptor &other); > > - FileDescriptor &operator=(FileDescriptor &&other); > > + SharedFD &operator=(const SharedFD &other); > > + SharedFD &operator=(SharedFD &&other); > > > > bool isValid() const { return fd_ != nullptr; } > > int fd() const { return fd_ ? fd_->fd() : -1; } > > diff --git a/include/libcamera/framebuffer.h b/include/libcamera/framebuffer.h > > index 2fbea9c5be16..357bbe189551 100644 > > --- a/include/libcamera/framebuffer.h > > +++ b/include/libcamera/framebuffer.h > > @@ -13,7 +13,7 @@ > > #include <vector> > > > > #include <libcamera/base/class.h> > > -#include <libcamera/base/file_descriptor.h> > > +#include <libcamera/base/shared_fd.h> > > #include <libcamera/base/span.h> > > > > namespace libcamera { > > @@ -51,7 +51,7 @@ class FrameBuffer final : public Extensible > > public: > > struct Plane { > > static constexpr unsigned int kInvalidOffset = std::numeric_limits<unsigned int>::max(); > > - FileDescriptor fd; > > + SharedFD fd; > > unsigned int offset = kInvalidOffset; > > unsigned int length; > > }; > > diff --git a/include/libcamera/internal/ipa_data_serializer.h b/include/libcamera/internal/ipa_data_serializer.h > > index c2f602d5b7de..a87449c9be48 100644 > > --- a/include/libcamera/internal/ipa_data_serializer.h > > +++ b/include/libcamera/internal/ipa_data_serializer.h > > @@ -66,7 +66,7 @@ template<typename T> > > class IPADataSerializer > > { > > public: > > - static std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > > + static std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > > serialize(const T &data, ControlSerializer *cs = nullptr); > > > > static T deserialize(const std::vector<uint8_t> &data, > > @@ -76,12 +76,12 @@ public: > > ControlSerializer *cs = nullptr); > > > > static T deserialize(const std::vector<uint8_t> &data, > > - const std::vector<FileDescriptor> &fds, > > + const std::vector<SharedFD> &fds, > > ControlSerializer *cs = nullptr); > > static T deserialize(std::vector<uint8_t>::const_iterator dataBegin, > > std::vector<uint8_t>::const_iterator dataEnd, > > - std::vector<FileDescriptor>::const_iterator fdsBegin, > > - std::vector<FileDescriptor>::const_iterator fdsEnd, > > + std::vector<SharedFD>::const_iterator fdsBegin, > > + std::vector<SharedFD>::const_iterator fdsEnd, > > ControlSerializer *cs = nullptr); > > }; > > > > @@ -104,11 +104,11 @@ template<typename V> > > class IPADataSerializer<std::vector<V>> > > { > > public: > > - static std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > > + static std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > > serialize(const std::vector<V> &data, ControlSerializer *cs = nullptr) > > { > > std::vector<uint8_t> dataVec; > > - std::vector<FileDescriptor> fdsVec; > > + std::vector<SharedFD> fdsVec; > > > > /* Serialize the length. */ > > uint32_t vecLen = data.size(); > > @@ -117,7 +117,7 @@ public: > > /* Serialize the members. */ > > for (auto const &it : data) { > > std::vector<uint8_t> dvec; > > - std::vector<FileDescriptor> fvec; > > + std::vector<SharedFD> fvec; > > > > std::tie(dvec, fvec) = > > IPADataSerializer<V>::serialize(it, cs); > > @@ -141,11 +141,11 @@ public: > > std::vector<uint8_t>::const_iterator dataEnd, > > ControlSerializer *cs = nullptr) > > { > > - std::vector<FileDescriptor> fds; > > + std::vector<SharedFD> fds; > > return deserialize(dataBegin, dataEnd, fds.cbegin(), fds.end(), cs); > > } > > > > - static std::vector<V> deserialize(std::vector<uint8_t> &data, std::vector<FileDescriptor> &fds, > > + static std::vector<V> deserialize(std::vector<uint8_t> &data, std::vector<SharedFD> &fds, > > ControlSerializer *cs = nullptr) > > { > > return deserialize(data.cbegin(), data.end(), fds.cbegin(), fds.end(), cs); > > @@ -153,15 +153,15 @@ public: > > > > static std::vector<V> deserialize(std::vector<uint8_t>::const_iterator dataBegin, > > std::vector<uint8_t>::const_iterator dataEnd, > > - std::vector<FileDescriptor>::const_iterator fdsBegin, > > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, > > + std::vector<SharedFD>::const_iterator fdsBegin, > > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, > > ControlSerializer *cs = nullptr) > > { > > uint32_t vecLen = readPOD<uint32_t>(dataBegin, 0, dataEnd); > > std::vector<V> ret(vecLen); > > > > std::vector<uint8_t>::const_iterator dataIter = dataBegin + 4; > > - std::vector<FileDescriptor>::const_iterator fdIter = fdsBegin; > > + std::vector<SharedFD>::const_iterator fdIter = fdsBegin; > > for (uint32_t i = 0; i < vecLen; i++) { > > uint32_t sizeofData = readPOD<uint32_t>(dataIter, 0, dataEnd); > > uint32_t sizeofFds = readPOD<uint32_t>(dataIter, 4, dataEnd); > > @@ -201,11 +201,11 @@ template<typename K, typename V> > > class IPADataSerializer<std::map<K, V>> > > { > > public: > > - static std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > > + static std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > > serialize(const std::map<K, V> &data, ControlSerializer *cs = nullptr) > > { > > std::vector<uint8_t> dataVec; > > - std::vector<FileDescriptor> fdsVec; > > + std::vector<SharedFD> fdsVec; > > > > /* Serialize the length. */ > > uint32_t mapLen = data.size(); > > @@ -214,7 +214,7 @@ public: > > /* Serialize the members. */ > > for (auto const &it : data) { > > std::vector<uint8_t> dvec; > > - std::vector<FileDescriptor> fvec; > > + std::vector<SharedFD> fvec; > > > > std::tie(dvec, fvec) = > > IPADataSerializer<K>::serialize(it.first, cs); > > @@ -247,11 +247,11 @@ public: > > std::vector<uint8_t>::const_iterator dataEnd, > > ControlSerializer *cs = nullptr) > > { > > - std::vector<FileDescriptor> fds; > > + std::vector<SharedFD> fds; > > return deserialize(dataBegin, dataEnd, fds.cbegin(), fds.end(), cs); > > } > > > > - static std::map<K, V> deserialize(std::vector<uint8_t> &data, std::vector<FileDescriptor> &fds, > > + static std::map<K, V> deserialize(std::vector<uint8_t> &data, std::vector<SharedFD> &fds, > > ControlSerializer *cs = nullptr) > > { > > return deserialize(data.cbegin(), data.end(), fds.cbegin(), fds.end(), cs); > > @@ -259,8 +259,8 @@ public: > > > > static std::map<K, V> deserialize(std::vector<uint8_t>::const_iterator dataBegin, > > std::vector<uint8_t>::const_iterator dataEnd, > > - std::vector<FileDescriptor>::const_iterator fdsBegin, > > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, > > + std::vector<SharedFD>::const_iterator fdsBegin, > > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, > > ControlSerializer *cs = nullptr) > > { > > std::map<K, V> ret; > > @@ -268,7 +268,7 @@ public: > > uint32_t mapLen = readPOD<uint32_t>(dataBegin, 0, dataEnd); > > > > std::vector<uint8_t>::const_iterator dataIter = dataBegin + 4; > > - std::vector<FileDescriptor>::const_iterator fdIter = fdsBegin; > > + std::vector<SharedFD>::const_iterator fdIter = fdsBegin; > > for (uint32_t i = 0; i < mapLen; i++) { > > uint32_t sizeofData = readPOD<uint32_t>(dataIter, 0, dataEnd); > > uint32_t sizeofFds = readPOD<uint32_t>(dataIter, 4, dataEnd); > > diff --git a/include/libcamera/internal/ipc_pipe.h b/include/libcamera/internal/ipc_pipe.h > > index 986f8d886fa6..ab5dd67c3813 100644 > > --- a/include/libcamera/internal/ipc_pipe.h > > +++ b/include/libcamera/internal/ipc_pipe.h > > @@ -9,7 +9,7 @@ > > > > #include <vector> > > > > -#include <libcamera/base/file_descriptor.h> > > +#include <libcamera/base/shared_fd.h> > > #include <libcamera/base/signal.h> > > > > #include "libcamera/internal/ipc_unixsocket.h" > > @@ -33,17 +33,17 @@ public: > > > > Header &header() { return header_; } > > std::vector<uint8_t> &data() { return data_; } > > - std::vector<FileDescriptor> &fds() { return fds_; } > > + std::vector<SharedFD> &fds() { return fds_; } > > > > const Header &header() const { return header_; } > > const std::vector<uint8_t> &data() const { return data_; } > > - const std::vector<FileDescriptor> &fds() const { return fds_; } > > + const std::vector<SharedFD> &fds() const { return fds_; } > > > > private: > > Header header_; > > > > std::vector<uint8_t> data_; > > - std::vector<FileDescriptor> fds_; > > + std::vector<SharedFD> fds_; > > }; > > > > class IPCPipe > > diff --git a/include/libcamera/ipa/core.mojom b/include/libcamera/ipa/core.mojom > > index f7eff0c7ab8c..74f3339e56f2 100644 > > --- a/include/libcamera/ipa/core.mojom > > +++ b/include/libcamera/ipa/core.mojom > > @@ -32,7 +32,7 @@ module libcamera; > > * - This attribute instructs the build system that a (de)serializer is > > * available for the type and there's no need to generate one > > * - hasFd - struct fields or empty structs only > > - * - Designate that this field or empty struct contains a FileDescriptor > > + * - Designate that this field or empty struct contains a SharedFD > > * > > * Rules: > > * - If the type is defined in a libcamera C++ header *and* a (de)serializer is > > @@ -60,7 +60,7 @@ module libcamera; > > * - In mojom, reference the type as FrameBuffer.Plane and only as map/array > > * member > > * - [skipHeader] and [skipSerdes] only work here in core.mojom > > - * - If a field in a struct has a FileDescriptor, but is not explicitly > > + * - If a field in a struct has a SharedFD, but is not explicitly > > * defined so in mojom, then the field must be marked with the [hasFd] > > * attribute > > * > > @@ -71,7 +71,7 @@ module libcamera; > > */ > > [skipSerdes, skipHeader] struct ControlInfoMap {}; > > [skipSerdes, skipHeader] struct ControlList {}; > > -[skipSerdes, skipHeader] struct FileDescriptor {}; > > +[skipSerdes, skipHeader] struct SharedFD {}; > > > > [skipHeader] struct Point { > > int32 x; > > diff --git a/include/libcamera/ipa/raspberrypi.mojom b/include/libcamera/ipa/raspberrypi.mojom > > index e453d46cb14f..acd3cafe6c91 100644 > > --- a/include/libcamera/ipa/raspberrypi.mojom > > +++ b/include/libcamera/ipa/raspberrypi.mojom > > @@ -35,7 +35,7 @@ struct ISPConfig { > > > > struct IPAConfig { > > uint32 transform; > > - libcamera.FileDescriptor lsTableHandle; > > + libcamera.SharedFD lsTableHandle; > > }; > > > > struct StartConfig { > > diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp > > index f2e0bdbdbbf6..1938b10509fa 100644 > > --- a/src/android/camera_device.cpp > > +++ b/src/android/camera_device.cpp > > @@ -725,7 +725,7 @@ CameraDevice::createFrameBuffer(const buffer_handle_t camera3buffer, > > > > std::vector<FrameBuffer::Plane> planes(buf.numPlanes()); > > for (size_t i = 0; i < buf.numPlanes(); ++i) { > > - FileDescriptor fd{ camera3buffer->data[i] }; > > + SharedFD fd{ camera3buffer->data[i] }; > > if (!fd.isValid()) { > > LOG(HAL, Fatal) << "No valid fd"; > > return nullptr; > > diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp > > index c6aec09046f7..aaf629eeb3fc 100644 > > --- a/src/ipa/raspberrypi/raspberrypi.cpp > > +++ b/src/ipa/raspberrypi/raspberrypi.cpp > > @@ -15,8 +15,8 @@ > > > > #include <linux/bcm2835-isp.h> > > > > -#include <libcamera/base/file_descriptor.h> > > #include <libcamera/base/log.h> > > +#include <libcamera/base/shared_fd.h> > > #include <libcamera/base/span.h> > > > > #include <libcamera/control_ids.h> > > @@ -164,7 +164,7 @@ private: > > bool processPending_; > > > > /* LS table allocation passed in from the pipeline handler. */ > > - FileDescriptor lsTableHandle_; > > + SharedFD lsTableHandle_; > > void *lsTable_; > > > > /* Distinguish the first camera start from others. */ > > diff --git a/src/libcamera/base/file.cpp b/src/libcamera/base/file.cpp > > index 66c73c406198..3ca9839bb989 100644 > > --- a/src/libcamera/base/file.cpp > > +++ b/src/libcamera/base/file.cpp > > @@ -14,8 +14,8 @@ > > #include <sys/types.h> > > #include <unistd.h> > > > > -#include <libcamera/base/file_descriptor.h> > > #include <libcamera/base/log.h> > > +#include <libcamera/base/shared_fd.h> > > > > /** > > * \file base/file.h > > @@ -473,11 +473,11 @@ bool File::exists(const std::string &name) > > } > > > > /** > > - * \brief Retrieve the inode of a FileDescriptor > > + * \brief Retrieve the inode of a SharedFD > > * > > * \return The file descriptor inode on success, or 0 on error > > */ > > -ino_t File::inode(const FileDescriptor &fd) > > +ino_t File::inode(const SharedFD &fd) > > { > > if (!fd.isValid()) > > return 0; > > diff --git a/src/libcamera/base/file_descriptor.cpp b/src/libcamera/base/file_descriptor.cpp > > deleted file mode 100644 > > index a83bf52c31e6..000000000000 > > --- a/src/libcamera/base/file_descriptor.cpp > > +++ /dev/null > > @@ -1,266 +0,0 @@ > > -/* SPDX-License-Identifier: LGPL-2.1-or-later */ > > -/* > > - * Copyright (C) 2019, Google Inc. > > - * > > - * file_descriptor.cpp - File descriptor wrapper > > - */ > > - > > -#include <libcamera/base/file_descriptor.h> > > - > > -#include <string.h> > > -#include <sys/types.h> > > -#include <unistd.h> > > -#include <utility> > > - > > -#include <libcamera/base/log.h> > > -#include <libcamera/base/unique_fd.h> > > - > > -/** > > - * \file base/file_descriptor.h > > - * \brief File descriptor wrapper > > - */ > > - > > -namespace libcamera { > > - > > -LOG_DEFINE_CATEGORY(FileDescriptor) > > - > > -/** > > - * \class FileDescriptor > > - * \brief RAII-style wrapper for file descriptors > > - * > > - * The FileDescriptor class provides RAII-style lifetime management of file > > - * descriptors with an efficient mechanism for ownership sharing. At its core, > > - * an internal Descriptor object wraps a file descriptor (expressed as a signed > > - * integer) with an RAII-style interface. The Descriptor is then implicitly > > - * shared with all FileDescriptor instances constructed as copies. > > - * > > - * When constructed from a numerical file descriptor, the FileDescriptor > > - * instance either duplicates or takes over the file descriptor: > > - * > > - * - The FileDescriptor(const int &) constructor duplicates the numerical file > > - * descriptor and wraps the duplicate in a Descriptor. The caller is > > - * responsible for closing the original file descriptor, and the value > > - * returned by fd() will be different from the value passed to the > > - * constructor. > > - * > > - * - The FileDescriptor(int &&) constructor takes over the numerical file > > - * descriptor and wraps it in a Descriptor. The caller shall not touch the > > - * original file descriptor once the function returns, and the value returned > > - * by fd() will be identical to the value passed to the constructor. > > - * > > - * The copy constructor and assignment operator create copies that share the > > - * Descriptor, while the move versions of those functions additionally make the > > - * other FileDescriptor invalid. When the last FileDescriptor that references a > > - * Descriptor is destroyed, the file descriptor is closed. > > - * > > - * The numerical file descriptor is available through the fd() function. All > > - * FileDescriptor instances created as copies of a FileDescriptor will report > > - * the same fd() value. Callers can perform operations on the fd(), but shall > > - * never close it manually. > > - */ > > - > > -/** > > - * \brief Create a FileDescriptor copying a given \a fd > > - * \param[in] fd File descriptor > > - * > > - * Construct a FileDescriptor from a numerical file descriptor by duplicating > > - * the \a fd, and take ownership of the copy. The original \a fd is left > > - * untouched, and the caller is responsible for closing it when appropriate. > > - * The duplicated file descriptor will be closed automatically when all > > - * FileDescriptor instances that reference it are destroyed. > > - * > > - * If the \a fd is negative, the FileDescriptor is constructed as invalid and > > - * the fd() function will return -1. > > - */ > > -FileDescriptor::FileDescriptor(const int &fd) > > -{ > > - if (fd < 0) > > - return; > > - > > - fd_ = std::make_shared<Descriptor>(fd, true); > > - if (fd_->fd() < 0) > > - fd_.reset(); > > -} > > - > > -/** > > - * \brief Create a FileDescriptor taking ownership of a given \a fd > > - * \param[in] fd File descriptor > > - * > > - * Construct a FileDescriptor from a numerical file descriptor by taking > > - * ownership of the \a fd. The original \a fd is set to -1 and shall not be > > - * touched by the caller anymore. In particular, the caller shall not close the > > - * original \a fd manually. The duplicated file descriptor will be closed > > - * automatically when all FileDescriptor instances that reference it are > > - * destroyed. > > - * > > - * If the \a fd is negative, the FileDescriptor is constructed as invalid and > > - * the fd() function will return -1. > > - */ > > -FileDescriptor::FileDescriptor(int &&fd) > > -{ > > - if (fd < 0) > > - return; > > - > > - fd_ = std::make_shared<Descriptor>(fd, false); > > - /* > > - * The Descriptor constructor can't have failed here, as it took over > > - * the fd without duplicating it. Just set the original fd to -1 to > > - * implement move semantics. > > - */ > > - fd = -1; > > -} > > - > > -/** > > - * \brief Create a FileDescriptor taking ownership of a given UniqueFD \a fd > > - * \param[in] fd UniqueFD > > - * > > - * Construct a FileDescriptor from UniqueFD by taking ownership of the \a fd. > > - * The original \a fd becomes invalid. > > - */ > > -FileDescriptor::FileDescriptor(UniqueFD fd) > > - : FileDescriptor(fd.release()) > > -{ > > -} > > - > > -/** > > - * \brief Copy constructor, create a FileDescriptor from a copy of \a other > > - * \param[in] other The other FileDescriptor > > - * > > - * Copying a FileDescriptor implicitly shares ownership of the wrapped file > > - * descriptor. The original FileDescriptor is left untouched, and the caller is > > - * responsible for destroying it when appropriate. The wrapped file descriptor > > - * will be closed automatically when all FileDescriptor instances that > > - * reference it are destroyed. > > - */ > > -FileDescriptor::FileDescriptor(const FileDescriptor &other) > > - : fd_(other.fd_) > > -{ > > -} > > - > > -/** > > - * \brief Move constructor, create a FileDescriptor by taking over \a other > > - * \param[in] other The other FileDescriptor > > - * > > - * Moving a FileDescriptor moves the reference to the wrapped descriptor owned > > - * by \a other to the new FileDescriptor. The \a other FileDescriptor is > > - * invalidated and its fd() function will return -1. The wrapped file descriptor > > - * will be closed automatically when all FileDescriptor instances that > > - * reference it are destroyed. > > - */ > > -FileDescriptor::FileDescriptor(FileDescriptor &&other) > > - : fd_(std::move(other.fd_)) > > -{ > > -} > > - > > -/** > > - * \brief Destroy the FileDescriptor instance > > - * > > - * Destroying a FileDescriptor instance releases its reference to the wrapped > > - * descriptor, if any. When the last instance that references a wrapped > > - * descriptor is destroyed, the file descriptor is automatically closed. > > - */ > > -FileDescriptor::~FileDescriptor() > > -{ > > -} > > - > > -/** > > - * \brief Copy assignment operator, replace the wrapped file descriptor with a > > - * copy of \a other > > - * \param[in] other The other FileDescriptor > > - * > > - * Copying a FileDescriptor creates a new reference to the wrapped file > > - * descriptor owner by \a other. If \a other is invalid, *this will also be > > - * invalid. The original FileDescriptor is left untouched, and the caller is > > - * responsible for destroying it when appropriate. The wrapped file descriptor > > - * will be closed automatically when all FileDescriptor instances that > > - * reference it are destroyed. > > - * > > - * \return A reference to this FileDescriptor > > - */ > > -FileDescriptor &FileDescriptor::operator=(const FileDescriptor &other) > > -{ > > - fd_ = other.fd_; > > - > > - return *this; > > -} > > - > > -/** > > - * \brief Move assignment operator, replace the wrapped file descriptor by > > - * taking over \a other > > - * \param[in] other The other FileDescriptor > > - * > > - * Moving a FileDescriptor moves the reference to the wrapped descriptor owned > > - * by \a other to the new FileDescriptor. If \a other is invalid, *this will > > - * also be invalid. The \a other FileDescriptor is invalidated and its fd() > > - * function will return -1. The wrapped file descriptor will be closed > > - * automatically when all FileDescriptor instances that reference it are > > - * destroyed. > > - * > > - * \return A reference to this FileDescriptor > > - */ > > -FileDescriptor &FileDescriptor::operator=(FileDescriptor &&other) > > -{ > > - fd_ = std::move(other.fd_); > > - > > - return *this; > > -} > > - > > -/** > > - * \fn FileDescriptor::isValid() > > - * \brief Check if the FileDescriptor instance is valid > > - * \return True if the FileDescriptor is valid, false otherwise > > - */ > > - > > -/** > > - * \fn FileDescriptor::fd() > > - * \brief Retrieve the numerical file descriptor > > - * \return The numerical file descriptor, which may be -1 if the FileDescriptor > > - * instance is invalid > > - */ > > - > > -/** > > - * \brief Duplicate a FileDescriptor > > - * > > - * Duplicating a FileDescriptor creates a duplicate of the wrapped file > > - * descriptor and returns a UniqueFD that owns the duplicate. The fd() function > > - * of the original and the get() function of the duplicate will return different > > - * values. The duplicate instance will not be affected by destruction of the > > - * original instance or its copies. > > - * > > - * \return A UniqueFD owning a duplicate of the original file descriptor > > - */ > > -UniqueFD FileDescriptor::dup() const > > -{ > > - int dupFd = ::dup(fd()); > > - if (dupFd == -1) { > > - int ret = -errno; > > - LOG(FileDescriptor, Error) > > - << "Failed to dup() fd: " << strerror(-ret); > > - } > > - > > - return UniqueFD(dupFd); > > -} > > - > > -FileDescriptor::Descriptor::Descriptor(int fd, bool duplicate) > > -{ > > - if (!duplicate) { > > - fd_ = fd; > > - return; > > - } > > - > > - /* Failing to dup() a fd should not happen and is fatal. */ > > - fd_ = ::dup(fd); > > - if (fd_ == -1) { > > - int ret = -errno; > > - LOG(FileDescriptor, Fatal) > > - << "Failed to dup() fd: " << strerror(-ret); > > - } > > -} > > - > > -FileDescriptor::Descriptor::~Descriptor() > > -{ > > - if (fd_ != -1) > > - close(fd_); > > -} > > - > > -} /* namespace libcamera */ > > diff --git a/src/libcamera/base/meson.build b/src/libcamera/base/meson.build > > index b0d85bc19245..ccb746c27466 100644 > > --- a/src/libcamera/base/meson.build > > +++ b/src/libcamera/base/meson.build > > @@ -8,12 +8,12 @@ libcamera_base_sources = files([ > > 'event_dispatcher_poll.cpp', > > 'event_notifier.cpp', > > 'file.cpp', > > - 'file_descriptor.cpp', > > 'flags.cpp', > > 'log.cpp', > > 'message.cpp', > > 'object.cpp', > > 'semaphore.cpp', > > + 'shared_fd.cpp', > > 'signal.cpp', > > 'thread.cpp', > > 'timer.cpp', > > diff --git a/src/libcamera/base/shared_fd.cpp b/src/libcamera/base/shared_fd.cpp > > new file mode 100644 > > index 000000000000..05b6892f7e19 > > --- /dev/null > > +++ b/src/libcamera/base/shared_fd.cpp > > @@ -0,0 +1,262 @@ > > +/* SPDX-License-Identifier: LGPL-2.1-or-later */ > > +/* > > + * Copyright (C) 2019, Google Inc. > > + * > > + * shared_fd.cpp - File descriptor wrapper with shared ownership > > + */ > > + > > +#include <libcamera/base/shared_fd.h> > > + > > +#include <string.h> > > +#include <sys/types.h> > > +#include <unistd.h> > > +#include <utility> > > + > > +#include <libcamera/base/log.h> > > +#include <libcamera/base/unique_fd.h> > > + > > +/** > > + * \file base/shared_fd.h > > + * \brief File descriptor wrapper > > + */ > > + > > +namespace libcamera { > > + > > +LOG_DEFINE_CATEGORY(SharedFD) > > + > > +/** > > + * \class SharedFD > > + * \brief RAII-style wrapper for file descriptors > > + * > > + * The SharedFD class provides RAII-style lifetime management of file > > + * descriptors with an efficient mechanism for ownership sharing. At its core, > > + * an internal Descriptor object wraps a file descriptor (expressed as a signed > > + * integer) with an RAII-style interface. The Descriptor is then implicitly > > + * shared with all SharedFD instances constructed as copies. > > + * > > + * When constructed from a numerical file descriptor, the SharedFD instance > > + * either duplicates or takes over the file descriptor: > > + * > > + * - The SharedFD(const int &) constructor duplicates the numerical file > > + * descriptor and wraps the duplicate in a Descriptor. The caller is > > + * responsible for closing the original file descriptor, and the value > > + * returned by fd() will be different from the value passed to the > > + * constructor. > > + * > > + * - The SharedFD(int &&) constructor takes over the numerical file descriptor > > + * and wraps it in a Descriptor. The caller shall not touch the original file > > + * descriptor once the function returns, and the value returned by fd() will > > + * be identical to the value passed to the constructor. > > + * > > + * The copy constructor and assignment operator create copies that share the > > + * Descriptor, while the move versions of those functions additionally make the > > + * other SharedFD invalid. When the last SharedFD that references a Descriptor > > + * is destroyed, the file descriptor is closed. > > + * > > + * The numerical file descriptor is available through the fd() function. All > > + * SharedFD instances created as copies of a SharedFD will report the same fd() > > + * value. Callers can perform operations on the fd(), but shall never close it > > + * manually. > > + */ > > + > > +/** > > + * \brief Create a SharedFD copying a given \a fd > > + * \param[in] fd File descriptor > > + * > > + * Construct a SharedFD from a numerical file descriptor by duplicating the > > + * \a fd, and take ownership of the copy. The original \a fd is left untouched, > > + * and the caller is responsible for closing it when appropriate. The duplicated > > + * file descriptor will be closed automatically when all SharedFD instances that > > + * reference it are destroyed. > > + * > > + * If the \a fd is negative, the SharedFD is constructed as invalid and the fd() > > + * function will return -1. > > + */ > > +SharedFD::SharedFD(const int &fd) > > +{ > > + if (fd < 0) > > + return; > > + > > + fd_ = std::make_shared<Descriptor>(fd, true); > > + if (fd_->fd() < 0) > > + fd_.reset(); > > +} > > + > > +/** > > + * \brief Create a SharedFD taking ownership of a given \a fd > > + * \param[in] fd File descriptor > > + * > > + * Construct a SharedFD from a numerical file descriptor by taking ownership of > > + * the \a fd. The original \a fd is set to -1 and shall not be touched by the > > + * caller anymore. In particular, the caller shall not close the original \a fd > > + * manually. The duplicated file descriptor will be closed automatically when > > + * all SharedFD instances that reference it are destroyed. > > + * > > + * If the \a fd is negative, the SharedFD is constructed as invalid and the fd() > > + * function will return -1. > > + */ > > +SharedFD::SharedFD(int &&fd) > > +{ > > + if (fd < 0) > > + return; > > + > > + fd_ = std::make_shared<Descriptor>(fd, false); > > + /* > > + * The Descriptor constructor can't have failed here, as it took over > > + * the fd without duplicating it. Just set the original fd to -1 to > > + * implement move semantics. > > + */ > > + fd = -1; > > +} > > + > > +/** > > + * \brief Create a SharedFD taking ownership of a given UniqueFD \a fd > > + * \param[in] fd UniqueFD > > + * > > + * Construct a SharedFD from UniqueFD by taking ownership of the \a fd. The > > + * original \a fd becomes invalid. > > + */ > > +SharedFD::SharedFD(UniqueFD fd) > > + : SharedFD(fd.release()) > > +{ > > +} > > + > > +/** > > + * \brief Copy constructor, create a SharedFD from a copy of \a other > > + * \param[in] other The other SharedFD > > + * > > + * Copying a SharedFD implicitly shares ownership of the wrapped file > > + * descriptor. The original SharedFD is left untouched, and the caller is > > + * responsible for destroying it when appropriate. The wrapped file descriptor > > + * will be closed automatically when all SharedFD instances that reference it > > + * are destroyed. > > + */ > > +SharedFD::SharedFD(const SharedFD &other) > > + : fd_(other.fd_) > > +{ > > +} > > + > > +/** > > + * \brief Move constructor, create a SharedFD by taking over \a other > > + * \param[in] other The other SharedFD > > + * > > + * Moving a SharedFD moves the reference to the wrapped descriptor owned by > > + * \a other to the new SharedFD. The \a other SharedFD is invalidated and its > > + * fd() function will return -1. The wrapped file descriptor will be closed > > + * automatically when all SharedFD instances that reference it are destroyed. > > + */ > > +SharedFD::SharedFD(SharedFD &&other) > > + : fd_(std::move(other.fd_)) > > +{ > > +} > > + > > +/** > > + * \brief Destroy the SharedFD instance > > + * > > + * Destroying a SharedFD instance releases its reference to the wrapped > > + * descriptor, if any. When the last instance that references a wrapped > > + * descriptor is destroyed, the file descriptor is automatically closed. > > + */ > > +SharedFD::~SharedFD() > > +{ > > +} > > + > > +/** > > + * \brief Copy assignment operator, replace the wrapped file descriptor with a > > + * copy of \a other > > + * \param[in] other The other SharedFD > > + * > > + * Copying a SharedFD creates a new reference to the wrapped file descriptor > > + * owner by \a other. If \a other is invalid, *this will also be invalid. The > > + * original SharedFD is left untouched, and the caller is responsible for > > + * destroying it when appropriate. The wrapped file descriptor will be closed > > + * automatically when all SharedFD instances that reference it are destroyed. > > + * > > + * \return A reference to this SharedFD > > + */ > > +SharedFD &SharedFD::operator=(const SharedFD &other) > > +{ > > + fd_ = other.fd_; > > + > > + return *this; > > +} > > + > > +/** > > + * \brief Move assignment operator, replace the wrapped file descriptor by > > + * taking over \a other > > + * \param[in] other The other SharedFD > > + * > > + * Moving a SharedFD moves the reference to the wrapped descriptor owned by > > + * \a other to the new SharedFD. If \a other is invalid, *this will also be > > + * invalid. The \a other SharedFD is invalidated and its fd() function will > > + * return -1. The wrapped file descriptor will be closed automatically when > > + * all SharedFD instances that reference it are destroyed. > > + * > > + * \return A reference to this SharedFD > > + */ > > +SharedFD &SharedFD::operator=(SharedFD &&other) > > +{ > > + fd_ = std::move(other.fd_); > > + > > + return *this; > > +} > > + > > +/** > > + * \fn SharedFD::isValid() > > + * \brief Check if the SharedFD instance is valid > > + * \return True if the SharedFD is valid, false otherwise > > + */ > > + > > +/** > > + * \fn SharedFD::fd() > > + * \brief Retrieve the numerical file descriptor > > + * \return The numerical file descriptor, which may be -1 if the SharedFD > > + * instance is invalid > > + */ > > + > > +/** > > + * \brief Duplicate a SharedFD > > + * > > + * Duplicating a SharedFD creates a duplicate of the wrapped file descriptor and > > + * returns a UniqueFD that owns the duplicate. The fd() function of the original > > + * and the get() function of the duplicate will return different values. The > > + * duplicate instance will not be affected by destruction of the original > > + * instance or its copies. > > + * > > + * \return A UniqueFD owning a duplicate of the original file descriptor > > + */ > > +UniqueFD SharedFD::dup() const > > +{ > > + int dupFd = ::dup(fd()); > > + if (dupFd == -1) { > > + int ret = -errno; > > + LOG(SharedFD, Error) > > + << "Failed to dup() fd: " << strerror(-ret); > > + } > > + > > + return UniqueFD(dupFd); > > +} > > + > > +SharedFD::Descriptor::Descriptor(int fd, bool duplicate) > > +{ > > + if (!duplicate) { > > + fd_ = fd; > > + return; > > + } > > + > > + /* Failing to dup() a fd should not happen and is fatal. */ > > + fd_ = ::dup(fd); > > + if (fd_ == -1) { > > + int ret = -errno; > > + LOG(SharedFD, Fatal) > > + << "Failed to dup() fd: " << strerror(-ret); > > + } > > +} > > + > > +SharedFD::Descriptor::~Descriptor() > > +{ > > + if (fd_ != -1) > > + close(fd_); > > +} > > + > > +} /* namespace libcamera */ > > diff --git a/src/libcamera/framebuffer.cpp b/src/libcamera/framebuffer.cpp > > index f5bcf107d7aa..0a5bf7fdbeb7 100644 > > --- a/src/libcamera/framebuffer.cpp > > +++ b/src/libcamera/framebuffer.cpp > > @@ -180,9 +180,9 @@ FrameBuffer::Private::Private() > > * offset and length. > > * > > * To support DMA access, planes are associated with dmabuf objects represented > > - * by FileDescriptor handles. The Plane class doesn't handle mapping of the > > - * memory to the CPU, but applications and IPAs may use the dmabuf file > > - * descriptors to map the plane memory with mmap() and access its contents. > > + * by SharedFD handles. The Plane class doesn't handle mapping of the memory to > > + * the CPU, but applications and IPAs may use the dmabuf file descriptors to map > > + * the plane memory with mmap() and access its contents. > > * > > * \todo Specify how an application shall decide whether to use a single or > > * multiple dmabufs, based on the camera requirements. > > diff --git a/src/libcamera/ipa_data_serializer.cpp b/src/libcamera/ipa_data_serializer.cpp > > index 82ec9b20a411..0a259305afa2 100644 > > --- a/src/libcamera/ipa_data_serializer.cpp > > +++ b/src/libcamera/ipa_data_serializer.cpp > > @@ -31,7 +31,7 @@ LOG_DEFINE_CATEGORY(IPADataSerializer) > > * > > * \todo Harden the vector and map deserializer > > * > > - * \todo For FileDescriptors, instead of storing a validity flag, store an > > + * \todo For SharedFDs, instead of storing a validity flag, store an > > * index into the fd array. This will allow us to use views instead of copying. > > */ > > > > @@ -112,7 +112,7 @@ namespace { > > * \param[in] cs ControlSerializer > > * > > * This version of deserialize() can be used if the object type \a T and its > > - * members don't have any FileDescriptor. > > + * members don't have any SharedFD. > > * > > * \a cs is only necessary if the object type \a T or its members contain > > * ControlList or ControlInfoMap. > > @@ -132,7 +132,7 @@ namespace { > > * \param[in] cs ControlSerializer > > * > > * This version of deserialize() can be used if the object type \a T and its > > - * members don't have any FileDescriptor. > > + * members don't have any SharedFD. > > * > > * \a cs is only necessary if the object type \a T or its members contain > > * ControlList or ControlInfoMap. > > @@ -143,7 +143,7 @@ namespace { > > /** > > * \fn template<typename T> IPADataSerializer<T>::deserialize( > > * const std::vector<uint8_t> &data, > > - * const std::vector<FileDescriptor> &fds, > > + * const std::vector<SharedFD> &fds, > > * ControlSerializer *cs = nullptr) > > * \brief Deserialize byte vector and fd vector into an object > > * \tparam T Type of object to deserialize to > > @@ -152,7 +152,7 @@ namespace { > > * \param[in] cs ControlSerializer > > * > > * This version of deserialize() (or the iterator version) must be used if > > - * the object type \a T or its members contain FileDescriptor. > > + * the object type \a T or its members contain SharedFD. > > * > > * \a cs is only necessary if the object type \a T or its members contain > > * ControlList or ControlInfoMap. > > @@ -164,8 +164,8 @@ namespace { > > * \fn template<typename T> IPADataSerializer::deserialize( > > * std::vector<uint8_t>::const_iterator dataBegin, > > * std::vector<uint8_t>::const_iterator dataEnd, > > - * std::vector<FileDescriptor>::const_iterator fdsBegin, > > - * std::vector<FileDescriptor>::const_iterator fdsEnd, > > + * std::vector<SharedFD>::const_iterator fdsBegin, > > + * std::vector<SharedFD>::const_iterator fdsEnd, > > * ControlSerializer *cs = nullptr) > > * \brief Deserialize byte vector and fd vector into an object > > * \tparam T Type of object to deserialize to > > @@ -176,7 +176,7 @@ namespace { > > * \param[in] cs ControlSerializer > > * > > * This version of deserialize() (or the vector version) must be used if > > - * the object type \a T or its members contain FileDescriptor. > > + * the object type \a T or its members contain SharedFD. > > * > > * \a cs is only necessary if the object type \a T or its members contain > > * ControlList or ControlInfoMap. > > @@ -189,7 +189,7 @@ namespace { > > #define DEFINE_POD_SERIALIZER(type) \ > > \ > > template<> \ > > -std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> \ > > +std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> \ > > IPADataSerializer<type>::serialize(const type &data, \ > > [[maybe_unused]] ControlSerializer *cs) \ > > { \ > > @@ -217,7 +217,7 @@ type IPADataSerializer<type>::deserialize(const std::vector<uint8_t> &data, \ > > \ > > template<> \ > > type IPADataSerializer<type>::deserialize(const std::vector<uint8_t> &data, \ > > - [[maybe_unused]] const std::vector<FileDescriptor> &fds, \ > > + [[maybe_unused]] const std::vector<SharedFD> &fds, \ > > ControlSerializer *cs) \ > > { \ > > return deserialize(data.cbegin(), data.end(), cs); \ > > @@ -226,8 +226,8 @@ type IPADataSerializer<type>::deserialize(const std::vector<uint8_t> &data, \ > > template<> \ > > type IPADataSerializer<type>::deserialize(std::vector<uint8_t>::const_iterator dataBegin, \ > > std::vector<uint8_t>::const_iterator dataEnd, \ > > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsBegin, \ > > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, \ > > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsBegin, \ > > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, \ > > ControlSerializer *cs) \ > > { \ > > return deserialize(dataBegin, dataEnd, cs); \ > > @@ -251,7 +251,7 @@ DEFINE_POD_SERIALIZER(double) > > * function parameter serdes). > > */ > > template<> > > -std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > > +std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > > IPADataSerializer<std::string>::serialize(const std::string &data, > > [[maybe_unused]] ControlSerializer *cs) > > { > > @@ -278,7 +278,7 @@ IPADataSerializer<std::string>::deserialize(std::vector<uint8_t>::const_iterator > > template<> > > std::string > > IPADataSerializer<std::string>::deserialize(const std::vector<uint8_t> &data, > > - [[maybe_unused]] const std::vector<FileDescriptor> &fds, > > + [[maybe_unused]] const std::vector<SharedFD> &fds, > > [[maybe_unused]] ControlSerializer *cs) > > { > > return { data.cbegin(), data.cend() }; > > @@ -288,8 +288,8 @@ template<> > > std::string > > IPADataSerializer<std::string>::deserialize(std::vector<uint8_t>::const_iterator dataBegin, > > std::vector<uint8_t>::const_iterator dataEnd, > > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsBegin, > > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, > > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsBegin, > > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, > > [[maybe_unused]] ControlSerializer *cs) > > { > > return { dataBegin, dataEnd }; > > @@ -307,7 +307,7 @@ IPADataSerializer<std::string>::deserialize(std::vector<uint8_t>::const_iterator > > * be used. The serialized ControlInfoMap will have zero length. > > */ > > template<> > > -std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > > +std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > > IPADataSerializer<ControlList>::serialize(const ControlList &data, ControlSerializer *cs) > > { > > if (!cs) > > @@ -407,7 +407,7 @@ IPADataSerializer<ControlList>::deserialize(const std::vector<uint8_t> &data, > > template<> > > ControlList > > IPADataSerializer<ControlList>::deserialize(const std::vector<uint8_t> &data, > > - [[maybe_unused]] const std::vector<FileDescriptor> &fds, > > + [[maybe_unused]] const std::vector<SharedFD> &fds, > > ControlSerializer *cs) > > { > > return deserialize(data.cbegin(), data.end(), cs); > > @@ -417,8 +417,8 @@ template<> > > ControlList > > IPADataSerializer<ControlList>::deserialize(std::vector<uint8_t>::const_iterator dataBegin, > > std::vector<uint8_t>::const_iterator dataEnd, > > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsBegin, > > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, > > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsBegin, > > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, > > ControlSerializer *cs) > > { > > return deserialize(dataBegin, dataEnd, cs); > > @@ -431,7 +431,7 @@ IPADataSerializer<ControlList>::deserialize(std::vector<uint8_t>::const_iterator > > * X bytes - Serialized ControlInfoMap (using ControlSerializer) > > */ > > template<> > > -std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > > +std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > > IPADataSerializer<ControlInfoMap>::serialize(const ControlInfoMap &map, > > ControlSerializer *cs) > > { > > @@ -493,7 +493,7 @@ IPADataSerializer<ControlInfoMap>::deserialize(const std::vector<uint8_t> &data, > > template<> > > ControlInfoMap > > IPADataSerializer<ControlInfoMap>::deserialize(const std::vector<uint8_t> &data, > > - [[maybe_unused]] const std::vector<FileDescriptor> &fds, > > + [[maybe_unused]] const std::vector<SharedFD> &fds, > > ControlSerializer *cs) > > { > > return deserialize(data.cbegin(), data.end(), cs); > > @@ -503,30 +503,30 @@ template<> > > ControlInfoMap > > IPADataSerializer<ControlInfoMap>::deserialize(std::vector<uint8_t>::const_iterator dataBegin, > > std::vector<uint8_t>::const_iterator dataEnd, > > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsBegin, > > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, > > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsBegin, > > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, > > ControlSerializer *cs) > > { > > return deserialize(dataBegin, dataEnd, cs); > > } > > > > /* > > - * FileDescriptors are serialized into four bytes that tells if the > > - * FileDescriptor is valid or not. If it is valid, then for serialization > > - * the fd will be written to the fd vector, or for deserialization the > > - * fd vector const_iterator will be valid. > > + * SharedFD instances are serialized into four bytes that tells if the SharedFD > > + * is valid or not. If it is valid, then for serialization the fd will be > > + * written to the fd vector, or for deserialization the fd vector const_iterator > > + * will be valid. > > * > > * This validity is necessary so that we don't send -1 fd over sendmsg(). It > > * also allows us to simply send the entire fd vector into the deserializer > > * and it will be recursively consumed as necessary. > > */ > > template<> > > -std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > > -IPADataSerializer<FileDescriptor>::serialize(const FileDescriptor &data, > > - [[maybe_unused]] ControlSerializer *cs) > > +std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > > +IPADataSerializer<SharedFD>::serialize(const SharedFD &data, > > + [[maybe_unused]] ControlSerializer *cs) > > { > > std::vector<uint8_t> dataVec; > > - std::vector<FileDescriptor> fdVec; > > + std::vector<SharedFD> fdVec; > > > > /* > > * Store as uint32_t to prepare for conversion from validity flag > > @@ -542,11 +542,11 @@ IPADataSerializer<FileDescriptor>::serialize(const FileDescriptor &data, > > } > > > > template<> > > -FileDescriptor IPADataSerializer<FileDescriptor>::deserialize([[maybe_unused]] std::vector<uint8_t>::const_iterator dataBegin, > > - [[maybe_unused]] std::vector<uint8_t>::const_iterator dataEnd, > > - std::vector<FileDescriptor>::const_iterator fdsBegin, > > - std::vector<FileDescriptor>::const_iterator fdsEnd, > > - [[maybe_unused]] ControlSerializer *cs) > > +SharedFD IPADataSerializer<SharedFD>::deserialize([[maybe_unused]] std::vector<uint8_t>::const_iterator dataBegin, > > + [[maybe_unused]] std::vector<uint8_t>::const_iterator dataEnd, > > + std::vector<SharedFD>::const_iterator fdsBegin, > > + std::vector<SharedFD>::const_iterator fdsEnd, > > + [[maybe_unused]] ControlSerializer *cs) > > { > > ASSERT(std::distance(dataBegin, dataEnd) >= 4); > > > > @@ -554,13 +554,13 @@ FileDescriptor IPADataSerializer<FileDescriptor>::deserialize([[maybe_unused]] s > > > > ASSERT(!(valid && std::distance(fdsBegin, fdsEnd) < 1)); > > > > - return valid ? *fdsBegin : FileDescriptor(); > > + return valid ? *fdsBegin : SharedFD(); > > } > > > > template<> > > -FileDescriptor IPADataSerializer<FileDescriptor>::deserialize(const std::vector<uint8_t> &data, > > - const std::vector<FileDescriptor> &fds, > > - [[maybe_unused]] ControlSerializer *cs) > > +SharedFD IPADataSerializer<SharedFD>::deserialize(const std::vector<uint8_t> &data, > > + const std::vector<SharedFD> &fds, > > + [[maybe_unused]] ControlSerializer *cs) > > { > > return deserialize(data.cbegin(), data.end(), fds.cbegin(), fds.end()); > > } > > @@ -568,22 +568,22 @@ FileDescriptor IPADataSerializer<FileDescriptor>::deserialize(const std::vector< > > /* > > * FrameBuffer::Plane is serialized as: > > * > > - * 4 byte - FileDescriptor > > + * 4 byte - SharedFD > > * 4 bytes - uint32_t Offset > > * 4 bytes - uint32_t Length > > */ > > template<> > > -std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > > +std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > > IPADataSerializer<FrameBuffer::Plane>::serialize(const FrameBuffer::Plane &data, > > [[maybe_unused]] ControlSerializer *cs) > > { > > std::vector<uint8_t> dataVec; > > - std::vector<FileDescriptor> fdsVec; > > + std::vector<SharedFD> fdsVec; > > > > std::vector<uint8_t> fdBuf; > > - std::vector<FileDescriptor> fdFds; > > + std::vector<SharedFD> fdFds; > > std::tie(fdBuf, fdFds) = > > - IPADataSerializer<FileDescriptor>::serialize(data.fd); > > + IPADataSerializer<SharedFD>::serialize(data.fd); > > dataVec.insert(dataVec.end(), fdBuf.begin(), fdBuf.end()); > > fdsVec.insert(fdsVec.end(), fdFds.begin(), fdFds.end()); > > > > @@ -597,13 +597,13 @@ template<> > > FrameBuffer::Plane > > IPADataSerializer<FrameBuffer::Plane>::deserialize(std::vector<uint8_t>::const_iterator dataBegin, > > std::vector<uint8_t>::const_iterator dataEnd, > > - std::vector<FileDescriptor>::const_iterator fdsBegin, > > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, > > + std::vector<SharedFD>::const_iterator fdsBegin, > > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, > > [[maybe_unused]] ControlSerializer *cs) > > { > > FrameBuffer::Plane ret; > > > > - ret.fd = IPADataSerializer<FileDescriptor>::deserialize(dataBegin, dataBegin + 4, > > + ret.fd = IPADataSerializer<SharedFD>::deserialize(dataBegin, dataBegin + 4, > > fdsBegin, fdsBegin + 1); > > ret.offset = readPOD<uint32_t>(dataBegin, 4, dataEnd); > > ret.length = readPOD<uint32_t>(dataBegin, 8, dataEnd); > > @@ -614,7 +614,7 @@ IPADataSerializer<FrameBuffer::Plane>::deserialize(std::vector<uint8_t>::const_i > > template<> > > FrameBuffer::Plane > > IPADataSerializer<FrameBuffer::Plane>::deserialize(const std::vector<uint8_t> &data, > > - const std::vector<FileDescriptor> &fds, > > + const std::vector<SharedFD> &fds, > > ControlSerializer *cs) > > { > > return deserialize(data.cbegin(), data.end(), fds.cbegin(), fds.end(), cs); > > diff --git a/src/libcamera/ipc_pipe.cpp b/src/libcamera/ipc_pipe.cpp > > index ad870fd4137f..3b47032de0a2 100644 > > --- a/src/libcamera/ipc_pipe.cpp > > +++ b/src/libcamera/ipc_pipe.cpp > > @@ -87,7 +87,7 @@ IPCMessage::IPCMessage(IPCUnixSocket::Payload &payload) > > data_ = std::vector<uint8_t>(payload.data.begin() + sizeof(header_), > > payload.data.end()); > > for (int32_t &fd : payload.fds) > > - fds_.push_back(FileDescriptor(std::move(fd))); > > + fds_.push_back(SharedFD(std::move(fd))); > > } > > > > /** > > @@ -112,7 +112,7 @@ IPCUnixSocket::Payload IPCMessage::payload() const > > data_.data(), data_.size()); > > } > > > > - for (const FileDescriptor &fd : fds_) > > + for (const SharedFD &fd : fds_) > > payload.fds.push_back(fd.fd()); > > > > return payload; > > diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp > > index ffa51a0c65ca..ea8243912a29 100644 > > --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp > > +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp > > @@ -12,7 +12,7 @@ > > #include <queue> > > #include <unordered_set> > > > > -#include <libcamera/base/file_descriptor.h> > > +#include <libcamera/base/shared_fd.h> > > > > #include <libcamera/camera.h> > > #include <libcamera/control_ids.h> > > @@ -228,7 +228,7 @@ public: > > > > /* DMAHEAP allocation helper. */ > > RPi::DmaHeap dmaHeap_; > > - FileDescriptor lsTable_; > > + SharedFD lsTable_; > > > > std::unique_ptr<DelayedControls> delayedCtrls_; > > bool sensorMetadata_; > > @@ -1365,7 +1365,7 @@ int RPiCameraData::configureIPA(const CameraConfiguration *config) > > if (!fd.isValid()) > > return -ENOMEM; > > > > - lsTable_ = FileDescriptor(std::move(fd)); > > + lsTable_ = SharedFD(std::move(fd)); > > > > /* Allow the IPA to mmap the LS table via the file descriptor. */ > > /* > > diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp > > index 3966483a365f..97d431071def 100644 > > --- a/src/libcamera/v4l2_videodevice.cpp > > +++ b/src/libcamera/v4l2_videodevice.cpp > > @@ -22,8 +22,8 @@ > > #include <linux/version.h> > > > > #include <libcamera/base/event_notifier.h> > > -#include <libcamera/base/file_descriptor.h> > > #include <libcamera/base/log.h> > > +#include <libcamera/base/shared_fd.h> > > #include <libcamera/base/unique_fd.h> > > #include <libcamera/base/utils.h> > > > > @@ -1325,7 +1325,7 @@ std::unique_ptr<FrameBuffer> V4L2VideoDevice::createBuffer(unsigned int index) > > return nullptr; > > > > FrameBuffer::Plane plane; > > - plane.fd = FileDescriptor(std::move(fd)); > > + plane.fd = SharedFD(std::move(fd)); > > /* > > * V4L2 API doesn't provide dmabuf offset information of plane. > > * Set 0 as a placeholder offset. > > @@ -1354,7 +1354,7 @@ std::unique_ptr<FrameBuffer> V4L2VideoDevice::createBuffer(unsigned int index) > > ASSERT(numPlanes == 1u); > > > > planes.resize(formatInfo_->numPlanes()); > > - const FileDescriptor &fd = planes[0].fd; > > + const SharedFD &fd = planes[0].fd; > > size_t offset = 0; > > > > for (auto [i, plane] : utils::enumerate(planes)) { > > diff --git a/src/v4l2/v4l2_camera.h b/src/v4l2/v4l2_camera.h > > index 9817fd393d59..586347829845 100644 > > --- a/src/v4l2/v4l2_camera.h > > +++ b/src/v4l2/v4l2_camera.h > > @@ -11,8 +11,8 @@ > > #include <mutex> > > #include <utility> > > > > -#include <libcamera/base/file_descriptor.h> > > #include <libcamera/base/semaphore.h> > > +#include <libcamera/base/shared_fd.h> > > > > #include <libcamera/camera.h> > > #include <libcamera/framebuffer.h> > > diff --git a/test/meson.build b/test/meson.build > > index 42dfbc1f8ee9..daaa3862cdd6 100644 > > --- a/test/meson.build > > +++ b/test/meson.build > > @@ -40,7 +40,6 @@ internal_tests = [ > > ['event-dispatcher', 'event-dispatcher.cpp'], > > ['event-thread', 'event-thread.cpp'], > > ['file', 'file.cpp'], > > - ['file-descriptor', 'file-descriptor.cpp'], > > ['flags', 'flags.cpp'], > > ['hotplug-cameras', 'hotplug-cameras.cpp'], > > ['mapped-buffer', 'mapped-buffer.cpp'], > > @@ -49,6 +48,7 @@ internal_tests = [ > > ['object-delete', 'object-delete.cpp'], > > ['object-invoke', 'object-invoke.cpp'], > > ['pixel-format', 'pixel-format.cpp'], > > + ['shared-fd', 'shared-fd.cpp'], > > ['signal-threads', 'signal-threads.cpp'], > > ['threads', 'threads.cpp'], > > ['timer', 'timer.cpp'], > > diff --git a/test/serialization/ipa_data_serializer_test.cpp b/test/serialization/ipa_data_serializer_test.cpp > > index 5fcdcb8eae92..d2050a868b38 100644 > > --- a/test/serialization/ipa_data_serializer_test.cpp > > +++ b/test/serialization/ipa_data_serializer_test.cpp > > @@ -53,7 +53,7 @@ template<typename T> > > int testPodSerdes(T in) > > { > > std::vector<uint8_t> buf; > > - std::vector<FileDescriptor> fds; > > + std::vector<SharedFD> fds; > > > > std::tie(buf, fds) = IPADataSerializer<T>::serialize(in); > > T out = IPADataSerializer<T>::deserialize(buf, fds); > > @@ -72,7 +72,7 @@ int testVectorSerdes(const std::vector<T> &in, > > ControlSerializer *cs = nullptr) > > { > > std::vector<uint8_t> buf; > > - std::vector<FileDescriptor> fds; > > + std::vector<SharedFD> fds; > > > > std::tie(buf, fds) = IPADataSerializer<std::vector<T>>::serialize(in, cs); > > std::vector<T> out = IPADataSerializer<std::vector<T>>::deserialize(buf, fds, cs); > > @@ -92,7 +92,7 @@ int testMapSerdes(const std::map<K, V> &in, > > ControlSerializer *cs = nullptr) > > { > > std::vector<uint8_t> buf; > > - std::vector<FileDescriptor> fds; > > + std::vector<SharedFD> fds; > > > > std::tie(buf, fds) = IPADataSerializer<std::map<K, V>>::serialize(in, cs); > > std::map<K, V> out = IPADataSerializer<std::map<K, V>>::deserialize(buf, fds, cs); > > @@ -198,7 +198,7 @@ private: > > ControlSerializer cs(ControlSerializer::Role::Proxy); > > > > /* > > - * We don't test FileDescriptor serdes because it dup()s, so we > > + * We don't test SharedFD serdes because it dup()s, so we > > * can't check for equality. > > */ > > std::vector<uint8_t> vecUint8 = { 1, 2, 3, 4, 5, 6 }; > > @@ -219,7 +219,7 @@ private: > > }; > > > > std::vector<uint8_t> buf; > > - std::vector<FileDescriptor> fds; > > + std::vector<SharedFD> fds; > > > > if (testVectorSerdes(vecUint8) != TestPass) > > return TestFail; > > @@ -291,7 +291,7 @@ private: > > { { "a", { 1, 2, 3 } }, { "b", { 4, 5, 6 } }, { "c", { 7, 8, 9 } } }; > > > > std::vector<uint8_t> buf; > > - std::vector<FileDescriptor> fds; > > + std::vector<SharedFD> fds; > > > > if (testMapSerdes(mapUintStr) != TestPass) > > return TestFail; > > @@ -359,7 +359,7 @@ private: > > std::string strEmpty = ""; > > > > std::vector<uint8_t> buf; > > - std::vector<FileDescriptor> fds; > > + std::vector<SharedFD> fds; > > > > if (testPodSerdes(u32min) != TestPass) > > return TestFail; > > diff --git a/test/file-descriptor.cpp b/test/shared-fd.cpp > > similarity index 80% > > rename from test/file-descriptor.cpp > > rename to test/shared-fd.cpp > > index 76badc4c5fad..60e5d0aaa395 100644 > > --- a/test/file-descriptor.cpp > > +++ b/test/shared-fd.cpp > > @@ -2,7 +2,7 @@ > > /* > > * Copyright (C) 2019, Google Inc. > > * > > - * file_descriptor.cpp - FileDescriptor test > > + * shared_fd.cpp - SharedFD test > > */ > > > > #include <fcntl.h> > > @@ -11,7 +11,7 @@ > > #include <sys/types.h> > > #include <unistd.h> > > > > -#include <libcamera/base/file_descriptor.h> > > +#include <libcamera/base/shared_fd.h> > > #include <libcamera/base/utils.h> > > > > #include "test.h" > > @@ -19,7 +19,7 @@ > > using namespace libcamera; > > using namespace std; > > > > -class FileDescriptorTest : public Test > > +class SharedFDTest : public Test > > { > > protected: > > int init() > > @@ -43,8 +43,8 @@ protected: > > > > int run() > > { > > - /* Test creating empty FileDescriptor. */ > > - desc1_ = new FileDescriptor(); > > + /* Test creating empty SharedFD. */ > > + desc1_ = new SharedFD(); > > > > if (desc1_->fd() != -1) { > > std::cout << "Failed fd numerical check (default constructor)" > > @@ -56,10 +56,10 @@ protected: > > desc1_ = nullptr; > > > > /* > > - * Test creating FileDescriptor by copying numerical file > > + * Test creating SharedFD by copying numerical file > > * descriptor. > > */ > > - desc1_ = new FileDescriptor(fd_); > > + desc1_ = new SharedFD(fd_); > > if (desc1_->fd() == fd_) { > > std::cout << "Failed fd numerical check (lvalue ref constructor)" > > << std::endl; > > @@ -84,13 +84,13 @@ protected: > > } > > > > /* > > - * Test creating FileDescriptor by taking ownership of > > + * Test creating SharedFD by taking ownership of > > * numerical file descriptor. > > */ > > int dupFd = dup(fd_); > > int dupFdCopy = dupFd; > > > > - desc1_ = new FileDescriptor(std::move(dupFd)); > > + desc1_ = new SharedFD(std::move(dupFd)); > > if (desc1_->fd() != dupFdCopy) { > > std::cout << "Failed fd numerical check (rvalue ref constructor)" > > << std::endl; > > @@ -114,9 +114,9 @@ protected: > > return TestFail; > > } > > > > - /* Test creating FileDescriptor from other FileDescriptor. */ > > - desc1_ = new FileDescriptor(fd_); > > - desc2_ = new FileDescriptor(*desc1_); > > + /* Test creating SharedFD from other SharedFD. */ > > + desc1_ = new SharedFD(fd_); > > + desc2_ = new SharedFD(*desc1_); > > > > if (desc1_->fd() == fd_ || desc2_->fd() == fd_ || desc1_->fd() != desc2_->fd()) { > > std::cout << "Failed fd numerical check (copy constructor)" > > @@ -142,10 +142,10 @@ protected: > > delete desc2_; > > desc2_ = nullptr; > > > > - /* Test creating FileDescriptor by taking over other FileDescriptor. */ > > - desc1_ = new FileDescriptor(fd_); > > + /* Test creating SharedFD by taking over other SharedFD. */ > > + desc1_ = new SharedFD(fd_); > > fd = desc1_->fd(); > > - desc2_ = new FileDescriptor(std::move(*desc1_)); > > + desc2_ = new SharedFD(std::move(*desc1_)); > > > > if (desc1_->fd() != -1 || desc2_->fd() != fd) { > > std::cout << "Failed fd numerical check (move constructor)" > > @@ -164,9 +164,9 @@ protected: > > delete desc2_; > > desc2_ = nullptr; > > > > - /* Test creating FileDescriptor by copy assignment. */ > > - desc1_ = new FileDescriptor(); > > - desc2_ = new FileDescriptor(fd_); > > + /* Test creating SharedFD by copy assignment. */ > > + desc1_ = new SharedFD(); > > + desc2_ = new SharedFD(fd_); > > > > fd = desc2_->fd(); > > *desc1_ = *desc2_; > > @@ -188,9 +188,9 @@ protected: > > delete desc2_; > > desc2_ = nullptr; > > > > - /* Test creating FileDescriptor by move assignment. */ > > - desc1_ = new FileDescriptor(); > > - desc2_ = new FileDescriptor(fd_); > > + /* Test creating SharedFD by move assignment. */ > > + desc1_ = new SharedFD(); > > + desc2_ = new SharedFD(fd_); > > > > fd = desc2_->fd(); > > *desc1_ = std::move(*desc2_); > > @@ -237,7 +237,7 @@ private: > > > > int fd_; > > ino_t inodeNr_; > > - FileDescriptor *desc1_, *desc2_; > > + SharedFD *desc1_, *desc2_; > > }; > > > > -TEST_REGISTER(FileDescriptorTest) > > +TEST_REGISTER(SharedFDTest) > > diff --git a/utils/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl b/utils/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl > > index d856339aa9ee..c37c4941b528 100644 > > --- a/utils/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl > > +++ b/utils/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl > > @@ -237,7 +237,7 @@ void {{proxy_name}}::recvMessage(const IPCMessage &data) > > void {{proxy_name}}::{{method.mojom_name}}IPC( > > std::vector<uint8_t>::const_iterator data, > > size_t dataSize, > > - [[maybe_unused]] const std::vector<FileDescriptor> &fds) > > + [[maybe_unused]] const std::vector<SharedFD> &fds) > > { > > {%- for param in method.parameters %} > > {{param|name}} {{param.mojom_name}}; > > diff --git a/utils/ipc/generators/libcamera_templates/module_ipa_proxy.h.tmpl b/utils/ipc/generators/libcamera_templates/module_ipa_proxy.h.tmpl > > index ce396c183d0c..c308dd10c7e5 100644 > > --- a/utils/ipc/generators/libcamera_templates/module_ipa_proxy.h.tmpl > > +++ b/utils/ipc/generators/libcamera_templates/module_ipa_proxy.h.tmpl > > @@ -64,7 +64,7 @@ private: > > void {{method.mojom_name}}IPC( > > std::vector<uint8_t>::const_iterator data, > > size_t dataSize, > > - const std::vector<FileDescriptor> &fds); > > + const std::vector<SharedFD> &fds); > > {% endfor %} > > > > /* Helper class to invoke async functions in another thread. */ > > diff --git a/utils/ipc/generators/libcamera_templates/proxy_functions.tmpl b/utils/ipc/generators/libcamera_templates/proxy_functions.tmpl > > index ebcd2aaaafae..bac826a74c2d 100644 > > --- a/utils/ipc/generators/libcamera_templates/proxy_functions.tmpl > > +++ b/utils/ipc/generators/libcamera_templates/proxy_functions.tmpl > > @@ -54,7 +54,7 @@ > > {%- for param in params %} > > std::vector<uint8_t> {{param.mojom_name}}Buf; > > {%- if param|has_fd %} > > - std::vector<FileDescriptor> {{param.mojom_name}}Fds; > > + std::vector<SharedFD> {{param.mojom_name}}Fds; > > std::tie({{param.mojom_name}}Buf, {{param.mojom_name}}Fds) = > > {%- else %} > > std::tie({{param.mojom_name}}Buf, std::ignore) = > > diff --git a/utils/ipc/generators/libcamera_templates/serializer.tmpl b/utils/ipc/generators/libcamera_templates/serializer.tmpl > > index b8ef8e7b974e..77bae36fe6b7 100644 > > --- a/utils/ipc/generators/libcamera_templates/serializer.tmpl > > +++ b/utils/ipc/generators/libcamera_templates/serializer.tmpl > > @@ -40,7 +40,7 @@ > > retData.insert(retData.end(), {{field.mojom_name}}.begin(), {{field.mojom_name}}.end()); > > {%- elif field|is_fd %} > > std::vector<uint8_t> {{field.mojom_name}}; > > - std::vector<FileDescriptor> {{field.mojom_name}}Fds; > > + std::vector<SharedFD> {{field.mojom_name}}Fds; > > std::tie({{field.mojom_name}}, {{field.mojom_name}}Fds) = > > IPADataSerializer<{{field|name}}>::serialize(data.{{field.mojom_name}}); > > retData.insert(retData.end(), {{field.mojom_name}}.begin(), {{field.mojom_name}}.end()); > > @@ -58,7 +58,7 @@ > > {%- elif field|is_plain_struct or field|is_array or field|is_map or field|is_str %} > > std::vector<uint8_t> {{field.mojom_name}}; > > {%- if field|has_fd %} > > - std::vector<FileDescriptor> {{field.mojom_name}}Fds; > > + std::vector<SharedFD> {{field.mojom_name}}Fds; > > std::tie({{field.mojom_name}}, {{field.mojom_name}}Fds) = > > {%- else %} > > std::tie({{field.mojom_name}}, std::ignore) = > > @@ -177,7 +177,7 @@ > > # \a struct. > > #} > > {%- macro serializer(struct, namespace) %} > > - static std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > > + static std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > > serialize(const {{struct|name_full}} &data, > > {%- if struct|needs_control_serializer %} > > ControlSerializer *cs) > > @@ -187,7 +187,7 @@ > > { > > std::vector<uint8_t> retData; > > {%- if struct|has_fd %} > > - std::vector<FileDescriptor> retFds; > > + std::vector<SharedFD> retFds; > > {%- endif %} > > {%- for field in struct.fields %} > > {{serializer_field(field, namespace, loop)}} > > @@ -210,7 +210,7 @@ > > {%- macro deserializer_fd(struct, namespace) %} > > static {{struct|name_full}} > > deserialize(std::vector<uint8_t> &data, > > - std::vector<FileDescriptor> &fds, > > + std::vector<SharedFD> &fds, > > {%- if struct|needs_control_serializer %} > > ControlSerializer *cs) > > {%- else %} > > @@ -224,8 +224,8 @@ > > static {{struct|name_full}} > > deserialize(std::vector<uint8_t>::const_iterator dataBegin, > > std::vector<uint8_t>::const_iterator dataEnd, > > - std::vector<FileDescriptor>::const_iterator fdsBegin, > > - std::vector<FileDescriptor>::const_iterator fdsEnd, > > + std::vector<SharedFD>::const_iterator fdsBegin, > > + std::vector<SharedFD>::const_iterator fdsEnd, > > {%- if struct|needs_control_serializer %} > > ControlSerializer *cs) > > {%- else %} > > @@ -234,7 +234,7 @@ > > { > > {{struct|name_full}} ret; > > std::vector<uint8_t>::const_iterator m = dataBegin; > > - std::vector<FileDescriptor>::const_iterator n = fdsBegin; > > + std::vector<SharedFD>::const_iterator n = fdsBegin; > > > > size_t dataSize = std::distance(dataBegin, dataEnd); > > [[maybe_unused]] size_t fdsSize = std::distance(fdsBegin, fdsEnd); > > @@ -255,7 +255,7 @@ > > {%- macro deserializer_fd_simple(struct, namespace) %} > > static {{struct|name_full}} > > deserialize(std::vector<uint8_t> &data, > > - [[maybe_unused]] std::vector<FileDescriptor> &fds, > > + [[maybe_unused]] std::vector<SharedFD> &fds, > > ControlSerializer *cs = nullptr) > > { > > return IPADataSerializer<{{struct|name_full}}>::deserialize(data.cbegin(), data.cend(), cs); > > @@ -264,8 +264,8 @@ > > static {{struct|name_full}} > > deserialize(std::vector<uint8_t>::const_iterator dataBegin, > > std::vector<uint8_t>::const_iterator dataEnd, > > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsBegin, > > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, > > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsBegin, > > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, > > ControlSerializer *cs = nullptr) > > { > > return IPADataSerializer<{{struct|name_full}}>::deserialize(dataBegin, dataEnd, cs); > > diff --git a/utils/ipc/generators/mojom_libcamera_generator.py b/utils/ipc/generators/mojom_libcamera_generator.py > > index c609f4e5c062..753bfc734e56 100644 > > --- a/utils/ipc/generators/mojom_libcamera_generator.py > > +++ b/utils/ipc/generators/mojom_libcamera_generator.py > > @@ -77,7 +77,7 @@ def GetDefaultValue(element): > > if mojom.IsEnumKind(element.kind): > > return f'static_cast<{element.kind.mojom_name}>(0)' > > if isinstance(element.kind, mojom.Struct) and \ > > - element.kind.mojom_name == 'FileDescriptor': > > + element.kind.mojom_name == 'SharedFD': > > return '-1' > > return '' > > > > @@ -140,7 +140,7 @@ def HasFd(element): > > types = GetAllTypes(element) > > else: > > types = GetAllTypes(element.kind) > > - return "FileDescriptor" in types or (attrs is not None and "hasFd" in attrs) > > + return "SharedFD" in types or (attrs is not None and "hasFd" in attrs) > > > > def WithDefaultValues(element): > > return [x for x in element if HasDefaultValue(x)] > > @@ -221,7 +221,7 @@ def IsEnum(element): > > return mojom.IsEnumKind(element.kind) > > > > def IsFd(element): > > - return mojom.IsStructKind(element.kind) and element.kind.mojom_name == "FileDescriptor" > > + return mojom.IsStructKind(element.kind) and element.kind.mojom_name == "SharedFD" > > > > def IsMap(element): > > return mojom.IsMapKind(element.kind)
Hi Laurent On Mon, Nov 29, 2021 at 07:24:47PM +0200, Laurent Pinchart wrote: > Hi Jacopo, > > On Mon, Nov 29, 2021 at 05:00:55PM +0100, Jacopo Mondi wrote: > > On Mon, Nov 29, 2021 at 01:57:52AM +0200, Laurent Pinchart wrote: > > > Now that we have a UniqueFD class, the name FileDescriptor is ambiguous. > > > Rename it to SharedFD. > > > > > > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > > > > makes sense! > > Does this mean Rb ? :-) > ups :) Reviewed-by: Jacopo Mondi <jacopo@jmondi.org> It does! > > > --- > > > include/libcamera/base/file.h | 4 +- > > > include/libcamera/base/meson.build | 2 +- > > > .../base/{file_descriptor.h => shared_fd.h} | 20 +- > > > include/libcamera/framebuffer.h | 4 +- > > > .../libcamera/internal/ipa_data_serializer.h | 40 +-- > > > include/libcamera/internal/ipc_pipe.h | 8 +- > > > include/libcamera/ipa/core.mojom | 6 +- > > > include/libcamera/ipa/raspberrypi.mojom | 2 +- > > > src/android/camera_device.cpp | 2 +- > > > src/ipa/raspberrypi/raspberrypi.cpp | 4 +- > > > src/libcamera/base/file.cpp | 6 +- > > > src/libcamera/base/file_descriptor.cpp | 266 ------------------ > > > src/libcamera/base/meson.build | 2 +- > > > src/libcamera/base/shared_fd.cpp | 262 +++++++++++++++++ > > > src/libcamera/framebuffer.cpp | 6 +- > > > src/libcamera/ipa_data_serializer.cpp | 100 +++---- > > > src/libcamera/ipc_pipe.cpp | 4 +- > > > .../pipeline/raspberrypi/raspberrypi.cpp | 6 +- > > > src/libcamera/v4l2_videodevice.cpp | 6 +- > > > src/v4l2/v4l2_camera.h | 2 +- > > > test/meson.build | 2 +- > > > .../ipa_data_serializer_test.cpp | 14 +- > > > test/{file-descriptor.cpp => shared-fd.cpp} | 46 +-- > > > .../module_ipa_proxy.cpp.tmpl | 2 +- > > > .../module_ipa_proxy.h.tmpl | 2 +- > > > .../libcamera_templates/proxy_functions.tmpl | 2 +- > > > .../libcamera_templates/serializer.tmpl | 22 +- > > > .../generators/mojom_libcamera_generator.py | 6 +- > > > 28 files changed, 422 insertions(+), 426 deletions(-) > > > rename include/libcamera/base/{file_descriptor.h => shared_fd.h} (55%) > > > delete mode 100644 src/libcamera/base/file_descriptor.cpp > > > create mode 100644 src/libcamera/base/shared_fd.cpp > > > rename test/{file-descriptor.cpp => shared-fd.cpp} (80%) > > > > > > diff --git a/include/libcamera/base/file.h b/include/libcamera/base/file.h > > > index 47769da7abc2..691b52d6ab2d 100644 > > > --- a/include/libcamera/base/file.h > > > +++ b/include/libcamera/base/file.h > > > @@ -21,7 +21,7 @@ > > > > > > namespace libcamera { > > > > > > -class FileDescriptor; > > > +class SharedFD; > > > > > > class File > > > { > > > @@ -69,7 +69,7 @@ public: > > > bool unmap(uint8_t *addr); > > > > > > static bool exists(const std::string &name); > > > - static ino_t inode(const FileDescriptor &fd); > > > + static ino_t inode(const SharedFD &fd); > > > > > > private: > > > LIBCAMERA_DISABLE_COPY(File) > > > diff --git a/include/libcamera/base/meson.build b/include/libcamera/base/meson.build > > > index cca374a769cc..112420dab225 100644 > > > --- a/include/libcamera/base/meson.build > > > +++ b/include/libcamera/base/meson.build > > > @@ -11,13 +11,13 @@ libcamera_base_headers = files([ > > > 'event_dispatcher_poll.h', > > > 'event_notifier.h', > > > 'file.h', > > > - 'file_descriptor.h', > > > 'flags.h', > > > 'log.h', > > > 'message.h', > > > 'object.h', > > > 'private.h', > > > 'semaphore.h', > > > + 'shared_fd.h', > > > 'signal.h', > > > 'span.h', > > > 'thread.h', > > > diff --git a/include/libcamera/base/file_descriptor.h b/include/libcamera/base/shared_fd.h > > > similarity index 55% > > > rename from include/libcamera/base/file_descriptor.h > > > rename to include/libcamera/base/shared_fd.h > > > index 12a43f95d414..a786885ceb32 100644 > > > --- a/include/libcamera/base/file_descriptor.h > > > +++ b/include/libcamera/base/shared_fd.h > > > @@ -2,7 +2,7 @@ > > > /* > > > * Copyright (C) 2019, Google Inc. > > > * > > > - * file_descriptor.h - File descriptor wrapper > > > + * shared_fd.h - File descriptor wrapper with shared ownership > > > */ > > > > > > #pragma once > > > @@ -13,18 +13,18 @@ namespace libcamera { > > > > > > class UniqueFD; > > > > > > -class FileDescriptor final > > > +class SharedFD final > > > { > > > public: > > > - explicit FileDescriptor(const int &fd = -1); > > > - explicit FileDescriptor(int &&fd); > > > - explicit FileDescriptor(UniqueFD fd); > > > - FileDescriptor(const FileDescriptor &other); > > > - FileDescriptor(FileDescriptor &&other); > > > - ~FileDescriptor(); > > > + explicit SharedFD(const int &fd = -1); > > > + explicit SharedFD(int &&fd); > > > + explicit SharedFD(UniqueFD fd); > > > + SharedFD(const SharedFD &other); > > > + SharedFD(SharedFD &&other); > > > + ~SharedFD(); > > > > > > - FileDescriptor &operator=(const FileDescriptor &other); > > > - FileDescriptor &operator=(FileDescriptor &&other); > > > + SharedFD &operator=(const SharedFD &other); > > > + SharedFD &operator=(SharedFD &&other); > > > > > > bool isValid() const { return fd_ != nullptr; } > > > int fd() const { return fd_ ? fd_->fd() : -1; } > > > diff --git a/include/libcamera/framebuffer.h b/include/libcamera/framebuffer.h > > > index 2fbea9c5be16..357bbe189551 100644 > > > --- a/include/libcamera/framebuffer.h > > > +++ b/include/libcamera/framebuffer.h > > > @@ -13,7 +13,7 @@ > > > #include <vector> > > > > > > #include <libcamera/base/class.h> > > > -#include <libcamera/base/file_descriptor.h> > > > +#include <libcamera/base/shared_fd.h> > > > #include <libcamera/base/span.h> > > > > > > namespace libcamera { > > > @@ -51,7 +51,7 @@ class FrameBuffer final : public Extensible > > > public: > > > struct Plane { > > > static constexpr unsigned int kInvalidOffset = std::numeric_limits<unsigned int>::max(); > > > - FileDescriptor fd; > > > + SharedFD fd; > > > unsigned int offset = kInvalidOffset; > > > unsigned int length; > > > }; > > > diff --git a/include/libcamera/internal/ipa_data_serializer.h b/include/libcamera/internal/ipa_data_serializer.h > > > index c2f602d5b7de..a87449c9be48 100644 > > > --- a/include/libcamera/internal/ipa_data_serializer.h > > > +++ b/include/libcamera/internal/ipa_data_serializer.h > > > @@ -66,7 +66,7 @@ template<typename T> > > > class IPADataSerializer > > > { > > > public: > > > - static std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > > > + static std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > > > serialize(const T &data, ControlSerializer *cs = nullptr); > > > > > > static T deserialize(const std::vector<uint8_t> &data, > > > @@ -76,12 +76,12 @@ public: > > > ControlSerializer *cs = nullptr); > > > > > > static T deserialize(const std::vector<uint8_t> &data, > > > - const std::vector<FileDescriptor> &fds, > > > + const std::vector<SharedFD> &fds, > > > ControlSerializer *cs = nullptr); > > > static T deserialize(std::vector<uint8_t>::const_iterator dataBegin, > > > std::vector<uint8_t>::const_iterator dataEnd, > > > - std::vector<FileDescriptor>::const_iterator fdsBegin, > > > - std::vector<FileDescriptor>::const_iterator fdsEnd, > > > + std::vector<SharedFD>::const_iterator fdsBegin, > > > + std::vector<SharedFD>::const_iterator fdsEnd, > > > ControlSerializer *cs = nullptr); > > > }; > > > > > > @@ -104,11 +104,11 @@ template<typename V> > > > class IPADataSerializer<std::vector<V>> > > > { > > > public: > > > - static std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > > > + static std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > > > serialize(const std::vector<V> &data, ControlSerializer *cs = nullptr) > > > { > > > std::vector<uint8_t> dataVec; > > > - std::vector<FileDescriptor> fdsVec; > > > + std::vector<SharedFD> fdsVec; > > > > > > /* Serialize the length. */ > > > uint32_t vecLen = data.size(); > > > @@ -117,7 +117,7 @@ public: > > > /* Serialize the members. */ > > > for (auto const &it : data) { > > > std::vector<uint8_t> dvec; > > > - std::vector<FileDescriptor> fvec; > > > + std::vector<SharedFD> fvec; > > > > > > std::tie(dvec, fvec) = > > > IPADataSerializer<V>::serialize(it, cs); > > > @@ -141,11 +141,11 @@ public: > > > std::vector<uint8_t>::const_iterator dataEnd, > > > ControlSerializer *cs = nullptr) > > > { > > > - std::vector<FileDescriptor> fds; > > > + std::vector<SharedFD> fds; > > > return deserialize(dataBegin, dataEnd, fds.cbegin(), fds.end(), cs); > > > } > > > > > > - static std::vector<V> deserialize(std::vector<uint8_t> &data, std::vector<FileDescriptor> &fds, > > > + static std::vector<V> deserialize(std::vector<uint8_t> &data, std::vector<SharedFD> &fds, > > > ControlSerializer *cs = nullptr) > > > { > > > return deserialize(data.cbegin(), data.end(), fds.cbegin(), fds.end(), cs); > > > @@ -153,15 +153,15 @@ public: > > > > > > static std::vector<V> deserialize(std::vector<uint8_t>::const_iterator dataBegin, > > > std::vector<uint8_t>::const_iterator dataEnd, > > > - std::vector<FileDescriptor>::const_iterator fdsBegin, > > > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, > > > + std::vector<SharedFD>::const_iterator fdsBegin, > > > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, > > > ControlSerializer *cs = nullptr) > > > { > > > uint32_t vecLen = readPOD<uint32_t>(dataBegin, 0, dataEnd); > > > std::vector<V> ret(vecLen); > > > > > > std::vector<uint8_t>::const_iterator dataIter = dataBegin + 4; > > > - std::vector<FileDescriptor>::const_iterator fdIter = fdsBegin; > > > + std::vector<SharedFD>::const_iterator fdIter = fdsBegin; > > > for (uint32_t i = 0; i < vecLen; i++) { > > > uint32_t sizeofData = readPOD<uint32_t>(dataIter, 0, dataEnd); > > > uint32_t sizeofFds = readPOD<uint32_t>(dataIter, 4, dataEnd); > > > @@ -201,11 +201,11 @@ template<typename K, typename V> > > > class IPADataSerializer<std::map<K, V>> > > > { > > > public: > > > - static std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > > > + static std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > > > serialize(const std::map<K, V> &data, ControlSerializer *cs = nullptr) > > > { > > > std::vector<uint8_t> dataVec; > > > - std::vector<FileDescriptor> fdsVec; > > > + std::vector<SharedFD> fdsVec; > > > > > > /* Serialize the length. */ > > > uint32_t mapLen = data.size(); > > > @@ -214,7 +214,7 @@ public: > > > /* Serialize the members. */ > > > for (auto const &it : data) { > > > std::vector<uint8_t> dvec; > > > - std::vector<FileDescriptor> fvec; > > > + std::vector<SharedFD> fvec; > > > > > > std::tie(dvec, fvec) = > > > IPADataSerializer<K>::serialize(it.first, cs); > > > @@ -247,11 +247,11 @@ public: > > > std::vector<uint8_t>::const_iterator dataEnd, > > > ControlSerializer *cs = nullptr) > > > { > > > - std::vector<FileDescriptor> fds; > > > + std::vector<SharedFD> fds; > > > return deserialize(dataBegin, dataEnd, fds.cbegin(), fds.end(), cs); > > > } > > > > > > - static std::map<K, V> deserialize(std::vector<uint8_t> &data, std::vector<FileDescriptor> &fds, > > > + static std::map<K, V> deserialize(std::vector<uint8_t> &data, std::vector<SharedFD> &fds, > > > ControlSerializer *cs = nullptr) > > > { > > > return deserialize(data.cbegin(), data.end(), fds.cbegin(), fds.end(), cs); > > > @@ -259,8 +259,8 @@ public: > > > > > > static std::map<K, V> deserialize(std::vector<uint8_t>::const_iterator dataBegin, > > > std::vector<uint8_t>::const_iterator dataEnd, > > > - std::vector<FileDescriptor>::const_iterator fdsBegin, > > > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, > > > + std::vector<SharedFD>::const_iterator fdsBegin, > > > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, > > > ControlSerializer *cs = nullptr) > > > { > > > std::map<K, V> ret; > > > @@ -268,7 +268,7 @@ public: > > > uint32_t mapLen = readPOD<uint32_t>(dataBegin, 0, dataEnd); > > > > > > std::vector<uint8_t>::const_iterator dataIter = dataBegin + 4; > > > - std::vector<FileDescriptor>::const_iterator fdIter = fdsBegin; > > > + std::vector<SharedFD>::const_iterator fdIter = fdsBegin; > > > for (uint32_t i = 0; i < mapLen; i++) { > > > uint32_t sizeofData = readPOD<uint32_t>(dataIter, 0, dataEnd); > > > uint32_t sizeofFds = readPOD<uint32_t>(dataIter, 4, dataEnd); > > > diff --git a/include/libcamera/internal/ipc_pipe.h b/include/libcamera/internal/ipc_pipe.h > > > index 986f8d886fa6..ab5dd67c3813 100644 > > > --- a/include/libcamera/internal/ipc_pipe.h > > > +++ b/include/libcamera/internal/ipc_pipe.h > > > @@ -9,7 +9,7 @@ > > > > > > #include <vector> > > > > > > -#include <libcamera/base/file_descriptor.h> > > > +#include <libcamera/base/shared_fd.h> > > > #include <libcamera/base/signal.h> > > > > > > #include "libcamera/internal/ipc_unixsocket.h" > > > @@ -33,17 +33,17 @@ public: > > > > > > Header &header() { return header_; } > > > std::vector<uint8_t> &data() { return data_; } > > > - std::vector<FileDescriptor> &fds() { return fds_; } > > > + std::vector<SharedFD> &fds() { return fds_; } > > > > > > const Header &header() const { return header_; } > > > const std::vector<uint8_t> &data() const { return data_; } > > > - const std::vector<FileDescriptor> &fds() const { return fds_; } > > > + const std::vector<SharedFD> &fds() const { return fds_; } > > > > > > private: > > > Header header_; > > > > > > std::vector<uint8_t> data_; > > > - std::vector<FileDescriptor> fds_; > > > + std::vector<SharedFD> fds_; > > > }; > > > > > > class IPCPipe > > > diff --git a/include/libcamera/ipa/core.mojom b/include/libcamera/ipa/core.mojom > > > index f7eff0c7ab8c..74f3339e56f2 100644 > > > --- a/include/libcamera/ipa/core.mojom > > > +++ b/include/libcamera/ipa/core.mojom > > > @@ -32,7 +32,7 @@ module libcamera; > > > * - This attribute instructs the build system that a (de)serializer is > > > * available for the type and there's no need to generate one > > > * - hasFd - struct fields or empty structs only > > > - * - Designate that this field or empty struct contains a FileDescriptor > > > + * - Designate that this field or empty struct contains a SharedFD > > > * > > > * Rules: > > > * - If the type is defined in a libcamera C++ header *and* a (de)serializer is > > > @@ -60,7 +60,7 @@ module libcamera; > > > * - In mojom, reference the type as FrameBuffer.Plane and only as map/array > > > * member > > > * - [skipHeader] and [skipSerdes] only work here in core.mojom > > > - * - If a field in a struct has a FileDescriptor, but is not explicitly > > > + * - If a field in a struct has a SharedFD, but is not explicitly > > > * defined so in mojom, then the field must be marked with the [hasFd] > > > * attribute > > > * > > > @@ -71,7 +71,7 @@ module libcamera; > > > */ > > > [skipSerdes, skipHeader] struct ControlInfoMap {}; > > > [skipSerdes, skipHeader] struct ControlList {}; > > > -[skipSerdes, skipHeader] struct FileDescriptor {}; > > > +[skipSerdes, skipHeader] struct SharedFD {}; > > > > > > [skipHeader] struct Point { > > > int32 x; > > > diff --git a/include/libcamera/ipa/raspberrypi.mojom b/include/libcamera/ipa/raspberrypi.mojom > > > index e453d46cb14f..acd3cafe6c91 100644 > > > --- a/include/libcamera/ipa/raspberrypi.mojom > > > +++ b/include/libcamera/ipa/raspberrypi.mojom > > > @@ -35,7 +35,7 @@ struct ISPConfig { > > > > > > struct IPAConfig { > > > uint32 transform; > > > - libcamera.FileDescriptor lsTableHandle; > > > + libcamera.SharedFD lsTableHandle; > > > }; > > > > > > struct StartConfig { > > > diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp > > > index f2e0bdbdbbf6..1938b10509fa 100644 > > > --- a/src/android/camera_device.cpp > > > +++ b/src/android/camera_device.cpp > > > @@ -725,7 +725,7 @@ CameraDevice::createFrameBuffer(const buffer_handle_t camera3buffer, > > > > > > std::vector<FrameBuffer::Plane> planes(buf.numPlanes()); > > > for (size_t i = 0; i < buf.numPlanes(); ++i) { > > > - FileDescriptor fd{ camera3buffer->data[i] }; > > > + SharedFD fd{ camera3buffer->data[i] }; > > > if (!fd.isValid()) { > > > LOG(HAL, Fatal) << "No valid fd"; > > > return nullptr; > > > diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp > > > index c6aec09046f7..aaf629eeb3fc 100644 > > > --- a/src/ipa/raspberrypi/raspberrypi.cpp > > > +++ b/src/ipa/raspberrypi/raspberrypi.cpp > > > @@ -15,8 +15,8 @@ > > > > > > #include <linux/bcm2835-isp.h> > > > > > > -#include <libcamera/base/file_descriptor.h> > > > #include <libcamera/base/log.h> > > > +#include <libcamera/base/shared_fd.h> > > > #include <libcamera/base/span.h> > > > > > > #include <libcamera/control_ids.h> > > > @@ -164,7 +164,7 @@ private: > > > bool processPending_; > > > > > > /* LS table allocation passed in from the pipeline handler. */ > > > - FileDescriptor lsTableHandle_; > > > + SharedFD lsTableHandle_; > > > void *lsTable_; > > > > > > /* Distinguish the first camera start from others. */ > > > diff --git a/src/libcamera/base/file.cpp b/src/libcamera/base/file.cpp > > > index 66c73c406198..3ca9839bb989 100644 > > > --- a/src/libcamera/base/file.cpp > > > +++ b/src/libcamera/base/file.cpp > > > @@ -14,8 +14,8 @@ > > > #include <sys/types.h> > > > #include <unistd.h> > > > > > > -#include <libcamera/base/file_descriptor.h> > > > #include <libcamera/base/log.h> > > > +#include <libcamera/base/shared_fd.h> > > > > > > /** > > > * \file base/file.h > > > @@ -473,11 +473,11 @@ bool File::exists(const std::string &name) > > > } > > > > > > /** > > > - * \brief Retrieve the inode of a FileDescriptor > > > + * \brief Retrieve the inode of a SharedFD > > > * > > > * \return The file descriptor inode on success, or 0 on error > > > */ > > > -ino_t File::inode(const FileDescriptor &fd) > > > +ino_t File::inode(const SharedFD &fd) > > > { > > > if (!fd.isValid()) > > > return 0; > > > diff --git a/src/libcamera/base/file_descriptor.cpp b/src/libcamera/base/file_descriptor.cpp > > > deleted file mode 100644 > > > index a83bf52c31e6..000000000000 > > > --- a/src/libcamera/base/file_descriptor.cpp > > > +++ /dev/null > > > @@ -1,266 +0,0 @@ > > > -/* SPDX-License-Identifier: LGPL-2.1-or-later */ > > > -/* > > > - * Copyright (C) 2019, Google Inc. > > > - * > > > - * file_descriptor.cpp - File descriptor wrapper > > > - */ > > > - > > > -#include <libcamera/base/file_descriptor.h> > > > - > > > -#include <string.h> > > > -#include <sys/types.h> > > > -#include <unistd.h> > > > -#include <utility> > > > - > > > -#include <libcamera/base/log.h> > > > -#include <libcamera/base/unique_fd.h> > > > - > > > -/** > > > - * \file base/file_descriptor.h > > > - * \brief File descriptor wrapper > > > - */ > > > - > > > -namespace libcamera { > > > - > > > -LOG_DEFINE_CATEGORY(FileDescriptor) > > > - > > > -/** > > > - * \class FileDescriptor > > > - * \brief RAII-style wrapper for file descriptors > > > - * > > > - * The FileDescriptor class provides RAII-style lifetime management of file > > > - * descriptors with an efficient mechanism for ownership sharing. At its core, > > > - * an internal Descriptor object wraps a file descriptor (expressed as a signed > > > - * integer) with an RAII-style interface. The Descriptor is then implicitly > > > - * shared with all FileDescriptor instances constructed as copies. > > > - * > > > - * When constructed from a numerical file descriptor, the FileDescriptor > > > - * instance either duplicates or takes over the file descriptor: > > > - * > > > - * - The FileDescriptor(const int &) constructor duplicates the numerical file > > > - * descriptor and wraps the duplicate in a Descriptor. The caller is > > > - * responsible for closing the original file descriptor, and the value > > > - * returned by fd() will be different from the value passed to the > > > - * constructor. > > > - * > > > - * - The FileDescriptor(int &&) constructor takes over the numerical file > > > - * descriptor and wraps it in a Descriptor. The caller shall not touch the > > > - * original file descriptor once the function returns, and the value returned > > > - * by fd() will be identical to the value passed to the constructor. > > > - * > > > - * The copy constructor and assignment operator create copies that share the > > > - * Descriptor, while the move versions of those functions additionally make the > > > - * other FileDescriptor invalid. When the last FileDescriptor that references a > > > - * Descriptor is destroyed, the file descriptor is closed. > > > - * > > > - * The numerical file descriptor is available through the fd() function. All > > > - * FileDescriptor instances created as copies of a FileDescriptor will report > > > - * the same fd() value. Callers can perform operations on the fd(), but shall > > > - * never close it manually. > > > - */ > > > - > > > -/** > > > - * \brief Create a FileDescriptor copying a given \a fd > > > - * \param[in] fd File descriptor > > > - * > > > - * Construct a FileDescriptor from a numerical file descriptor by duplicating > > > - * the \a fd, and take ownership of the copy. The original \a fd is left > > > - * untouched, and the caller is responsible for closing it when appropriate. > > > - * The duplicated file descriptor will be closed automatically when all > > > - * FileDescriptor instances that reference it are destroyed. > > > - * > > > - * If the \a fd is negative, the FileDescriptor is constructed as invalid and > > > - * the fd() function will return -1. > > > - */ > > > -FileDescriptor::FileDescriptor(const int &fd) > > > -{ > > > - if (fd < 0) > > > - return; > > > - > > > - fd_ = std::make_shared<Descriptor>(fd, true); > > > - if (fd_->fd() < 0) > > > - fd_.reset(); > > > -} > > > - > > > -/** > > > - * \brief Create a FileDescriptor taking ownership of a given \a fd > > > - * \param[in] fd File descriptor > > > - * > > > - * Construct a FileDescriptor from a numerical file descriptor by taking > > > - * ownership of the \a fd. The original \a fd is set to -1 and shall not be > > > - * touched by the caller anymore. In particular, the caller shall not close the > > > - * original \a fd manually. The duplicated file descriptor will be closed > > > - * automatically when all FileDescriptor instances that reference it are > > > - * destroyed. > > > - * > > > - * If the \a fd is negative, the FileDescriptor is constructed as invalid and > > > - * the fd() function will return -1. > > > - */ > > > -FileDescriptor::FileDescriptor(int &&fd) > > > -{ > > > - if (fd < 0) > > > - return; > > > - > > > - fd_ = std::make_shared<Descriptor>(fd, false); > > > - /* > > > - * The Descriptor constructor can't have failed here, as it took over > > > - * the fd without duplicating it. Just set the original fd to -1 to > > > - * implement move semantics. > > > - */ > > > - fd = -1; > > > -} > > > - > > > -/** > > > - * \brief Create a FileDescriptor taking ownership of a given UniqueFD \a fd > > > - * \param[in] fd UniqueFD > > > - * > > > - * Construct a FileDescriptor from UniqueFD by taking ownership of the \a fd. > > > - * The original \a fd becomes invalid. > > > - */ > > > -FileDescriptor::FileDescriptor(UniqueFD fd) > > > - : FileDescriptor(fd.release()) > > > -{ > > > -} > > > - > > > -/** > > > - * \brief Copy constructor, create a FileDescriptor from a copy of \a other > > > - * \param[in] other The other FileDescriptor > > > - * > > > - * Copying a FileDescriptor implicitly shares ownership of the wrapped file > > > - * descriptor. The original FileDescriptor is left untouched, and the caller is > > > - * responsible for destroying it when appropriate. The wrapped file descriptor > > > - * will be closed automatically when all FileDescriptor instances that > > > - * reference it are destroyed. > > > - */ > > > -FileDescriptor::FileDescriptor(const FileDescriptor &other) > > > - : fd_(other.fd_) > > > -{ > > > -} > > > - > > > -/** > > > - * \brief Move constructor, create a FileDescriptor by taking over \a other > > > - * \param[in] other The other FileDescriptor > > > - * > > > - * Moving a FileDescriptor moves the reference to the wrapped descriptor owned > > > - * by \a other to the new FileDescriptor. The \a other FileDescriptor is > > > - * invalidated and its fd() function will return -1. The wrapped file descriptor > > > - * will be closed automatically when all FileDescriptor instances that > > > - * reference it are destroyed. > > > - */ > > > -FileDescriptor::FileDescriptor(FileDescriptor &&other) > > > - : fd_(std::move(other.fd_)) > > > -{ > > > -} > > > - > > > -/** > > > - * \brief Destroy the FileDescriptor instance > > > - * > > > - * Destroying a FileDescriptor instance releases its reference to the wrapped > > > - * descriptor, if any. When the last instance that references a wrapped > > > - * descriptor is destroyed, the file descriptor is automatically closed. > > > - */ > > > -FileDescriptor::~FileDescriptor() > > > -{ > > > -} > > > - > > > -/** > > > - * \brief Copy assignment operator, replace the wrapped file descriptor with a > > > - * copy of \a other > > > - * \param[in] other The other FileDescriptor > > > - * > > > - * Copying a FileDescriptor creates a new reference to the wrapped file > > > - * descriptor owner by \a other. If \a other is invalid, *this will also be > > > - * invalid. The original FileDescriptor is left untouched, and the caller is > > > - * responsible for destroying it when appropriate. The wrapped file descriptor > > > - * will be closed automatically when all FileDescriptor instances that > > > - * reference it are destroyed. > > > - * > > > - * \return A reference to this FileDescriptor > > > - */ > > > -FileDescriptor &FileDescriptor::operator=(const FileDescriptor &other) > > > -{ > > > - fd_ = other.fd_; > > > - > > > - return *this; > > > -} > > > - > > > -/** > > > - * \brief Move assignment operator, replace the wrapped file descriptor by > > > - * taking over \a other > > > - * \param[in] other The other FileDescriptor > > > - * > > > - * Moving a FileDescriptor moves the reference to the wrapped descriptor owned > > > - * by \a other to the new FileDescriptor. If \a other is invalid, *this will > > > - * also be invalid. The \a other FileDescriptor is invalidated and its fd() > > > - * function will return -1. The wrapped file descriptor will be closed > > > - * automatically when all FileDescriptor instances that reference it are > > > - * destroyed. > > > - * > > > - * \return A reference to this FileDescriptor > > > - */ > > > -FileDescriptor &FileDescriptor::operator=(FileDescriptor &&other) > > > -{ > > > - fd_ = std::move(other.fd_); > > > - > > > - return *this; > > > -} > > > - > > > -/** > > > - * \fn FileDescriptor::isValid() > > > - * \brief Check if the FileDescriptor instance is valid > > > - * \return True if the FileDescriptor is valid, false otherwise > > > - */ > > > - > > > -/** > > > - * \fn FileDescriptor::fd() > > > - * \brief Retrieve the numerical file descriptor > > > - * \return The numerical file descriptor, which may be -1 if the FileDescriptor > > > - * instance is invalid > > > - */ > > > - > > > -/** > > > - * \brief Duplicate a FileDescriptor > > > - * > > > - * Duplicating a FileDescriptor creates a duplicate of the wrapped file > > > - * descriptor and returns a UniqueFD that owns the duplicate. The fd() function > > > - * of the original and the get() function of the duplicate will return different > > > - * values. The duplicate instance will not be affected by destruction of the > > > - * original instance or its copies. > > > - * > > > - * \return A UniqueFD owning a duplicate of the original file descriptor > > > - */ > > > -UniqueFD FileDescriptor::dup() const > > > -{ > > > - int dupFd = ::dup(fd()); > > > - if (dupFd == -1) { > > > - int ret = -errno; > > > - LOG(FileDescriptor, Error) > > > - << "Failed to dup() fd: " << strerror(-ret); > > > - } > > > - > > > - return UniqueFD(dupFd); > > > -} > > > - > > > -FileDescriptor::Descriptor::Descriptor(int fd, bool duplicate) > > > -{ > > > - if (!duplicate) { > > > - fd_ = fd; > > > - return; > > > - } > > > - > > > - /* Failing to dup() a fd should not happen and is fatal. */ > > > - fd_ = ::dup(fd); > > > - if (fd_ == -1) { > > > - int ret = -errno; > > > - LOG(FileDescriptor, Fatal) > > > - << "Failed to dup() fd: " << strerror(-ret); > > > - } > > > -} > > > - > > > -FileDescriptor::Descriptor::~Descriptor() > > > -{ > > > - if (fd_ != -1) > > > - close(fd_); > > > -} > > > - > > > -} /* namespace libcamera */ > > > diff --git a/src/libcamera/base/meson.build b/src/libcamera/base/meson.build > > > index b0d85bc19245..ccb746c27466 100644 > > > --- a/src/libcamera/base/meson.build > > > +++ b/src/libcamera/base/meson.build > > > @@ -8,12 +8,12 @@ libcamera_base_sources = files([ > > > 'event_dispatcher_poll.cpp', > > > 'event_notifier.cpp', > > > 'file.cpp', > > > - 'file_descriptor.cpp', > > > 'flags.cpp', > > > 'log.cpp', > > > 'message.cpp', > > > 'object.cpp', > > > 'semaphore.cpp', > > > + 'shared_fd.cpp', > > > 'signal.cpp', > > > 'thread.cpp', > > > 'timer.cpp', > > > diff --git a/src/libcamera/base/shared_fd.cpp b/src/libcamera/base/shared_fd.cpp > > > new file mode 100644 > > > index 000000000000..05b6892f7e19 > > > --- /dev/null > > > +++ b/src/libcamera/base/shared_fd.cpp > > > @@ -0,0 +1,262 @@ > > > +/* SPDX-License-Identifier: LGPL-2.1-or-later */ > > > +/* > > > + * Copyright (C) 2019, Google Inc. > > > + * > > > + * shared_fd.cpp - File descriptor wrapper with shared ownership > > > + */ > > > + > > > +#include <libcamera/base/shared_fd.h> > > > + > > > +#include <string.h> > > > +#include <sys/types.h> > > > +#include <unistd.h> > > > +#include <utility> > > > + > > > +#include <libcamera/base/log.h> > > > +#include <libcamera/base/unique_fd.h> > > > + > > > +/** > > > + * \file base/shared_fd.h > > > + * \brief File descriptor wrapper > > > + */ > > > + > > > +namespace libcamera { > > > + > > > +LOG_DEFINE_CATEGORY(SharedFD) > > > + > > > +/** > > > + * \class SharedFD > > > + * \brief RAII-style wrapper for file descriptors > > > + * > > > + * The SharedFD class provides RAII-style lifetime management of file > > > + * descriptors with an efficient mechanism for ownership sharing. At its core, > > > + * an internal Descriptor object wraps a file descriptor (expressed as a signed > > > + * integer) with an RAII-style interface. The Descriptor is then implicitly > > > + * shared with all SharedFD instances constructed as copies. > > > + * > > > + * When constructed from a numerical file descriptor, the SharedFD instance > > > + * either duplicates or takes over the file descriptor: > > > + * > > > + * - The SharedFD(const int &) constructor duplicates the numerical file > > > + * descriptor and wraps the duplicate in a Descriptor. The caller is > > > + * responsible for closing the original file descriptor, and the value > > > + * returned by fd() will be different from the value passed to the > > > + * constructor. > > > + * > > > + * - The SharedFD(int &&) constructor takes over the numerical file descriptor > > > + * and wraps it in a Descriptor. The caller shall not touch the original file > > > + * descriptor once the function returns, and the value returned by fd() will > > > + * be identical to the value passed to the constructor. > > > + * > > > + * The copy constructor and assignment operator create copies that share the > > > + * Descriptor, while the move versions of those functions additionally make the > > > + * other SharedFD invalid. When the last SharedFD that references a Descriptor > > > + * is destroyed, the file descriptor is closed. > > > + * > > > + * The numerical file descriptor is available through the fd() function. All > > > + * SharedFD instances created as copies of a SharedFD will report the same fd() > > > + * value. Callers can perform operations on the fd(), but shall never close it > > > + * manually. > > > + */ > > > + > > > +/** > > > + * \brief Create a SharedFD copying a given \a fd > > > + * \param[in] fd File descriptor > > > + * > > > + * Construct a SharedFD from a numerical file descriptor by duplicating the > > > + * \a fd, and take ownership of the copy. The original \a fd is left untouched, > > > + * and the caller is responsible for closing it when appropriate. The duplicated > > > + * file descriptor will be closed automatically when all SharedFD instances that > > > + * reference it are destroyed. > > > + * > > > + * If the \a fd is negative, the SharedFD is constructed as invalid and the fd() > > > + * function will return -1. > > > + */ > > > +SharedFD::SharedFD(const int &fd) > > > +{ > > > + if (fd < 0) > > > + return; > > > + > > > + fd_ = std::make_shared<Descriptor>(fd, true); > > > + if (fd_->fd() < 0) > > > + fd_.reset(); > > > +} > > > + > > > +/** > > > + * \brief Create a SharedFD taking ownership of a given \a fd > > > + * \param[in] fd File descriptor > > > + * > > > + * Construct a SharedFD from a numerical file descriptor by taking ownership of > > > + * the \a fd. The original \a fd is set to -1 and shall not be touched by the > > > + * caller anymore. In particular, the caller shall not close the original \a fd > > > + * manually. The duplicated file descriptor will be closed automatically when > > > + * all SharedFD instances that reference it are destroyed. > > > + * > > > + * If the \a fd is negative, the SharedFD is constructed as invalid and the fd() > > > + * function will return -1. > > > + */ > > > +SharedFD::SharedFD(int &&fd) > > > +{ > > > + if (fd < 0) > > > + return; > > > + > > > + fd_ = std::make_shared<Descriptor>(fd, false); > > > + /* > > > + * The Descriptor constructor can't have failed here, as it took over > > > + * the fd without duplicating it. Just set the original fd to -1 to > > > + * implement move semantics. > > > + */ > > > + fd = -1; > > > +} > > > + > > > +/** > > > + * \brief Create a SharedFD taking ownership of a given UniqueFD \a fd > > > + * \param[in] fd UniqueFD > > > + * > > > + * Construct a SharedFD from UniqueFD by taking ownership of the \a fd. The > > > + * original \a fd becomes invalid. > > > + */ > > > +SharedFD::SharedFD(UniqueFD fd) > > > + : SharedFD(fd.release()) > > > +{ > > > +} > > > + > > > +/** > > > + * \brief Copy constructor, create a SharedFD from a copy of \a other > > > + * \param[in] other The other SharedFD > > > + * > > > + * Copying a SharedFD implicitly shares ownership of the wrapped file > > > + * descriptor. The original SharedFD is left untouched, and the caller is > > > + * responsible for destroying it when appropriate. The wrapped file descriptor > > > + * will be closed automatically when all SharedFD instances that reference it > > > + * are destroyed. > > > + */ > > > +SharedFD::SharedFD(const SharedFD &other) > > > + : fd_(other.fd_) > > > +{ > > > +} > > > + > > > +/** > > > + * \brief Move constructor, create a SharedFD by taking over \a other > > > + * \param[in] other The other SharedFD > > > + * > > > + * Moving a SharedFD moves the reference to the wrapped descriptor owned by > > > + * \a other to the new SharedFD. The \a other SharedFD is invalidated and its > > > + * fd() function will return -1. The wrapped file descriptor will be closed > > > + * automatically when all SharedFD instances that reference it are destroyed. > > > + */ > > > +SharedFD::SharedFD(SharedFD &&other) > > > + : fd_(std::move(other.fd_)) > > > +{ > > > +} > > > + > > > +/** > > > + * \brief Destroy the SharedFD instance > > > + * > > > + * Destroying a SharedFD instance releases its reference to the wrapped > > > + * descriptor, if any. When the last instance that references a wrapped > > > + * descriptor is destroyed, the file descriptor is automatically closed. > > > + */ > > > +SharedFD::~SharedFD() > > > +{ > > > +} > > > + > > > +/** > > > + * \brief Copy assignment operator, replace the wrapped file descriptor with a > > > + * copy of \a other > > > + * \param[in] other The other SharedFD > > > + * > > > + * Copying a SharedFD creates a new reference to the wrapped file descriptor > > > + * owner by \a other. If \a other is invalid, *this will also be invalid. The > > > + * original SharedFD is left untouched, and the caller is responsible for > > > + * destroying it when appropriate. The wrapped file descriptor will be closed > > > + * automatically when all SharedFD instances that reference it are destroyed. > > > + * > > > + * \return A reference to this SharedFD > > > + */ > > > +SharedFD &SharedFD::operator=(const SharedFD &other) > > > +{ > > > + fd_ = other.fd_; > > > + > > > + return *this; > > > +} > > > + > > > +/** > > > + * \brief Move assignment operator, replace the wrapped file descriptor by > > > + * taking over \a other > > > + * \param[in] other The other SharedFD > > > + * > > > + * Moving a SharedFD moves the reference to the wrapped descriptor owned by > > > + * \a other to the new SharedFD. If \a other is invalid, *this will also be > > > + * invalid. The \a other SharedFD is invalidated and its fd() function will > > > + * return -1. The wrapped file descriptor will be closed automatically when > > > + * all SharedFD instances that reference it are destroyed. > > > + * > > > + * \return A reference to this SharedFD > > > + */ > > > +SharedFD &SharedFD::operator=(SharedFD &&other) > > > +{ > > > + fd_ = std::move(other.fd_); > > > + > > > + return *this; > > > +} > > > + > > > +/** > > > + * \fn SharedFD::isValid() > > > + * \brief Check if the SharedFD instance is valid > > > + * \return True if the SharedFD is valid, false otherwise > > > + */ > > > + > > > +/** > > > + * \fn SharedFD::fd() > > > + * \brief Retrieve the numerical file descriptor > > > + * \return The numerical file descriptor, which may be -1 if the SharedFD > > > + * instance is invalid > > > + */ > > > + > > > +/** > > > + * \brief Duplicate a SharedFD > > > + * > > > + * Duplicating a SharedFD creates a duplicate of the wrapped file descriptor and > > > + * returns a UniqueFD that owns the duplicate. The fd() function of the original > > > + * and the get() function of the duplicate will return different values. The > > > + * duplicate instance will not be affected by destruction of the original > > > + * instance or its copies. > > > + * > > > + * \return A UniqueFD owning a duplicate of the original file descriptor > > > + */ > > > +UniqueFD SharedFD::dup() const > > > +{ > > > + int dupFd = ::dup(fd()); > > > + if (dupFd == -1) { > > > + int ret = -errno; > > > + LOG(SharedFD, Error) > > > + << "Failed to dup() fd: " << strerror(-ret); > > > + } > > > + > > > + return UniqueFD(dupFd); > > > +} > > > + > > > +SharedFD::Descriptor::Descriptor(int fd, bool duplicate) > > > +{ > > > + if (!duplicate) { > > > + fd_ = fd; > > > + return; > > > + } > > > + > > > + /* Failing to dup() a fd should not happen and is fatal. */ > > > + fd_ = ::dup(fd); > > > + if (fd_ == -1) { > > > + int ret = -errno; > > > + LOG(SharedFD, Fatal) > > > + << "Failed to dup() fd: " << strerror(-ret); > > > + } > > > +} > > > + > > > +SharedFD::Descriptor::~Descriptor() > > > +{ > > > + if (fd_ != -1) > > > + close(fd_); > > > +} > > > + > > > +} /* namespace libcamera */ > > > diff --git a/src/libcamera/framebuffer.cpp b/src/libcamera/framebuffer.cpp > > > index f5bcf107d7aa..0a5bf7fdbeb7 100644 > > > --- a/src/libcamera/framebuffer.cpp > > > +++ b/src/libcamera/framebuffer.cpp > > > @@ -180,9 +180,9 @@ FrameBuffer::Private::Private() > > > * offset and length. > > > * > > > * To support DMA access, planes are associated with dmabuf objects represented > > > - * by FileDescriptor handles. The Plane class doesn't handle mapping of the > > > - * memory to the CPU, but applications and IPAs may use the dmabuf file > > > - * descriptors to map the plane memory with mmap() and access its contents. > > > + * by SharedFD handles. The Plane class doesn't handle mapping of the memory to > > > + * the CPU, but applications and IPAs may use the dmabuf file descriptors to map > > > + * the plane memory with mmap() and access its contents. > > > * > > > * \todo Specify how an application shall decide whether to use a single or > > > * multiple dmabufs, based on the camera requirements. > > > diff --git a/src/libcamera/ipa_data_serializer.cpp b/src/libcamera/ipa_data_serializer.cpp > > > index 82ec9b20a411..0a259305afa2 100644 > > > --- a/src/libcamera/ipa_data_serializer.cpp > > > +++ b/src/libcamera/ipa_data_serializer.cpp > > > @@ -31,7 +31,7 @@ LOG_DEFINE_CATEGORY(IPADataSerializer) > > > * > > > * \todo Harden the vector and map deserializer > > > * > > > - * \todo For FileDescriptors, instead of storing a validity flag, store an > > > + * \todo For SharedFDs, instead of storing a validity flag, store an > > > * index into the fd array. This will allow us to use views instead of copying. > > > */ > > > > > > @@ -112,7 +112,7 @@ namespace { > > > * \param[in] cs ControlSerializer > > > * > > > * This version of deserialize() can be used if the object type \a T and its > > > - * members don't have any FileDescriptor. > > > + * members don't have any SharedFD. > > > * > > > * \a cs is only necessary if the object type \a T or its members contain > > > * ControlList or ControlInfoMap. > > > @@ -132,7 +132,7 @@ namespace { > > > * \param[in] cs ControlSerializer > > > * > > > * This version of deserialize() can be used if the object type \a T and its > > > - * members don't have any FileDescriptor. > > > + * members don't have any SharedFD. > > > * > > > * \a cs is only necessary if the object type \a T or its members contain > > > * ControlList or ControlInfoMap. > > > @@ -143,7 +143,7 @@ namespace { > > > /** > > > * \fn template<typename T> IPADataSerializer<T>::deserialize( > > > * const std::vector<uint8_t> &data, > > > - * const std::vector<FileDescriptor> &fds, > > > + * const std::vector<SharedFD> &fds, > > > * ControlSerializer *cs = nullptr) > > > * \brief Deserialize byte vector and fd vector into an object > > > * \tparam T Type of object to deserialize to > > > @@ -152,7 +152,7 @@ namespace { > > > * \param[in] cs ControlSerializer > > > * > > > * This version of deserialize() (or the iterator version) must be used if > > > - * the object type \a T or its members contain FileDescriptor. > > > + * the object type \a T or its members contain SharedFD. > > > * > > > * \a cs is only necessary if the object type \a T or its members contain > > > * ControlList or ControlInfoMap. > > > @@ -164,8 +164,8 @@ namespace { > > > * \fn template<typename T> IPADataSerializer::deserialize( > > > * std::vector<uint8_t>::const_iterator dataBegin, > > > * std::vector<uint8_t>::const_iterator dataEnd, > > > - * std::vector<FileDescriptor>::const_iterator fdsBegin, > > > - * std::vector<FileDescriptor>::const_iterator fdsEnd, > > > + * std::vector<SharedFD>::const_iterator fdsBegin, > > > + * std::vector<SharedFD>::const_iterator fdsEnd, > > > * ControlSerializer *cs = nullptr) > > > * \brief Deserialize byte vector and fd vector into an object > > > * \tparam T Type of object to deserialize to > > > @@ -176,7 +176,7 @@ namespace { > > > * \param[in] cs ControlSerializer > > > * > > > * This version of deserialize() (or the vector version) must be used if > > > - * the object type \a T or its members contain FileDescriptor. > > > + * the object type \a T or its members contain SharedFD. > > > * > > > * \a cs is only necessary if the object type \a T or its members contain > > > * ControlList or ControlInfoMap. > > > @@ -189,7 +189,7 @@ namespace { > > > #define DEFINE_POD_SERIALIZER(type) \ > > > \ > > > template<> \ > > > -std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> \ > > > +std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> \ > > > IPADataSerializer<type>::serialize(const type &data, \ > > > [[maybe_unused]] ControlSerializer *cs) \ > > > { \ > > > @@ -217,7 +217,7 @@ type IPADataSerializer<type>::deserialize(const std::vector<uint8_t> &data, \ > > > \ > > > template<> \ > > > type IPADataSerializer<type>::deserialize(const std::vector<uint8_t> &data, \ > > > - [[maybe_unused]] const std::vector<FileDescriptor> &fds, \ > > > + [[maybe_unused]] const std::vector<SharedFD> &fds, \ > > > ControlSerializer *cs) \ > > > { \ > > > return deserialize(data.cbegin(), data.end(), cs); \ > > > @@ -226,8 +226,8 @@ type IPADataSerializer<type>::deserialize(const std::vector<uint8_t> &data, \ > > > template<> \ > > > type IPADataSerializer<type>::deserialize(std::vector<uint8_t>::const_iterator dataBegin, \ > > > std::vector<uint8_t>::const_iterator dataEnd, \ > > > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsBegin, \ > > > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, \ > > > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsBegin, \ > > > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, \ > > > ControlSerializer *cs) \ > > > { \ > > > return deserialize(dataBegin, dataEnd, cs); \ > > > @@ -251,7 +251,7 @@ DEFINE_POD_SERIALIZER(double) > > > * function parameter serdes). > > > */ > > > template<> > > > -std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > > > +std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > > > IPADataSerializer<std::string>::serialize(const std::string &data, > > > [[maybe_unused]] ControlSerializer *cs) > > > { > > > @@ -278,7 +278,7 @@ IPADataSerializer<std::string>::deserialize(std::vector<uint8_t>::const_iterator > > > template<> > > > std::string > > > IPADataSerializer<std::string>::deserialize(const std::vector<uint8_t> &data, > > > - [[maybe_unused]] const std::vector<FileDescriptor> &fds, > > > + [[maybe_unused]] const std::vector<SharedFD> &fds, > > > [[maybe_unused]] ControlSerializer *cs) > > > { > > > return { data.cbegin(), data.cend() }; > > > @@ -288,8 +288,8 @@ template<> > > > std::string > > > IPADataSerializer<std::string>::deserialize(std::vector<uint8_t>::const_iterator dataBegin, > > > std::vector<uint8_t>::const_iterator dataEnd, > > > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsBegin, > > > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, > > > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsBegin, > > > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, > > > [[maybe_unused]] ControlSerializer *cs) > > > { > > > return { dataBegin, dataEnd }; > > > @@ -307,7 +307,7 @@ IPADataSerializer<std::string>::deserialize(std::vector<uint8_t>::const_iterator > > > * be used. The serialized ControlInfoMap will have zero length. > > > */ > > > template<> > > > -std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > > > +std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > > > IPADataSerializer<ControlList>::serialize(const ControlList &data, ControlSerializer *cs) > > > { > > > if (!cs) > > > @@ -407,7 +407,7 @@ IPADataSerializer<ControlList>::deserialize(const std::vector<uint8_t> &data, > > > template<> > > > ControlList > > > IPADataSerializer<ControlList>::deserialize(const std::vector<uint8_t> &data, > > > - [[maybe_unused]] const std::vector<FileDescriptor> &fds, > > > + [[maybe_unused]] const std::vector<SharedFD> &fds, > > > ControlSerializer *cs) > > > { > > > return deserialize(data.cbegin(), data.end(), cs); > > > @@ -417,8 +417,8 @@ template<> > > > ControlList > > > IPADataSerializer<ControlList>::deserialize(std::vector<uint8_t>::const_iterator dataBegin, > > > std::vector<uint8_t>::const_iterator dataEnd, > > > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsBegin, > > > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, > > > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsBegin, > > > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, > > > ControlSerializer *cs) > > > { > > > return deserialize(dataBegin, dataEnd, cs); > > > @@ -431,7 +431,7 @@ IPADataSerializer<ControlList>::deserialize(std::vector<uint8_t>::const_iterator > > > * X bytes - Serialized ControlInfoMap (using ControlSerializer) > > > */ > > > template<> > > > -std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > > > +std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > > > IPADataSerializer<ControlInfoMap>::serialize(const ControlInfoMap &map, > > > ControlSerializer *cs) > > > { > > > @@ -493,7 +493,7 @@ IPADataSerializer<ControlInfoMap>::deserialize(const std::vector<uint8_t> &data, > > > template<> > > > ControlInfoMap > > > IPADataSerializer<ControlInfoMap>::deserialize(const std::vector<uint8_t> &data, > > > - [[maybe_unused]] const std::vector<FileDescriptor> &fds, > > > + [[maybe_unused]] const std::vector<SharedFD> &fds, > > > ControlSerializer *cs) > > > { > > > return deserialize(data.cbegin(), data.end(), cs); > > > @@ -503,30 +503,30 @@ template<> > > > ControlInfoMap > > > IPADataSerializer<ControlInfoMap>::deserialize(std::vector<uint8_t>::const_iterator dataBegin, > > > std::vector<uint8_t>::const_iterator dataEnd, > > > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsBegin, > > > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, > > > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsBegin, > > > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, > > > ControlSerializer *cs) > > > { > > > return deserialize(dataBegin, dataEnd, cs); > > > } > > > > > > /* > > > - * FileDescriptors are serialized into four bytes that tells if the > > > - * FileDescriptor is valid or not. If it is valid, then for serialization > > > - * the fd will be written to the fd vector, or for deserialization the > > > - * fd vector const_iterator will be valid. > > > + * SharedFD instances are serialized into four bytes that tells if the SharedFD > > > + * is valid or not. If it is valid, then for serialization the fd will be > > > + * written to the fd vector, or for deserialization the fd vector const_iterator > > > + * will be valid. > > > * > > > * This validity is necessary so that we don't send -1 fd over sendmsg(). It > > > * also allows us to simply send the entire fd vector into the deserializer > > > * and it will be recursively consumed as necessary. > > > */ > > > template<> > > > -std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > > > -IPADataSerializer<FileDescriptor>::serialize(const FileDescriptor &data, > > > - [[maybe_unused]] ControlSerializer *cs) > > > +std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > > > +IPADataSerializer<SharedFD>::serialize(const SharedFD &data, > > > + [[maybe_unused]] ControlSerializer *cs) > > > { > > > std::vector<uint8_t> dataVec; > > > - std::vector<FileDescriptor> fdVec; > > > + std::vector<SharedFD> fdVec; > > > > > > /* > > > * Store as uint32_t to prepare for conversion from validity flag > > > @@ -542,11 +542,11 @@ IPADataSerializer<FileDescriptor>::serialize(const FileDescriptor &data, > > > } > > > > > > template<> > > > -FileDescriptor IPADataSerializer<FileDescriptor>::deserialize([[maybe_unused]] std::vector<uint8_t>::const_iterator dataBegin, > > > - [[maybe_unused]] std::vector<uint8_t>::const_iterator dataEnd, > > > - std::vector<FileDescriptor>::const_iterator fdsBegin, > > > - std::vector<FileDescriptor>::const_iterator fdsEnd, > > > - [[maybe_unused]] ControlSerializer *cs) > > > +SharedFD IPADataSerializer<SharedFD>::deserialize([[maybe_unused]] std::vector<uint8_t>::const_iterator dataBegin, > > > + [[maybe_unused]] std::vector<uint8_t>::const_iterator dataEnd, > > > + std::vector<SharedFD>::const_iterator fdsBegin, > > > + std::vector<SharedFD>::const_iterator fdsEnd, > > > + [[maybe_unused]] ControlSerializer *cs) > > > { > > > ASSERT(std::distance(dataBegin, dataEnd) >= 4); > > > > > > @@ -554,13 +554,13 @@ FileDescriptor IPADataSerializer<FileDescriptor>::deserialize([[maybe_unused]] s > > > > > > ASSERT(!(valid && std::distance(fdsBegin, fdsEnd) < 1)); > > > > > > - return valid ? *fdsBegin : FileDescriptor(); > > > + return valid ? *fdsBegin : SharedFD(); > > > } > > > > > > template<> > > > -FileDescriptor IPADataSerializer<FileDescriptor>::deserialize(const std::vector<uint8_t> &data, > > > - const std::vector<FileDescriptor> &fds, > > > - [[maybe_unused]] ControlSerializer *cs) > > > +SharedFD IPADataSerializer<SharedFD>::deserialize(const std::vector<uint8_t> &data, > > > + const std::vector<SharedFD> &fds, > > > + [[maybe_unused]] ControlSerializer *cs) > > > { > > > return deserialize(data.cbegin(), data.end(), fds.cbegin(), fds.end()); > > > } > > > @@ -568,22 +568,22 @@ FileDescriptor IPADataSerializer<FileDescriptor>::deserialize(const std::vector< > > > /* > > > * FrameBuffer::Plane is serialized as: > > > * > > > - * 4 byte - FileDescriptor > > > + * 4 byte - SharedFD > > > * 4 bytes - uint32_t Offset > > > * 4 bytes - uint32_t Length > > > */ > > > template<> > > > -std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > > > +std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > > > IPADataSerializer<FrameBuffer::Plane>::serialize(const FrameBuffer::Plane &data, > > > [[maybe_unused]] ControlSerializer *cs) > > > { > > > std::vector<uint8_t> dataVec; > > > - std::vector<FileDescriptor> fdsVec; > > > + std::vector<SharedFD> fdsVec; > > > > > > std::vector<uint8_t> fdBuf; > > > - std::vector<FileDescriptor> fdFds; > > > + std::vector<SharedFD> fdFds; > > > std::tie(fdBuf, fdFds) = > > > - IPADataSerializer<FileDescriptor>::serialize(data.fd); > > > + IPADataSerializer<SharedFD>::serialize(data.fd); > > > dataVec.insert(dataVec.end(), fdBuf.begin(), fdBuf.end()); > > > fdsVec.insert(fdsVec.end(), fdFds.begin(), fdFds.end()); > > > > > > @@ -597,13 +597,13 @@ template<> > > > FrameBuffer::Plane > > > IPADataSerializer<FrameBuffer::Plane>::deserialize(std::vector<uint8_t>::const_iterator dataBegin, > > > std::vector<uint8_t>::const_iterator dataEnd, > > > - std::vector<FileDescriptor>::const_iterator fdsBegin, > > > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, > > > + std::vector<SharedFD>::const_iterator fdsBegin, > > > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, > > > [[maybe_unused]] ControlSerializer *cs) > > > { > > > FrameBuffer::Plane ret; > > > > > > - ret.fd = IPADataSerializer<FileDescriptor>::deserialize(dataBegin, dataBegin + 4, > > > + ret.fd = IPADataSerializer<SharedFD>::deserialize(dataBegin, dataBegin + 4, > > > fdsBegin, fdsBegin + 1); > > > ret.offset = readPOD<uint32_t>(dataBegin, 4, dataEnd); > > > ret.length = readPOD<uint32_t>(dataBegin, 8, dataEnd); > > > @@ -614,7 +614,7 @@ IPADataSerializer<FrameBuffer::Plane>::deserialize(std::vector<uint8_t>::const_i > > > template<> > > > FrameBuffer::Plane > > > IPADataSerializer<FrameBuffer::Plane>::deserialize(const std::vector<uint8_t> &data, > > > - const std::vector<FileDescriptor> &fds, > > > + const std::vector<SharedFD> &fds, > > > ControlSerializer *cs) > > > { > > > return deserialize(data.cbegin(), data.end(), fds.cbegin(), fds.end(), cs); > > > diff --git a/src/libcamera/ipc_pipe.cpp b/src/libcamera/ipc_pipe.cpp > > > index ad870fd4137f..3b47032de0a2 100644 > > > --- a/src/libcamera/ipc_pipe.cpp > > > +++ b/src/libcamera/ipc_pipe.cpp > > > @@ -87,7 +87,7 @@ IPCMessage::IPCMessage(IPCUnixSocket::Payload &payload) > > > data_ = std::vector<uint8_t>(payload.data.begin() + sizeof(header_), > > > payload.data.end()); > > > for (int32_t &fd : payload.fds) > > > - fds_.push_back(FileDescriptor(std::move(fd))); > > > + fds_.push_back(SharedFD(std::move(fd))); > > > } > > > > > > /** > > > @@ -112,7 +112,7 @@ IPCUnixSocket::Payload IPCMessage::payload() const > > > data_.data(), data_.size()); > > > } > > > > > > - for (const FileDescriptor &fd : fds_) > > > + for (const SharedFD &fd : fds_) > > > payload.fds.push_back(fd.fd()); > > > > > > return payload; > > > diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp > > > index ffa51a0c65ca..ea8243912a29 100644 > > > --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp > > > +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp > > > @@ -12,7 +12,7 @@ > > > #include <queue> > > > #include <unordered_set> > > > > > > -#include <libcamera/base/file_descriptor.h> > > > +#include <libcamera/base/shared_fd.h> > > > > > > #include <libcamera/camera.h> > > > #include <libcamera/control_ids.h> > > > @@ -228,7 +228,7 @@ public: > > > > > > /* DMAHEAP allocation helper. */ > > > RPi::DmaHeap dmaHeap_; > > > - FileDescriptor lsTable_; > > > + SharedFD lsTable_; > > > > > > std::unique_ptr<DelayedControls> delayedCtrls_; > > > bool sensorMetadata_; > > > @@ -1365,7 +1365,7 @@ int RPiCameraData::configureIPA(const CameraConfiguration *config) > > > if (!fd.isValid()) > > > return -ENOMEM; > > > > > > - lsTable_ = FileDescriptor(std::move(fd)); > > > + lsTable_ = SharedFD(std::move(fd)); > > > > > > /* Allow the IPA to mmap the LS table via the file descriptor. */ > > > /* > > > diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp > > > index 3966483a365f..97d431071def 100644 > > > --- a/src/libcamera/v4l2_videodevice.cpp > > > +++ b/src/libcamera/v4l2_videodevice.cpp > > > @@ -22,8 +22,8 @@ > > > #include <linux/version.h> > > > > > > #include <libcamera/base/event_notifier.h> > > > -#include <libcamera/base/file_descriptor.h> > > > #include <libcamera/base/log.h> > > > +#include <libcamera/base/shared_fd.h> > > > #include <libcamera/base/unique_fd.h> > > > #include <libcamera/base/utils.h> > > > > > > @@ -1325,7 +1325,7 @@ std::unique_ptr<FrameBuffer> V4L2VideoDevice::createBuffer(unsigned int index) > > > return nullptr; > > > > > > FrameBuffer::Plane plane; > > > - plane.fd = FileDescriptor(std::move(fd)); > > > + plane.fd = SharedFD(std::move(fd)); > > > /* > > > * V4L2 API doesn't provide dmabuf offset information of plane. > > > * Set 0 as a placeholder offset. > > > @@ -1354,7 +1354,7 @@ std::unique_ptr<FrameBuffer> V4L2VideoDevice::createBuffer(unsigned int index) > > > ASSERT(numPlanes == 1u); > > > > > > planes.resize(formatInfo_->numPlanes()); > > > - const FileDescriptor &fd = planes[0].fd; > > > + const SharedFD &fd = planes[0].fd; > > > size_t offset = 0; > > > > > > for (auto [i, plane] : utils::enumerate(planes)) { > > > diff --git a/src/v4l2/v4l2_camera.h b/src/v4l2/v4l2_camera.h > > > index 9817fd393d59..586347829845 100644 > > > --- a/src/v4l2/v4l2_camera.h > > > +++ b/src/v4l2/v4l2_camera.h > > > @@ -11,8 +11,8 @@ > > > #include <mutex> > > > #include <utility> > > > > > > -#include <libcamera/base/file_descriptor.h> > > > #include <libcamera/base/semaphore.h> > > > +#include <libcamera/base/shared_fd.h> > > > > > > #include <libcamera/camera.h> > > > #include <libcamera/framebuffer.h> > > > diff --git a/test/meson.build b/test/meson.build > > > index 42dfbc1f8ee9..daaa3862cdd6 100644 > > > --- a/test/meson.build > > > +++ b/test/meson.build > > > @@ -40,7 +40,6 @@ internal_tests = [ > > > ['event-dispatcher', 'event-dispatcher.cpp'], > > > ['event-thread', 'event-thread.cpp'], > > > ['file', 'file.cpp'], > > > - ['file-descriptor', 'file-descriptor.cpp'], > > > ['flags', 'flags.cpp'], > > > ['hotplug-cameras', 'hotplug-cameras.cpp'], > > > ['mapped-buffer', 'mapped-buffer.cpp'], > > > @@ -49,6 +48,7 @@ internal_tests = [ > > > ['object-delete', 'object-delete.cpp'], > > > ['object-invoke', 'object-invoke.cpp'], > > > ['pixel-format', 'pixel-format.cpp'], > > > + ['shared-fd', 'shared-fd.cpp'], > > > ['signal-threads', 'signal-threads.cpp'], > > > ['threads', 'threads.cpp'], > > > ['timer', 'timer.cpp'], > > > diff --git a/test/serialization/ipa_data_serializer_test.cpp b/test/serialization/ipa_data_serializer_test.cpp > > > index 5fcdcb8eae92..d2050a868b38 100644 > > > --- a/test/serialization/ipa_data_serializer_test.cpp > > > +++ b/test/serialization/ipa_data_serializer_test.cpp > > > @@ -53,7 +53,7 @@ template<typename T> > > > int testPodSerdes(T in) > > > { > > > std::vector<uint8_t> buf; > > > - std::vector<FileDescriptor> fds; > > > + std::vector<SharedFD> fds; > > > > > > std::tie(buf, fds) = IPADataSerializer<T>::serialize(in); > > > T out = IPADataSerializer<T>::deserialize(buf, fds); > > > @@ -72,7 +72,7 @@ int testVectorSerdes(const std::vector<T> &in, > > > ControlSerializer *cs = nullptr) > > > { > > > std::vector<uint8_t> buf; > > > - std::vector<FileDescriptor> fds; > > > + std::vector<SharedFD> fds; > > > > > > std::tie(buf, fds) = IPADataSerializer<std::vector<T>>::serialize(in, cs); > > > std::vector<T> out = IPADataSerializer<std::vector<T>>::deserialize(buf, fds, cs); > > > @@ -92,7 +92,7 @@ int testMapSerdes(const std::map<K, V> &in, > > > ControlSerializer *cs = nullptr) > > > { > > > std::vector<uint8_t> buf; > > > - std::vector<FileDescriptor> fds; > > > + std::vector<SharedFD> fds; > > > > > > std::tie(buf, fds) = IPADataSerializer<std::map<K, V>>::serialize(in, cs); > > > std::map<K, V> out = IPADataSerializer<std::map<K, V>>::deserialize(buf, fds, cs); > > > @@ -198,7 +198,7 @@ private: > > > ControlSerializer cs(ControlSerializer::Role::Proxy); > > > > > > /* > > > - * We don't test FileDescriptor serdes because it dup()s, so we > > > + * We don't test SharedFD serdes because it dup()s, so we > > > * can't check for equality. > > > */ > > > std::vector<uint8_t> vecUint8 = { 1, 2, 3, 4, 5, 6 }; > > > @@ -219,7 +219,7 @@ private: > > > }; > > > > > > std::vector<uint8_t> buf; > > > - std::vector<FileDescriptor> fds; > > > + std::vector<SharedFD> fds; > > > > > > if (testVectorSerdes(vecUint8) != TestPass) > > > return TestFail; > > > @@ -291,7 +291,7 @@ private: > > > { { "a", { 1, 2, 3 } }, { "b", { 4, 5, 6 } }, { "c", { 7, 8, 9 } } }; > > > > > > std::vector<uint8_t> buf; > > > - std::vector<FileDescriptor> fds; > > > + std::vector<SharedFD> fds; > > > > > > if (testMapSerdes(mapUintStr) != TestPass) > > > return TestFail; > > > @@ -359,7 +359,7 @@ private: > > > std::string strEmpty = ""; > > > > > > std::vector<uint8_t> buf; > > > - std::vector<FileDescriptor> fds; > > > + std::vector<SharedFD> fds; > > > > > > if (testPodSerdes(u32min) != TestPass) > > > return TestFail; > > > diff --git a/test/file-descriptor.cpp b/test/shared-fd.cpp > > > similarity index 80% > > > rename from test/file-descriptor.cpp > > > rename to test/shared-fd.cpp > > > index 76badc4c5fad..60e5d0aaa395 100644 > > > --- a/test/file-descriptor.cpp > > > +++ b/test/shared-fd.cpp > > > @@ -2,7 +2,7 @@ > > > /* > > > * Copyright (C) 2019, Google Inc. > > > * > > > - * file_descriptor.cpp - FileDescriptor test > > > + * shared_fd.cpp - SharedFD test > > > */ > > > > > > #include <fcntl.h> > > > @@ -11,7 +11,7 @@ > > > #include <sys/types.h> > > > #include <unistd.h> > > > > > > -#include <libcamera/base/file_descriptor.h> > > > +#include <libcamera/base/shared_fd.h> > > > #include <libcamera/base/utils.h> > > > > > > #include "test.h" > > > @@ -19,7 +19,7 @@ > > > using namespace libcamera; > > > using namespace std; > > > > > > -class FileDescriptorTest : public Test > > > +class SharedFDTest : public Test > > > { > > > protected: > > > int init() > > > @@ -43,8 +43,8 @@ protected: > > > > > > int run() > > > { > > > - /* Test creating empty FileDescriptor. */ > > > - desc1_ = new FileDescriptor(); > > > + /* Test creating empty SharedFD. */ > > > + desc1_ = new SharedFD(); > > > > > > if (desc1_->fd() != -1) { > > > std::cout << "Failed fd numerical check (default constructor)" > > > @@ -56,10 +56,10 @@ protected: > > > desc1_ = nullptr; > > > > > > /* > > > - * Test creating FileDescriptor by copying numerical file > > > + * Test creating SharedFD by copying numerical file > > > * descriptor. > > > */ > > > - desc1_ = new FileDescriptor(fd_); > > > + desc1_ = new SharedFD(fd_); > > > if (desc1_->fd() == fd_) { > > > std::cout << "Failed fd numerical check (lvalue ref constructor)" > > > << std::endl; > > > @@ -84,13 +84,13 @@ protected: > > > } > > > > > > /* > > > - * Test creating FileDescriptor by taking ownership of > > > + * Test creating SharedFD by taking ownership of > > > * numerical file descriptor. > > > */ > > > int dupFd = dup(fd_); > > > int dupFdCopy = dupFd; > > > > > > - desc1_ = new FileDescriptor(std::move(dupFd)); > > > + desc1_ = new SharedFD(std::move(dupFd)); > > > if (desc1_->fd() != dupFdCopy) { > > > std::cout << "Failed fd numerical check (rvalue ref constructor)" > > > << std::endl; > > > @@ -114,9 +114,9 @@ protected: > > > return TestFail; > > > } > > > > > > - /* Test creating FileDescriptor from other FileDescriptor. */ > > > - desc1_ = new FileDescriptor(fd_); > > > - desc2_ = new FileDescriptor(*desc1_); > > > + /* Test creating SharedFD from other SharedFD. */ > > > + desc1_ = new SharedFD(fd_); > > > + desc2_ = new SharedFD(*desc1_); > > > > > > if (desc1_->fd() == fd_ || desc2_->fd() == fd_ || desc1_->fd() != desc2_->fd()) { > > > std::cout << "Failed fd numerical check (copy constructor)" > > > @@ -142,10 +142,10 @@ protected: > > > delete desc2_; > > > desc2_ = nullptr; > > > > > > - /* Test creating FileDescriptor by taking over other FileDescriptor. */ > > > - desc1_ = new FileDescriptor(fd_); > > > + /* Test creating SharedFD by taking over other SharedFD. */ > > > + desc1_ = new SharedFD(fd_); > > > fd = desc1_->fd(); > > > - desc2_ = new FileDescriptor(std::move(*desc1_)); > > > + desc2_ = new SharedFD(std::move(*desc1_)); > > > > > > if (desc1_->fd() != -1 || desc2_->fd() != fd) { > > > std::cout << "Failed fd numerical check (move constructor)" > > > @@ -164,9 +164,9 @@ protected: > > > delete desc2_; > > > desc2_ = nullptr; > > > > > > - /* Test creating FileDescriptor by copy assignment. */ > > > - desc1_ = new FileDescriptor(); > > > - desc2_ = new FileDescriptor(fd_); > > > + /* Test creating SharedFD by copy assignment. */ > > > + desc1_ = new SharedFD(); > > > + desc2_ = new SharedFD(fd_); > > > > > > fd = desc2_->fd(); > > > *desc1_ = *desc2_; > > > @@ -188,9 +188,9 @@ protected: > > > delete desc2_; > > > desc2_ = nullptr; > > > > > > - /* Test creating FileDescriptor by move assignment. */ > > > - desc1_ = new FileDescriptor(); > > > - desc2_ = new FileDescriptor(fd_); > > > + /* Test creating SharedFD by move assignment. */ > > > + desc1_ = new SharedFD(); > > > + desc2_ = new SharedFD(fd_); > > > > > > fd = desc2_->fd(); > > > *desc1_ = std::move(*desc2_); > > > @@ -237,7 +237,7 @@ private: > > > > > > int fd_; > > > ino_t inodeNr_; > > > - FileDescriptor *desc1_, *desc2_; > > > + SharedFD *desc1_, *desc2_; > > > }; > > > > > > -TEST_REGISTER(FileDescriptorTest) > > > +TEST_REGISTER(SharedFDTest) > > > diff --git a/utils/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl b/utils/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl > > > index d856339aa9ee..c37c4941b528 100644 > > > --- a/utils/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl > > > +++ b/utils/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl > > > @@ -237,7 +237,7 @@ void {{proxy_name}}::recvMessage(const IPCMessage &data) > > > void {{proxy_name}}::{{method.mojom_name}}IPC( > > > std::vector<uint8_t>::const_iterator data, > > > size_t dataSize, > > > - [[maybe_unused]] const std::vector<FileDescriptor> &fds) > > > + [[maybe_unused]] const std::vector<SharedFD> &fds) > > > { > > > {%- for param in method.parameters %} > > > {{param|name}} {{param.mojom_name}}; > > > diff --git a/utils/ipc/generators/libcamera_templates/module_ipa_proxy.h.tmpl b/utils/ipc/generators/libcamera_templates/module_ipa_proxy.h.tmpl > > > index ce396c183d0c..c308dd10c7e5 100644 > > > --- a/utils/ipc/generators/libcamera_templates/module_ipa_proxy.h.tmpl > > > +++ b/utils/ipc/generators/libcamera_templates/module_ipa_proxy.h.tmpl > > > @@ -64,7 +64,7 @@ private: > > > void {{method.mojom_name}}IPC( > > > std::vector<uint8_t>::const_iterator data, > > > size_t dataSize, > > > - const std::vector<FileDescriptor> &fds); > > > + const std::vector<SharedFD> &fds); > > > {% endfor %} > > > > > > /* Helper class to invoke async functions in another thread. */ > > > diff --git a/utils/ipc/generators/libcamera_templates/proxy_functions.tmpl b/utils/ipc/generators/libcamera_templates/proxy_functions.tmpl > > > index ebcd2aaaafae..bac826a74c2d 100644 > > > --- a/utils/ipc/generators/libcamera_templates/proxy_functions.tmpl > > > +++ b/utils/ipc/generators/libcamera_templates/proxy_functions.tmpl > > > @@ -54,7 +54,7 @@ > > > {%- for param in params %} > > > std::vector<uint8_t> {{param.mojom_name}}Buf; > > > {%- if param|has_fd %} > > > - std::vector<FileDescriptor> {{param.mojom_name}}Fds; > > > + std::vector<SharedFD> {{param.mojom_name}}Fds; > > > std::tie({{param.mojom_name}}Buf, {{param.mojom_name}}Fds) = > > > {%- else %} > > > std::tie({{param.mojom_name}}Buf, std::ignore) = > > > diff --git a/utils/ipc/generators/libcamera_templates/serializer.tmpl b/utils/ipc/generators/libcamera_templates/serializer.tmpl > > > index b8ef8e7b974e..77bae36fe6b7 100644 > > > --- a/utils/ipc/generators/libcamera_templates/serializer.tmpl > > > +++ b/utils/ipc/generators/libcamera_templates/serializer.tmpl > > > @@ -40,7 +40,7 @@ > > > retData.insert(retData.end(), {{field.mojom_name}}.begin(), {{field.mojom_name}}.end()); > > > {%- elif field|is_fd %} > > > std::vector<uint8_t> {{field.mojom_name}}; > > > - std::vector<FileDescriptor> {{field.mojom_name}}Fds; > > > + std::vector<SharedFD> {{field.mojom_name}}Fds; > > > std::tie({{field.mojom_name}}, {{field.mojom_name}}Fds) = > > > IPADataSerializer<{{field|name}}>::serialize(data.{{field.mojom_name}}); > > > retData.insert(retData.end(), {{field.mojom_name}}.begin(), {{field.mojom_name}}.end()); > > > @@ -58,7 +58,7 @@ > > > {%- elif field|is_plain_struct or field|is_array or field|is_map or field|is_str %} > > > std::vector<uint8_t> {{field.mojom_name}}; > > > {%- if field|has_fd %} > > > - std::vector<FileDescriptor> {{field.mojom_name}}Fds; > > > + std::vector<SharedFD> {{field.mojom_name}}Fds; > > > std::tie({{field.mojom_name}}, {{field.mojom_name}}Fds) = > > > {%- else %} > > > std::tie({{field.mojom_name}}, std::ignore) = > > > @@ -177,7 +177,7 @@ > > > # \a struct. > > > #} > > > {%- macro serializer(struct, namespace) %} > > > - static std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> > > > + static std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> > > > serialize(const {{struct|name_full}} &data, > > > {%- if struct|needs_control_serializer %} > > > ControlSerializer *cs) > > > @@ -187,7 +187,7 @@ > > > { > > > std::vector<uint8_t> retData; > > > {%- if struct|has_fd %} > > > - std::vector<FileDescriptor> retFds; > > > + std::vector<SharedFD> retFds; > > > {%- endif %} > > > {%- for field in struct.fields %} > > > {{serializer_field(field, namespace, loop)}} > > > @@ -210,7 +210,7 @@ > > > {%- macro deserializer_fd(struct, namespace) %} > > > static {{struct|name_full}} > > > deserialize(std::vector<uint8_t> &data, > > > - std::vector<FileDescriptor> &fds, > > > + std::vector<SharedFD> &fds, > > > {%- if struct|needs_control_serializer %} > > > ControlSerializer *cs) > > > {%- else %} > > > @@ -224,8 +224,8 @@ > > > static {{struct|name_full}} > > > deserialize(std::vector<uint8_t>::const_iterator dataBegin, > > > std::vector<uint8_t>::const_iterator dataEnd, > > > - std::vector<FileDescriptor>::const_iterator fdsBegin, > > > - std::vector<FileDescriptor>::const_iterator fdsEnd, > > > + std::vector<SharedFD>::const_iterator fdsBegin, > > > + std::vector<SharedFD>::const_iterator fdsEnd, > > > {%- if struct|needs_control_serializer %} > > > ControlSerializer *cs) > > > {%- else %} > > > @@ -234,7 +234,7 @@ > > > { > > > {{struct|name_full}} ret; > > > std::vector<uint8_t>::const_iterator m = dataBegin; > > > - std::vector<FileDescriptor>::const_iterator n = fdsBegin; > > > + std::vector<SharedFD>::const_iterator n = fdsBegin; > > > > > > size_t dataSize = std::distance(dataBegin, dataEnd); > > > [[maybe_unused]] size_t fdsSize = std::distance(fdsBegin, fdsEnd); > > > @@ -255,7 +255,7 @@ > > > {%- macro deserializer_fd_simple(struct, namespace) %} > > > static {{struct|name_full}} > > > deserialize(std::vector<uint8_t> &data, > > > - [[maybe_unused]] std::vector<FileDescriptor> &fds, > > > + [[maybe_unused]] std::vector<SharedFD> &fds, > > > ControlSerializer *cs = nullptr) > > > { > > > return IPADataSerializer<{{struct|name_full}}>::deserialize(data.cbegin(), data.cend(), cs); > > > @@ -264,8 +264,8 @@ > > > static {{struct|name_full}} > > > deserialize(std::vector<uint8_t>::const_iterator dataBegin, > > > std::vector<uint8_t>::const_iterator dataEnd, > > > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsBegin, > > > - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, > > > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsBegin, > > > + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, > > > ControlSerializer *cs = nullptr) > > > { > > > return IPADataSerializer<{{struct|name_full}}>::deserialize(dataBegin, dataEnd, cs); > > > diff --git a/utils/ipc/generators/mojom_libcamera_generator.py b/utils/ipc/generators/mojom_libcamera_generator.py > > > index c609f4e5c062..753bfc734e56 100644 > > > --- a/utils/ipc/generators/mojom_libcamera_generator.py > > > +++ b/utils/ipc/generators/mojom_libcamera_generator.py > > > @@ -77,7 +77,7 @@ def GetDefaultValue(element): > > > if mojom.IsEnumKind(element.kind): > > > return f'static_cast<{element.kind.mojom_name}>(0)' > > > if isinstance(element.kind, mojom.Struct) and \ > > > - element.kind.mojom_name == 'FileDescriptor': > > > + element.kind.mojom_name == 'SharedFD': > > > return '-1' > > > return '' > > > > > > @@ -140,7 +140,7 @@ def HasFd(element): > > > types = GetAllTypes(element) > > > else: > > > types = GetAllTypes(element.kind) > > > - return "FileDescriptor" in types or (attrs is not None and "hasFd" in attrs) > > > + return "SharedFD" in types or (attrs is not None and "hasFd" in attrs) > > > > > > def WithDefaultValues(element): > > > return [x for x in element if HasDefaultValue(x)] > > > @@ -221,7 +221,7 @@ def IsEnum(element): > > > return mojom.IsEnumKind(element.kind) > > > > > > def IsFd(element): > > > - return mojom.IsStructKind(element.kind) and element.kind.mojom_name == "FileDescriptor" > > > + return mojom.IsStructKind(element.kind) and element.kind.mojom_name == "SharedFD" > > > > > > def IsMap(element): > > > return mojom.IsMapKind(element.kind) > > -- > Regards, > > Laurent Pinchart
diff --git a/include/libcamera/base/file.h b/include/libcamera/base/file.h index 47769da7abc2..691b52d6ab2d 100644 --- a/include/libcamera/base/file.h +++ b/include/libcamera/base/file.h @@ -21,7 +21,7 @@ namespace libcamera { -class FileDescriptor; +class SharedFD; class File { @@ -69,7 +69,7 @@ public: bool unmap(uint8_t *addr); static bool exists(const std::string &name); - static ino_t inode(const FileDescriptor &fd); + static ino_t inode(const SharedFD &fd); private: LIBCAMERA_DISABLE_COPY(File) diff --git a/include/libcamera/base/meson.build b/include/libcamera/base/meson.build index cca374a769cc..112420dab225 100644 --- a/include/libcamera/base/meson.build +++ b/include/libcamera/base/meson.build @@ -11,13 +11,13 @@ libcamera_base_headers = files([ 'event_dispatcher_poll.h', 'event_notifier.h', 'file.h', - 'file_descriptor.h', 'flags.h', 'log.h', 'message.h', 'object.h', 'private.h', 'semaphore.h', + 'shared_fd.h', 'signal.h', 'span.h', 'thread.h', diff --git a/include/libcamera/base/file_descriptor.h b/include/libcamera/base/shared_fd.h similarity index 55% rename from include/libcamera/base/file_descriptor.h rename to include/libcamera/base/shared_fd.h index 12a43f95d414..a786885ceb32 100644 --- a/include/libcamera/base/file_descriptor.h +++ b/include/libcamera/base/shared_fd.h @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * file_descriptor.h - File descriptor wrapper + * shared_fd.h - File descriptor wrapper with shared ownership */ #pragma once @@ -13,18 +13,18 @@ namespace libcamera { class UniqueFD; -class FileDescriptor final +class SharedFD final { public: - explicit FileDescriptor(const int &fd = -1); - explicit FileDescriptor(int &&fd); - explicit FileDescriptor(UniqueFD fd); - FileDescriptor(const FileDescriptor &other); - FileDescriptor(FileDescriptor &&other); - ~FileDescriptor(); + explicit SharedFD(const int &fd = -1); + explicit SharedFD(int &&fd); + explicit SharedFD(UniqueFD fd); + SharedFD(const SharedFD &other); + SharedFD(SharedFD &&other); + ~SharedFD(); - FileDescriptor &operator=(const FileDescriptor &other); - FileDescriptor &operator=(FileDescriptor &&other); + SharedFD &operator=(const SharedFD &other); + SharedFD &operator=(SharedFD &&other); bool isValid() const { return fd_ != nullptr; } int fd() const { return fd_ ? fd_->fd() : -1; } diff --git a/include/libcamera/framebuffer.h b/include/libcamera/framebuffer.h index 2fbea9c5be16..357bbe189551 100644 --- a/include/libcamera/framebuffer.h +++ b/include/libcamera/framebuffer.h @@ -13,7 +13,7 @@ #include <vector> #include <libcamera/base/class.h> -#include <libcamera/base/file_descriptor.h> +#include <libcamera/base/shared_fd.h> #include <libcamera/base/span.h> namespace libcamera { @@ -51,7 +51,7 @@ class FrameBuffer final : public Extensible public: struct Plane { static constexpr unsigned int kInvalidOffset = std::numeric_limits<unsigned int>::max(); - FileDescriptor fd; + SharedFD fd; unsigned int offset = kInvalidOffset; unsigned int length; }; diff --git a/include/libcamera/internal/ipa_data_serializer.h b/include/libcamera/internal/ipa_data_serializer.h index c2f602d5b7de..a87449c9be48 100644 --- a/include/libcamera/internal/ipa_data_serializer.h +++ b/include/libcamera/internal/ipa_data_serializer.h @@ -66,7 +66,7 @@ template<typename T> class IPADataSerializer { public: - static std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> + static std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> serialize(const T &data, ControlSerializer *cs = nullptr); static T deserialize(const std::vector<uint8_t> &data, @@ -76,12 +76,12 @@ public: ControlSerializer *cs = nullptr); static T deserialize(const std::vector<uint8_t> &data, - const std::vector<FileDescriptor> &fds, + const std::vector<SharedFD> &fds, ControlSerializer *cs = nullptr); static T deserialize(std::vector<uint8_t>::const_iterator dataBegin, std::vector<uint8_t>::const_iterator dataEnd, - std::vector<FileDescriptor>::const_iterator fdsBegin, - std::vector<FileDescriptor>::const_iterator fdsEnd, + std::vector<SharedFD>::const_iterator fdsBegin, + std::vector<SharedFD>::const_iterator fdsEnd, ControlSerializer *cs = nullptr); }; @@ -104,11 +104,11 @@ template<typename V> class IPADataSerializer<std::vector<V>> { public: - static std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> + static std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> serialize(const std::vector<V> &data, ControlSerializer *cs = nullptr) { std::vector<uint8_t> dataVec; - std::vector<FileDescriptor> fdsVec; + std::vector<SharedFD> fdsVec; /* Serialize the length. */ uint32_t vecLen = data.size(); @@ -117,7 +117,7 @@ public: /* Serialize the members. */ for (auto const &it : data) { std::vector<uint8_t> dvec; - std::vector<FileDescriptor> fvec; + std::vector<SharedFD> fvec; std::tie(dvec, fvec) = IPADataSerializer<V>::serialize(it, cs); @@ -141,11 +141,11 @@ public: std::vector<uint8_t>::const_iterator dataEnd, ControlSerializer *cs = nullptr) { - std::vector<FileDescriptor> fds; + std::vector<SharedFD> fds; return deserialize(dataBegin, dataEnd, fds.cbegin(), fds.end(), cs); } - static std::vector<V> deserialize(std::vector<uint8_t> &data, std::vector<FileDescriptor> &fds, + static std::vector<V> deserialize(std::vector<uint8_t> &data, std::vector<SharedFD> &fds, ControlSerializer *cs = nullptr) { return deserialize(data.cbegin(), data.end(), fds.cbegin(), fds.end(), cs); @@ -153,15 +153,15 @@ public: static std::vector<V> deserialize(std::vector<uint8_t>::const_iterator dataBegin, std::vector<uint8_t>::const_iterator dataEnd, - std::vector<FileDescriptor>::const_iterator fdsBegin, - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, + std::vector<SharedFD>::const_iterator fdsBegin, + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, ControlSerializer *cs = nullptr) { uint32_t vecLen = readPOD<uint32_t>(dataBegin, 0, dataEnd); std::vector<V> ret(vecLen); std::vector<uint8_t>::const_iterator dataIter = dataBegin + 4; - std::vector<FileDescriptor>::const_iterator fdIter = fdsBegin; + std::vector<SharedFD>::const_iterator fdIter = fdsBegin; for (uint32_t i = 0; i < vecLen; i++) { uint32_t sizeofData = readPOD<uint32_t>(dataIter, 0, dataEnd); uint32_t sizeofFds = readPOD<uint32_t>(dataIter, 4, dataEnd); @@ -201,11 +201,11 @@ template<typename K, typename V> class IPADataSerializer<std::map<K, V>> { public: - static std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> + static std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> serialize(const std::map<K, V> &data, ControlSerializer *cs = nullptr) { std::vector<uint8_t> dataVec; - std::vector<FileDescriptor> fdsVec; + std::vector<SharedFD> fdsVec; /* Serialize the length. */ uint32_t mapLen = data.size(); @@ -214,7 +214,7 @@ public: /* Serialize the members. */ for (auto const &it : data) { std::vector<uint8_t> dvec; - std::vector<FileDescriptor> fvec; + std::vector<SharedFD> fvec; std::tie(dvec, fvec) = IPADataSerializer<K>::serialize(it.first, cs); @@ -247,11 +247,11 @@ public: std::vector<uint8_t>::const_iterator dataEnd, ControlSerializer *cs = nullptr) { - std::vector<FileDescriptor> fds; + std::vector<SharedFD> fds; return deserialize(dataBegin, dataEnd, fds.cbegin(), fds.end(), cs); } - static std::map<K, V> deserialize(std::vector<uint8_t> &data, std::vector<FileDescriptor> &fds, + static std::map<K, V> deserialize(std::vector<uint8_t> &data, std::vector<SharedFD> &fds, ControlSerializer *cs = nullptr) { return deserialize(data.cbegin(), data.end(), fds.cbegin(), fds.end(), cs); @@ -259,8 +259,8 @@ public: static std::map<K, V> deserialize(std::vector<uint8_t>::const_iterator dataBegin, std::vector<uint8_t>::const_iterator dataEnd, - std::vector<FileDescriptor>::const_iterator fdsBegin, - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, + std::vector<SharedFD>::const_iterator fdsBegin, + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, ControlSerializer *cs = nullptr) { std::map<K, V> ret; @@ -268,7 +268,7 @@ public: uint32_t mapLen = readPOD<uint32_t>(dataBegin, 0, dataEnd); std::vector<uint8_t>::const_iterator dataIter = dataBegin + 4; - std::vector<FileDescriptor>::const_iterator fdIter = fdsBegin; + std::vector<SharedFD>::const_iterator fdIter = fdsBegin; for (uint32_t i = 0; i < mapLen; i++) { uint32_t sizeofData = readPOD<uint32_t>(dataIter, 0, dataEnd); uint32_t sizeofFds = readPOD<uint32_t>(dataIter, 4, dataEnd); diff --git a/include/libcamera/internal/ipc_pipe.h b/include/libcamera/internal/ipc_pipe.h index 986f8d886fa6..ab5dd67c3813 100644 --- a/include/libcamera/internal/ipc_pipe.h +++ b/include/libcamera/internal/ipc_pipe.h @@ -9,7 +9,7 @@ #include <vector> -#include <libcamera/base/file_descriptor.h> +#include <libcamera/base/shared_fd.h> #include <libcamera/base/signal.h> #include "libcamera/internal/ipc_unixsocket.h" @@ -33,17 +33,17 @@ public: Header &header() { return header_; } std::vector<uint8_t> &data() { return data_; } - std::vector<FileDescriptor> &fds() { return fds_; } + std::vector<SharedFD> &fds() { return fds_; } const Header &header() const { return header_; } const std::vector<uint8_t> &data() const { return data_; } - const std::vector<FileDescriptor> &fds() const { return fds_; } + const std::vector<SharedFD> &fds() const { return fds_; } private: Header header_; std::vector<uint8_t> data_; - std::vector<FileDescriptor> fds_; + std::vector<SharedFD> fds_; }; class IPCPipe diff --git a/include/libcamera/ipa/core.mojom b/include/libcamera/ipa/core.mojom index f7eff0c7ab8c..74f3339e56f2 100644 --- a/include/libcamera/ipa/core.mojom +++ b/include/libcamera/ipa/core.mojom @@ -32,7 +32,7 @@ module libcamera; * - This attribute instructs the build system that a (de)serializer is * available for the type and there's no need to generate one * - hasFd - struct fields or empty structs only - * - Designate that this field or empty struct contains a FileDescriptor + * - Designate that this field or empty struct contains a SharedFD * * Rules: * - If the type is defined in a libcamera C++ header *and* a (de)serializer is @@ -60,7 +60,7 @@ module libcamera; * - In mojom, reference the type as FrameBuffer.Plane and only as map/array * member * - [skipHeader] and [skipSerdes] only work here in core.mojom - * - If a field in a struct has a FileDescriptor, but is not explicitly + * - If a field in a struct has a SharedFD, but is not explicitly * defined so in mojom, then the field must be marked with the [hasFd] * attribute * @@ -71,7 +71,7 @@ module libcamera; */ [skipSerdes, skipHeader] struct ControlInfoMap {}; [skipSerdes, skipHeader] struct ControlList {}; -[skipSerdes, skipHeader] struct FileDescriptor {}; +[skipSerdes, skipHeader] struct SharedFD {}; [skipHeader] struct Point { int32 x; diff --git a/include/libcamera/ipa/raspberrypi.mojom b/include/libcamera/ipa/raspberrypi.mojom index e453d46cb14f..acd3cafe6c91 100644 --- a/include/libcamera/ipa/raspberrypi.mojom +++ b/include/libcamera/ipa/raspberrypi.mojom @@ -35,7 +35,7 @@ struct ISPConfig { struct IPAConfig { uint32 transform; - libcamera.FileDescriptor lsTableHandle; + libcamera.SharedFD lsTableHandle; }; struct StartConfig { diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp index f2e0bdbdbbf6..1938b10509fa 100644 --- a/src/android/camera_device.cpp +++ b/src/android/camera_device.cpp @@ -725,7 +725,7 @@ CameraDevice::createFrameBuffer(const buffer_handle_t camera3buffer, std::vector<FrameBuffer::Plane> planes(buf.numPlanes()); for (size_t i = 0; i < buf.numPlanes(); ++i) { - FileDescriptor fd{ camera3buffer->data[i] }; + SharedFD fd{ camera3buffer->data[i] }; if (!fd.isValid()) { LOG(HAL, Fatal) << "No valid fd"; return nullptr; diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp index c6aec09046f7..aaf629eeb3fc 100644 --- a/src/ipa/raspberrypi/raspberrypi.cpp +++ b/src/ipa/raspberrypi/raspberrypi.cpp @@ -15,8 +15,8 @@ #include <linux/bcm2835-isp.h> -#include <libcamera/base/file_descriptor.h> #include <libcamera/base/log.h> +#include <libcamera/base/shared_fd.h> #include <libcamera/base/span.h> #include <libcamera/control_ids.h> @@ -164,7 +164,7 @@ private: bool processPending_; /* LS table allocation passed in from the pipeline handler. */ - FileDescriptor lsTableHandle_; + SharedFD lsTableHandle_; void *lsTable_; /* Distinguish the first camera start from others. */ diff --git a/src/libcamera/base/file.cpp b/src/libcamera/base/file.cpp index 66c73c406198..3ca9839bb989 100644 --- a/src/libcamera/base/file.cpp +++ b/src/libcamera/base/file.cpp @@ -14,8 +14,8 @@ #include <sys/types.h> #include <unistd.h> -#include <libcamera/base/file_descriptor.h> #include <libcamera/base/log.h> +#include <libcamera/base/shared_fd.h> /** * \file base/file.h @@ -473,11 +473,11 @@ bool File::exists(const std::string &name) } /** - * \brief Retrieve the inode of a FileDescriptor + * \brief Retrieve the inode of a SharedFD * * \return The file descriptor inode on success, or 0 on error */ -ino_t File::inode(const FileDescriptor &fd) +ino_t File::inode(const SharedFD &fd) { if (!fd.isValid()) return 0; diff --git a/src/libcamera/base/file_descriptor.cpp b/src/libcamera/base/file_descriptor.cpp deleted file mode 100644 index a83bf52c31e6..000000000000 --- a/src/libcamera/base/file_descriptor.cpp +++ /dev/null @@ -1,266 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2019, Google Inc. - * - * file_descriptor.cpp - File descriptor wrapper - */ - -#include <libcamera/base/file_descriptor.h> - -#include <string.h> -#include <sys/types.h> -#include <unistd.h> -#include <utility> - -#include <libcamera/base/log.h> -#include <libcamera/base/unique_fd.h> - -/** - * \file base/file_descriptor.h - * \brief File descriptor wrapper - */ - -namespace libcamera { - -LOG_DEFINE_CATEGORY(FileDescriptor) - -/** - * \class FileDescriptor - * \brief RAII-style wrapper for file descriptors - * - * The FileDescriptor class provides RAII-style lifetime management of file - * descriptors with an efficient mechanism for ownership sharing. At its core, - * an internal Descriptor object wraps a file descriptor (expressed as a signed - * integer) with an RAII-style interface. The Descriptor is then implicitly - * shared with all FileDescriptor instances constructed as copies. - * - * When constructed from a numerical file descriptor, the FileDescriptor - * instance either duplicates or takes over the file descriptor: - * - * - The FileDescriptor(const int &) constructor duplicates the numerical file - * descriptor and wraps the duplicate in a Descriptor. The caller is - * responsible for closing the original file descriptor, and the value - * returned by fd() will be different from the value passed to the - * constructor. - * - * - The FileDescriptor(int &&) constructor takes over the numerical file - * descriptor and wraps it in a Descriptor. The caller shall not touch the - * original file descriptor once the function returns, and the value returned - * by fd() will be identical to the value passed to the constructor. - * - * The copy constructor and assignment operator create copies that share the - * Descriptor, while the move versions of those functions additionally make the - * other FileDescriptor invalid. When the last FileDescriptor that references a - * Descriptor is destroyed, the file descriptor is closed. - * - * The numerical file descriptor is available through the fd() function. All - * FileDescriptor instances created as copies of a FileDescriptor will report - * the same fd() value. Callers can perform operations on the fd(), but shall - * never close it manually. - */ - -/** - * \brief Create a FileDescriptor copying a given \a fd - * \param[in] fd File descriptor - * - * Construct a FileDescriptor from a numerical file descriptor by duplicating - * the \a fd, and take ownership of the copy. The original \a fd is left - * untouched, and the caller is responsible for closing it when appropriate. - * The duplicated file descriptor will be closed automatically when all - * FileDescriptor instances that reference it are destroyed. - * - * If the \a fd is negative, the FileDescriptor is constructed as invalid and - * the fd() function will return -1. - */ -FileDescriptor::FileDescriptor(const int &fd) -{ - if (fd < 0) - return; - - fd_ = std::make_shared<Descriptor>(fd, true); - if (fd_->fd() < 0) - fd_.reset(); -} - -/** - * \brief Create a FileDescriptor taking ownership of a given \a fd - * \param[in] fd File descriptor - * - * Construct a FileDescriptor from a numerical file descriptor by taking - * ownership of the \a fd. The original \a fd is set to -1 and shall not be - * touched by the caller anymore. In particular, the caller shall not close the - * original \a fd manually. The duplicated file descriptor will be closed - * automatically when all FileDescriptor instances that reference it are - * destroyed. - * - * If the \a fd is negative, the FileDescriptor is constructed as invalid and - * the fd() function will return -1. - */ -FileDescriptor::FileDescriptor(int &&fd) -{ - if (fd < 0) - return; - - fd_ = std::make_shared<Descriptor>(fd, false); - /* - * The Descriptor constructor can't have failed here, as it took over - * the fd without duplicating it. Just set the original fd to -1 to - * implement move semantics. - */ - fd = -1; -} - -/** - * \brief Create a FileDescriptor taking ownership of a given UniqueFD \a fd - * \param[in] fd UniqueFD - * - * Construct a FileDescriptor from UniqueFD by taking ownership of the \a fd. - * The original \a fd becomes invalid. - */ -FileDescriptor::FileDescriptor(UniqueFD fd) - : FileDescriptor(fd.release()) -{ -} - -/** - * \brief Copy constructor, create a FileDescriptor from a copy of \a other - * \param[in] other The other FileDescriptor - * - * Copying a FileDescriptor implicitly shares ownership of the wrapped file - * descriptor. The original FileDescriptor is left untouched, and the caller is - * responsible for destroying it when appropriate. The wrapped file descriptor - * will be closed automatically when all FileDescriptor instances that - * reference it are destroyed. - */ -FileDescriptor::FileDescriptor(const FileDescriptor &other) - : fd_(other.fd_) -{ -} - -/** - * \brief Move constructor, create a FileDescriptor by taking over \a other - * \param[in] other The other FileDescriptor - * - * Moving a FileDescriptor moves the reference to the wrapped descriptor owned - * by \a other to the new FileDescriptor. The \a other FileDescriptor is - * invalidated and its fd() function will return -1. The wrapped file descriptor - * will be closed automatically when all FileDescriptor instances that - * reference it are destroyed. - */ -FileDescriptor::FileDescriptor(FileDescriptor &&other) - : fd_(std::move(other.fd_)) -{ -} - -/** - * \brief Destroy the FileDescriptor instance - * - * Destroying a FileDescriptor instance releases its reference to the wrapped - * descriptor, if any. When the last instance that references a wrapped - * descriptor is destroyed, the file descriptor is automatically closed. - */ -FileDescriptor::~FileDescriptor() -{ -} - -/** - * \brief Copy assignment operator, replace the wrapped file descriptor with a - * copy of \a other - * \param[in] other The other FileDescriptor - * - * Copying a FileDescriptor creates a new reference to the wrapped file - * descriptor owner by \a other. If \a other is invalid, *this will also be - * invalid. The original FileDescriptor is left untouched, and the caller is - * responsible for destroying it when appropriate. The wrapped file descriptor - * will be closed automatically when all FileDescriptor instances that - * reference it are destroyed. - * - * \return A reference to this FileDescriptor - */ -FileDescriptor &FileDescriptor::operator=(const FileDescriptor &other) -{ - fd_ = other.fd_; - - return *this; -} - -/** - * \brief Move assignment operator, replace the wrapped file descriptor by - * taking over \a other - * \param[in] other The other FileDescriptor - * - * Moving a FileDescriptor moves the reference to the wrapped descriptor owned - * by \a other to the new FileDescriptor. If \a other is invalid, *this will - * also be invalid. The \a other FileDescriptor is invalidated and its fd() - * function will return -1. The wrapped file descriptor will be closed - * automatically when all FileDescriptor instances that reference it are - * destroyed. - * - * \return A reference to this FileDescriptor - */ -FileDescriptor &FileDescriptor::operator=(FileDescriptor &&other) -{ - fd_ = std::move(other.fd_); - - return *this; -} - -/** - * \fn FileDescriptor::isValid() - * \brief Check if the FileDescriptor instance is valid - * \return True if the FileDescriptor is valid, false otherwise - */ - -/** - * \fn FileDescriptor::fd() - * \brief Retrieve the numerical file descriptor - * \return The numerical file descriptor, which may be -1 if the FileDescriptor - * instance is invalid - */ - -/** - * \brief Duplicate a FileDescriptor - * - * Duplicating a FileDescriptor creates a duplicate of the wrapped file - * descriptor and returns a UniqueFD that owns the duplicate. The fd() function - * of the original and the get() function of the duplicate will return different - * values. The duplicate instance will not be affected by destruction of the - * original instance or its copies. - * - * \return A UniqueFD owning a duplicate of the original file descriptor - */ -UniqueFD FileDescriptor::dup() const -{ - int dupFd = ::dup(fd()); - if (dupFd == -1) { - int ret = -errno; - LOG(FileDescriptor, Error) - << "Failed to dup() fd: " << strerror(-ret); - } - - return UniqueFD(dupFd); -} - -FileDescriptor::Descriptor::Descriptor(int fd, bool duplicate) -{ - if (!duplicate) { - fd_ = fd; - return; - } - - /* Failing to dup() a fd should not happen and is fatal. */ - fd_ = ::dup(fd); - if (fd_ == -1) { - int ret = -errno; - LOG(FileDescriptor, Fatal) - << "Failed to dup() fd: " << strerror(-ret); - } -} - -FileDescriptor::Descriptor::~Descriptor() -{ - if (fd_ != -1) - close(fd_); -} - -} /* namespace libcamera */ diff --git a/src/libcamera/base/meson.build b/src/libcamera/base/meson.build index b0d85bc19245..ccb746c27466 100644 --- a/src/libcamera/base/meson.build +++ b/src/libcamera/base/meson.build @@ -8,12 +8,12 @@ libcamera_base_sources = files([ 'event_dispatcher_poll.cpp', 'event_notifier.cpp', 'file.cpp', - 'file_descriptor.cpp', 'flags.cpp', 'log.cpp', 'message.cpp', 'object.cpp', 'semaphore.cpp', + 'shared_fd.cpp', 'signal.cpp', 'thread.cpp', 'timer.cpp', diff --git a/src/libcamera/base/shared_fd.cpp b/src/libcamera/base/shared_fd.cpp new file mode 100644 index 000000000000..05b6892f7e19 --- /dev/null +++ b/src/libcamera/base/shared_fd.cpp @@ -0,0 +1,262 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * shared_fd.cpp - File descriptor wrapper with shared ownership + */ + +#include <libcamera/base/shared_fd.h> + +#include <string.h> +#include <sys/types.h> +#include <unistd.h> +#include <utility> + +#include <libcamera/base/log.h> +#include <libcamera/base/unique_fd.h> + +/** + * \file base/shared_fd.h + * \brief File descriptor wrapper + */ + +namespace libcamera { + +LOG_DEFINE_CATEGORY(SharedFD) + +/** + * \class SharedFD + * \brief RAII-style wrapper for file descriptors + * + * The SharedFD class provides RAII-style lifetime management of file + * descriptors with an efficient mechanism for ownership sharing. At its core, + * an internal Descriptor object wraps a file descriptor (expressed as a signed + * integer) with an RAII-style interface. The Descriptor is then implicitly + * shared with all SharedFD instances constructed as copies. + * + * When constructed from a numerical file descriptor, the SharedFD instance + * either duplicates or takes over the file descriptor: + * + * - The SharedFD(const int &) constructor duplicates the numerical file + * descriptor and wraps the duplicate in a Descriptor. The caller is + * responsible for closing the original file descriptor, and the value + * returned by fd() will be different from the value passed to the + * constructor. + * + * - The SharedFD(int &&) constructor takes over the numerical file descriptor + * and wraps it in a Descriptor. The caller shall not touch the original file + * descriptor once the function returns, and the value returned by fd() will + * be identical to the value passed to the constructor. + * + * The copy constructor and assignment operator create copies that share the + * Descriptor, while the move versions of those functions additionally make the + * other SharedFD invalid. When the last SharedFD that references a Descriptor + * is destroyed, the file descriptor is closed. + * + * The numerical file descriptor is available through the fd() function. All + * SharedFD instances created as copies of a SharedFD will report the same fd() + * value. Callers can perform operations on the fd(), but shall never close it + * manually. + */ + +/** + * \brief Create a SharedFD copying a given \a fd + * \param[in] fd File descriptor + * + * Construct a SharedFD from a numerical file descriptor by duplicating the + * \a fd, and take ownership of the copy. The original \a fd is left untouched, + * and the caller is responsible for closing it when appropriate. The duplicated + * file descriptor will be closed automatically when all SharedFD instances that + * reference it are destroyed. + * + * If the \a fd is negative, the SharedFD is constructed as invalid and the fd() + * function will return -1. + */ +SharedFD::SharedFD(const int &fd) +{ + if (fd < 0) + return; + + fd_ = std::make_shared<Descriptor>(fd, true); + if (fd_->fd() < 0) + fd_.reset(); +} + +/** + * \brief Create a SharedFD taking ownership of a given \a fd + * \param[in] fd File descriptor + * + * Construct a SharedFD from a numerical file descriptor by taking ownership of + * the \a fd. The original \a fd is set to -1 and shall not be touched by the + * caller anymore. In particular, the caller shall not close the original \a fd + * manually. The duplicated file descriptor will be closed automatically when + * all SharedFD instances that reference it are destroyed. + * + * If the \a fd is negative, the SharedFD is constructed as invalid and the fd() + * function will return -1. + */ +SharedFD::SharedFD(int &&fd) +{ + if (fd < 0) + return; + + fd_ = std::make_shared<Descriptor>(fd, false); + /* + * The Descriptor constructor can't have failed here, as it took over + * the fd without duplicating it. Just set the original fd to -1 to + * implement move semantics. + */ + fd = -1; +} + +/** + * \brief Create a SharedFD taking ownership of a given UniqueFD \a fd + * \param[in] fd UniqueFD + * + * Construct a SharedFD from UniqueFD by taking ownership of the \a fd. The + * original \a fd becomes invalid. + */ +SharedFD::SharedFD(UniqueFD fd) + : SharedFD(fd.release()) +{ +} + +/** + * \brief Copy constructor, create a SharedFD from a copy of \a other + * \param[in] other The other SharedFD + * + * Copying a SharedFD implicitly shares ownership of the wrapped file + * descriptor. The original SharedFD is left untouched, and the caller is + * responsible for destroying it when appropriate. The wrapped file descriptor + * will be closed automatically when all SharedFD instances that reference it + * are destroyed. + */ +SharedFD::SharedFD(const SharedFD &other) + : fd_(other.fd_) +{ +} + +/** + * \brief Move constructor, create a SharedFD by taking over \a other + * \param[in] other The other SharedFD + * + * Moving a SharedFD moves the reference to the wrapped descriptor owned by + * \a other to the new SharedFD. The \a other SharedFD is invalidated and its + * fd() function will return -1. The wrapped file descriptor will be closed + * automatically when all SharedFD instances that reference it are destroyed. + */ +SharedFD::SharedFD(SharedFD &&other) + : fd_(std::move(other.fd_)) +{ +} + +/** + * \brief Destroy the SharedFD instance + * + * Destroying a SharedFD instance releases its reference to the wrapped + * descriptor, if any. When the last instance that references a wrapped + * descriptor is destroyed, the file descriptor is automatically closed. + */ +SharedFD::~SharedFD() +{ +} + +/** + * \brief Copy assignment operator, replace the wrapped file descriptor with a + * copy of \a other + * \param[in] other The other SharedFD + * + * Copying a SharedFD creates a new reference to the wrapped file descriptor + * owner by \a other. If \a other is invalid, *this will also be invalid. The + * original SharedFD is left untouched, and the caller is responsible for + * destroying it when appropriate. The wrapped file descriptor will be closed + * automatically when all SharedFD instances that reference it are destroyed. + * + * \return A reference to this SharedFD + */ +SharedFD &SharedFD::operator=(const SharedFD &other) +{ + fd_ = other.fd_; + + return *this; +} + +/** + * \brief Move assignment operator, replace the wrapped file descriptor by + * taking over \a other + * \param[in] other The other SharedFD + * + * Moving a SharedFD moves the reference to the wrapped descriptor owned by + * \a other to the new SharedFD. If \a other is invalid, *this will also be + * invalid. The \a other SharedFD is invalidated and its fd() function will + * return -1. The wrapped file descriptor will be closed automatically when + * all SharedFD instances that reference it are destroyed. + * + * \return A reference to this SharedFD + */ +SharedFD &SharedFD::operator=(SharedFD &&other) +{ + fd_ = std::move(other.fd_); + + return *this; +} + +/** + * \fn SharedFD::isValid() + * \brief Check if the SharedFD instance is valid + * \return True if the SharedFD is valid, false otherwise + */ + +/** + * \fn SharedFD::fd() + * \brief Retrieve the numerical file descriptor + * \return The numerical file descriptor, which may be -1 if the SharedFD + * instance is invalid + */ + +/** + * \brief Duplicate a SharedFD + * + * Duplicating a SharedFD creates a duplicate of the wrapped file descriptor and + * returns a UniqueFD that owns the duplicate. The fd() function of the original + * and the get() function of the duplicate will return different values. The + * duplicate instance will not be affected by destruction of the original + * instance or its copies. + * + * \return A UniqueFD owning a duplicate of the original file descriptor + */ +UniqueFD SharedFD::dup() const +{ + int dupFd = ::dup(fd()); + if (dupFd == -1) { + int ret = -errno; + LOG(SharedFD, Error) + << "Failed to dup() fd: " << strerror(-ret); + } + + return UniqueFD(dupFd); +} + +SharedFD::Descriptor::Descriptor(int fd, bool duplicate) +{ + if (!duplicate) { + fd_ = fd; + return; + } + + /* Failing to dup() a fd should not happen and is fatal. */ + fd_ = ::dup(fd); + if (fd_ == -1) { + int ret = -errno; + LOG(SharedFD, Fatal) + << "Failed to dup() fd: " << strerror(-ret); + } +} + +SharedFD::Descriptor::~Descriptor() +{ + if (fd_ != -1) + close(fd_); +} + +} /* namespace libcamera */ diff --git a/src/libcamera/framebuffer.cpp b/src/libcamera/framebuffer.cpp index f5bcf107d7aa..0a5bf7fdbeb7 100644 --- a/src/libcamera/framebuffer.cpp +++ b/src/libcamera/framebuffer.cpp @@ -180,9 +180,9 @@ FrameBuffer::Private::Private() * offset and length. * * To support DMA access, planes are associated with dmabuf objects represented - * by FileDescriptor handles. The Plane class doesn't handle mapping of the - * memory to the CPU, but applications and IPAs may use the dmabuf file - * descriptors to map the plane memory with mmap() and access its contents. + * by SharedFD handles. The Plane class doesn't handle mapping of the memory to + * the CPU, but applications and IPAs may use the dmabuf file descriptors to map + * the plane memory with mmap() and access its contents. * * \todo Specify how an application shall decide whether to use a single or * multiple dmabufs, based on the camera requirements. diff --git a/src/libcamera/ipa_data_serializer.cpp b/src/libcamera/ipa_data_serializer.cpp index 82ec9b20a411..0a259305afa2 100644 --- a/src/libcamera/ipa_data_serializer.cpp +++ b/src/libcamera/ipa_data_serializer.cpp @@ -31,7 +31,7 @@ LOG_DEFINE_CATEGORY(IPADataSerializer) * * \todo Harden the vector and map deserializer * - * \todo For FileDescriptors, instead of storing a validity flag, store an + * \todo For SharedFDs, instead of storing a validity flag, store an * index into the fd array. This will allow us to use views instead of copying. */ @@ -112,7 +112,7 @@ namespace { * \param[in] cs ControlSerializer * * This version of deserialize() can be used if the object type \a T and its - * members don't have any FileDescriptor. + * members don't have any SharedFD. * * \a cs is only necessary if the object type \a T or its members contain * ControlList or ControlInfoMap. @@ -132,7 +132,7 @@ namespace { * \param[in] cs ControlSerializer * * This version of deserialize() can be used if the object type \a T and its - * members don't have any FileDescriptor. + * members don't have any SharedFD. * * \a cs is only necessary if the object type \a T or its members contain * ControlList or ControlInfoMap. @@ -143,7 +143,7 @@ namespace { /** * \fn template<typename T> IPADataSerializer<T>::deserialize( * const std::vector<uint8_t> &data, - * const std::vector<FileDescriptor> &fds, + * const std::vector<SharedFD> &fds, * ControlSerializer *cs = nullptr) * \brief Deserialize byte vector and fd vector into an object * \tparam T Type of object to deserialize to @@ -152,7 +152,7 @@ namespace { * \param[in] cs ControlSerializer * * This version of deserialize() (or the iterator version) must be used if - * the object type \a T or its members contain FileDescriptor. + * the object type \a T or its members contain SharedFD. * * \a cs is only necessary if the object type \a T or its members contain * ControlList or ControlInfoMap. @@ -164,8 +164,8 @@ namespace { * \fn template<typename T> IPADataSerializer::deserialize( * std::vector<uint8_t>::const_iterator dataBegin, * std::vector<uint8_t>::const_iterator dataEnd, - * std::vector<FileDescriptor>::const_iterator fdsBegin, - * std::vector<FileDescriptor>::const_iterator fdsEnd, + * std::vector<SharedFD>::const_iterator fdsBegin, + * std::vector<SharedFD>::const_iterator fdsEnd, * ControlSerializer *cs = nullptr) * \brief Deserialize byte vector and fd vector into an object * \tparam T Type of object to deserialize to @@ -176,7 +176,7 @@ namespace { * \param[in] cs ControlSerializer * * This version of deserialize() (or the vector version) must be used if - * the object type \a T or its members contain FileDescriptor. + * the object type \a T or its members contain SharedFD. * * \a cs is only necessary if the object type \a T or its members contain * ControlList or ControlInfoMap. @@ -189,7 +189,7 @@ namespace { #define DEFINE_POD_SERIALIZER(type) \ \ template<> \ -std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> \ +std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> \ IPADataSerializer<type>::serialize(const type &data, \ [[maybe_unused]] ControlSerializer *cs) \ { \ @@ -217,7 +217,7 @@ type IPADataSerializer<type>::deserialize(const std::vector<uint8_t> &data, \ \ template<> \ type IPADataSerializer<type>::deserialize(const std::vector<uint8_t> &data, \ - [[maybe_unused]] const std::vector<FileDescriptor> &fds, \ + [[maybe_unused]] const std::vector<SharedFD> &fds, \ ControlSerializer *cs) \ { \ return deserialize(data.cbegin(), data.end(), cs); \ @@ -226,8 +226,8 @@ type IPADataSerializer<type>::deserialize(const std::vector<uint8_t> &data, \ template<> \ type IPADataSerializer<type>::deserialize(std::vector<uint8_t>::const_iterator dataBegin, \ std::vector<uint8_t>::const_iterator dataEnd, \ - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsBegin, \ - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, \ + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsBegin, \ + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, \ ControlSerializer *cs) \ { \ return deserialize(dataBegin, dataEnd, cs); \ @@ -251,7 +251,7 @@ DEFINE_POD_SERIALIZER(double) * function parameter serdes). */ template<> -std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> +std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> IPADataSerializer<std::string>::serialize(const std::string &data, [[maybe_unused]] ControlSerializer *cs) { @@ -278,7 +278,7 @@ IPADataSerializer<std::string>::deserialize(std::vector<uint8_t>::const_iterator template<> std::string IPADataSerializer<std::string>::deserialize(const std::vector<uint8_t> &data, - [[maybe_unused]] const std::vector<FileDescriptor> &fds, + [[maybe_unused]] const std::vector<SharedFD> &fds, [[maybe_unused]] ControlSerializer *cs) { return { data.cbegin(), data.cend() }; @@ -288,8 +288,8 @@ template<> std::string IPADataSerializer<std::string>::deserialize(std::vector<uint8_t>::const_iterator dataBegin, std::vector<uint8_t>::const_iterator dataEnd, - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsBegin, - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsBegin, + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, [[maybe_unused]] ControlSerializer *cs) { return { dataBegin, dataEnd }; @@ -307,7 +307,7 @@ IPADataSerializer<std::string>::deserialize(std::vector<uint8_t>::const_iterator * be used. The serialized ControlInfoMap will have zero length. */ template<> -std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> +std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> IPADataSerializer<ControlList>::serialize(const ControlList &data, ControlSerializer *cs) { if (!cs) @@ -407,7 +407,7 @@ IPADataSerializer<ControlList>::deserialize(const std::vector<uint8_t> &data, template<> ControlList IPADataSerializer<ControlList>::deserialize(const std::vector<uint8_t> &data, - [[maybe_unused]] const std::vector<FileDescriptor> &fds, + [[maybe_unused]] const std::vector<SharedFD> &fds, ControlSerializer *cs) { return deserialize(data.cbegin(), data.end(), cs); @@ -417,8 +417,8 @@ template<> ControlList IPADataSerializer<ControlList>::deserialize(std::vector<uint8_t>::const_iterator dataBegin, std::vector<uint8_t>::const_iterator dataEnd, - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsBegin, - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsBegin, + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, ControlSerializer *cs) { return deserialize(dataBegin, dataEnd, cs); @@ -431,7 +431,7 @@ IPADataSerializer<ControlList>::deserialize(std::vector<uint8_t>::const_iterator * X bytes - Serialized ControlInfoMap (using ControlSerializer) */ template<> -std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> +std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> IPADataSerializer<ControlInfoMap>::serialize(const ControlInfoMap &map, ControlSerializer *cs) { @@ -493,7 +493,7 @@ IPADataSerializer<ControlInfoMap>::deserialize(const std::vector<uint8_t> &data, template<> ControlInfoMap IPADataSerializer<ControlInfoMap>::deserialize(const std::vector<uint8_t> &data, - [[maybe_unused]] const std::vector<FileDescriptor> &fds, + [[maybe_unused]] const std::vector<SharedFD> &fds, ControlSerializer *cs) { return deserialize(data.cbegin(), data.end(), cs); @@ -503,30 +503,30 @@ template<> ControlInfoMap IPADataSerializer<ControlInfoMap>::deserialize(std::vector<uint8_t>::const_iterator dataBegin, std::vector<uint8_t>::const_iterator dataEnd, - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsBegin, - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsBegin, + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, ControlSerializer *cs) { return deserialize(dataBegin, dataEnd, cs); } /* - * FileDescriptors are serialized into four bytes that tells if the - * FileDescriptor is valid or not. If it is valid, then for serialization - * the fd will be written to the fd vector, or for deserialization the - * fd vector const_iterator will be valid. + * SharedFD instances are serialized into four bytes that tells if the SharedFD + * is valid or not. If it is valid, then for serialization the fd will be + * written to the fd vector, or for deserialization the fd vector const_iterator + * will be valid. * * This validity is necessary so that we don't send -1 fd over sendmsg(). It * also allows us to simply send the entire fd vector into the deserializer * and it will be recursively consumed as necessary. */ template<> -std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> -IPADataSerializer<FileDescriptor>::serialize(const FileDescriptor &data, - [[maybe_unused]] ControlSerializer *cs) +std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> +IPADataSerializer<SharedFD>::serialize(const SharedFD &data, + [[maybe_unused]] ControlSerializer *cs) { std::vector<uint8_t> dataVec; - std::vector<FileDescriptor> fdVec; + std::vector<SharedFD> fdVec; /* * Store as uint32_t to prepare for conversion from validity flag @@ -542,11 +542,11 @@ IPADataSerializer<FileDescriptor>::serialize(const FileDescriptor &data, } template<> -FileDescriptor IPADataSerializer<FileDescriptor>::deserialize([[maybe_unused]] std::vector<uint8_t>::const_iterator dataBegin, - [[maybe_unused]] std::vector<uint8_t>::const_iterator dataEnd, - std::vector<FileDescriptor>::const_iterator fdsBegin, - std::vector<FileDescriptor>::const_iterator fdsEnd, - [[maybe_unused]] ControlSerializer *cs) +SharedFD IPADataSerializer<SharedFD>::deserialize([[maybe_unused]] std::vector<uint8_t>::const_iterator dataBegin, + [[maybe_unused]] std::vector<uint8_t>::const_iterator dataEnd, + std::vector<SharedFD>::const_iterator fdsBegin, + std::vector<SharedFD>::const_iterator fdsEnd, + [[maybe_unused]] ControlSerializer *cs) { ASSERT(std::distance(dataBegin, dataEnd) >= 4); @@ -554,13 +554,13 @@ FileDescriptor IPADataSerializer<FileDescriptor>::deserialize([[maybe_unused]] s ASSERT(!(valid && std::distance(fdsBegin, fdsEnd) < 1)); - return valid ? *fdsBegin : FileDescriptor(); + return valid ? *fdsBegin : SharedFD(); } template<> -FileDescriptor IPADataSerializer<FileDescriptor>::deserialize(const std::vector<uint8_t> &data, - const std::vector<FileDescriptor> &fds, - [[maybe_unused]] ControlSerializer *cs) +SharedFD IPADataSerializer<SharedFD>::deserialize(const std::vector<uint8_t> &data, + const std::vector<SharedFD> &fds, + [[maybe_unused]] ControlSerializer *cs) { return deserialize(data.cbegin(), data.end(), fds.cbegin(), fds.end()); } @@ -568,22 +568,22 @@ FileDescriptor IPADataSerializer<FileDescriptor>::deserialize(const std::vector< /* * FrameBuffer::Plane is serialized as: * - * 4 byte - FileDescriptor + * 4 byte - SharedFD * 4 bytes - uint32_t Offset * 4 bytes - uint32_t Length */ template<> -std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> +std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> IPADataSerializer<FrameBuffer::Plane>::serialize(const FrameBuffer::Plane &data, [[maybe_unused]] ControlSerializer *cs) { std::vector<uint8_t> dataVec; - std::vector<FileDescriptor> fdsVec; + std::vector<SharedFD> fdsVec; std::vector<uint8_t> fdBuf; - std::vector<FileDescriptor> fdFds; + std::vector<SharedFD> fdFds; std::tie(fdBuf, fdFds) = - IPADataSerializer<FileDescriptor>::serialize(data.fd); + IPADataSerializer<SharedFD>::serialize(data.fd); dataVec.insert(dataVec.end(), fdBuf.begin(), fdBuf.end()); fdsVec.insert(fdsVec.end(), fdFds.begin(), fdFds.end()); @@ -597,13 +597,13 @@ template<> FrameBuffer::Plane IPADataSerializer<FrameBuffer::Plane>::deserialize(std::vector<uint8_t>::const_iterator dataBegin, std::vector<uint8_t>::const_iterator dataEnd, - std::vector<FileDescriptor>::const_iterator fdsBegin, - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, + std::vector<SharedFD>::const_iterator fdsBegin, + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, [[maybe_unused]] ControlSerializer *cs) { FrameBuffer::Plane ret; - ret.fd = IPADataSerializer<FileDescriptor>::deserialize(dataBegin, dataBegin + 4, + ret.fd = IPADataSerializer<SharedFD>::deserialize(dataBegin, dataBegin + 4, fdsBegin, fdsBegin + 1); ret.offset = readPOD<uint32_t>(dataBegin, 4, dataEnd); ret.length = readPOD<uint32_t>(dataBegin, 8, dataEnd); @@ -614,7 +614,7 @@ IPADataSerializer<FrameBuffer::Plane>::deserialize(std::vector<uint8_t>::const_i template<> FrameBuffer::Plane IPADataSerializer<FrameBuffer::Plane>::deserialize(const std::vector<uint8_t> &data, - const std::vector<FileDescriptor> &fds, + const std::vector<SharedFD> &fds, ControlSerializer *cs) { return deserialize(data.cbegin(), data.end(), fds.cbegin(), fds.end(), cs); diff --git a/src/libcamera/ipc_pipe.cpp b/src/libcamera/ipc_pipe.cpp index ad870fd4137f..3b47032de0a2 100644 --- a/src/libcamera/ipc_pipe.cpp +++ b/src/libcamera/ipc_pipe.cpp @@ -87,7 +87,7 @@ IPCMessage::IPCMessage(IPCUnixSocket::Payload &payload) data_ = std::vector<uint8_t>(payload.data.begin() + sizeof(header_), payload.data.end()); for (int32_t &fd : payload.fds) - fds_.push_back(FileDescriptor(std::move(fd))); + fds_.push_back(SharedFD(std::move(fd))); } /** @@ -112,7 +112,7 @@ IPCUnixSocket::Payload IPCMessage::payload() const data_.data(), data_.size()); } - for (const FileDescriptor &fd : fds_) + for (const SharedFD &fd : fds_) payload.fds.push_back(fd.fd()); return payload; diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index ffa51a0c65ca..ea8243912a29 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -12,7 +12,7 @@ #include <queue> #include <unordered_set> -#include <libcamera/base/file_descriptor.h> +#include <libcamera/base/shared_fd.h> #include <libcamera/camera.h> #include <libcamera/control_ids.h> @@ -228,7 +228,7 @@ public: /* DMAHEAP allocation helper. */ RPi::DmaHeap dmaHeap_; - FileDescriptor lsTable_; + SharedFD lsTable_; std::unique_ptr<DelayedControls> delayedCtrls_; bool sensorMetadata_; @@ -1365,7 +1365,7 @@ int RPiCameraData::configureIPA(const CameraConfiguration *config) if (!fd.isValid()) return -ENOMEM; - lsTable_ = FileDescriptor(std::move(fd)); + lsTable_ = SharedFD(std::move(fd)); /* Allow the IPA to mmap the LS table via the file descriptor. */ /* diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp index 3966483a365f..97d431071def 100644 --- a/src/libcamera/v4l2_videodevice.cpp +++ b/src/libcamera/v4l2_videodevice.cpp @@ -22,8 +22,8 @@ #include <linux/version.h> #include <libcamera/base/event_notifier.h> -#include <libcamera/base/file_descriptor.h> #include <libcamera/base/log.h> +#include <libcamera/base/shared_fd.h> #include <libcamera/base/unique_fd.h> #include <libcamera/base/utils.h> @@ -1325,7 +1325,7 @@ std::unique_ptr<FrameBuffer> V4L2VideoDevice::createBuffer(unsigned int index) return nullptr; FrameBuffer::Plane plane; - plane.fd = FileDescriptor(std::move(fd)); + plane.fd = SharedFD(std::move(fd)); /* * V4L2 API doesn't provide dmabuf offset information of plane. * Set 0 as a placeholder offset. @@ -1354,7 +1354,7 @@ std::unique_ptr<FrameBuffer> V4L2VideoDevice::createBuffer(unsigned int index) ASSERT(numPlanes == 1u); planes.resize(formatInfo_->numPlanes()); - const FileDescriptor &fd = planes[0].fd; + const SharedFD &fd = planes[0].fd; size_t offset = 0; for (auto [i, plane] : utils::enumerate(planes)) { diff --git a/src/v4l2/v4l2_camera.h b/src/v4l2/v4l2_camera.h index 9817fd393d59..586347829845 100644 --- a/src/v4l2/v4l2_camera.h +++ b/src/v4l2/v4l2_camera.h @@ -11,8 +11,8 @@ #include <mutex> #include <utility> -#include <libcamera/base/file_descriptor.h> #include <libcamera/base/semaphore.h> +#include <libcamera/base/shared_fd.h> #include <libcamera/camera.h> #include <libcamera/framebuffer.h> diff --git a/test/meson.build b/test/meson.build index 42dfbc1f8ee9..daaa3862cdd6 100644 --- a/test/meson.build +++ b/test/meson.build @@ -40,7 +40,6 @@ internal_tests = [ ['event-dispatcher', 'event-dispatcher.cpp'], ['event-thread', 'event-thread.cpp'], ['file', 'file.cpp'], - ['file-descriptor', 'file-descriptor.cpp'], ['flags', 'flags.cpp'], ['hotplug-cameras', 'hotplug-cameras.cpp'], ['mapped-buffer', 'mapped-buffer.cpp'], @@ -49,6 +48,7 @@ internal_tests = [ ['object-delete', 'object-delete.cpp'], ['object-invoke', 'object-invoke.cpp'], ['pixel-format', 'pixel-format.cpp'], + ['shared-fd', 'shared-fd.cpp'], ['signal-threads', 'signal-threads.cpp'], ['threads', 'threads.cpp'], ['timer', 'timer.cpp'], diff --git a/test/serialization/ipa_data_serializer_test.cpp b/test/serialization/ipa_data_serializer_test.cpp index 5fcdcb8eae92..d2050a868b38 100644 --- a/test/serialization/ipa_data_serializer_test.cpp +++ b/test/serialization/ipa_data_serializer_test.cpp @@ -53,7 +53,7 @@ template<typename T> int testPodSerdes(T in) { std::vector<uint8_t> buf; - std::vector<FileDescriptor> fds; + std::vector<SharedFD> fds; std::tie(buf, fds) = IPADataSerializer<T>::serialize(in); T out = IPADataSerializer<T>::deserialize(buf, fds); @@ -72,7 +72,7 @@ int testVectorSerdes(const std::vector<T> &in, ControlSerializer *cs = nullptr) { std::vector<uint8_t> buf; - std::vector<FileDescriptor> fds; + std::vector<SharedFD> fds; std::tie(buf, fds) = IPADataSerializer<std::vector<T>>::serialize(in, cs); std::vector<T> out = IPADataSerializer<std::vector<T>>::deserialize(buf, fds, cs); @@ -92,7 +92,7 @@ int testMapSerdes(const std::map<K, V> &in, ControlSerializer *cs = nullptr) { std::vector<uint8_t> buf; - std::vector<FileDescriptor> fds; + std::vector<SharedFD> fds; std::tie(buf, fds) = IPADataSerializer<std::map<K, V>>::serialize(in, cs); std::map<K, V> out = IPADataSerializer<std::map<K, V>>::deserialize(buf, fds, cs); @@ -198,7 +198,7 @@ private: ControlSerializer cs(ControlSerializer::Role::Proxy); /* - * We don't test FileDescriptor serdes because it dup()s, so we + * We don't test SharedFD serdes because it dup()s, so we * can't check for equality. */ std::vector<uint8_t> vecUint8 = { 1, 2, 3, 4, 5, 6 }; @@ -219,7 +219,7 @@ private: }; std::vector<uint8_t> buf; - std::vector<FileDescriptor> fds; + std::vector<SharedFD> fds; if (testVectorSerdes(vecUint8) != TestPass) return TestFail; @@ -291,7 +291,7 @@ private: { { "a", { 1, 2, 3 } }, { "b", { 4, 5, 6 } }, { "c", { 7, 8, 9 } } }; std::vector<uint8_t> buf; - std::vector<FileDescriptor> fds; + std::vector<SharedFD> fds; if (testMapSerdes(mapUintStr) != TestPass) return TestFail; @@ -359,7 +359,7 @@ private: std::string strEmpty = ""; std::vector<uint8_t> buf; - std::vector<FileDescriptor> fds; + std::vector<SharedFD> fds; if (testPodSerdes(u32min) != TestPass) return TestFail; diff --git a/test/file-descriptor.cpp b/test/shared-fd.cpp similarity index 80% rename from test/file-descriptor.cpp rename to test/shared-fd.cpp index 76badc4c5fad..60e5d0aaa395 100644 --- a/test/file-descriptor.cpp +++ b/test/shared-fd.cpp @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * file_descriptor.cpp - FileDescriptor test + * shared_fd.cpp - SharedFD test */ #include <fcntl.h> @@ -11,7 +11,7 @@ #include <sys/types.h> #include <unistd.h> -#include <libcamera/base/file_descriptor.h> +#include <libcamera/base/shared_fd.h> #include <libcamera/base/utils.h> #include "test.h" @@ -19,7 +19,7 @@ using namespace libcamera; using namespace std; -class FileDescriptorTest : public Test +class SharedFDTest : public Test { protected: int init() @@ -43,8 +43,8 @@ protected: int run() { - /* Test creating empty FileDescriptor. */ - desc1_ = new FileDescriptor(); + /* Test creating empty SharedFD. */ + desc1_ = new SharedFD(); if (desc1_->fd() != -1) { std::cout << "Failed fd numerical check (default constructor)" @@ -56,10 +56,10 @@ protected: desc1_ = nullptr; /* - * Test creating FileDescriptor by copying numerical file + * Test creating SharedFD by copying numerical file * descriptor. */ - desc1_ = new FileDescriptor(fd_); + desc1_ = new SharedFD(fd_); if (desc1_->fd() == fd_) { std::cout << "Failed fd numerical check (lvalue ref constructor)" << std::endl; @@ -84,13 +84,13 @@ protected: } /* - * Test creating FileDescriptor by taking ownership of + * Test creating SharedFD by taking ownership of * numerical file descriptor. */ int dupFd = dup(fd_); int dupFdCopy = dupFd; - desc1_ = new FileDescriptor(std::move(dupFd)); + desc1_ = new SharedFD(std::move(dupFd)); if (desc1_->fd() != dupFdCopy) { std::cout << "Failed fd numerical check (rvalue ref constructor)" << std::endl; @@ -114,9 +114,9 @@ protected: return TestFail; } - /* Test creating FileDescriptor from other FileDescriptor. */ - desc1_ = new FileDescriptor(fd_); - desc2_ = new FileDescriptor(*desc1_); + /* Test creating SharedFD from other SharedFD. */ + desc1_ = new SharedFD(fd_); + desc2_ = new SharedFD(*desc1_); if (desc1_->fd() == fd_ || desc2_->fd() == fd_ || desc1_->fd() != desc2_->fd()) { std::cout << "Failed fd numerical check (copy constructor)" @@ -142,10 +142,10 @@ protected: delete desc2_; desc2_ = nullptr; - /* Test creating FileDescriptor by taking over other FileDescriptor. */ - desc1_ = new FileDescriptor(fd_); + /* Test creating SharedFD by taking over other SharedFD. */ + desc1_ = new SharedFD(fd_); fd = desc1_->fd(); - desc2_ = new FileDescriptor(std::move(*desc1_)); + desc2_ = new SharedFD(std::move(*desc1_)); if (desc1_->fd() != -1 || desc2_->fd() != fd) { std::cout << "Failed fd numerical check (move constructor)" @@ -164,9 +164,9 @@ protected: delete desc2_; desc2_ = nullptr; - /* Test creating FileDescriptor by copy assignment. */ - desc1_ = new FileDescriptor(); - desc2_ = new FileDescriptor(fd_); + /* Test creating SharedFD by copy assignment. */ + desc1_ = new SharedFD(); + desc2_ = new SharedFD(fd_); fd = desc2_->fd(); *desc1_ = *desc2_; @@ -188,9 +188,9 @@ protected: delete desc2_; desc2_ = nullptr; - /* Test creating FileDescriptor by move assignment. */ - desc1_ = new FileDescriptor(); - desc2_ = new FileDescriptor(fd_); + /* Test creating SharedFD by move assignment. */ + desc1_ = new SharedFD(); + desc2_ = new SharedFD(fd_); fd = desc2_->fd(); *desc1_ = std::move(*desc2_); @@ -237,7 +237,7 @@ private: int fd_; ino_t inodeNr_; - FileDescriptor *desc1_, *desc2_; + SharedFD *desc1_, *desc2_; }; -TEST_REGISTER(FileDescriptorTest) +TEST_REGISTER(SharedFDTest) diff --git a/utils/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl b/utils/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl index d856339aa9ee..c37c4941b528 100644 --- a/utils/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl +++ b/utils/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl @@ -237,7 +237,7 @@ void {{proxy_name}}::recvMessage(const IPCMessage &data) void {{proxy_name}}::{{method.mojom_name}}IPC( std::vector<uint8_t>::const_iterator data, size_t dataSize, - [[maybe_unused]] const std::vector<FileDescriptor> &fds) + [[maybe_unused]] const std::vector<SharedFD> &fds) { {%- for param in method.parameters %} {{param|name}} {{param.mojom_name}}; diff --git a/utils/ipc/generators/libcamera_templates/module_ipa_proxy.h.tmpl b/utils/ipc/generators/libcamera_templates/module_ipa_proxy.h.tmpl index ce396c183d0c..c308dd10c7e5 100644 --- a/utils/ipc/generators/libcamera_templates/module_ipa_proxy.h.tmpl +++ b/utils/ipc/generators/libcamera_templates/module_ipa_proxy.h.tmpl @@ -64,7 +64,7 @@ private: void {{method.mojom_name}}IPC( std::vector<uint8_t>::const_iterator data, size_t dataSize, - const std::vector<FileDescriptor> &fds); + const std::vector<SharedFD> &fds); {% endfor %} /* Helper class to invoke async functions in another thread. */ diff --git a/utils/ipc/generators/libcamera_templates/proxy_functions.tmpl b/utils/ipc/generators/libcamera_templates/proxy_functions.tmpl index ebcd2aaaafae..bac826a74c2d 100644 --- a/utils/ipc/generators/libcamera_templates/proxy_functions.tmpl +++ b/utils/ipc/generators/libcamera_templates/proxy_functions.tmpl @@ -54,7 +54,7 @@ {%- for param in params %} std::vector<uint8_t> {{param.mojom_name}}Buf; {%- if param|has_fd %} - std::vector<FileDescriptor> {{param.mojom_name}}Fds; + std::vector<SharedFD> {{param.mojom_name}}Fds; std::tie({{param.mojom_name}}Buf, {{param.mojom_name}}Fds) = {%- else %} std::tie({{param.mojom_name}}Buf, std::ignore) = diff --git a/utils/ipc/generators/libcamera_templates/serializer.tmpl b/utils/ipc/generators/libcamera_templates/serializer.tmpl index b8ef8e7b974e..77bae36fe6b7 100644 --- a/utils/ipc/generators/libcamera_templates/serializer.tmpl +++ b/utils/ipc/generators/libcamera_templates/serializer.tmpl @@ -40,7 +40,7 @@ retData.insert(retData.end(), {{field.mojom_name}}.begin(), {{field.mojom_name}}.end()); {%- elif field|is_fd %} std::vector<uint8_t> {{field.mojom_name}}; - std::vector<FileDescriptor> {{field.mojom_name}}Fds; + std::vector<SharedFD> {{field.mojom_name}}Fds; std::tie({{field.mojom_name}}, {{field.mojom_name}}Fds) = IPADataSerializer<{{field|name}}>::serialize(data.{{field.mojom_name}}); retData.insert(retData.end(), {{field.mojom_name}}.begin(), {{field.mojom_name}}.end()); @@ -58,7 +58,7 @@ {%- elif field|is_plain_struct or field|is_array or field|is_map or field|is_str %} std::vector<uint8_t> {{field.mojom_name}}; {%- if field|has_fd %} - std::vector<FileDescriptor> {{field.mojom_name}}Fds; + std::vector<SharedFD> {{field.mojom_name}}Fds; std::tie({{field.mojom_name}}, {{field.mojom_name}}Fds) = {%- else %} std::tie({{field.mojom_name}}, std::ignore) = @@ -177,7 +177,7 @@ # \a struct. #} {%- macro serializer(struct, namespace) %} - static std::tuple<std::vector<uint8_t>, std::vector<FileDescriptor>> + static std::tuple<std::vector<uint8_t>, std::vector<SharedFD>> serialize(const {{struct|name_full}} &data, {%- if struct|needs_control_serializer %} ControlSerializer *cs) @@ -187,7 +187,7 @@ { std::vector<uint8_t> retData; {%- if struct|has_fd %} - std::vector<FileDescriptor> retFds; + std::vector<SharedFD> retFds; {%- endif %} {%- for field in struct.fields %} {{serializer_field(field, namespace, loop)}} @@ -210,7 +210,7 @@ {%- macro deserializer_fd(struct, namespace) %} static {{struct|name_full}} deserialize(std::vector<uint8_t> &data, - std::vector<FileDescriptor> &fds, + std::vector<SharedFD> &fds, {%- if struct|needs_control_serializer %} ControlSerializer *cs) {%- else %} @@ -224,8 +224,8 @@ static {{struct|name_full}} deserialize(std::vector<uint8_t>::const_iterator dataBegin, std::vector<uint8_t>::const_iterator dataEnd, - std::vector<FileDescriptor>::const_iterator fdsBegin, - std::vector<FileDescriptor>::const_iterator fdsEnd, + std::vector<SharedFD>::const_iterator fdsBegin, + std::vector<SharedFD>::const_iterator fdsEnd, {%- if struct|needs_control_serializer %} ControlSerializer *cs) {%- else %} @@ -234,7 +234,7 @@ { {{struct|name_full}} ret; std::vector<uint8_t>::const_iterator m = dataBegin; - std::vector<FileDescriptor>::const_iterator n = fdsBegin; + std::vector<SharedFD>::const_iterator n = fdsBegin; size_t dataSize = std::distance(dataBegin, dataEnd); [[maybe_unused]] size_t fdsSize = std::distance(fdsBegin, fdsEnd); @@ -255,7 +255,7 @@ {%- macro deserializer_fd_simple(struct, namespace) %} static {{struct|name_full}} deserialize(std::vector<uint8_t> &data, - [[maybe_unused]] std::vector<FileDescriptor> &fds, + [[maybe_unused]] std::vector<SharedFD> &fds, ControlSerializer *cs = nullptr) { return IPADataSerializer<{{struct|name_full}}>::deserialize(data.cbegin(), data.cend(), cs); @@ -264,8 +264,8 @@ static {{struct|name_full}} deserialize(std::vector<uint8_t>::const_iterator dataBegin, std::vector<uint8_t>::const_iterator dataEnd, - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsBegin, - [[maybe_unused]] std::vector<FileDescriptor>::const_iterator fdsEnd, + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsBegin, + [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd, ControlSerializer *cs = nullptr) { return IPADataSerializer<{{struct|name_full}}>::deserialize(dataBegin, dataEnd, cs); diff --git a/utils/ipc/generators/mojom_libcamera_generator.py b/utils/ipc/generators/mojom_libcamera_generator.py index c609f4e5c062..753bfc734e56 100644 --- a/utils/ipc/generators/mojom_libcamera_generator.py +++ b/utils/ipc/generators/mojom_libcamera_generator.py @@ -77,7 +77,7 @@ def GetDefaultValue(element): if mojom.IsEnumKind(element.kind): return f'static_cast<{element.kind.mojom_name}>(0)' if isinstance(element.kind, mojom.Struct) and \ - element.kind.mojom_name == 'FileDescriptor': + element.kind.mojom_name == 'SharedFD': return '-1' return '' @@ -140,7 +140,7 @@ def HasFd(element): types = GetAllTypes(element) else: types = GetAllTypes(element.kind) - return "FileDescriptor" in types or (attrs is not None and "hasFd" in attrs) + return "SharedFD" in types or (attrs is not None and "hasFd" in attrs) def WithDefaultValues(element): return [x for x in element if HasDefaultValue(x)] @@ -221,7 +221,7 @@ def IsEnum(element): return mojom.IsEnumKind(element.kind) def IsFd(element): - return mojom.IsStructKind(element.kind) and element.kind.mojom_name == "FileDescriptor" + return mojom.IsStructKind(element.kind) and element.kind.mojom_name == "SharedFD" def IsMap(element): return mojom.IsMapKind(element.kind)
Now that we have a UniqueFD class, the name FileDescriptor is ambiguous. Rename it to SharedFD. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> --- include/libcamera/base/file.h | 4 +- include/libcamera/base/meson.build | 2 +- .../base/{file_descriptor.h => shared_fd.h} | 20 +- include/libcamera/framebuffer.h | 4 +- .../libcamera/internal/ipa_data_serializer.h | 40 +-- include/libcamera/internal/ipc_pipe.h | 8 +- include/libcamera/ipa/core.mojom | 6 +- include/libcamera/ipa/raspberrypi.mojom | 2 +- src/android/camera_device.cpp | 2 +- src/ipa/raspberrypi/raspberrypi.cpp | 4 +- src/libcamera/base/file.cpp | 6 +- src/libcamera/base/file_descriptor.cpp | 266 ------------------ src/libcamera/base/meson.build | 2 +- src/libcamera/base/shared_fd.cpp | 262 +++++++++++++++++ src/libcamera/framebuffer.cpp | 6 +- src/libcamera/ipa_data_serializer.cpp | 100 +++---- src/libcamera/ipc_pipe.cpp | 4 +- .../pipeline/raspberrypi/raspberrypi.cpp | 6 +- src/libcamera/v4l2_videodevice.cpp | 6 +- src/v4l2/v4l2_camera.h | 2 +- test/meson.build | 2 +- .../ipa_data_serializer_test.cpp | 14 +- test/{file-descriptor.cpp => shared-fd.cpp} | 46 +-- .../module_ipa_proxy.cpp.tmpl | 2 +- .../module_ipa_proxy.h.tmpl | 2 +- .../libcamera_templates/proxy_functions.tmpl | 2 +- .../libcamera_templates/serializer.tmpl | 22 +- .../generators/mojom_libcamera_generator.py | 6 +- 28 files changed, 422 insertions(+), 426 deletions(-) rename include/libcamera/base/{file_descriptor.h => shared_fd.h} (55%) delete mode 100644 src/libcamera/base/file_descriptor.cpp create mode 100644 src/libcamera/base/shared_fd.cpp rename test/{file-descriptor.cpp => shared-fd.cpp} (80%)