Simple thread PAL type (until core/ is rewritten).
This commit is contained in:
parent
88431eadce
commit
da23c00d31
|
@ -18,5 +18,6 @@
|
||||||
#include <xenia/core/mutex.h>
|
#include <xenia/core/mutex.h>
|
||||||
#include <xenia/core/pal.h>
|
#include <xenia/core/pal.h>
|
||||||
#include <xenia/core/ref.h>
|
#include <xenia/core/ref.h>
|
||||||
|
#include <xenia/core/thread.h>
|
||||||
|
|
||||||
#endif // XENIA_CORE_H_
|
#endif // XENIA_CORE_H_
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
'pal.h',
|
'pal.h',
|
||||||
'ref.cc',
|
'ref.cc',
|
||||||
'ref.h',
|
'ref.h',
|
||||||
|
'thread.cc',
|
||||||
|
'thread.h',
|
||||||
],
|
],
|
||||||
|
|
||||||
'conditions': [
|
'conditions': [
|
||||||
|
|
|
@ -0,0 +1,137 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <xenia/core/thread.h>
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct xe_thread {
|
||||||
|
xe_ref_t ref;
|
||||||
|
|
||||||
|
char* name;
|
||||||
|
|
||||||
|
xe_thread_callback callback;
|
||||||
|
void* callback_param;
|
||||||
|
|
||||||
|
void* handle;
|
||||||
|
} xe_thread_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
xe_thread_ref xe_thread_create(
|
||||||
|
xe_pal_ref pal, const char* name, xe_thread_callback callback,
|
||||||
|
void* param) {
|
||||||
|
xe_thread_ref thread = (xe_thread_ref)xe_calloc(sizeof(xe_thread_t));
|
||||||
|
xe_ref_init((xe_ref)thread);
|
||||||
|
|
||||||
|
thread->name = xestrdupa(name);
|
||||||
|
thread->callback = callback;
|
||||||
|
thread->callback_param = param;
|
||||||
|
|
||||||
|
return thread;
|
||||||
|
}
|
||||||
|
|
||||||
|
void xe_thread_dealloc(xe_thread_ref thread) {
|
||||||
|
thread->handle = NULL;
|
||||||
|
xe_free(thread->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
xe_thread_ref xe_thread_retain(xe_thread_ref thread) {
|
||||||
|
xe_ref_retain((xe_ref)thread);
|
||||||
|
return thread;
|
||||||
|
}
|
||||||
|
|
||||||
|
void xe_thread_release(xe_thread_ref thread) {
|
||||||
|
xe_ref_release((xe_ref)thread, (xe_ref_dealloc_t)xe_thread_dealloc);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if XE_PLATFORM(WIN32)
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
|
||||||
|
#pragma pack(push,8)
|
||||||
|
typedef struct tagTHREADNAME_INFO
|
||||||
|
{
|
||||||
|
DWORD dwType; // Must be 0x1000.
|
||||||
|
LPCSTR szName; // Pointer to name (in user addr space).
|
||||||
|
DWORD dwThreadID; // Thread ID (-1=caller thread).
|
||||||
|
DWORD dwFlags; // Reserved for future use, must be zero.
|
||||||
|
} THREADNAME_INFO;
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
#pragma warning(disable : 6320; disable : 6322)
|
||||||
|
static uint32_t __stdcall xe_thread_callback_win32(void* param) {
|
||||||
|
xe_thread_t* thread = reinterpret_cast<xe_thread_t*>(param);
|
||||||
|
|
||||||
|
if (IsDebuggerPresent()) {
|
||||||
|
THREADNAME_INFO info;
|
||||||
|
info.dwType = 0x1000;
|
||||||
|
info.szName = thread->name;
|
||||||
|
info.dwThreadID = (DWORD)-1;
|
||||||
|
info.dwFlags = 0;
|
||||||
|
__try {
|
||||||
|
RaiseException(0x406D1388, 0, sizeof(info) / sizeof(ULONG_PTR),
|
||||||
|
(ULONG_PTR*)&info);
|
||||||
|
} __except(EXCEPTION_EXECUTE_HANDLER) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
thread->callback(thread->callback_param);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#pragma warning(default : 6320; default : 6322)
|
||||||
|
|
||||||
|
int xe_thread_start(xe_thread_ref thread) {
|
||||||
|
HANDLE thread_handle = CreateThread(
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
(LPTHREAD_START_ROUTINE)xe_thread_callback_win32,
|
||||||
|
thread,
|
||||||
|
0,
|
||||||
|
NULL);
|
||||||
|
if (!handle) {
|
||||||
|
uint32_t last_error = GetLastError();
|
||||||
|
// TODO(benvanik): translate?
|
||||||
|
XELOGE(XT("CreateThread failed with %d"), last_error);
|
||||||
|
return last_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
thread->handle = reinterpret_cast<void*>(thread_handle);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
static void* xe_thread_callback_pthreads(void* param) {
|
||||||
|
xe_thread_t* thread = reinterpret_cast<xe_thread_t*>(param);
|
||||||
|
XEIGNORE(pthread_setname_np(thread->name));
|
||||||
|
thread->callback(thread->callback_param);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int xe_thread_start(xe_thread_ref thread) {
|
||||||
|
pthread_attr_t attr;
|
||||||
|
pthread_attr_init(&attr);
|
||||||
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||||
|
pthread_t thread_handle;
|
||||||
|
int result_code = pthread_create(
|
||||||
|
&thread_handle,
|
||||||
|
&attr,
|
||||||
|
&xe_thread_callback_pthreads,
|
||||||
|
thread);
|
||||||
|
pthread_attr_destroy(&attr);
|
||||||
|
if (result_code) {
|
||||||
|
return result_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
thread->handle = reinterpret_cast<void*>(thread_handle);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // WIN32
|
|
@ -0,0 +1,33 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XENIA_CORE_THREAD_H_
|
||||||
|
#define XENIA_CORE_THREAD_H_
|
||||||
|
|
||||||
|
#include <xenia/common.h>
|
||||||
|
#include <xenia/core/pal.h>
|
||||||
|
#include <xenia/core/ref.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct xe_thread;
|
||||||
|
typedef struct xe_thread* xe_thread_ref;
|
||||||
|
|
||||||
|
|
||||||
|
typedef void (*xe_thread_callback)(void* param);
|
||||||
|
|
||||||
|
|
||||||
|
xe_thread_ref xe_thread_create(
|
||||||
|
xe_pal_ref pal, const char* name, xe_thread_callback callback, void* param);
|
||||||
|
xe_thread_ref xe_thread_retain(xe_thread_ref thread);
|
||||||
|
void xe_thread_release(xe_thread_ref thread);
|
||||||
|
|
||||||
|
int xe_thread_start(xe_thread_ref thread);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // XENIA_CORE_THREAD_H_
|
|
@ -48,6 +48,10 @@ Debugger::~Debugger() {
|
||||||
xe_pal_release(pal_);
|
xe_pal_release(pal_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xe_pal_ref Debugger::pal() {
|
||||||
|
return xe_pal_retain(pal_);
|
||||||
|
}
|
||||||
|
|
||||||
void Debugger::RegisterContentSource(ContentSource* content_source) {
|
void Debugger::RegisterContentSource(ContentSource* content_source) {
|
||||||
content_sources_.insert(std::pair<uint32_t, ContentSource*>(
|
content_sources_.insert(std::pair<uint32_t, ContentSource*>(
|
||||||
content_source->source_id(), content_source));
|
content_source->source_id(), content_source));
|
||||||
|
|
|
@ -31,6 +31,8 @@ public:
|
||||||
Debugger(xe_pal_ref pal);
|
Debugger(xe_pal_ref pal);
|
||||||
virtual ~Debugger();
|
virtual ~Debugger();
|
||||||
|
|
||||||
|
xe_pal_ref pal();
|
||||||
|
|
||||||
void RegisterContentSource(ContentSource* content_source);
|
void RegisterContentSource(ContentSource* content_source);
|
||||||
|
|
||||||
int Startup();
|
int Startup();
|
||||||
|
|
|
@ -30,6 +30,7 @@ using namespace xe::dbg;
|
||||||
|
|
||||||
WsClient::WsClient(Debugger* debugger, int socket_id) :
|
WsClient::WsClient(Debugger* debugger, int socket_id) :
|
||||||
Client(debugger),
|
Client(debugger),
|
||||||
|
thread_(NULL),
|
||||||
socket_id_(socket_id) {
|
socket_id_(socket_id) {
|
||||||
mutex_ = xe_mutex_alloc(1000);
|
mutex_ = xe_mutex_alloc(1000);
|
||||||
|
|
||||||
|
@ -49,6 +50,8 @@ WsClient::~WsClient() {
|
||||||
xe_mutex_unlock(mutex);
|
xe_mutex_unlock(mutex);
|
||||||
xe_mutex_free(mutex);
|
xe_mutex_free(mutex);
|
||||||
|
|
||||||
|
xe_thread_release(thread_);
|
||||||
|
|
||||||
close(notify_rd_id_);
|
close(notify_rd_id_);
|
||||||
close(notify_wr_id_);
|
close(notify_wr_id_);
|
||||||
}
|
}
|
||||||
|
@ -67,25 +70,16 @@ int WsClient::Setup() {
|
||||||
setsockopt(socket_id_, IPPROTO_TCP, TCP_NODELAY,
|
setsockopt(socket_id_, IPPROTO_TCP, TCP_NODELAY,
|
||||||
&opt_value, sizeof(opt_value));
|
&opt_value, sizeof(opt_value));
|
||||||
|
|
||||||
// TODO(benvanik): win32 support - put simple threads in PAL
|
xe_pal_ref pal = debugger_->pal();
|
||||||
pthread_attr_t attr;
|
thread_ = xe_thread_create(pal, "Debugger Client",
|
||||||
pthread_attr_init(&attr);
|
StartCallback, this);
|
||||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
xe_pal_release(pal);
|
||||||
pthread_t thread_handle;
|
return xe_thread_start(thread_);
|
||||||
int result_code = pthread_create(
|
|
||||||
&thread_handle,
|
|
||||||
&attr,
|
|
||||||
&StartCallbackPthreads,
|
|
||||||
this);
|
|
||||||
pthread_attr_destroy(&attr);
|
|
||||||
|
|
||||||
return result_code;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void* WsClient::StartCallbackPthreads(void* param) {
|
void WsClient::StartCallback(void* param) {
|
||||||
WsClient* thread = reinterpret_cast<WsClient*>(param);
|
WsClient* client = reinterpret_cast<WsClient*>(param);
|
||||||
thread->EventThread();
|
client->EventThread();
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
|
@ -37,11 +37,13 @@ public:
|
||||||
virtual void Write(uint8_t** buffers, size_t* lengths, size_t count);
|
virtual void Write(uint8_t** buffers, size_t* lengths, size_t count);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void* StartCallbackPthreads(void* param);
|
static void StartCallback(void* param);
|
||||||
|
|
||||||
int PerformHandshake();
|
int PerformHandshake();
|
||||||
void EventThread();
|
void EventThread();
|
||||||
|
|
||||||
|
xe_thread_ref thread_;
|
||||||
|
|
||||||
int socket_id_;
|
int socket_id_;
|
||||||
|
|
||||||
int notify_rd_id_;
|
int notify_rd_id_;
|
||||||
|
|
Loading…
Reference in New Issue