From patchwork Tue Nov 30 15:55:53 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hirokazu Honda X-Patchwork-Id: 14902 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 45C51BF415 for ; Tue, 30 Nov 2021 15:56:24 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 018506072C; Tue, 30 Nov 2021 16:56:24 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="gimMj3GU"; dkim-atps=neutral Received: from mail-pj1-x1029.google.com (mail-pj1-x1029.google.com [IPv6:2607:f8b0:4864:20::1029]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A778C60721 for ; Tue, 30 Nov 2021 16:56:17 +0100 (CET) Received: by mail-pj1-x1029.google.com with SMTP id j5-20020a17090a318500b001a6c749e697so14095491pjb.1 for ; Tue, 30 Nov 2021 07:56:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=AAc/KAYnNTACC5cCKhDfWsaHmWoRqjF3AfvdOey73Xk=; b=gimMj3GUVwJXigxBhYuAFj7Ak867vEEmM20+zmSiewdMRQ5tdsH9c2KCle4wTY2mYM CbcSYH8OO6XYAwJ623ZEEYpc8As5MCEBWBbNPQjZgkZc0BdreqhCaQAi+KnqrwoZnjpi 92pwW6q/pbhOpSnCNvxscUHDvkY6EYWxXzwE8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=AAc/KAYnNTACC5cCKhDfWsaHmWoRqjF3AfvdOey73Xk=; b=3sK+a9zlB8BND82TPyjxWU20fWUByjyxJ61DQU2wc5z0brAvQRZ6R8xH4YdVmOm/e9 82j2QmuV2m7gUUS+XY2BTlwja6c58UPxyXAuRQ746Er+kyR1Q9MtAtkk38kAWgfXRA32 Fyp/b/jIgkEL203R8SPGOJWHBgh1mumFV01+uBJB4QIE5mjzaYhoxCwW7gJdub3gufFp pfWBSINLGh1YpiPP835LZ7NRZHZHmpcv0QtpqSoAWUmQ5vc5CDQAASVu731uulSjx0fS 8USaQ66+IiWoIjSciKOPcm6RdBIVjhEiaGzN9UA1qMvnwRMtS4u6RLLmPARTSHVAh+dd XqzQ== X-Gm-Message-State: AOAM533PYFu/UdJCPOW8fu359o8k1y0xGYX01yDzJJlvLYqbUw8XtlM0 ZzebQ9qSl9axEnfuxsdE36VsmFrrYyy8Sg== X-Google-Smtp-Source: ABdhPJzsZVdZgQjRb420INIYgioxYUGFUzHh92MIOuAz/hIn9wxTZAZUPZscDNQnzVdif9Hf/7et7g== X-Received: by 2002:a17:90b:230c:: with SMTP id mt12mr285357pjb.63.1638287775909; Tue, 30 Nov 2021 07:56:15 -0800 (PST) Received: from hiroh2.tok.corp.google.com ([2401:fa00:8f:203:c90a:5a53:b139:1336]) by smtp.gmail.com with ESMTPSA id pc10sm3510283pjb.9.2021.11.30.07.56.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 30 Nov 2021 07:56:15 -0800 (PST) From: Hirokazu Honda To: libcamera-devel@lists.libcamera.org Date: Wed, 1 Dec 2021 00:55:53 +0900 Message-Id: <20211130155600.2203123-6-hiroh@chromium.org> X-Mailer: git-send-email 2.34.0.rc2.393.gf8c9666880-goog In-Reply-To: <20211130155600.2203123-1-hiroh@chromium.org> References: <20211130155600.2203123-1-hiroh@chromium.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 05/12] libcamera: base: Add mutex classes with thread safety annotations 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" This replaces Mutex and MutexLocker with our own defined classes. The classes are annotated by clang thread safety annotations. So we can add annotation to code where the classes are used. v4l2 code needs to be annotated, which violates Mutex capability. Signed-off-by: Hirokazu Honda --- include/libcamera/base/meson.build | 1 + include/libcamera/base/mutex.h | 131 +++++++++++++++++++++++++++++ include/libcamera/base/thread.h | 7 +- src/libcamera/base/meson.build | 1 + src/libcamera/base/mutex.cpp | 121 ++++++++++++++++++++++++++ src/libcamera/base/thread.cpp | 15 ---- src/v4l2/v4l2_camera_proxy.h | 5 +- 7 files changed, 258 insertions(+), 23 deletions(-) create mode 100644 include/libcamera/base/mutex.h create mode 100644 src/libcamera/base/mutex.cpp diff --git a/include/libcamera/base/meson.build b/include/libcamera/base/meson.build index 1a71ce5a..37c4435a 100644 --- a/include/libcamera/base/meson.build +++ b/include/libcamera/base/meson.build @@ -13,6 +13,7 @@ libcamera_base_headers = files([ 'flags.h', 'log.h', 'message.h', + 'mutex.h', 'object.h', 'private.h', 'semaphore.h', diff --git a/include/libcamera/base/mutex.h b/include/libcamera/base/mutex.h new file mode 100644 index 00000000..2792551c --- /dev/null +++ b/include/libcamera/base/mutex.h @@ -0,0 +1,131 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021, Google Inc. + * + * thread.h - Thread support + */ + +#pragma once + +#include +#include + +#include + +namespace libcamera { + +class ConditionVariable; + +#ifndef __DOXYGEN__ +class LIBCAMERA_TSA_SCOPED_CAPABILITY MutexLocker; +#else +class MutexLocker; +#endif /* __DOXYGEN__ */ + +/* \todo using Mutex = std::mutex if lib++ is used. */ + +#ifndef __DOXYGEN__ +class LIBCAMERA_TSA_CAPABILITY("mutex") Mutex final +#else +class Mutex final +#endif /* __DOXYGEN__ */ +{ +public: + constexpr Mutex() + { + } + + void lock() LIBCAMERA_TSA_ACQUIRE() + { + mutex_.lock(); + } + + void unlock() LIBCAMERA_TSA_RELEASE() + { + mutex_.unlock(); + } + +private: + friend MutexLocker; + + std::mutex mutex_; +}; + +#ifndef __DOXYGEN__ +class LIBCAMERA_TSA_SCOPED_CAPABILITY MutexLocker final +#else +class MutexLocker final +#endif /* __DOXYGEN__ */ +{ +public: + explicit MutexLocker(Mutex &mutex) LIBCAMERA_TSA_ACQUIRE(mutex) + : lock_(mutex.mutex_) + { + } + + MutexLocker(Mutex &mutex, std::defer_lock_t t) noexcept LIBCAMERA_TSA_EXCLUDES(mutex) + : lock_(mutex.mutex_, t) + { + } + + ~MutexLocker() LIBCAMERA_TSA_RELEASE() + { + } + + void lock() LIBCAMERA_TSA_ACQUIRE() + { + lock_.lock(); + } + + bool try_lock() LIBCAMERA_TSA_TRY_ACQUIRE(true) + { + return lock_.try_lock(); + } + + void unlock() LIBCAMERA_TSA_RELEASE() + { + lock_.unlock(); + } + +private: + friend ConditionVariable; + + std::unique_lock lock_; +}; + +class ConditionVariable final +{ +public: + ConditionVariable() + { + } + + void notify_one() noexcept + { + cv_.notify_one(); + } + + void notify_all() noexcept + { + cv_.notify_all(); + } + + template + void wait(MutexLocker &locker, Predicate stopWaiting) + { + cv_.wait(locker.lock_, stopWaiting); + } + + template + bool wait_for(MutexLocker &locker, + const std::chrono::duration &relTime, + Predicate stopWaiting) + { + return cv_.wait_for(locker.lock_, relTime, stopWaiting); + } + +private: + std::condition_variable cv_; +}; + +} /* namespace libcamera */ diff --git a/include/libcamera/base/thread.h b/include/libcamera/base/thread.h index 1ebf8363..44678c34 100644 --- a/include/libcamera/base/thread.h +++ b/include/libcamera/base/thread.h @@ -7,15 +7,14 @@ #pragma once -#include #include -#include #include #include #include #include +#include #include #include @@ -27,10 +26,6 @@ class Object; class ThreadData; class ThreadMain; -using ConditionVariable = std::condition_variable; -using Mutex = std::mutex; -using MutexLocker = std::unique_lock; - class Thread { public: diff --git a/src/libcamera/base/meson.build b/src/libcamera/base/meson.build index 05fed7ac..b93b8505 100644 --- a/src/libcamera/base/meson.build +++ b/src/libcamera/base/meson.build @@ -11,6 +11,7 @@ libcamera_base_sources = files([ 'flags.cpp', 'log.cpp', 'message.cpp', + 'mutex.cpp', 'object.cpp', 'semaphore.cpp', 'signal.cpp', diff --git a/src/libcamera/base/mutex.cpp b/src/libcamera/base/mutex.cpp new file mode 100644 index 00000000..327b90c0 --- /dev/null +++ b/src/libcamera/base/mutex.cpp @@ -0,0 +1,121 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021, Google Inc. + * + * mutex.cpp - Mutex classes with clang thread safety annotation + */ + +#include + +/** + * \file base/mutex.h + * \brief Mutex classes with clang thread safety annotation + */ + +namespace libcamera { + +/** + * \class Mutex + * \brief std::mutex wrapper with clang thread safety annotation + */ + +/** + * \fn Mutex::Mutex() + * \brief Construct a Mutex instance + */ + +/** + * \fn Mutex::lock() + * \brief Locks std::mutex + */ + +/** + * \fn Mutex::unlock() + * \brief Unlocks std::mutex + */ + +/** + * \class MutexLocker + * \brief std::unique_lock wrapper with clang thread safety annotation + */ + +/** + * \fn MutexLocker::MutexLocker(Mutex &mutex) + * \brief Constructs MutexLocker with \a mutex as as the associated mutex and + * locks \a mutex + * \param[in] mutex Mutex to be locked/unlocked by MutexLocker + * + * This blocks until \a mutex is acquired. + */ + +/** + * \fn MutexLocker::MutexLocker(Mutex &mutex, std::defer_lock_t t) + * \brief Constructs MutexLocker with \a mutex as as the associated mutex but + * does not lock \a mutex + * \param[in] mutex Mutex to be locked/unlocked by MutexLocker + * \param[in] t mark to specify this constructor is called1 + * + */ + +/** + * \fn MutexLocker::~MutexLocker() + * \brief Destroys MutexLocker and unlock the associated mutex if it is locked + */ + +/** + * \fn MutexLocker::lock() + * \brief Locks the associated mutex + */ + +/** + * \fn MutexLocker::try_lock() + * \brief Tries to lock the associated mutex + * \return True if the ownership of the mutex has been acquired successfully, + false otherwise. + */ + +/** + * \fn MutexLocker::unlock() + * \brief Unlocks the associated mutex + */ + +/** + * \class ConditionVariable + * \brief std::condition_variable wrapper with clang thread safety annotation + */ + +/** + * \fn ConditionVariable::ConditionVariable() + * \brief Constructs ConditionVariable + */ + +/** + * \fn ConditionVariable::notify_one() + * \brief Delegates std::condition_variable::notify_one() + */ + +/** + * \fn ConditionVariable::notify_all() + * \brief Delegates std::condition_variable::notify_all() + */ + +/** + * \fn ConditionVariable::wait(MutexLocker& locker, Predicate stopWaiting) + * \brief Call std::condition_variable::wait() with \a locker and \a stopWaiting + * \param[in] locker MutexLocker that is locked/unlocked during wait() + * \param[in] stopWaiting The predicate to be satisfied + */ + +/** + * \fn ConditionVariable::wait_for(MutexLocker& locker, + const std::chrono::duration &relTime, + Predicate stopWaiting) + * \brief Call std::condition_variable::wait_for() with \a locker, \a relTime, + \a stopWaiting + * \param[in] locker MutexLocker that is locked/unlocked during wait() + * \param[in] relTime std::chrono::duration representing the maximum time to + spend waiting + * \param[in] stopWaiting The predicate to be satisfied + */ + +} /* namespace libcamera */ diff --git a/src/libcamera/base/thread.cpp b/src/libcamera/base/thread.cpp index b893135f..b2043b7e 100644 --- a/src/libcamera/base/thread.cpp +++ b/src/libcamera/base/thread.cpp @@ -204,21 +204,6 @@ ThreadData *ThreadData::current() return data; } -/** - * \typedef ConditionVariable - * \brief An alias for std::condition_variable - */ - -/** - * \typedef Mutex - * \brief An alias for std::mutex - */ - -/** - * \typedef MutexLocker - * \brief An alias for std::unique_lock - */ - /** * \class Thread * \brief A thread of execution diff --git a/src/v4l2/v4l2_camera_proxy.h b/src/v4l2/v4l2_camera_proxy.h index 040954dd..23be995d 100644 --- a/src/v4l2/v4l2_camera_proxy.h +++ b/src/v4l2/v4l2_camera_proxy.h @@ -14,7 +14,8 @@ #include #include -#include +#include +#include #include @@ -59,7 +60,7 @@ private: int vidioc_querybuf(V4L2CameraFile *file, struct v4l2_buffer *arg); int vidioc_qbuf(V4L2CameraFile *file, struct v4l2_buffer *arg); int vidioc_dqbuf(V4L2CameraFile *file, struct v4l2_buffer *arg, - libcamera::Mutex *lock); + libcamera::Mutex *lock) LIBCAMERA_TSA_REQUIRES(*lock); int vidioc_streamon(V4L2CameraFile *file, int *arg); int vidioc_streamoff(V4L2CameraFile *file, int *arg);