thread_t cleanup

This commit is contained in:
Nekotekina 2015-08-11 16:26:08 +03:00
parent be9a599beb
commit d9403c2ed2
7 changed files with 40 additions and 94 deletions

View file

@ -1199,36 +1199,6 @@ std::string thread_ctrl_t::get_name() const
return name(); return name();
} }
void thread_ctrl_t::set_current()
{
const auto old_value = g_tls_this_thread;
if (old_value == this)
{
return;
}
if (old_value)
{
vm::reservation_free();
}
if (true && assigned.exchange(true))
{
LOG_ERROR(GENERAL, "Thread '%s' was already assigned to g_tls_this_thread of another thread", get_name());
g_tls_this_thread = nullptr;
}
else
{
g_tls_this_thread = this;
}
if (old_value)
{
old_value->assigned = false;
}
}
thread_t::thread_t(std::function<std::string()> name, std::function<void()> func) thread_t::thread_t(std::function<std::string()> name, std::function<void()> func)
{ {
start(std::move(name), func); start(std::move(name), func);
@ -1272,12 +1242,12 @@ void thread_t::start(std::function<std::string()> name, std::function<void()> fu
// start thread // start thread
m_thread->m_thread = std::thread([](std::shared_ptr<thread_ctrl_t> ctrl, std::function<void()> func) m_thread->m_thread = std::thread([](std::shared_ptr<thread_ctrl_t> ctrl, std::function<void()> func)
{ {
g_thread_count++; g_tls_this_thread = ctrl.get();
SetCurrentThreadDebugName(ctrl->get_name().c_str()); SetCurrentThreadDebugName(ctrl->get_name().c_str());
#if defined(_MSC_VER) #if defined(_MSC_VER)
auto old_se_translator = _set_se_translator(_se_translator); _set_se_translator(_se_translator);
#endif #endif
#ifdef _WIN32 #ifdef _WIN32
@ -1294,16 +1264,9 @@ void thread_t::start(std::function<std::string()> name, std::function<void()> fu
} }
#endif #endif
// error handler
const auto error = [&](const char* text)
{
log_message(GENERAL, Emu.IsStopped() ? Log::Severity::Warning : Log::Severity::Error, "Exception: %s", text);
Emu.Pause();
};
try try
{ {
ctrl->set_current(); g_thread_count++;
if (Ini.HLELogging.GetValue()) if (Ini.HLELogging.GetValue())
{ {
@ -1311,36 +1274,31 @@ void thread_t::start(std::function<std::string()> name, std::function<void()> fu
} }
func(); func();
}
catch (const char* e) // obsolete
{
LOG_ERROR(GENERAL, "Deprecated exception type (const char*)");
error(e);
}
catch (const std::string& e) // obsolete
{
LOG_ERROR(GENERAL, "Deprecated exception type (std::string)");
error(e.c_str());
}
catch (const fmt::exception& e)
{
error(e);
}
if (Ini.HLELogging.GetValue()) if (Ini.HLELogging.GetValue())
{ {
LOG_NOTICE(GENERAL, "Thread ended"); LOG_NOTICE(GENERAL, "Thread ended");
} }
}
//ctrl->set_current(false); catch (const fmt::exception& e)
{
LOG_ERROR(GENERAL, "Exception: %s", e.message.get());
Emu.Pause();
}
catch (const std::exception& e)
{
LOG_ERROR(GENERAL, "STD Exception: %s", e.what());
Emu.Pause();
}
catch (EmulationStopped)
{
LOG_NOTICE(GENERAL, "Thread aborted");
}
vm::reservation_free(); vm::reservation_free();
g_thread_count--; g_thread_count--;
#if defined(_MSC_VER)
_set_se_translator(old_se_translator);
#endif
}, m_thread, std::move(func)); }, m_thread, std::move(func));
} }

View file

@ -13,12 +13,6 @@ class thread_ctrl_t final
// name getter // name getter
const std::function<std::string()> name; const std::function<std::string()> name;
// true if assigned somewhere in TLS
std::atomic<bool> assigned{ false };
// assign TLS (must be assigned only once)
void set_current();
public: public:
thread_ctrl_t(std::function<std::string()> name) thread_ctrl_t(std::function<std::string()> name)
: name(std::move(name)) : name(std::move(name))

View file

@ -48,7 +48,7 @@ CPUThread::CPUThread(CPUThreadType type, const std::string& name, std::function<
m_state |= CPU_STATE_DEAD; m_state |= CPU_STATE_DEAD;
break; break;
} }
catch (const fmt::exception&) catch (...)
{ {
dump_info(); dump_info();
throw; throw;

View file

@ -2,11 +2,6 @@
#include "Utilities/Thread.h" #include "Utilities/Thread.h"
namespace vm
{
class waiter_lock_t;
}
enum CPUThreadType enum CPUThreadType
{ {
CPU_THREAD_PPU, CPU_THREAD_PPU,
@ -41,9 +36,15 @@ class CPUThreadExit{};
class CPUDecoder; class CPUDecoder;
class CPUThread : protected thread_t, public std::enable_shared_from_this<CPUThread> class CPUThread : public thread_t, public std::enable_shared_from_this<CPUThread>
{ {
using thread_t::start;
protected: protected:
using thread_t::detach;
using thread_t::join;
using thread_t::joinable;
atomic_t<u64> m_state; // thread state flags atomic_t<u64> m_state; // thread state flags
std::unique_ptr<CPUDecoder> m_dec; std::unique_ptr<CPUDecoder> m_dec;
@ -52,15 +53,6 @@ protected:
const CPUThreadType m_type; const CPUThreadType m_type;
const std::string m_name; // changing m_name would be terribly thread-unsafe in current implementation const std::string m_name; // changing m_name would be terribly thread-unsafe in current implementation
public:
using thread_t::mutex;
using thread_t::cv;
using thread_t::is_current;
using thread_t::get_thread_ctrl;
friend vm::waiter_lock_t;
protected:
CPUThread(CPUThreadType type, const std::string& name, std::function<std::string()> thread_name); CPUThread(CPUThreadType type, const std::string& name, std::function<std::string()> thread_name);
public: public:

View file

@ -248,6 +248,12 @@ namespace vm
return true; return true;
} }
waiter_lock_t::waiter_lock_t(thread_t& thread, u32 addr, u32 size)
: m_waiter(_add_waiter(thread, addr, size))
, m_lock(thread.mutex, std::adopt_lock) // must be locked in _add_waiter
{
}
void waiter_lock_t::wait() void waiter_lock_t::wait()
{ {
// if another thread successfully called pred(), it must be set to null // if another thread successfully called pred(), it must be set to null

View file

@ -62,9 +62,6 @@ namespace vm
bool try_notify(); bool try_notify();
}; };
// for internal use
waiter_t* _add_waiter(thread_t& thread, u32 addr, u32 size);
class waiter_lock_t class waiter_lock_t
{ {
waiter_t* m_waiter; waiter_t* m_waiter;
@ -73,11 +70,7 @@ namespace vm
public: public:
waiter_lock_t() = delete; waiter_lock_t() = delete;
template<typename T> inline waiter_lock_t(T& thread, u32 addr, u32 size) waiter_lock_t(thread_t& thread, u32 addr, u32 size);
: m_waiter(_add_waiter(static_cast<thread_t&>(thread), addr, size))
, m_lock(thread.mutex, std::adopt_lock) // must be locked in _add_waiter
{
}
waiter_t* operator ->() const waiter_t* operator ->() const
{ {
@ -90,7 +83,7 @@ namespace vm
}; };
// wait until pred() returns true, addr must be aligned to size which must be a power of 2, pred() may be called by any thread // wait until pred() returns true, addr must be aligned to size which must be a power of 2, pred() may be called by any thread
template<typename T, typename F, typename... Args> auto wait_op(T& thread, u32 addr, u32 size, F pred, Args&&... args) -> decltype(static_cast<void>(pred(args...))) template<typename F, typename... Args> auto wait_op(thread_t& thread, u32 addr, u32 size, F pred, Args&&... args) -> decltype(static_cast<void>(pred(args...)))
{ {
// return immediately if condition passed (optimistic case) // return immediately if condition passed (optimistic case)
if (pred(args...)) return; if (pred(args...)) return;

View file

@ -10,6 +10,9 @@ enum Status : u32
Ready, Ready,
}; };
// Emulation Stopped exception event
class EmulationStopped {};
class CPUThreadManager; class CPUThreadManager;
class PadManager; class PadManager;
class KeyboardManager; class KeyboardManager;
@ -209,7 +212,7 @@ inline bool check_lv2_lock(lv2_lock_t& lv2_lock)
#define LV2_LOCK lv2_lock_t lv2_lock(Emu.GetCoreMutex()) #define LV2_LOCK lv2_lock_t lv2_lock(Emu.GetCoreMutex())
#define LV2_DEFER_LOCK lv2_lock_t lv2_lock #define LV2_DEFER_LOCK lv2_lock_t lv2_lock
#define CHECK_LV2_LOCK(x) if (!check_lv2_lock(x)) throw EXCEPTION("lv2_lock is invalid or not locked") #define CHECK_LV2_LOCK(x) if (!check_lv2_lock(x)) throw EXCEPTION("lv2_lock is invalid or not locked")
#define CHECK_EMU_STATUS if (Emu.IsStopped()) throw EXCEPTION("Aborted (emulation stopped)") #define CHECK_EMU_STATUS if (Emu.IsStopped()) throw EmulationStopped{}
typedef void(*CallAfterCbType)(std::function<void()> func); typedef void(*CallAfterCbType)(std::function<void()> func);