From patchwork Sat Jan 30 00:19:14 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: 11069 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 C6F55BD808 for ; Sat, 30 Jan 2021 00:19:40 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 595E6683CA; Sat, 30 Jan 2021 01:19:39 +0100 (CET) Received: from vsp-unauthed02.binero.net (vsp-unauthed02.binero.net [195.74.38.227]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3E503683BE for ; Sat, 30 Jan 2021 01:19:38 +0100 (CET) X-Halon-ID: d5c197ae-6290-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 d5c197ae-6290-11eb-b73f-0050569116f7; Sat, 30 Jan 2021 01:19:37 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Sat, 30 Jan 2021 01:19:14 +0100 Message-Id: <20210130001915.489703-2-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20210130001915.489703-1-niklas.soderlund@ragnatech.se> References: <20210130001915.489703-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 1/2] cam: event_loop: Stop queuing calls when the event loop are exiting 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" Terminating the event loop with EventLoop::exit() does not grantee that it will terminate. If the event loops 'call later' queue can be kept non-empty by continuously queuing new calls using EventLoop::callLater() either from a different thread or from callbacks in the loop itself EventLoop::dispatchCalls() will never complete and the loop will run forever. Solve this by only executing the already queued calls each invocation of dispatchCalls() and only enter the idle loop if dispatchCalls() had no calls to dispatch. Reported-by: Sebastian Fricke Fixes: f49e93338b6309a6 ("cam: event_loop: Add deferred calls support") Signed-off-by: Niklas Söderlund --- src/cam/event_loop.cpp | 21 +++++++++------------ src/cam/event_loop.h | 2 +- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/cam/event_loop.cpp b/src/cam/event_loop.cpp index 94c5d1d362455f33..f0b1ecbb6244c40a 100644 --- a/src/cam/event_loop.cpp +++ b/src/cam/event_loop.cpp @@ -41,8 +41,8 @@ int EventLoop::exec() exit_.store(false, std::memory_order_release); while (!exit_.load(std::memory_order_acquire)) { - dispatchCalls(); - event_base_loop(event_, EVLOOP_NO_EXIT_ON_EMPTY); + if (!dispatchCalls()) + event_base_loop(event_, EVLOOP_NO_EXIT_ON_EMPTY); } return exitCode_; @@ -70,17 +70,14 @@ void EventLoop::callLater(const std::function &func) interrupt(); } -void EventLoop::dispatchCalls() +bool EventLoop::dispatchCalls() { - std::unique_lock locker(lock_); + lock_.lock(); + std::list> calls = std::move(calls_); + lock_.unlock(); - for (auto iter = calls_.begin(); iter != calls_.end(); ) { - std::function call = std::move(*iter); - - iter = calls_.erase(iter); - - locker.unlock(); + for (std::function call : calls) call(); - locker.lock(); - } + + return !calls.empty(); } diff --git a/src/cam/event_loop.h b/src/cam/event_loop.h index 408073c50594d09d..b2535f7bdd96742a 100644 --- a/src/cam/event_loop.h +++ b/src/cam/event_loop.h @@ -38,7 +38,7 @@ private: std::mutex lock_; void interrupt(); - void dispatchCalls(); + bool dispatchCalls(); }; #endif /* __CAM_EVENT_LOOP_H__ */ From patchwork Sat Jan 30 00:19:15 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: 11070 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 80566BD808 for ; Sat, 30 Jan 2021 00:19:41 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 78167683CE; Sat, 30 Jan 2021 01:19:39 +0100 (CET) Received: from bin-mail-out-06.binero.net (bin-mail-out-06.binero.net [195.74.38.229]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D08AE6030A for ; Sat, 30 Jan 2021 01:19:38 +0100 (CET) X-Halon-ID: d687d398-6290-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 d687d398-6290-11eb-b73f-0050569116f7; Sat, 30 Jan 2021 01:19:38 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Sat, 30 Jan 2021 01:19:15 +0100 Message-Id: <20210130001915.489703-3-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20210130001915.489703-1-niklas.soderlund@ragnatech.se> References: <20210130001915.489703-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 2/2] 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 --- 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_;