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;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
// 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__)
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#if defined(__linux__)
|
||||
#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__)
|
||||
#include <pthread_np.h>
|
||||
#endif
|
||||
|
@ -96,6 +109,96 @@ u64 Threading::GetThreadCpuTime()
|
|||
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
|
||||
{
|
||||
// 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
|
||||
{
|
||||
class ThreadHandle;
|
||||
class pxThread;
|
||||
class RwMutex;
|
||||
|
||||
|
@ -198,6 +199,45 @@ namespace Threading
|
|||
};
|
||||
#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
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
|
|
@ -47,6 +47,84 @@ __fi void Threading::DisableHiresScheduler()
|
|||
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 ret = 0;
|
||||
|
|
Loading…
Reference in New Issue