From patchwork Fri Sep 18 07:59:49 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 28323 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 44628C335A for ; Fri, 18 Sep 2026 08:08:00 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 99CFF6849B; Fri, 18 Sep 2026 10:07:59 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="WLXLrAy5"; dkim-atps=neutral Received: from mail-wr2-x10.google.com (mail-wr2-x10.google.com [IPv6:2a00:1450:4864:30::10]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D88BB68712 for ; Fri, 18 Sep 2026 10:07:49 +0200 (CEST) Received: by mail-wr2-x10.google.com with SMTP id ffacd0b85a97d-48435ae9ca4so68043f8f.3 for ; Fri, 18 Sep 2026 01:07:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; t=1789718869; x=1790323669; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=Riz3/b6/DlGts9lPleK/2NKhUOk8MiC+6sV1WDmdEVI=; b=WLXLrAy5HcMQ8mF0koFX/qBt+hX4ZGUOu5PsPVQdATneVhnffYS89ZjXVq6xvaWrm4 3jNtRLuSZYx3SN6zNjaWHJhaVZxZerGtx/L30RpnQYu8zQ0fReKi1LfjtshTTQ86r+bX sAPj8FPOSI8rRE8B57U+wEs+JwAnSoyX+RVPoGWCRYDlBafAUqZmdq8Lnt+UN3Omt8F8 QyNeE+/rmcL/fx7JXm06D5Z0fwy/+pVFPD9BOSbjxGZI7fTvkKfT4Z0qaQCQK8De9PJV 9pv+sDW2bdL64ICqL+7myFmx+ncgHJ+qz6VcKXXO/7Gitxdxu1+nHIs986/tETmoZ4DU IVXw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789718869; x=1790323669; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=Riz3/b6/DlGts9lPleK/2NKhUOk8MiC+6sV1WDmdEVI=; b=O1z7h3Lt7vzNKUfBFB+vV5pEXR1EWWmT5UDri1zYET0aYAOI7YEXlQt0CrIOZJfc9h 3H33HoreBM1MqXqRvJpjgRHiYct20JuuExh5qUHArSrRUxXT3JHI2OSsyzWEdQHQBpk7 wklmcNB6OwF2c6vB+tyjPi8gC4eqJc2upcHVapAXSmTpbyhPoKeTjAfu0JBuNbj3Nn1/ +PvFgWTq3x4q7JEuRmZ+7l+V+vsKL8w7hgoBeX1uDFuvb8M6+N5HUjNZxddgDKv3Bmtk ywkJm3rqz1Gh5xxWku7uVHyI8tbu0nbM9JFakPOvb6aYFMOQ49eH7O6Vr1jjB7XDEy7p 226g== X-Gm-Message-State: AFuF++lvfjxAXyX1AtHAhX3BlhLUqx+Ku7JqAQnVsXzdcJz51jE5wcMe hgKhcG8bQ1lx2Dq8GswUUJ23osQSrXk+rY4XbFqS+JAYaDijxbIwCJq8FQjcPv1+0DaxwCCfKmv 6XPlOwM0= X-Gm-Gg: AYBFou3/OiSq1XmSk1KHjwoHmxuu/aBT/c0bMCN8PAgcm4rzApudgoi75eMqodYzsqQ bD56RC56FvOUH4+kAGxNCY9EIU6OPl02+1dO2+gSxSZB87bmXOvcV5p6mf7V5jUuqj+KMzJABEF LiY5BbDiV+LKudHy7B2kPwCQT7H0Awf7dFsNtW6ZbeB1/37BcQ6tdeycPfGvQIzDH5j5kZ6rrK9 8whsQw1Moep595TxICZFWHgBGqSfQIaFftcKieQ9PLprpRbSvuDFnaNepSj46u5wcenNU2Q7WUR Bt4HLL1NZNgV4FVSirgfwJ8yxU+APl/OtFZhsGlEFBxrOEMuBzx49sOxhXtX7O2i4C+qZ0C8acb GMOOOu7Ov+v4QZCWomrRUCJk2kUeCbfADgvxruUfj2GEm7zkfB563lP7sWheFMxvWgAYdaDrX2o qzZ5WjbxNMGC+J/1xlJlZyBDm+Y+BvBpylSPs/ThrzxGHBn8b/s7kg+pLh9ru7rs2I28dz2bjuQ crUYE8fqI8PAXjzYnB5sjjtkKE4/aPx/WODnbN5q6UhRR1IkxMLU6tjZM8OBD6LQ7jw+2ZRa8K/ MMMvgywt2DNZ8h2Tgb+QWXnsjNgjjeJ+7OESeDKU9uFbUkLi+jUSIQkf8uNSnQB7ingXWGTuLpY Y9Vg/WQMAqeoI23b2BPZHcw60BaexIGYB53B4 X-Received: by 2002:a05:6000:3104:b0:487:8ba:8b4c with SMTP id ffacd0b85a97d-4871fa26da2mr1355877f8f.1.1789718869071; Fri, 18 Sep 2026 01:07:49 -0700 (PDT) Received: from naush-dell.pitowers.org ([2a00:1098:3142:1f:45e3:df8b:2b18:6253]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-487203f077fsm1742230f8f.26.2026.09.18.01.07.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 18 Sep 2026 01:07:48 -0700 (PDT) From: Naushir Patuck To: libcamera-devel@lists.libcamera.org Cc: Naushir Patuck Subject: [RFC PATCH v1 11/20] libcamera: camera_manager: Marshal work onto the camera manager thread Date: Fri, 18 Sep 2026 08:59:49 +0100 Message-ID: <20260918080734.1228227-12-naush@raspberrypi.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260918080734.1228227-1-naush@raspberrypi.com> References: <20260918080734.1228227-1-naush@raspberrypi.com> MIME-Version: 1.0 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 upcoming enumerate() and initialize() interfaces are called from the application thread, but the device enumerator, pipeline handlers and media devices they operate on are all bound to the camera manager thread, so their work must be marshalled onto it. CameraManager::Private is a Thread and not an Object, so it cannot be the target of Object::invokeMethod(). Derive it from Object as well and move it to its own thread on construction. Changes in future commits can then start the thread and invoke work on it regardless of the order in which they are called. notify_all() replaces notify_one() as more than one caller can now be waiting in startThread() for the same initialisation. Signed-off-by: Naushir Patuck --- include/libcamera/internal/camera_manager.h | 6 ++- src/libcamera/camera_manager.cpp | 44 +++++++++++++++++++-- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/include/libcamera/internal/camera_manager.h b/include/libcamera/internal/camera_manager.h index e6df676bb655..ed90d1d471a0 100644 --- a/include/libcamera/internal/camera_manager.h +++ b/include/libcamera/internal/camera_manager.h @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -30,7 +31,7 @@ class MediaDevice; class PipelineHandler; class PipelineHandlerFactoryBase; -class CameraManager::Private : public Extensible::Private, public Thread +class CameraManager::Private : public Extensible::Private, public Thread, public Object { LIBCAMERA_DECLARE_PUBLIC(CameraManager) @@ -54,6 +55,7 @@ protected: private: int init(); std::vector pipelineFactories() const; + int startThread() LIBCAMERA_TSA_EXCLUDES(mutex_); void createPipelineHandlers(); void pipelineFactoryMatch(const PipelineHandlerFactoryBase *factory); std::shared_ptr findMatchingHandler(const MediaDevice *media); @@ -72,6 +74,8 @@ private: bool initialized_ LIBCAMERA_TSA_GUARDED_BY(mutex_); int status_ LIBCAMERA_TSA_GUARDED_BY(mutex_); + bool started_ LIBCAMERA_TSA_GUARDED_BY(mutex_) = false; + std::unique_ptr enumerator_; /* diff --git a/src/libcamera/camera_manager.cpp b/src/libcamera/camera_manager.cpp index 55cf650b8e66..55532179a61c 100644 --- a/src/libcamera/camera_manager.cpp +++ b/src/libcamera/camera_manager.cpp @@ -41,14 +41,45 @@ LOG_DEFINE_CATEGORY(Camera) CameraManager::Private::Private() : Thread("CameraManager"), initialized_(false) { + /* + * Bind this Object to its own thread, so that work can be marshalled + * onto the camera manager thread with invokeMethod(). + */ + moveToThread(this); } int CameraManager::Private::start() { - int status; + return startThread(); +} + +/* + * Start the camera manager thread if not started yet, and wait for its + * initialization to complete. Returns the initialization status. + */ +int CameraManager::Private::startThread() +{ + bool start = false; + + { + MutexLocker locker(mutex_); - /* Start the thread and wait for initialization to complete. */ - Thread::start(); + if (!started_) { + started_ = true; + initialized_ = false; + start = true; + } + } + + if (start) + Thread::start(); + + /* + * Wait for initialization to complete, whether this call started the + * thread or another one did, as the caller may otherwise proceed before + * the thread is ready. + */ + int status; { MutexLocker locker(mutex_); @@ -78,7 +109,7 @@ void CameraManager::Private::run() status_ = ret; initialized_ = true; mutex_.unlock(); - cv_.notify_one(); + cv_.notify_all(); if (ret < 0) { cleanup(); @@ -228,6 +259,11 @@ void CameraManager::Private::cleanup() { enumerator_->devicesAdded.disconnect(this); + { + MutexLocker locker(mutex_); + started_ = false; + } + /* * Release all references to cameras to ensure they all get destroyed * before the device enumerator deletes the media devices. Cameras are