2016-04-17 19:34:47 +00:00
|
|
|
#include "Thread.h"
|
2021-04-12 09:41:28 +00:00
|
|
|
#include "Trace.h"
|
|
|
|
#include "TraceModulesCommon.h"
|
2018-11-18 00:42:49 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
#include <Windows.h>
|
|
|
|
#else
|
2016-04-17 19:34:47 +00:00
|
|
|
#include <pthread.h>
|
2016-04-28 22:27:35 +00:00
|
|
|
#include <sys/syscall.h>
|
2022-10-03 08:04:42 +00:00
|
|
|
#include <unistd.h>
|
2016-04-17 19:34:47 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
CThread::CThread(CTHREAD_START_ROUTINE lpStartAddress) :
|
|
|
|
m_StartAddress(lpStartAddress),
|
2021-04-12 11:35:39 +00:00
|
|
|
m_lpThreadParameter(nullptr),
|
|
|
|
m_thread(nullptr),
|
2016-04-28 07:34:09 +00:00
|
|
|
#ifndef _WIN32
|
|
|
|
m_running(false),
|
|
|
|
#endif
|
2016-06-16 11:13:29 +00:00
|
|
|
m_threadID(0)
|
2016-04-17 19:34:47 +00:00
|
|
|
{
|
|
|
|
WriteTrace(TraceThread, TraceDebug, "Start");
|
|
|
|
WriteTrace(TraceThread, TraceDebug, "Done");
|
|
|
|
}
|
|
|
|
|
|
|
|
CThread::~CThread()
|
|
|
|
{
|
|
|
|
WriteTrace(TraceThread, TraceDebug, "Start");
|
2016-06-30 08:11:08 +00:00
|
|
|
if (CThread::GetCurrentThreadId() == m_threadID)
|
|
|
|
{
|
2021-03-16 23:01:45 +00:00
|
|
|
WriteTrace(TraceThread, TraceError, "Deleting from thread!");
|
2016-06-30 08:11:08 +00:00
|
|
|
}
|
2016-06-16 11:13:29 +00:00
|
|
|
if (CThread::GetCurrentThreadId() != m_threadID && isRunning())
|
2016-04-17 19:34:47 +00:00
|
|
|
{
|
|
|
|
Terminate();
|
|
|
|
}
|
|
|
|
#ifdef _WIN32
|
|
|
|
CloseHandle(m_thread);
|
|
|
|
#endif
|
|
|
|
WriteTrace(TraceThread, TraceDebug, "Done");
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CThread::Start(void * lpThreadParameter)
|
|
|
|
{
|
|
|
|
WriteTrace(TraceThread, TraceDebug, "Start");
|
|
|
|
m_lpThreadParameter = lpThreadParameter;
|
2016-04-28 07:34:09 +00:00
|
|
|
#ifdef _WIN32
|
2021-04-12 11:35:39 +00:00
|
|
|
m_thread = CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)ThreadWrapper, this, 0, (LPDWORD)&m_threadID);
|
2016-04-28 07:34:09 +00:00
|
|
|
#else
|
|
|
|
pthread_t * thread_id = new pthread_t;
|
|
|
|
|
2022-10-03 08:04:42 +00:00
|
|
|
m_thread = (void *)thread_id;
|
2016-04-28 07:34:09 +00:00
|
|
|
|
2022-10-03 08:04:42 +00:00
|
|
|
int res = pthread_create(thread_id, nullptr, (void * (*)(void *))ThreadWrapper, this);
|
2016-04-28 07:34:09 +00:00
|
|
|
#endif
|
2016-04-17 19:34:47 +00:00
|
|
|
WriteTrace(TraceThread, TraceDebug, "Done");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-10-03 08:04:42 +00:00
|
|
|
void * CThread::ThreadWrapper(CThread * _this)
|
2016-04-17 19:34:47 +00:00
|
|
|
{
|
|
|
|
WriteTrace(TraceThread, TraceDebug, "Start");
|
2016-06-16 11:13:29 +00:00
|
|
|
_this->m_threadID = CThread::GetCurrentThreadId();
|
2016-04-28 07:34:09 +00:00
|
|
|
#ifndef _WIN32
|
|
|
|
_this->m_running = true;
|
|
|
|
WriteTrace(TraceThread, TraceDebug, "Thread is running");
|
|
|
|
#endif
|
2021-04-12 11:35:39 +00:00
|
|
|
void * res = nullptr;
|
2016-04-17 19:34:47 +00:00
|
|
|
try
|
|
|
|
{
|
2018-11-18 01:06:02 +00:00
|
|
|
#if defined(__i386__) || defined(_M_IX86) || defined(__arm__) || defined(_M_ARM)
|
2016-04-17 19:34:47 +00:00
|
|
|
res = (void *)_this->m_StartAddress(_this->m_lpThreadParameter);
|
2018-11-18 01:06:02 +00:00
|
|
|
#else
|
|
|
|
res = (void *)((uint64_t)_this->m_StartAddress(_this->m_lpThreadParameter));
|
|
|
|
#endif
|
2016-04-17 19:34:47 +00:00
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
//WriteTrace(TraceUserInterface, TraceError, "Unhandled Exception ");
|
|
|
|
}
|
2016-04-28 07:34:09 +00:00
|
|
|
#ifndef _WIN32
|
|
|
|
_this->m_running = false;
|
|
|
|
WriteTrace(TraceThread, TraceDebug, "Thread is finished");
|
|
|
|
#endif
|
|
|
|
#ifdef _WIN32
|
2016-04-17 19:34:47 +00:00
|
|
|
CloseHandle(_this->m_thread);
|
2016-04-28 07:34:09 +00:00
|
|
|
#else
|
|
|
|
pthread_t * thread_id = (pthread_t *)_this->m_thread;
|
|
|
|
delete thread_id;
|
|
|
|
#endif
|
2021-04-12 11:35:39 +00:00
|
|
|
_this->m_thread = nullptr;
|
2016-04-17 19:34:47 +00:00
|
|
|
WriteTrace(TraceThread, TraceDebug, "Done");
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CThread::isRunning(void) const
|
|
|
|
{
|
|
|
|
WriteTrace(TraceThread, TraceDebug, "Start");
|
2021-04-12 11:35:39 +00:00
|
|
|
if (m_thread == nullptr)
|
2016-04-17 19:34:47 +00:00
|
|
|
{
|
|
|
|
WriteTrace(TraceThread, TraceDebug, "Done (res: false), m_thread is null");
|
|
|
|
return false;
|
|
|
|
}
|
2016-04-28 07:34:09 +00:00
|
|
|
#ifndef _WIN32
|
|
|
|
WriteTrace(TraceThread, TraceDebug, "Done (res: %s)", m_running ? "true" : "false");
|
|
|
|
return m_running;
|
|
|
|
#endif
|
|
|
|
#ifdef _WIN32
|
2016-04-17 19:34:47 +00:00
|
|
|
DWORD ExitCode;
|
|
|
|
if (GetExitCodeThread(m_thread, &ExitCode))
|
|
|
|
{
|
|
|
|
if (ExitCode == STILL_ACTIVE)
|
|
|
|
{
|
|
|
|
WriteTrace(TraceThread, TraceDebug, "Done (res: true)");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
WriteTrace(TraceThread, TraceDebug, "Done (res: false)");
|
|
|
|
return false;
|
2016-04-28 07:34:09 +00:00
|
|
|
#else
|
|
|
|
return true;
|
|
|
|
#endif
|
2016-04-17 19:34:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CThread::Terminate(void)
|
|
|
|
{
|
|
|
|
WriteTrace(TraceThread, TraceDebug, "Start");
|
|
|
|
if (isRunning())
|
|
|
|
{
|
2016-04-28 07:34:09 +00:00
|
|
|
#ifdef _WIN32
|
2016-04-17 19:34:47 +00:00
|
|
|
WriteTrace(TraceThread, TraceDebug, "Terminating thread");
|
|
|
|
TerminateThread(m_thread, 0);
|
2016-04-28 07:34:09 +00:00
|
|
|
#else
|
2016-06-30 08:11:08 +00:00
|
|
|
WriteTrace(TraceThread, TraceError, "Need to fix");
|
2016-04-28 07:34:09 +00:00
|
|
|
#endif
|
2016-04-17 19:34:47 +00:00
|
|
|
}
|
|
|
|
WriteTrace(TraceThread, TraceDebug, "Done");
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t CThread::GetCurrentThreadId(void)
|
|
|
|
{
|
2016-04-28 07:34:09 +00:00
|
|
|
#ifdef _WIN32
|
2016-04-17 19:34:47 +00:00
|
|
|
return ::GetCurrentThreadId();
|
2016-04-28 22:27:35 +00:00
|
|
|
#elif defined(SYS_gettid) || defined(__NR_gettid)
|
2021-05-18 11:51:36 +00:00
|
|
|
return syscall(__NR_gettid); // GLIBC has no implementation of gettid()
|
2016-04-28 07:34:09 +00:00
|
|
|
#else
|
|
|
|
return gettid();
|
|
|
|
#endif
|
2016-04-17 19:34:47 +00:00
|
|
|
}
|