[libcamera-devel] [PATCH v2 2/5] libcamera: base: thread: Apply clang thread safety annotation

Laurent Pinchart laurent.pinchart at ideasonboard.com
Sun Aug 28 21:18:31 CEST 2022


On Sun, Aug 28, 2022 at 09:30:08PM +0300, Laurent Pinchart via libcamera-devel wrote:
> Hi Umang and Hiro,
> 
> Thank you for the patch.
> 
> On Mon, Jun 20, 2022 at 10:20:24PM +0530, Umang Jain via libcamera-devel wrote:
> > From: Hirokazu Honda <hiroh at chromium.org>
> > 
> > This annotates member variables of ThreadData by clang thread
> > safety annotations.
> > 
> > Signed-off-by: Hirokazu Honda <hiroh at chromium.org>
> > Signed-off-by: Umang Jain <umang.jain at ideasonboard.com>
> > ---
> >  src/libcamera/base/thread.cpp | 22 +++++++++++++++-------
> >  1 file changed, 15 insertions(+), 7 deletions(-)
> > 
> > diff --git a/src/libcamera/base/thread.cpp b/src/libcamera/base/thread.cpp
> > index 6bda9d14..2e26b83c 100644
> > --- a/src/libcamera/base/thread.cpp
> > +++ b/src/libcamera/base/thread.cpp
> > @@ -151,7 +151,7 @@ private:
> >  	friend class ThreadMain;
> >  
> >  	Thread *thread_;
> > -	bool running_;
> > +	bool running_ LIBCAMERA_TSA_GUARDED_BY(mutex_);
> >  	pid_t tid_;
> >  
> >  	Mutex mutex_;
> > @@ -160,7 +160,7 @@ private:
> >  
> >  	ConditionVariable cv_;
> >  	std::atomic<bool> exit_;
> > -	int exitCode_;
> > +	int exitCode_ LIBCAMERA_TSA_GUARDED_BY(mutex_);
> >  
> >  	MessageQueue messages_;
> >  };
> > @@ -422,11 +422,19 @@ bool Thread::wait(utils::duration duration)
> >  	{
> >  		MutexLocker locker(data_->mutex_);
> >  
> > -		if (duration == utils::duration::max())
> > -			data_->cv_.wait(locker, [&]() { return !data_->running_; });
> > -		else
> > -			hasFinished = data_->cv_.wait_for(locker, duration,
> > -							  [&]() { return !data_->running_; });
> > +		if (duration == utils::duration::max()) {
> > +			data_->cv_.wait(
> > +				locker,
> > +				[&]() LIBCAMERA_TSA_REQUIRES(data_->mutex_) {
> > +					return !data_->running_;
> > +				});
> > +		} else {
> > +			hasFinished = data_->cv_.wait_for(
> > +				locker, duration,
> > +				[&]() LIBCAMERA_TSA_REQUIRES(data_->mutex_) {
> > +					return !data_->running_;
> > +				});
> > +		}
> 
> Let's improve readability a bit:
> 
> 		auto isRunning = [&]() LIBCAMERA_TSA_REQUIRES(data_->mutex_) {
> 			return !data_->running_;
> 		});
> 
> 		if (duration == utils::duration::max())
> 			data_->cv_.wait(locker, isRunning);
> 		else
> 			hasFinished = data_->cv_.wait_for(locker, duration,
> 							  isRunning);
> 
> Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>

Actually... Have you tried compiling this series with clang ? :-)

../../src/libcamera/base/thread.cpp:395:9: error: writing variable 'exitCode_' requires holding mutex 'data_->mutex_' exclusively [-Werror,-Wthread-safety-analysis]
        data_->exitCode_ = code;
               ^
1 error generated.

The most simple fix is to take the lock in Thread::exit(). It however
goes against the design goal of not requiring locks for exit(), as shown
by the exit_ variable being an atomic. I believe the current
implementation is safe, although it would probably be worth it
revisiting the code to double-check that all necessary memory barriers
are in place. You could thus drop the LIBCAMERA_TSA_GUARDED_BY
annotation for exitCode_.

There's also an error in camera_manager.cpp:

../../src/libcamera/camera_manager.cpp:182:2: error: reading variable 'cameras_' requires holding mutex 'mutex_' [-Werror,-Wthread-safety-analysis]
        cameras_.clear();
        ^
1 error generated.

This shuld just be a matter of taking the lock in the CameraManager
destructor in patch 3/5.

> >  	}
> >  
> >  	if (thread_.joinable())

-- 
Regards,

Laurent Pinchart


More information about the libcamera-devel mailing list