From patchwork Sun Oct 6 05:32:18 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2106 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3133161967 for ; Sun, 6 Oct 2019 07:32:35 +0200 (CEST) Received: from pendragon.ideasonboard.com (modemcable151.96-160-184.mc.videotron.ca [184.160.96.151]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 1BFC8DD for ; Sun, 6 Oct 2019 07:32:33 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1570339954; bh=oeyEcRU61jKXvjVuh6cDcmWwY7TFbjFzkCCd2rVasKU=; h=From:To:Subject:Date:In-Reply-To:References:From; b=VJvzCaHCJomfUKLK1j5yG/6o5t1BuQSJqR9lw5F9if+w/rvHv5UmbFVcXzSdsuysD TyUa2M4Vjnpw7HnEBR1xCWhJEhrpJ1uoCOyC28JJAWe9oO8Ww0X3/oX5mUChpeN+XK RFwNqPrvzj/aZ1D3Q6uiA1ffTWsuXNqfGsdy7NhM= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Sun, 6 Oct 2019 08:32:18 +0300 Message-Id: <20191006053226.8976-2-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191006053226.8976-1-laurent.pinchart@ideasonboard.com> References: <20191006053226.8976-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 1/9] libcamera: timer: Remove the interval() method 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: , X-List-Received-Date: Sun, 06 Oct 2019 05:32:35 -0000 The libcamera timers are single-shot timers. They are started with a duration, but fire once only, not based on an interval. Remove the interval concept by removing the interval() method, and rename other occurences of interval to duration. Signed-off-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- include/libcamera/timer.h | 4 +--- src/libcamera/timer.cpp | 19 ++++++------------- src/qcam/qt_event_dispatcher.cpp | 7 ++++++- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/include/libcamera/timer.h b/include/libcamera/timer.h index 476ae45f1e53..09f426a59993 100644 --- a/include/libcamera/timer.h +++ b/include/libcamera/timer.h @@ -24,11 +24,10 @@ public: ~Timer(); void start(unsigned int msec) { start(std::chrono::milliseconds(msec)); } - void start(std::chrono::milliseconds interval); + void start(std::chrono::milliseconds duration); void stop(); bool isRunning() const; - std::chrono::milliseconds interval() const { return interval_; } std::chrono::steady_clock::time_point deadline() const { return deadline_; } Signal timeout; @@ -40,7 +39,6 @@ private: void registerTimer(); void unregisterTimer(); - std::chrono::milliseconds interval_; std::chrono::steady_clock::time_point deadline_; }; diff --git a/src/libcamera/timer.cpp b/src/libcamera/timer.cpp index b3cea3dadb49..34410bab0fb0 100644 --- a/src/libcamera/timer.cpp +++ b/src/libcamera/timer.cpp @@ -61,19 +61,18 @@ Timer::~Timer() */ /** - * \brief Start or restart the timer with a timeout of \a interval - * \param[in] interval The timer duration in milliseconds + * \brief Start or restart the timer with a timeout of \a duration + * \param[in] duration The timer duration in milliseconds * * If the timer is already running it will be stopped and restarted. */ -void Timer::start(std::chrono::milliseconds interval) +void Timer::start(std::chrono::milliseconds duration) { - interval_ = interval; - deadline_ = utils::clock::now() + interval; + deadline_ = utils::clock::now() + duration; LOG(Timer, Debug) - << "Starting timer " << this << " with interval " - << interval.count() << ": deadline " + << "Starting timer " << this << " with duration " + << duration.count() << ": deadline " << utils::time_point_to_string(deadline_); registerTimer(); @@ -113,12 +112,6 @@ bool Timer::isRunning() const return deadline_ != utils::time_point(); } -/** - * \fn Timer::interval() - * \brief Retrieve the timer interval - * \return The timer interval in milliseconds - */ - /** * \fn Timer::deadline() * \brief Retrieve the timer deadline diff --git a/src/qcam/qt_event_dispatcher.cpp b/src/qcam/qt_event_dispatcher.cpp index 994af3ead82a..9e989bef7d53 100644 --- a/src/qcam/qt_event_dispatcher.cpp +++ b/src/qcam/qt_event_dispatcher.cpp @@ -5,6 +5,7 @@ * qt_event_dispatcher.cpp - qcam - Qt-based event dispatcher */ +#include #include #include @@ -112,7 +113,11 @@ void QtEventDispatcher::exceptionNotifierActivated(int socket) void QtEventDispatcher::registerTimer(Timer *timer) { - int timerId = startTimer(timer->interval()); + std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); + std::chrono::steady_clock::duration duration = timer->deadline() - now; + std::chrono::milliseconds msec = + std::chrono::duration_cast(duration); + int timerId = startTimer(msec); timers_[timerId] = timer; timerIds_[timer] = timerId; } From patchwork Sun Oct 6 05:32:19 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2107 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2F6476196C for ; Sun, 6 Oct 2019 07:32:36 +0200 (CEST) Received: from pendragon.ideasonboard.com (modemcable151.96-160-184.mc.videotron.ca [184.160.96.151]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 3C96873E for ; Sun, 6 Oct 2019 07:32:35 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1570339955; bh=j1pj0IqYbtPk/mpshRjLG/+gpVQWXI+q/1SuPr2TdyE=; h=From:To:Subject:Date:In-Reply-To:References:From; b=VYp9PMFladsZQWUcPyi2fQ3akmFbp6+By79aNSM9RhmRzQrwKPgOzhGDjFz9yivG0 FDP56OncQJ4VtKD4H2CzoNTz5Heo/1oNe1ieGo244o9fRBv6YDMVI2kvNkoyw8nIAt xBYJLKF96uzYVCCEAYINp8wzl4fdy149y+vYtVMc= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Sun, 6 Oct 2019 08:32:19 +0300 Message-Id: <20191006053226.8976-3-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191006053226.8976-1-laurent.pinchart@ideasonboard.com> References: <20191006053226.8976-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 2/9] libcamera: timer: Don't reset deadline after time out 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: , X-List-Received-Date: Sun, 06 Oct 2019 05:32:36 -0000 Users of the Timer class may benefit from retrieving the timer deadline after it times out. This is currently not possible as the deadline is reset to 0 when the timer times out or is stopped. Fix this by not resetting the deadline, and adding a new running_ field to the Timer class to implement isRunning(). Signed-off-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- include/libcamera/timer.h | 1 + src/libcamera/timer.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/include/libcamera/timer.h b/include/libcamera/timer.h index 09f426a59993..3540efb41b6f 100644 --- a/include/libcamera/timer.h +++ b/include/libcamera/timer.h @@ -39,6 +39,7 @@ private: void registerTimer(); void unregisterTimer(); + bool running_; std::chrono::steady_clock::time_point deadline_; }; diff --git a/src/libcamera/timer.cpp b/src/libcamera/timer.cpp index 34410bab0fb0..8c74e1015e43 100644 --- a/src/libcamera/timer.cpp +++ b/src/libcamera/timer.cpp @@ -43,7 +43,7 @@ LOG_DEFINE_CATEGORY(Timer) * \param[in] parent The parent Object */ Timer::Timer(Object *parent) - : Object(parent) + : Object(parent), running_(false) { } @@ -89,17 +89,17 @@ void Timer::start(std::chrono::milliseconds duration) void Timer::stop() { unregisterTimer(); - - deadline_ = utils::time_point(); } void Timer::registerTimer() { thread()->eventDispatcher()->registerTimer(this); + running_ = true; } void Timer::unregisterTimer() { + running_ = false; thread()->eventDispatcher()->unregisterTimer(this); } @@ -109,7 +109,7 @@ void Timer::unregisterTimer() */ bool Timer::isRunning() const { - return deadline_ != utils::time_point(); + return running_; } /** From patchwork Sun Oct 6 05:32:20 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2108 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 37BD561967 for ; Sun, 6 Oct 2019 07:32:37 +0200 (CEST) Received: from pendragon.ideasonboard.com (modemcable151.96-160-184.mc.videotron.ca [184.160.96.151]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 54A9273E for ; Sun, 6 Oct 2019 07:32:36 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1570339956; bh=kEGCTuidhIjcKppbkB5bxzA/zzUVL1xO20g5whvZ3Fs=; h=From:To:Subject:Date:In-Reply-To:References:From; b=asJ+wcj2Z8ou5u5m26S5JXtFZQT4GtCiKhQn/a6dLII2O2qte6M8g0nQNnaYDpics gE5NoVJ3XU1k6GvGT+6nvsidW+yx+ey2FAuw7qDT70SvzPkOk3WULreh/YC8H6mo4h YBOtmX4FB0pt+IaQk84n6wjHa8GApTYTyEl5NHYA= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Sun, 6 Oct 2019 08:32:20 +0300 Message-Id: <20191006053226.8976-4-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191006053226.8976-1-laurent.pinchart@ideasonboard.com> References: <20191006053226.8976-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 3/9] test: timer: Test that deadline() isn't reset upon time out 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: , X-List-Received-Date: Sun, 06 Oct 2019 05:32:37 -0000 Verify that the timer deadline stays valid after the timer expires. As the test now uses the deadline in order to compute the jitter, the interval_ field isn't used anymore and can be removed. Signed-off-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- test/timer.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/test/timer.cpp b/test/timer.cpp index af922cb371cd..d4f16a9bdd97 100644 --- a/test/timer.cpp +++ b/test/timer.cpp @@ -21,14 +21,13 @@ class ManagedTimer : public Timer { public: ManagedTimer() - : Timer(), interval_(0) + : Timer() { timeout.connect(this, &ManagedTimer::timeoutHandler); } void start(int msec) { - interval_ = msec; start_ = std::chrono::steady_clock::now(); expiration_ = std::chrono::steady_clock::time_point(); @@ -37,9 +36,8 @@ public: int jitter() { - std::chrono::steady_clock::duration duration = expiration_ - start_; - int msecs = std::chrono::duration_cast(duration).count(); - return abs(msecs - interval_); + std::chrono::steady_clock::duration duration = expiration_ - deadline(); + return abs(std::chrono::duration_cast(duration).count()); } private: @@ -48,7 +46,6 @@ private: expiration_ = std::chrono::steady_clock::now(); } - int interval_; std::chrono::steady_clock::time_point start_; std::chrono::steady_clock::time_point expiration_; }; From patchwork Sun Oct 6 05:32:21 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2109 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D51CA6196C for ; Sun, 6 Oct 2019 07:32:37 +0200 (CEST) Received: from pendragon.ideasonboard.com (modemcable151.96-160-184.mc.videotron.ca [184.160.96.151]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 40460DD for ; Sun, 6 Oct 2019 07:32:37 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1570339957; bh=TL/JInXT1/VKkEKGlh6gIo9p7VKswEP0BpSBTjHdIjo=; h=From:To:Subject:Date:In-Reply-To:References:From; b=qUxj0lFiB432AUy3vzF6BYL374AruyhR2g1c9SJTiDfjxRbiCH0hIneNdiuVejXA9 Efm0lsTqqOZjak2BGajwBb4btz6iadb0eknyh5BTGeGgCybK0kXyGr+uBoLOd3FH5q XYPVLJdLwDP/1Y83LC+xl3Hju+Gbh9qyUHzG0Gqo= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Sun, 6 Oct 2019 08:32:21 +0300 Message-Id: <20191006053226.8976-5-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191006053226.8976-1-laurent.pinchart@ideasonboard.com> References: <20191006053226.8976-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 4/9] test: timer: Test that a timer can be restarted before it expires 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: , X-List-Received-Date: Sun, 06 Oct 2019 05:32:38 -0000 The Timer API allows restarting a timer before it expires. Add a corresponding test. The test fails as the Timer class doesn't comply with its API documentation. Signed-off-by: Laurent Pinchart --- test/timer.cpp | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/test/timer.cpp b/test/timer.cpp index d4f16a9bdd97..5ff94dbbdeb0 100644 --- a/test/timer.cpp +++ b/test/timer.cpp @@ -21,13 +21,14 @@ class ManagedTimer : public Timer { public: ManagedTimer() - : Timer() + : Timer(), count_(0) { timeout.connect(this, &ManagedTimer::timeoutHandler); } void start(int msec) { + count_ = 0; start_ = std::chrono::steady_clock::now(); expiration_ = std::chrono::steady_clock::time_point(); @@ -40,12 +41,19 @@ public: return abs(std::chrono::duration_cast(duration).count()); } + bool hasFailed() + { + return isRunning() || count_ != 1 || jitter() > 50; + } + private: void timeoutHandler(Timer *timer) { expiration_ = std::chrono::steady_clock::now(); + count_++; } + unsigned int count_; std::chrono::steady_clock::time_point start_; std::chrono::steady_clock::time_point expiration_; }; @@ -74,7 +82,7 @@ protected: dispatcher->processEvents(); - if (timer.isRunning() || timer.jitter() > 50) { + if (timer.hasFailed()) { cout << "Timer expiration test failed" << endl; return TestFail; } @@ -87,7 +95,7 @@ protected: timer.start(4295); dispatcher->processEvents(); - if (timer.isRunning() || timer.jitter() > 50) { + if (timer.hasFailed()) { cout << "Timer expiration test failed" << endl; return TestFail; } @@ -102,11 +110,23 @@ protected: dispatcher->processEvents(); - if (timer.isRunning() || timer.jitter() > 50) { + if (timer.hasFailed()) { cout << "Timer restart test failed" << endl; return TestFail; } + /* Timer restart before expiration. */ + timer.start(50); + timer.start(100); + timer.start(150); + + dispatcher->processEvents(); + + if (timer.hasFailed()) { + cout << "Timer restart before expiration test failed" << endl; + return TestFail; + } + /* Two timers. */ timer.start(1000); timer2.start(300); From patchwork Sun Oct 6 05:32:22 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2110 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 86E4061966 for ; Sun, 6 Oct 2019 07:32:38 +0200 (CEST) Received: from pendragon.ideasonboard.com (modemcable151.96-160-184.mc.videotron.ca [184.160.96.151]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id E81AADD for ; Sun, 6 Oct 2019 07:32:37 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1570339958; bh=ImhNCsB9BuFvCR5zNPTeOikzRwJgDOrb5WEyZPJzm6I=; h=From:To:Subject:Date:In-Reply-To:References:From; b=Tb5UdfAqnNjSC7YpuQWncKKYRy3GkO7/kqDKO/35f4jL710crM6ClPgdBFSCKuVPI hyKla0ii/J5sCZDYG5IUA5GWJyo7+TGUJ0MKtQz/pqyv0lmkw9psVihBxqFnXD7Ike Jbui9k0aDJDx75AXmB0DmUZ3D+HqSdibKPXShvuU= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Sun, 6 Oct 2019 08:32:22 +0300 Message-Id: <20191006053226.8976-6-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191006053226.8976-1-laurent.pinchart@ideasonboard.com> References: <20191006053226.8976-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 5/9] libcamera: timer: Allow restarting a timer before expiration 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: , X-List-Received-Date: Sun, 06 Oct 2019 05:32:38 -0000 The Timer API allows restarting a timer before expiration. This isn't correctly implemented, fix it. Signed-off-by: Laurent Pinchart --- src/libcamera/timer.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libcamera/timer.cpp b/src/libcamera/timer.cpp index 8c74e1015e43..5d4e52713e6e 100644 --- a/src/libcamera/timer.cpp +++ b/src/libcamera/timer.cpp @@ -75,6 +75,9 @@ void Timer::start(std::chrono::milliseconds duration) << duration.count() << ": deadline " << utils::time_point_to_string(deadline_); + if (isRunning()) + unregisterTimer(); + registerTimer(); } @@ -88,6 +91,9 @@ void Timer::start(std::chrono::milliseconds duration) */ void Timer::stop() { + if (!isRunning()) + return; + unregisterTimer(); } From patchwork Sun Oct 6 05:32:23 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2111 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3A4C66196E for ; Sun, 6 Oct 2019 07:32:39 +0200 (CEST) Received: from pendragon.ideasonboard.com (modemcable151.96-160-184.mc.videotron.ca [184.160.96.151]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 99EE2DD for ; Sun, 6 Oct 2019 07:32:38 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1570339958; bh=KVVAKqGdxut9JHBGlZQRoDo4n+8wG0LViVGNO9UV+18=; h=From:To:Subject:Date:In-Reply-To:References:From; b=NkKnb1+DROYRB0bLbKiVRc2sTKGCve3noWzz63H2jQTX51Nss5nlFUm3rPfO45SWF 9RLDATMFWw8teWcXmeSshXs/C2yZRnQRk0NqQAEwTBmb6+YgEOXQTGK1uzkW3Sb97o d7PabWwCURQWBmE3x+WTeHkxB05qF5N4X53JExe8= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Sun, 6 Oct 2019 08:32:23 +0300 Message-Id: <20191006053226.8976-7-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191006053226.8976-1-laurent.pinchart@ideasonboard.com> References: <20191006053226.8976-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 6/9] libcamera: timer: Forbid starting or stopping timer from another thread 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: , X-List-Received-Date: Sun, 06 Oct 2019 05:32:39 -0000 Starting or stopping a timer from a different thread than the one it belongs to is inherently racy. Disallow it. Signed-off-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- src/libcamera/timer.cpp | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/libcamera/timer.cpp b/src/libcamera/timer.cpp index 5d4e52713e6e..8749d66c8662 100644 --- a/src/libcamera/timer.cpp +++ b/src/libcamera/timer.cpp @@ -36,6 +36,11 @@ LOG_DEFINE_CATEGORY(Timer) * Once started the timer will run until it times out. It can be stopped with * stop(), and once it times out or is stopped, can be started again with * start(). + * + * Timers run in the thread they belong to, and thus emit the \a ref timeout + * signal from that thread. To avoid race conditions they must not be started + * or stopped from a different thread, attempts to do so will be rejected and + * logged, and may cause undefined behaviour. */ /** @@ -57,17 +62,24 @@ Timer::~Timer() * \brief Start or restart the timer with a timeout of \a msec * \param[in] msec The timer duration in milliseconds * - * If the timer is already running it will be stopped and restarted. + * This method shall be called from the thread the timer is associated with. If + * the timer is already running it will be stopped and restarted. */ /** * \brief Start or restart the timer with a timeout of \a duration * \param[in] duration The timer duration in milliseconds * - * If the timer is already running it will be stopped and restarted. + * This method shall be called from the thread the timer is associated with. If + * the timer is already running it will be stopped and restarted. */ void Timer::start(std::chrono::milliseconds duration) { + if (Thread::current() != thread()) { + LOG(Timer, Error) << "Timer can't be started from another thread"; + return; + } + deadline_ = utils::clock::now() + duration; LOG(Timer, Debug) @@ -87,13 +99,19 @@ void Timer::start(std::chrono::milliseconds duration) * After this function returns the timer is guaranteed not to emit the * \ref timeout signal. * - * If the timer is not running this function performs no operation. + * This method shall be called from the thread the timer is associated with. If + * the timer is not running this function performs no operation. */ void Timer::stop() { if (!isRunning()) return; + if (Thread::current() != thread()) { + LOG(Timer, Error) << "Timer can't be stopped from another thread"; + return; + } + unregisterTimer(); } From patchwork Sun Oct 6 05:32:24 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2112 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D1FB961565 for ; Sun, 6 Oct 2019 07:32:39 +0200 (CEST) Received: from pendragon.ideasonboard.com (modemcable151.96-160-184.mc.videotron.ca [184.160.96.151]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 467A073E for ; Sun, 6 Oct 2019 07:32:39 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1570339959; bh=n0oxRCU3o0jCj1C0jnXAE4by/bnEtj/Wxf0C+S2Ptg0=; h=From:To:Subject:Date:In-Reply-To:References:From; b=jn7WA6NG8yYyObSqXOBzwt03IgSNyQMGwkXfyGN9hN6oBk6Ad2O1qrluQZXRJC6uo zPDx+tr3DAvFxp6LdfCox5FwWTPg8Mb6kw6WUr5l0dzodaAYLBlVRMUZewxEst04B4 +IdQmLmLvbTp9rLr691UjF8ue7sg6+fkjUObu5OU= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Sun, 6 Oct 2019 08:32:24 +0300 Message-Id: <20191006053226.8976-8-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191006053226.8976-1-laurent.pinchart@ideasonboard.com> References: <20191006053226.8976-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 7/9] test: timer-thread: Test starting a timer from another thread 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: , X-List-Received-Date: Sun, 06 Oct 2019 05:32:40 -0000 Timers can't be started from another thread. Ensure that attempting to do so fails. Signed-off-by: Laurent Pinchart --- test/timer-thread.cpp | 58 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 12 deletions(-) diff --git a/test/timer-thread.cpp b/test/timer-thread.cpp index 5c1b4ac4a401..32853b4e80ef 100644 --- a/test/timer-thread.cpp +++ b/test/timer-thread.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include "test.h" @@ -26,6 +27,12 @@ public: timer_.start(100); } + void restart() + { + timeout_ = false; + timer_.start(100); + } + bool timeout() const { return timeout_; @@ -44,29 +51,56 @@ private: class TimerThreadTest : public Test { protected: + int init() + { + thread_.start(); + timeout_.moveToThread(&thread_); + + return TestPass; + } + int run() { - Thread thread; - thread.start(); + /* + * Test that the timer expires and emits the timeout signal in + * the thread it belongs to. + */ + this_thread::sleep_for(chrono::milliseconds(200)); - TimeoutHandler timeout; - timeout.moveToThread(&thread); - - this_thread::sleep_for(chrono::milliseconds(100)); - - /* Must stop thread before destroying timeout. */ - thread.exit(0); - thread.wait(); - - if (!timeout.timeout()) { + if (!timeout_.timeout()) { cout << "Timer expiration test failed" << endl; return TestFail; } + /* + * Test that starting the timer from another thread fails. We + * need to interrupt the event dispatcher to make sure we don't + * succeed simply because the event dispatcher hasn't noticed + * the timer restart. + */ + timeout_.restart(); + thread_.eventDispatcher()->interrupt(); + + this_thread::sleep_for(chrono::milliseconds(200)); + + if (timeout_.timeout()) { + cout << "Timer restart test failed" << endl; + return TestFail; + } + return TestPass; } + void cleanup() + { + /* Must stop thread before destroying timeout. */ + thread_.exit(0); + thread_.wait(); + } + private: + TimeoutHandler timeout_; + Thread thread_; }; TEST_REGISTER(TimerThreadTest) From patchwork Sun Oct 6 05:32:25 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2113 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id AC0B06196F for ; Sun, 6 Oct 2019 07:32:40 +0200 (CEST) Received: from pendragon.ideasonboard.com (modemcable151.96-160-184.mc.videotron.ca [184.160.96.151]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id E378B73E for ; Sun, 6 Oct 2019 07:32:39 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1570339960; bh=fzp/Klj2MQpQRsxLIaDQdaRrGuikhrbtdXkb7CRSdAo=; h=From:To:Subject:Date:In-Reply-To:References:From; b=ve9zUSNb9RHXdovg5cx0kRij8l1zA8UMPm0rJo1I5Jx4lrpJFPfCb9p/SRAYaIqKV 9f2YMAbKVxZ2KF1sZnRSPKxXfiW/wa5Gofm93kxkh39W8ErjXX634OFBtLk4ExqKl1 7w/BCznl3QQoC23STCRAFYvbXbDmjpdXKoK03c+U= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Sun, 6 Oct 2019 08:32:25 +0300 Message-Id: <20191006053226.8976-9-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191006053226.8976-1-laurent.pinchart@ideasonboard.com> References: <20191006053226.8976-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 8/9] libcamera: timer: Add start() method with absolute deadline 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: , X-List-Received-Date: Sun, 06 Oct 2019 05:32:40 -0000 The Timer class is started using a timer duration. To help callers that require waiting for an absolute deadline, add a start() overload that takes a std::chrono::steady_clock::time_point value. This will be used by IPAs. Signed-off-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- include/libcamera/timer.h | 1 + src/libcamera/timer.cpp | 22 +++++++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/include/libcamera/timer.h b/include/libcamera/timer.h index 3540efb41b6f..34e7b8ac8e87 100644 --- a/include/libcamera/timer.h +++ b/include/libcamera/timer.h @@ -25,6 +25,7 @@ public: void start(unsigned int msec) { start(std::chrono::milliseconds(msec)); } void start(std::chrono::milliseconds duration); + void start(std::chrono::steady_clock::time_point deadline); void stop(); bool isRunning() const; diff --git a/src/libcamera/timer.cpp b/src/libcamera/timer.cpp index 8749d66c8662..705ce60b8fbd 100644 --- a/src/libcamera/timer.cpp +++ b/src/libcamera/timer.cpp @@ -37,6 +37,11 @@ LOG_DEFINE_CATEGORY(Timer) * stop(), and once it times out or is stopped, can be started again with * start(). * + * The timer deadline is specified as either a duration in milliseconds or an + * absolute time point. If the deadline is set to the past or the current time, + * the timer will time out immediately when execution returns to the event + * loop of the timer's thread. + * * Timers run in the thread they belong to, and thus emit the \a ref timeout * signal from that thread. To avoid race conditions they must not be started * or stopped from a different thread, attempts to do so will be rejected and @@ -74,17 +79,28 @@ Timer::~Timer() * the timer is already running it will be stopped and restarted. */ void Timer::start(std::chrono::milliseconds duration) +{ + start(utils::clock::now() + duration); +} + +/** + * \brief Start or restart the timer with a \a deadline + * \param[in] deadline The timer deadline + * + * This method shall be called from the thread the timer is associated with. If + * the timer is already running it will be stopped and restarted. + */ +void Timer::start(std::chrono::steady_clock::time_point deadline) { if (Thread::current() != thread()) { LOG(Timer, Error) << "Timer can't be started from another thread"; return; } - deadline_ = utils::clock::now() + duration; + deadline_ = deadline; LOG(Timer, Debug) - << "Starting timer " << this << " with duration " - << duration.count() << ": deadline " + << "Starting timer " << this << ": deadline " << utils::time_point_to_string(deadline_); if (isRunning()) From patchwork Sun Oct 6 05:32:26 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 2114 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 59A016196C for ; Sun, 6 Oct 2019 07:32:41 +0200 (CEST) Received: from pendragon.ideasonboard.com (modemcable151.96-160-184.mc.videotron.ca [184.160.96.151]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id B659FDD for ; Sun, 6 Oct 2019 07:32:40 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1570339961; bh=K4zCgQQ/cfTe4ehoUQ4IDib/z6/RbtUFOL7+XatkA0Y=; h=From:To:Subject:Date:In-Reply-To:References:From; b=M3ABP5AkNMoiyci+3ihzqGYP72CGeQRbI4ycDgGh4x5EBSRVi112SwYYEpnIUMIWv syLdV7yWRz55ZjoCTuLsFEeyxdrKwQvy8ymNbnRBZCL3a2YV9lwqjlKaybE18UbC44 7NAZesfOct/gMnRh1U5QJ9G6r9k8s8g9CSMK3OzM= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Sun, 6 Oct 2019 08:32:26 +0300 Message-Id: <20191006053226.8976-10-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20191006053226.8976-1-laurent.pinchart@ideasonboard.com> References: <20191006053226.8976-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 9/9] test: timer: Test start() with absolute deadline 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: , X-List-Received-Date: Sun, 06 Oct 2019 05:32:41 -0000 Signed-off-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- test/timer.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/timer.cpp b/test/timer.cpp index 5ff94dbbdeb0..93ce26a0a9a3 100644 --- a/test/timer.cpp +++ b/test/timer.cpp @@ -35,6 +35,15 @@ public: Timer::start(msec); } + void start(std::chrono::steady_clock::time_point deadline) + { + count_ = 0; + start_ = std::chrono::steady_clock::now(); + expiration_ = std::chrono::steady_clock::time_point(); + + Timer::start(deadline); + } + int jitter() { std::chrono::steady_clock::duration duration = expiration_ - deadline(); @@ -127,6 +136,16 @@ protected: return TestFail; } + /* Timer with absolute deadline. */ + timer.start(std::chrono::steady_clock::now() + std::chrono::milliseconds(200)); + + dispatcher->processEvents(); + + if (timer.isRunning() || timer.jitter() > 50) { + cout << "Absolute timer test failed" << endl; + return TestFail; + } + /* Two timers. */ timer.start(1000); timer2.start(300);