diff --git a/include/libcamera/base/thread.h b/include/libcamera/base/thread.h
index b9284c2c0556..56055261e920 100644
--- a/include/libcamera/base/thread.h
+++ b/include/libcamera/base/thread.h
@@ -8,6 +8,7 @@
 #pragma once
 
 #include <memory>
+#include <string>
 #include <sys/types.h>
 #include <thread>
 
@@ -30,7 +31,7 @@ class ThreadMain;
 class Thread
 {
 public:
-	Thread();
+	Thread(std::string name = std::string());
 	virtual ~Thread();
 
 	void start();
@@ -74,6 +75,7 @@ private:
 	void moveObject(Object *object, ThreadData *currentData,
 			ThreadData *targetData);
 
+	std::string name_;
 	std::thread thread_;
 	ThreadData *data_;
 };
diff --git a/src/libcamera/base/thread.cpp b/src/libcamera/base/thread.cpp
index d8fe0d6971ec..d016f352a783 100644
--- a/src/libcamera/base/thread.cpp
+++ b/src/libcamera/base/thread.cpp
@@ -10,6 +10,7 @@
 #include <atomic>
 #include <list>
 #include <optional>
+#include <pthread.h>
 #include <sys/syscall.h>
 #include <sys/types.h>
 #include <unistd.h>
@@ -140,6 +141,7 @@ class ThreadMain : public Thread
 {
 public:
 	ThreadMain()
+		: Thread("libcamera-main")
 	{
 		data_->running_ = true;
 	}
@@ -230,7 +232,8 @@ ThreadData *ThreadData::current()
 /**
  * \brief Create a thread
  */
-Thread::Thread()
+Thread::Thread(std::string name)
+	: name_(std::move(name))
 {
 	data_ = new ThreadData;
 	data_->thread_ = this;
@@ -286,6 +289,9 @@ void Thread::startThread()
 	data_->tid_ = syscall(SYS_gettid);
 	currentThreadData = data_;
 
+	if (!name_.empty())
+		pthread_setname_np(thread_.native_handle(), name_.substr(0, 15).c_str());
+
 	run();
 }
 
diff --git a/src/libcamera/camera_manager.cpp b/src/libcamera/camera_manager.cpp
index f81794bfd6fe..a42835c18739 100644
--- a/src/libcamera/camera_manager.cpp
+++ b/src/libcamera/camera_manager.cpp
@@ -38,7 +38,7 @@ LOG_DEFINE_CATEGORY(Camera)
 
 #ifndef __DOXYGEN_PUBLIC__
 CameraManager::Private::Private()
-	: initialized_(false)
+	: Thread("CameraManager"), initialized_(false)
 {
 	ipaManager_ = std::make_unique<IPAManager>();
 }
diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp
index 28e2a360e7e6..b2f6cf61b646 100644
--- a/src/libcamera/software_isp/software_isp.cpp
+++ b/src/libcamera/software_isp/software_isp.cpp
@@ -75,9 +75,9 @@ LOG_DEFINE_CATEGORY(SoftwareIsp)
  */
 SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor,
 			 ControlInfoMap *ipaControls)
-	: dmaHeap_(DmaBufAllocator::DmaBufAllocatorFlag::CmaHeap |
-		   DmaBufAllocator::DmaBufAllocatorFlag::SystemHeap |
-		   DmaBufAllocator::DmaBufAllocatorFlag::UDmaBuf)
+	: ispWorkerThread_("SWIspWorker"), dmaHeap_(DmaBufAllocator::DmaBufAllocatorFlag::CmaHeap |
+						    DmaBufAllocator::DmaBufAllocatorFlag::SystemHeap |
+						    DmaBufAllocator::DmaBufAllocatorFlag::UDmaBuf)
 {
 	/*
 	 * debayerParams_ must be initialized because the initial value is used for
diff --git a/utils/codegen/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl b/utils/codegen/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl
index beb646e2d157..7d2d510f5a79 100644
--- a/utils/codegen/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl
+++ b/utils/codegen/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl
@@ -46,7 +46,7 @@ namespace {{ns}} {
 {%- endif %}
 
 {{proxy_name}}::{{proxy_name}}(IPAModule *ipam, bool isolate)
-	: IPAProxy(ipam), isolate_(isolate),
+	: IPAProxy(ipam), thread_("{{proxy_name}}"), isolate_(isolate),
 	  controlSerializer_(ControlSerializer::Role::Proxy), seq_(0)
 {
 	LOG(IPAProxy, Debug)
