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(); }