mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-12 17:27:52 -06:00
Support for naming slicer own threads for debugging.
The following threads are named with this commit: slic3r_main, slic3r_BackgroundSlicingProcess, slic3r_tbbpool_xx_yy where xx is a one based index of the TTB thread and yy is the platform thread ID.
This commit is contained in:
parent
8d59abfdf8
commit
6531061d09
12 changed files with 219 additions and 38 deletions
158
src/libslic3r/Thread.cpp
Normal file
158
src/libslic3r/Thread.cpp
Normal file
|
@ -0,0 +1,158 @@
|
|||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <processthreadsapi.h>
|
||||
#include <boost/nowide/convert.hpp>
|
||||
#else
|
||||
// any posix system
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <tbb/parallel_for.h>
|
||||
#include <tbb/tbb_thread.h>
|
||||
|
||||
#define SLIC3R_THREAD_NAME_WIN32_MODERN
|
||||
|
||||
#include "Thread.hpp"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
#ifdef SLIC3R_THREAD_NAME_WIN32_MODERN
|
||||
|
||||
static void WindowsSetThreadName(HANDLE hThread, const char *thread_name)
|
||||
{
|
||||
size_t len = strlen(thread_name);
|
||||
if (len < 1024) {
|
||||
// Allocate the temp string on stack.
|
||||
wchar_t buf[1024];
|
||||
::SetThreadDescription(hThread, boost::nowide::widen(buf, 1024, thread_name));
|
||||
} else {
|
||||
// Allocate dynamically.
|
||||
::SetThreadDescription(hThread, boost::nowide::widen(thread_name).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
#else // SLIC3R_THREAD_NAME_WIN32_MODERN
|
||||
// use the old way by throwing an exception
|
||||
|
||||
const DWORD MS_VC_EXCEPTION=0x406D1388;
|
||||
|
||||
#pragma pack(push,8)
|
||||
typedef struct tagTHREADNAME_INFO
|
||||
{
|
||||
DWORD dwType; // Must be 0x1000.
|
||||
LPCSTR szName; // Pointer to name (in user addr space).
|
||||
DWORD dwThreadID; // Thread ID (-1=caller thread).
|
||||
DWORD dwFlags; // Reserved for future use, must be zero.
|
||||
} THREADNAME_INFO;
|
||||
#pragma pack(pop)
|
||||
static void WindowsSetThreadName(HANDLE hThread, const char *thread_name)
|
||||
{
|
||||
THREADNAME_INFO info;
|
||||
info.dwType = 0x1000;
|
||||
info.szName = threadName;
|
||||
info.dwThreadID = ::GetThreadId(hThread);
|
||||
info.dwFlags = 0;
|
||||
|
||||
__try
|
||||
{
|
||||
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info);
|
||||
}
|
||||
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SLIC3R_THREAD_NAME_WIN32_MODERN
|
||||
|
||||
// posix
|
||||
void set_thread_name(std::thread &thread, const char *thread_name)
|
||||
{
|
||||
WindowsSetThreadName(static_cast<HANDLE>(thread.native_handle()), thread_name);
|
||||
}
|
||||
|
||||
void set_thread_name(boost::thread &thread, const char *thread_name)
|
||||
{
|
||||
WindowsSetThreadName(static_cast<HANDLE>(thread.native_handle()), thread_name);
|
||||
}
|
||||
|
||||
void set_current_thread_name(const char *thread_name)
|
||||
{
|
||||
WindowsSetThreadName(::GetCurrentThread(), thread_name);
|
||||
}
|
||||
|
||||
#else // _WIN32
|
||||
|
||||
// posix
|
||||
void set_thread_name(std::thread &thread, const char *thread_name)
|
||||
{
|
||||
pthread_setname_np(thread->native_handle(), thread_name);
|
||||
}
|
||||
|
||||
void set_thread_name(boost::thread &thread, const char *thread_name)
|
||||
{
|
||||
pthread_setname_np(thread->native_handle(), thread_name);
|
||||
}
|
||||
|
||||
void set_current_thread_name(const char *thread_name)
|
||||
{
|
||||
set_thread_name(pthread_self(), thread_name);
|
||||
}
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
// Spawn (n - 1) worker threads on Intel TBB thread pool and name them by an index and a system thread ID.
|
||||
void name_tbb_thread_pool_threads()
|
||||
{
|
||||
static bool initialized = false;
|
||||
if (initialized)
|
||||
return;
|
||||
initialized = true;
|
||||
|
||||
const size_t nthreads_hw = std::thread::hardware_concurrency();
|
||||
size_t nthreads = nthreads_hw;
|
||||
|
||||
#ifdef SLIC3R_PROFILE
|
||||
// Shiny profiler is not thread safe, thus disable parallelization.
|
||||
nthreads = 1;
|
||||
#endif
|
||||
|
||||
if (nthreads != nthreads_hw) {
|
||||
static tbb::task_scheduler_init *tbb_init = nullptr;
|
||||
tbb_init = new tbb::task_scheduler_init(nthreads);
|
||||
}
|
||||
|
||||
std::atomic<size_t> nthreads_running(0);
|
||||
std::condition_variable cv;
|
||||
std::mutex cv_m;
|
||||
auto master_thread_id = tbb::this_tbb_thread::get_id();
|
||||
tbb::parallel_for(
|
||||
tbb::blocked_range<size_t>(0, nthreads, 1),
|
||||
[&nthreads_running, nthreads, &master_thread_id, &cv, &cv_m](const tbb::blocked_range<size_t> &range) {
|
||||
assert(range.begin() + 1 == range.end());
|
||||
if (nthreads_running.fetch_add(1) + 1 == nthreads) {
|
||||
// All threads are spinning.
|
||||
// Wake them up.
|
||||
cv.notify_all();
|
||||
} else {
|
||||
// Wait for the last thread to wake the others.
|
||||
std::unique_lock<std::mutex> lk(cv_m);
|
||||
cv.wait(lk, [&nthreads_running, nthreads]{return nthreads_running == nthreads;});
|
||||
}
|
||||
auto thread_id = tbb::this_tbb_thread::get_id();
|
||||
if (thread_id == master_thread_id) {
|
||||
// The calling thread runs the 0'th task.
|
||||
assert(range.begin() == 0);
|
||||
} else {
|
||||
assert(range.begin() > 0);
|
||||
std::ostringstream name;
|
||||
name << "slic3r_tbbpool_" << range.begin() << "_" << thread_id;
|
||||
set_current_thread_name(name.str());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue