mirror of https://github.com/PCSX2/pcsx2.git
Threading: Add ThreadHandle class
This commit is contained in:
parent
5eae7a6328
commit
6ebb8c2e91
|
@ -94,6 +94,52 @@ u64 Threading::GetThreadCpuTime()
|
||||||
return us;
|
return us;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Threading::ThreadHandle::ThreadHandle() = default;
|
||||||
|
|
||||||
|
Threading::ThreadHandle::ThreadHandle(const ThreadHandle& handle)
|
||||||
|
: m_native_handle(handle.m_native_handle)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Threading::ThreadHandle::ThreadHandle(ThreadHandle&& handle)
|
||||||
|
: m_native_handle(handle.m_native_handle)
|
||||||
|
{
|
||||||
|
handle.m_native_handle = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Threading::ThreadHandle::~ThreadHandle() = default;
|
||||||
|
|
||||||
|
Threading::ThreadHandle Threading::ThreadHandle::GetForCallingThread()
|
||||||
|
{
|
||||||
|
ThreadHandle ret;
|
||||||
|
ret.m_native_handle = pthread_self();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Threading::ThreadHandle& Threading::ThreadHandle::operator=(ThreadHandle&& handle)
|
||||||
|
{
|
||||||
|
m_native_handle = handle.m_native_handle;
|
||||||
|
handle.m_native_handle = nullptr;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Threading::ThreadHandle& Threading::ThreadHandle::operator=(const ThreadHandle& handle)
|
||||||
|
{
|
||||||
|
m_native_handle = handle.m_native_handle;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 Threading::ThreadHandle::GetCPUTime() const
|
||||||
|
{
|
||||||
|
return getthreadtime(pthread_mach_thread_np((pthread_t)m_native_handle));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Threading::ThreadHandle::SetAffinity(u64 processor_mask) const
|
||||||
|
{
|
||||||
|
// Doesn't appear to be possible to set affinity.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
u64 Threading::pxThread::GetCpuTime() const
|
u64 Threading::pxThread::GetCpuTime() const
|
||||||
{
|
{
|
||||||
// Get the cpu time for the thread belonging to this object. Use m_native_id and/or
|
// Get the cpu time for the thread belonging to this object. Use m_native_id and/or
|
||||||
|
|
|
@ -14,9 +14,22 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||||
|
#ifndef _GNU_SOURCE
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sched.h>
|
||||||
|
|
||||||
|
// glibc < v2.30 doesn't define gettid...
|
||||||
|
#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 30
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#define gettid() syscall(SYS_gettid)
|
||||||
|
#endif
|
||||||
|
|
||||||
#elif defined(__unix__)
|
#elif defined(__unix__)
|
||||||
#include <pthread_np.h>
|
#include <pthread_np.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -96,6 +109,96 @@ u64 Threading::GetThreadCpuTime()
|
||||||
return get_thread_time();
|
return get_thread_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Threading::ThreadHandle::ThreadHandle() = default;
|
||||||
|
|
||||||
|
Threading::ThreadHandle::ThreadHandle(const ThreadHandle& handle)
|
||||||
|
: m_native_handle(handle.m_native_handle)
|
||||||
|
#ifdef __linux__
|
||||||
|
, m_native_id(handle.m_native_id)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Threading::ThreadHandle::ThreadHandle(ThreadHandle&& handle)
|
||||||
|
: m_native_handle(handle.m_native_handle)
|
||||||
|
#ifdef __linux__
|
||||||
|
, m_native_id(handle.m_native_id)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
handle.m_native_handle = nullptr;
|
||||||
|
#ifdef __linux__
|
||||||
|
handle.m_native_id = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
Threading::ThreadHandle::~ThreadHandle() = default;
|
||||||
|
|
||||||
|
Threading::ThreadHandle Threading::ThreadHandle::GetForCallingThread()
|
||||||
|
{
|
||||||
|
ThreadHandle ret;
|
||||||
|
ret.m_native_handle = (void*)pthread_self();
|
||||||
|
#ifdef __linux__
|
||||||
|
ret.m_native_id = gettid();
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Threading::ThreadHandle& Threading::ThreadHandle::operator=(ThreadHandle&& handle)
|
||||||
|
{
|
||||||
|
m_native_handle = handle.m_native_handle;
|
||||||
|
handle.m_native_handle = nullptr;
|
||||||
|
#ifdef __linux__
|
||||||
|
m_native_id = handle.m_native_id;
|
||||||
|
handle.m_native_id = 0;
|
||||||
|
#endif
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Threading::ThreadHandle& Threading::ThreadHandle::operator=(const ThreadHandle& handle)
|
||||||
|
{
|
||||||
|
m_native_handle = handle.m_native_handle;
|
||||||
|
#ifdef __linux__
|
||||||
|
m_native_id = handle.m_native_id;
|
||||||
|
#endif
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 Threading::ThreadHandle::GetCPUTime() const
|
||||||
|
{
|
||||||
|
return m_native_handle ? get_thread_time((uptr)m_native_handle) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Threading::ThreadHandle::SetAffinity(u64 processor_mask) const
|
||||||
|
{
|
||||||
|
#if defined(__linux__)
|
||||||
|
cpu_set_t set;
|
||||||
|
CPU_ZERO(&set);
|
||||||
|
|
||||||
|
if (processor_mask != 0)
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < 64; i++)
|
||||||
|
{
|
||||||
|
if (processor_mask & (static_cast<u64>(1) << i))
|
||||||
|
{
|
||||||
|
CPU_SET(i, &set);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
long num_processors = sysconf(_SC_NPROCESSORS_CONF);
|
||||||
|
for (long i = 0; i < num_processors; i++)
|
||||||
|
{
|
||||||
|
CPU_SET(i, &set);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sched_setaffinity((pid_t)m_native_id, sizeof(set), &set) >= 0;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
u64 Threading::pxThread::GetCpuTime() const
|
u64 Threading::pxThread::GetCpuTime() const
|
||||||
{
|
{
|
||||||
// Get the cpu time for the thread belonging to this object. Use m_native_id and/or
|
// Get the cpu time for the thread belonging to this object. Use m_native_id and/or
|
||||||
|
|
|
@ -90,6 +90,7 @@ class wxTimeSpan;
|
||||||
|
|
||||||
namespace Threading
|
namespace Threading
|
||||||
{
|
{
|
||||||
|
class ThreadHandle;
|
||||||
class pxThread;
|
class pxThread;
|
||||||
class RwMutex;
|
class RwMutex;
|
||||||
|
|
||||||
|
@ -198,6 +199,45 @@ namespace Threading
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
// ThreadHandle
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
// Abstracts an OS's handle to a thread, closing the handle when necessary. Currently,
|
||||||
|
// only used for getting the CPU time for a thread.
|
||||||
|
//
|
||||||
|
class ThreadHandle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ThreadHandle();
|
||||||
|
ThreadHandle(ThreadHandle&& handle);
|
||||||
|
ThreadHandle(const ThreadHandle& handle);
|
||||||
|
~ThreadHandle();
|
||||||
|
|
||||||
|
/// Returns a new handle for the calling thread.
|
||||||
|
static ThreadHandle GetForCallingThread();
|
||||||
|
|
||||||
|
ThreadHandle& operator=(ThreadHandle&& handle);
|
||||||
|
ThreadHandle& operator=(const ThreadHandle& handle);
|
||||||
|
|
||||||
|
operator void*() const { return m_native_handle; }
|
||||||
|
operator bool() const { return (m_native_handle != nullptr); }
|
||||||
|
|
||||||
|
/// Returns the amount of CPU time consumed by the thread, at the GetThreadTicksPerSecond() frequency.
|
||||||
|
u64 GetCPUTime() const;
|
||||||
|
|
||||||
|
/// Sets the affinity for a thread to the specified processors.
|
||||||
|
/// Obviously, only works up to 64 processors.
|
||||||
|
bool SetAffinity(u64 processor_mask) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void* m_native_handle = nullptr;
|
||||||
|
|
||||||
|
// We need the thread ID for affinity adjustments on Linux.
|
||||||
|
#if defined(__linux__)
|
||||||
|
unsigned int m_native_id = 0;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// NonblockingMutex
|
// NonblockingMutex
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -47,6 +47,84 @@ __fi void Threading::DisableHiresScheduler()
|
||||||
timeEndPeriod(1);
|
timeEndPeriod(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Threading::ThreadHandle::ThreadHandle() = default;
|
||||||
|
|
||||||
|
Threading::ThreadHandle::ThreadHandle(const ThreadHandle& handle)
|
||||||
|
{
|
||||||
|
if (handle.m_native_handle)
|
||||||
|
{
|
||||||
|
HANDLE new_handle;
|
||||||
|
if (DuplicateHandle(GetCurrentProcess(), (HANDLE)handle.m_native_handle,
|
||||||
|
GetCurrentProcess(), &new_handle, THREAD_QUERY_INFORMATION | THREAD_SET_LIMITED_INFORMATION, FALSE, 0))
|
||||||
|
{
|
||||||
|
m_native_handle = (void*)new_handle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Threading::ThreadHandle::ThreadHandle(ThreadHandle&& handle)
|
||||||
|
: m_native_handle(handle.m_native_handle)
|
||||||
|
{
|
||||||
|
handle.m_native_handle = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Threading::ThreadHandle::~ThreadHandle()
|
||||||
|
{
|
||||||
|
if (m_native_handle)
|
||||||
|
CloseHandle(m_native_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
Threading::ThreadHandle Threading::ThreadHandle::GetForCallingThread()
|
||||||
|
{
|
||||||
|
ThreadHandle ret;
|
||||||
|
ret.m_native_handle = (void*)OpenThread(THREAD_QUERY_INFORMATION | THREAD_SET_LIMITED_INFORMATION, FALSE, GetCurrentThreadId());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Threading::ThreadHandle& Threading::ThreadHandle::operator=(ThreadHandle&& handle)
|
||||||
|
{
|
||||||
|
if (m_native_handle)
|
||||||
|
CloseHandle((HANDLE)m_native_handle);
|
||||||
|
m_native_handle = handle.m_native_handle;
|
||||||
|
handle.m_native_handle = nullptr;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Threading::ThreadHandle& Threading::ThreadHandle::operator=(const ThreadHandle& handle)
|
||||||
|
{
|
||||||
|
if (m_native_handle)
|
||||||
|
{
|
||||||
|
CloseHandle((HANDLE)m_native_handle);
|
||||||
|
m_native_handle = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE new_handle;
|
||||||
|
if (DuplicateHandle(GetCurrentProcess(), (HANDLE)handle.m_native_handle,
|
||||||
|
GetCurrentProcess(), &new_handle, THREAD_QUERY_INFORMATION | THREAD_SET_LIMITED_INFORMATION, FALSE, 0))
|
||||||
|
{
|
||||||
|
m_native_handle = (void*)new_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 Threading::ThreadHandle::GetCPUTime() const
|
||||||
|
{
|
||||||
|
u64 ret = 0;
|
||||||
|
if (m_native_handle)
|
||||||
|
QueryThreadCycleTime((HANDLE)m_native_handle, &ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Threading::ThreadHandle::SetAffinity(u64 processor_mask) const
|
||||||
|
{
|
||||||
|
if (processor_mask == 0)
|
||||||
|
processor_mask = ~processor_mask;
|
||||||
|
|
||||||
|
return (SetThreadAffinityMask(GetCurrentThread(), (DWORD_PTR)processor_mask) != 0 || GetLastError() != ERROR_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
u64 Threading::GetThreadCpuTime()
|
u64 Threading::GetThreadCpuTime()
|
||||||
{
|
{
|
||||||
u64 ret = 0;
|
u64 ret = 0;
|
||||||
|
|
Loading…
Reference in New Issue