Simplify communication with thread pool

Add "entry_point" member to "thread_base".
Don't use "m_thread" to exchange values.
This commit is contained in:
Nekotekina 2020-11-23 11:32:34 +03:00
parent a4458e2c8c
commit d4c17ecda5
2 changed files with 28 additions and 30 deletions

View file

@ -1849,7 +1849,7 @@ static atomic_t<u128, 64> s_thread_bits{0};
static atomic_t<thread_base**> s_thread_pool[128]{}; static atomic_t<thread_base**> s_thread_pool[128]{};
void thread_base::start(native_entry entry) void thread_base::start()
{ {
for (u128 bits = s_thread_bits.load(); bits; bits &= bits - 1) for (u128 bits = s_thread_bits.load(); bits; bits &= bits - 1)
{ {
@ -1867,22 +1867,20 @@ void thread_base::start(native_entry entry)
continue; continue;
} }
// Send "this" and entry point // Receive "that" native thread handle, sent "this" thread_base
const u64 entry_val = reinterpret_cast<u64>(entry); const u64 _self = reinterpret_cast<u64>(atomic_storage<thread_base*>::load(*tls));
m_thread = entry_val; m_thread.release(_self);
atomic_storage<thread_base*>::release(*tls, this); verify(HERE), _self != reinterpret_cast<u64>(this);
atomic_storage<thread_base*>::store(*tls, this);
s_thread_pool[pos].notify_all(); s_thread_pool[pos].notify_all();
// Wait for actual "m_thread" in return
m_thread.wait(entry_val);
return; return;
} }
#ifdef _WIN32 #ifdef _WIN32
m_thread = ::_beginthreadex(nullptr, 0, entry, this, CREATE_SUSPENDED, nullptr); m_thread = ::_beginthreadex(nullptr, 0, entry_point, this, CREATE_SUSPENDED, nullptr);
verify("thread_ctrl::start" HERE), m_thread, ::ResumeThread(reinterpret_cast<HANDLE>(+m_thread)) != -1; verify("thread_ctrl::start" HERE), m_thread, ::ResumeThread(reinterpret_cast<HANDLE>(+m_thread)) != -1;
#else #else
verify("thread_ctrl::start" HERE), pthread_create(reinterpret_cast<pthread_t*>(&m_thread.raw()), nullptr, entry, this) == 0; verify("thread_ctrl::start" HERE), pthread_create(reinterpret_cast<pthread_t*>(&m_thread.raw()), nullptr, entry_point, this) == 0;
#endif #endif
} }
@ -2026,7 +2024,7 @@ u64 thread_base::finalize(thread_state result_state) noexcept
return m_thread; return m_thread;
} }
u64 thread_base::finalize(u64 _self) noexcept thread_base::native_entry thread_base::finalize(u64 _self) noexcept
{ {
g_tls_fault_all = 0; g_tls_fault_all = 0;
g_tls_fault_rsx = 0; g_tls_fault_rsx = 0;
@ -2043,7 +2041,7 @@ u64 thread_base::finalize(u64 _self) noexcept
if (!_self) if (!_self)
{ {
return 0; return nullptr;
} }
// Try to add self to thread pool // Try to add self to thread pool
@ -2138,17 +2136,14 @@ u64 thread_base::finalize(u64 _self) noexcept
if (--s_pool_ctr & s_stop_bit) if (--s_pool_ctr & s_stop_bit)
{ {
return 0; return nullptr;
} }
// Restore thread id // Restore thread base
const auto _this = atomic_storage<thread_base*>::load(*tls); const auto _this = atomic_storage<thread_base*>::load(*tls);
const auto entry = _this->m_thread.exchange(_self);
verify(HERE), entry != _self;
_this->m_thread.notify_one();
// Return new entry // Return new entry
return entry; return _this->entry_point;
} }
thread_base::native_entry thread_base::make_trampoline(u64(*entry)(thread_base* _base)) thread_base::native_entry thread_base::make_trampoline(u64(*entry)(thread_base* _base))
@ -2166,7 +2161,7 @@ thread_base::native_entry thread_base::make_trampoline(u64(*entry)(thread_base*
// Call finalize, return if zero // Call finalize, return if zero
c.mov(args[0], x86::rax); c.mov(args[0], x86::rax);
c.call(imm_ptr<u64(*)(u64)>(finalize)); c.call(imm_ptr<native_entry(*)(u64)>(finalize));
c.test(x86::rax, x86::rax); c.test(x86::rax, x86::rax);
c.jz(_ret); c.jz(_ret);
@ -2260,8 +2255,9 @@ std::string thread_ctrl::get_name_cached()
return *name_cache; return *name_cache;
} }
thread_base::thread_base(std::string_view name) thread_base::thread_base(native_entry entry, std::string_view name)
: m_tname(stx::shared_cptr<std::string>::make(name)) : entry_point(entry)
, m_tname(stx::shared_cptr<std::string>::make(name))
{ {
} }

