summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libcamera/pipeline/rpi/common/shared_mem_object.h128
1 files changed, 128 insertions, 0 deletions
diff --git a/src/libcamera/pipeline/rpi/common/shared_mem_object.h b/src/libcamera/pipeline/rpi/common/shared_mem_object.h
new file mode 100644
index 00000000..aa56c220
--- /dev/null
+++ b/src/libcamera/pipeline/rpi/common/shared_mem_object.h
@@ -0,0 +1,128 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2023, Raspberry Pi Ltd
+ *
+ * shared_mem_object.h - Helper class for shared memory allocations
+ */
+#pragma once
+
+#include <cstddef>
+#include <fcntl.h>
+#include <string>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <utility>
+
+#include <libcamera/base/class.h>
+#include <libcamera/base/shared_fd.h>
+
+namespace libcamera {
+
+namespace RPi {
+
+template<class T>
+class SharedMemObject
+{
+public:
+ static constexpr std::size_t SIZE = sizeof(T);
+
+ SharedMemObject()
+ : obj_(nullptr)
+ {
+ }
+
+ template<class... Args>
+ SharedMemObject(const std::string &name, Args &&...args)
+ : name_(name), obj_(nullptr)
+ {
+ void *mem;
+ int ret;
+
+ ret = memfd_create(name_.c_str(), MFD_CLOEXEC);
+ if (ret < 0)
+ return;
+
+ fd_ = SharedFD(std::move(ret));
+ if (!fd_.isValid())
+ return;
+
+ ret = ftruncate(fd_.get(), SIZE);
+ if (ret < 0)
+ return;
+
+ mem = mmap(nullptr, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
+ fd_.get(), 0);
+ if (mem == MAP_FAILED)
+ return;
+
+ obj_ = new (mem) T(std::forward<Args>(args)...);
+ }
+
+ SharedMemObject(SharedMemObject<T> &&rhs)
+ {
+ this->name_ = std::move(rhs.name_);
+ this->fd_ = std::move(rhs.fd_);
+ this->obj_ = rhs.obj_;
+ rhs.obj_ = nullptr;
+ }
+
+ ~SharedMemObject()
+ {
+ if (obj_) {
+ obj_->~T();
+ munmap(obj_, SIZE);
+ }
+ }
+
+ /* Make SharedMemObject non-copyable for now. */
+ LIBCAMERA_DISABLE_COPY(SharedMemObject)
+
+ SharedMemObject<T> &operator=(SharedMemObject<T> &&rhs)
+ {
+ this->name_ = std::move(rhs.name_);
+ this->fd_ = std::move(rhs.fd_);
+ this->obj_ = rhs.obj_;
+ rhs.obj_ = nullptr;
+ return *this;
+ }
+
+ T *operator->()
+ {
+ return obj_;
+ }
+
+ const T *operator->() const
+ {
+ return obj_;
+ }
+
+ T &operator*()
+ {
+ return *obj_;
+ }
+
+ const T &operator*() const
+ {
+ return *obj_;
+ }
+
+ const SharedFD &fd() const
+ {
+ return fd_;
+ }
+
+ explicit operator bool() const
+ {
+ return !!obj_;
+ }
+
+private:
+ std::string name_;
+ SharedFD fd_;
+ T *obj_;
+};
+
+} /* namespace RPi */
+
+} /* namespace libcamera */