Simple thread PAL type (until core/ is rewritten).

This commit is contained in:
Ben Vanik 2013-02-06 02:44:15 -08:00
parent 88431eadce
commit da23c00d31
8 changed files with 193 additions and 18 deletions

View File

@ -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_

View File

@ -11,6 +11,8 @@
'pal.h', 'pal.h',
'ref.cc', 'ref.cc',
'ref.h', 'ref.h',
'thread.cc',
'thread.h',
], ],
'conditions': [ 'conditions': [

137
src/xenia/core/thread.cc Normal file
View File

@ -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

33
src/xenia/core/thread.h Normal file
View File

@ -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_

View File

@ -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));

View File

@ -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();

View File

@ -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 {

View File

@ -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_;