diff --git a/include/libcamera/base/thread.h b/include/libcamera/base/thread.h
index dc1aca275e23..6aa36fa1bfb0 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 = {});
 	virtual ~Thread();
 
 	void start();
@@ -74,6 +75,7 @@ private:
 	void moveObject(Object *object, ThreadData *currentData,
 			ThreadData *targetData);
 
+	std::string name_;
 	std::thread thread_;
 	std::unique_ptr<ThreadData> data_;
 };
diff --git a/src/libcamera/base/thread.cpp b/src/libcamera/base/thread.cpp
index 338cbcc260c8..39209ec8ad0d 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>
@@ -144,6 +145,7 @@ class ThreadMain : public Thread
 {
 public:
 	ThreadMain()
+		: Thread("libcamera-main")
 	{
 		data_->running_ = true;
 	}
@@ -234,8 +236,9 @@ ThreadData *ThreadData::current()
 /**
  * \brief Create a thread
  */
-Thread::Thread()
-	: data_(std::make_unique<ThreadData>(this))
+Thread::Thread(std::string name)
+	: name_(std::move(name)),
+	  data_(std::make_unique<ThreadData>(this))
 {
 }
 
@@ -288,6 +291,10 @@ void Thread::startThread()
 	data_->tid_ = syscall(SYS_gettid);
 	currentThreadData = data_.get();
 
+	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 c203b08f7de3..83510e062fae 100644
--- a/src/libcamera/camera_manager.cpp
+++ b/src/libcamera/camera_manager.cpp
@@ -39,7 +39,7 @@ LOG_DEFINE_CATEGORY(Camera)
 
 #ifndef __DOXYGEN_PUBLIC__
 CameraManager::Private::Private()
-	: initialized_(false)
+	: Thread("CameraManager"), initialized_(false)
 {
 	ipaManager_ = std::make_unique<IPAManager>(this->configuration());
 }
diff --git a/src/libcamera/pipeline/virtual/virtual.cpp b/src/libcamera/pipeline/virtual/virtual.cpp
index 23eae852f79b..09e0afc956fd 100644
--- a/src/libcamera/pipeline/virtual/virtual.cpp
+++ b/src/libcamera/pipeline/virtual/virtual.cpp
@@ -115,7 +115,7 @@ private:
 
 VirtualCameraData::VirtualCameraData(PipelineHandler *pipe,
 				     const std::vector<Resolution> &supportedResolutions)
-	: Camera::Private(pipe)
+	: Camera::Private(pipe), Thread("VirtualCamera")
 {
 	config_.resolutions = supportedResolutions;
 	for (const auto &resolution : config_.resolutions) {
diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp
index fdadf79e1966..341c0352cf0c 100644
--- a/src/libcamera/software_isp/software_isp.cpp
+++ b/src/libcamera/software_isp/software_isp.cpp
@@ -75,7 +75,8 @@ LOG_DEFINE_CATEGORY(SoftwareIsp)
  */
 SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor,
 			 ControlInfoMap *ipaControls)
-	: dmaHeap_(DmaBufAllocator::DmaBufAllocatorFlag::CmaHeap |
+	: ispWorkerThread_("SWIspWorker"),
+	  dmaHeap_(DmaBufAllocator::DmaBufAllocatorFlag::CmaHeap |
 		   DmaBufAllocator::DmaBufAllocatorFlag::SystemHeap |
 		   DmaBufAllocator::DmaBufAllocatorFlag::UDmaBuf)
 {
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 0d03c1df0dd9..e6e19b3030b9 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}}Threaded::{{proxy_name}}Threaded(IPAModule *ipam, const GlobalConfiguration &configuration)
-	: {{proxy_name}}(ipam, configuration)
+	: {{proxy_name}}(ipam, configuration), thread_("{{proxy_name}}")
 {
 	LOG(IPAProxy, Debug)
 		<< "initializing {{module_name}} proxy in thread: loading IPA from "