View file

@ -100,6 +100,8 @@ public:
using native_entry = void*(*)(void* arg); using native_entry = void*(*)(void* arg);
#endif #endif
const native_entry entry_point;
private: private:
// Thread handle (platform-specific) // Thread handle (platform-specific)
atomic_t<u64> m_thread{0}; atomic_t<u64> m_thread{0};
@ -111,7 +113,7 @@ private:
stx::atomic_cptr<std::string> m_tname; stx::atomic_cptr<std::string> m_tname;
// Start thread // Start thread
void start(native_entry); void start();
// Called at the thread start // Called at the thread start
void initialize(void (*error_cb)()); void initialize(void (*error_cb)());
@ -120,7 +122,7 @@ private:
u64 finalize(thread_state result) noexcept; u64 finalize(thread_state result) noexcept;
// Cleanup after possibly deleting the thread instance // Cleanup after possibly deleting the thread instance
static u64 finalize(u64 _self) noexcept; static native_entry finalize(u64 _self) noexcept;
// Set name for debugger // Set name for debugger
static void set_name(std::string); static void set_name(std::string);
@ -134,7 +136,7 @@ private:
friend class named_thread; friend class named_thread;
protected: protected:
thread_base(std::string_view name); thread_base(native_entry, std::string_view name);
~thread_base(); ~thread_base();
@ -316,26 +318,26 @@ public:
template <bool Valid = std::is_default_constructible_v<Context> && thread_thread_name<Context>(), typename = std::enable_if_t<Valid>> template <bool Valid = std::is_default_constructible_v<Context> && thread_thread_name<Context>(), typename = std::enable_if_t<Valid>>
named_thread() named_thread()
: Context() : Context()
, thread(Context::thread_name) , thread(trampoline, Context::thread_name)
{ {
thread::start(trampoline); thread::start();
} }
// Normal forwarding constructor // Normal forwarding constructor
template <typename... Args, typename = std::enable_if_t<std::is_constructible_v<Context, Args&&...>>> template <typename... Args, typename = std::enable_if_t<std::is_constructible_v<Context, Args&&...>>>
named_thread(std::string_view name, Args&&... args) named_thread(std::string_view name, Args&&... args)
: Context(std::forward<Args>(args)...) : Context(std::forward<Args>(args)...)
, thread(name) , thread(trampoline, name)
{ {
thread::start(trampoline); thread::start();
} }
// Lambda constructor, also the implicit deduction guide candidate // Lambda constructor, also the implicit deduction guide candidate
named_thread(std::string_view name, Context&& f) named_thread(std::string_view name, Context&& f)
: Context(std::forward<Context>(f)) : Context(std::forward<Context>(f))
, thread(name) , thread(trampoline, name)
{ {
thread::start(trampoline); thread::start();
} }
named_thread(const named_thread&) = delete; named_thread(const named_thread&) = delete;