From patchwork Tue Feb 2 22:10:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Niklas_S=C3=B6derlund?= X-Patchwork-Id: 11109 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 82AF3BD161 for ; Tue, 2 Feb 2021 22:11:26 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6070668439; Tue, 2 Feb 2021 23:11:26 +0100 (CET) Received: from vsp-unauthed02.binero.net (vsp-unauthed02.binero.net [195.74.38.227]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 156CB60307 for ; Tue, 2 Feb 2021 23:11:25 +0100 (CET) X-Halon-ID: 93f4b597-65a3-11eb-b73f-0050569116f7 Authorized-sender: niklas.soderlund@fsdn.se Received: from bismarck.berto.se (p4fca2458.dip0.t-ipconnect.de [79.202.36.88]) by bin-vsp-out-03.atm.binero.net (Halon) with ESMTPA id 93f4b597-65a3-11eb-b73f-0050569116f7; Tue, 02 Feb 2021 23:11:20 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Tue, 2 Feb 2021 23:10:49 +0100 Message-Id: <20210202221051.1740237-2-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20210202221051.1740237-1-niklas.soderlund@ragnatech.se> References: <20210202221051.1740237-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 1/3] cam: event_loop: Rename event_ to base_ X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The 'event' variable name is usually used for events added to the base event loop, not the loop itself. Rename the struct event_base member to base_ as a preparation for future work adding events to the loop. There is no functional change. Signed-off-by: Niklas Söderlund Reviewed-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- src/cam/event_loop.cpp | 8 ++++---- src/cam/event_loop.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cam/event_loop.cpp b/src/cam/event_loop.cpp index 94c5d1d362455f33..3a2b665abdc063de 100644 --- a/src/cam/event_loop.cpp +++ b/src/cam/event_loop.cpp @@ -18,7 +18,7 @@ EventLoop::EventLoop() assert(!instance_); evthread_use_pthreads(); - event_ = event_base_new(); + base_ = event_base_new(); instance_ = this; } @@ -26,7 +26,7 @@ EventLoop::~EventLoop() { instance_ = nullptr; - event_base_free(event_); + event_base_free(base_); libevent_global_shutdown(); } @@ -42,7 +42,7 @@ int EventLoop::exec() while (!exit_.load(std::memory_order_acquire)) { dispatchCalls(); - event_base_loop(event_, EVLOOP_NO_EXIT_ON_EMPTY); + event_base_loop(base_, EVLOOP_NO_EXIT_ON_EMPTY); } return exitCode_; @@ -57,7 +57,7 @@ void EventLoop::exit(int code) void EventLoop::interrupt() { - event_base_loopbreak(event_); + event_base_loopbreak(base_); } void EventLoop::callLater(const std::function &func) diff --git a/src/cam/event_loop.h b/src/cam/event_loop.h index 408073c50594d09d..d0d5b5a53c830670 100644 --- a/src/cam/event_loop.h +++ b/src/cam/event_loop.h @@ -30,7 +30,7 @@ public: private: static EventLoop *instance_; - struct event_base *event_; + struct event_base *base_; std::atomic exit_; int exitCode_; From patchwork Tue Feb 2 22:10:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Niklas_S=C3=B6derlund?= X-Patchwork-Id: 11110 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 048FCBD161 for ; Tue, 2 Feb 2021 22:11:27 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 88B426843C; Tue, 2 Feb 2021 23:11:26 +0100 (CET) Received: from vsp-unauthed02.binero.net (vsp-unauthed02.binero.net [195.74.38.227]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4B85568430 for ; Tue, 2 Feb 2021 23:11:25 +0100 (CET) X-Halon-ID: 96370623-65a3-11eb-b73f-0050569116f7 Authorized-sender: niklas.soderlund@fsdn.se Received: from bismarck.berto.se (p4fca2458.dip0.t-ipconnect.de [79.202.36.88]) by bin-vsp-out-03.atm.binero.net (Halon) with ESMTPA id 96370623-65a3-11eb-b73f-0050569116f7; Tue, 02 Feb 2021 23:11:24 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Tue, 2 Feb 2021 23:10:50 +0100 Message-Id: <20210202221051.1740237-3-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20210202221051.1740237-1-niklas.soderlund@ragnatech.se> References: <20210202221051.1740237-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 2/3] cam: event_loop: Execute events in the libevent loop X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Cam uses libevent to deal with threads and idle loop while still implementing its own event queue. This creates issues when the event loop is terminated as it might get stuck in the idle loop if exit() is called while the thread is busy with dispatchCalls(). Solve this my removing the custom event execution and instead injecting the calls as events to the base event loop. Reported-by: Sebastian Fricke Signed-off-by: Niklas Söderlund Reviewed-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- src/cam/event_loop.cpp | 43 ++++++++++++++++++++---------------------- src/cam/event_loop.h | 6 +----- 2 files changed, 21 insertions(+), 28 deletions(-) diff --git a/src/cam/event_loop.cpp b/src/cam/event_loop.cpp index 3a2b665abdc063de..e84e437f1f8ff6d7 100644 --- a/src/cam/event_loop.cpp +++ b/src/cam/event_loop.cpp @@ -13,6 +13,13 @@ EventLoop *EventLoop::instance_ = nullptr; +static void dispatchCallback([[maybe_unused]] evutil_socket_t fd, + [[maybe_unused]] short flags, void *param) +{ + EventLoop *loop = static_cast(param); + loop->dispatchCall(); +} + EventLoop::EventLoop() { assert(!instance_); @@ -38,25 +45,13 @@ EventLoop *EventLoop::instance() int EventLoop::exec() { exitCode_ = -1; - exit_.store(false, std::memory_order_release); - - while (!exit_.load(std::memory_order_acquire)) { - dispatchCalls(); - event_base_loop(base_, EVLOOP_NO_EXIT_ON_EMPTY); - } - + event_base_loop(base_, EVLOOP_NO_EXIT_ON_EMPTY); return exitCode_; } void EventLoop::exit(int code) { exitCode_ = code; - exit_.store(true, std::memory_order_release); - interrupt(); -} - -void EventLoop::interrupt() -{ event_base_loopbreak(base_); } @@ -67,20 +62,22 @@ void EventLoop::callLater(const std::function &func) calls_.push_back(func); } - interrupt(); + struct event *event = event_new(base_, -1, 0, dispatchCallback, this); + event_active(event, 0, 0); } -void EventLoop::dispatchCalls() +void EventLoop::dispatchCall() { - std::unique_lock locker(lock_); + std::function call; - for (auto iter = calls_.begin(); iter != calls_.end(); ) { - std::function call = std::move(*iter); + { + std::unique_lock locker(lock_); + if (calls_.empty()) + return; - iter = calls_.erase(iter); - - locker.unlock(); - call(); - locker.lock(); + call = calls_.front(); + calls_.pop_front(); } + + call(); } diff --git a/src/cam/event_loop.h b/src/cam/event_loop.h index d0d5b5a53c830670..5f1cd88c2f5c830e 100644 --- a/src/cam/event_loop.h +++ b/src/cam/event_loop.h @@ -7,7 +7,6 @@ #ifndef __CAM_EVENT_LOOP_H__ #define __CAM_EVENT_LOOP_H__ -#include #include #include #include @@ -26,19 +25,16 @@ public: void exit(int code = 0); void callLater(const std::function &func); + void dispatchCall(); private: static EventLoop *instance_; struct event_base *base_; - std::atomic exit_; int exitCode_; std::list> calls_; std::mutex lock_; - - void interrupt(); - void dispatchCalls(); }; #endif /* __CAM_EVENT_LOOP_H__ */ From patchwork Tue Feb 2 22:10:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Niklas_S=C3=B6derlund?= X-Patchwork-Id: 11111 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id C6296BD161 for ; Tue, 2 Feb 2021 22:11:27 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A48BA68437; Tue, 2 Feb 2021 23:11:27 +0100 (CET) Received: from bin-mail-out-05.binero.net (bin-mail-out-05.binero.net [195.74.38.228]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DF80868430 for ; Tue, 2 Feb 2021 23:11:25 +0100 (CET) X-Halon-ID: 96d8795f-65a3-11eb-b73f-0050569116f7 Authorized-sender: niklas.soderlund@fsdn.se Received: from bismarck.berto.se (p4fca2458.dip0.t-ipconnect.de [79.202.36.88]) by bin-vsp-out-03.atm.binero.net (Halon) with ESMTPA id 96d8795f-65a3-11eb-b73f-0050569116f7; Tue, 02 Feb 2021 23:11:25 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Tue, 2 Feb 2021 23:10:51 +0100 Message-Id: <20210202221051.1740237-4-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20210202221051.1740237-1-niklas.soderlund@ragnatech.se> References: <20210202221051.1740237-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 3/3] cam: Only queue the exact number of requests asked for X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The cam option --capture=N is suppose to only capture N requests. But if the processing done for each request is large (such as writing it to a slow disk) the current implementation could queue more then N requests before the exit condition is detected and capturing stopped. Solve this by only queueing N requests while still waiting for N requests to complete before exiting. Signed-off-by: Niklas Söderlund Reviewed-by: Jacopo Mondi Reviewed-by: Laurent Pinchart --- src/cam/capture.cpp | 16 +++++++++++++--- src/cam/capture.h | 2 ++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/cam/capture.cpp b/src/cam/capture.cpp index 113ea49d50046e5b..e498b562826b8794 100644 --- a/src/cam/capture.cpp +++ b/src/cam/capture.cpp @@ -18,7 +18,7 @@ using namespace libcamera; Capture::Capture(std::shared_ptr camera, CameraConfiguration *config, EventLoop *loop) : camera_(camera), config_(config), writer_(nullptr), last_(0), loop_(loop), - captureCount_(0), captureLimit_(0) + queueCount_(0), captureCount_(0), captureLimit_(0) { } @@ -26,6 +26,7 @@ int Capture::run(const OptionsParser::Options &options) { int ret; + queueCount_ = 0; captureCount_ = 0; captureLimit_ = options[OptCapture].toInteger(); @@ -128,7 +129,7 @@ int Capture::capture(FrameBufferAllocator *allocator) } for (std::unique_ptr &request : requests_) { - ret = camera_->queueRequest(request.get()); + ret = queueRequest(request.get()); if (ret < 0) { std::cerr << "Can't queue request" << std::endl; camera_->stop(); @@ -152,6 +153,15 @@ int Capture::capture(FrameBufferAllocator *allocator) return ret; } +int Capture::queueRequest(Request *request) +{ + queueCount_++; + if (captureLimit_ && queueCount_ > captureLimit_) + return 0; + + return camera_->queueRequest(request); +} + void Capture::requestComplete(Request *request) { if (request->status() == Request::RequestCancelled) @@ -213,5 +223,5 @@ void Capture::processRequest(Request *request) } request->reuse(Request::ReuseBuffers); - camera_->queueRequest(request); + queueRequest(request); } diff --git a/src/cam/capture.h b/src/cam/capture.h index d21c95a26ce7d83a..c7c9dc00d30f06d6 100644 --- a/src/cam/capture.h +++ b/src/cam/capture.h @@ -32,6 +32,7 @@ public: private: int capture(libcamera::FrameBufferAllocator *allocator); + int queueRequest(libcamera::Request *request); void requestComplete(libcamera::Request *request); void processRequest(libcamera::Request *request); @@ -43,6 +44,7 @@ private: uint64_t last_; EventLoop *loop_; + unsigned int queueCount_; unsigned int captureCount_; unsigned int captureLimit_;