diff --git a/src/Xenia.Debug/Debugger.cs b/src/Xenia.Debug/Debugger.cs index 6769ac848..705071a84 100644 --- a/src/Xenia.Debug/Debugger.cs +++ b/src/Xenia.Debug/Debugger.cs @@ -312,6 +312,7 @@ namespace Xenia.Debug { private async Task CompleteRunStateTransition(RunState newRunState) { await Task.WhenAll(new Task[] { ModuleList.Invalidate(), + ThreadList.Invalidate(), }); CurrentContext.SetRunState(newRunState); diff --git a/src/Xenia.Debug/Proto/xe/debug/proto/ListThreadsResponse.cs b/src/Xenia.Debug/Proto/xe/debug/proto/ListThreadsResponse.cs index 59c106621..8eab9491a 100644 --- a/src/Xenia.Debug/Proto/xe/debug/proto/ListThreadsResponse.cs +++ b/src/Xenia.Debug/Proto/xe/debug/proto/ListThreadsResponse.cs @@ -10,8 +10,21 @@ public sealed class ListThreadsResponse : Table { public static ListThreadsResponse GetRootAsListThreadsResponse(ByteBuffer _bb, ListThreadsResponse obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } public ListThreadsResponse __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } + public Thread GetThread(int j) { return GetThread(new Thread(), j); } + public Thread GetThread(Thread obj, int j) { int o = __offset(4); return o != 0 ? obj.__init(__indirect(__vector(o) + j * 4), bb) : null; } + public int ThreadLength { get { int o = __offset(4); return o != 0 ? __vector_len(o) : 0; } } - public static void StartListThreadsResponse(FlatBufferBuilder builder) { builder.StartObject(0); } + public static int CreateListThreadsResponse(FlatBufferBuilder builder, + int thread = 0) { + builder.StartObject(1); + ListThreadsResponse.AddThread(builder, thread); + return ListThreadsResponse.EndListThreadsResponse(builder); + } + + public static void StartListThreadsResponse(FlatBufferBuilder builder) { builder.StartObject(1); } + public static void AddThread(FlatBufferBuilder builder, int threadOffset) { builder.AddOffset(0, threadOffset, 0); } + public static int CreateThreadVector(FlatBufferBuilder builder, int[] data) { builder.StartVector(4, data.Length, 4); for (int i = data.Length - 1; i >= 0; i--) builder.AddOffset(data[i]); return builder.EndVector(); } + public static void StartThreadVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } public static int EndListThreadsResponse(FlatBufferBuilder builder) { int o = builder.EndObject(); return o; diff --git a/src/Xenia.Debug/Proto/xe/debug/proto/RequestData.cs b/src/Xenia.Debug/Proto/xe/debug/proto/RequestData.cs index d76d6b417..6992f7213 100644 --- a/src/Xenia.Debug/Proto/xe/debug/proto/RequestData.cs +++ b/src/Xenia.Debug/Proto/xe/debug/proto/RequestData.cs @@ -15,10 +15,11 @@ public enum RequestData : byte GetModuleRequest = 7, ListFunctionsRequest = 8, GetFunctionRequest = 9, - StopRequest = 10, - BreakRequest = 11, - ContinueRequest = 12, - StepRequest = 13, + ListThreadsRequest = 10, + StopRequest = 11, + BreakRequest = 12, + ContinueRequest = 13, + StepRequest = 14, }; diff --git a/src/Xenia.Debug/Proto/xe/debug/proto/ResponseData.cs b/src/Xenia.Debug/Proto/xe/debug/proto/ResponseData.cs index e7bec17f4..5dc419d88 100644 --- a/src/Xenia.Debug/Proto/xe/debug/proto/ResponseData.cs +++ b/src/Xenia.Debug/Proto/xe/debug/proto/ResponseData.cs @@ -15,12 +15,13 @@ public enum ResponseData : byte GetModuleResponse = 7, ListFunctionsResponse = 8, GetFunctionResponse = 9, - StopResponse = 10, - BreakResponse = 11, - ContinueResponse = 12, - StepResponse = 13, - BreakpointEvent = 14, - AccessViolationEvent = 15, + ListThreadsResponse = 10, + StopResponse = 11, + BreakResponse = 12, + ContinueResponse = 13, + StepResponse = 14, + BreakpointEvent = 15, + AccessViolationEvent = 16, }; diff --git a/src/Xenia.Debug/Proto/xe/debug/proto/Thread.cs b/src/Xenia.Debug/Proto/xe/debug/proto/Thread.cs index 8e6506264..ef624eee2 100644 --- a/src/Xenia.Debug/Proto/xe/debug/proto/Thread.cs +++ b/src/Xenia.Debug/Proto/xe/debug/proto/Thread.cs @@ -13,10 +13,36 @@ public sealed class Thread : Table { public XObject Object { get { return GetObject(new XObject()); } } public XObject GetObject(XObject obj) { int o = __offset(4); return o != 0 ? obj.__init(o + bb_pos, bb) : null; } public ThreadType Type { get { int o = __offset(6); return o != 0 ? (ThreadType)bb.GetSbyte(o + bb_pos) : (ThreadType)0; } } + public uint StackSize { get { int o = __offset(8); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } } + public uint XapiThreadStartup { get { int o = __offset(10); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } } + public uint StartAddress { get { int o = __offset(12); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } } + public uint StartContext { get { int o = __offset(14); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } } + public uint CreationFlags { get { int o = __offset(16); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } } + public uint TlsAddress { get { int o = __offset(18); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } } + public uint PcrAddress { get { int o = __offset(20); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } } + public uint ThreadStateAddress { get { int o = __offset(22); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } } + public uint ThreadId { get { int o = __offset(24); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } } + public string Name { get { int o = __offset(26); return o != 0 ? __string(o + bb_pos) : null; } } + public uint Priority { get { int o = __offset(28); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } } + public uint Affinity { get { int o = __offset(30); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } } + public uint State { get { int o = __offset(32); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } } - public static void StartThread(FlatBufferBuilder builder) { builder.StartObject(2); } + public static void StartThread(FlatBufferBuilder builder) { builder.StartObject(15); } public static void AddObject(FlatBufferBuilder builder, int objectOffset) { builder.AddStruct(0, objectOffset, 0); } public static void AddType(FlatBufferBuilder builder, ThreadType type) { builder.AddSbyte(1, (sbyte)(type), 0); } + public static void AddStackSize(FlatBufferBuilder builder, uint stackSize) { builder.AddUint(2, stackSize, 0); } + public static void AddXapiThreadStartup(FlatBufferBuilder builder, uint xapiThreadStartup) { builder.AddUint(3, xapiThreadStartup, 0); } + public static void AddStartAddress(FlatBufferBuilder builder, uint startAddress) { builder.AddUint(4, startAddress, 0); } + public static void AddStartContext(FlatBufferBuilder builder, uint startContext) { builder.AddUint(5, startContext, 0); } + public static void AddCreationFlags(FlatBufferBuilder builder, uint creationFlags) { builder.AddUint(6, creationFlags, 0); } + public static void AddTlsAddress(FlatBufferBuilder builder, uint tlsAddress) { builder.AddUint(7, tlsAddress, 0); } + public static void AddPcrAddress(FlatBufferBuilder builder, uint pcrAddress) { builder.AddUint(8, pcrAddress, 0); } + public static void AddThreadStateAddress(FlatBufferBuilder builder, uint threadStateAddress) { builder.AddUint(9, threadStateAddress, 0); } + public static void AddThreadId(FlatBufferBuilder builder, uint threadId) { builder.AddUint(10, threadId, 0); } + public static void AddName(FlatBufferBuilder builder, int nameOffset) { builder.AddOffset(11, nameOffset, 0); } + public static void AddPriority(FlatBufferBuilder builder, uint priority) { builder.AddUint(12, priority, 0); } + public static void AddAffinity(FlatBufferBuilder builder, uint affinity) { builder.AddUint(13, affinity, 0); } + public static void AddState(FlatBufferBuilder builder, uint state) { builder.AddUint(14, state, 0); } public static int EndThread(FlatBufferBuilder builder) { int o = builder.EndObject(); return o; diff --git a/src/Xenia.Debug/ThreadList.cs b/src/Xenia.Debug/ThreadList.cs index 737c8c437..4f1e93808 100644 --- a/src/Xenia.Debug/ThreadList.cs +++ b/src/Xenia.Debug/ThreadList.cs @@ -13,6 +13,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using xe.debug.proto; using Xenia.Debug.Utilities; namespace Xenia.Debug { @@ -25,6 +26,23 @@ namespace Xenia.Debug { this.debugger = debugger; } + public async Task Invalidate() { + var fbb = debugger.BeginRequest(); + ListThreadsRequest.StartListThreadsRequest(fbb); + int requestDataOffset = ListThreadsRequest.EndListThreadsRequest(fbb); + var response = await debugger.CommitRequest( + fbb, RequestData.ListThreadsRequest, requestDataOffset); + ListThreadsResponse responseData = new ListThreadsResponse(); + response.GetResponseData(responseData); + + for (int i = 0; i < responseData.ThreadLength; ++i) { + var threadData = responseData.GetThread(i); + // threadData.Name; + } + + OnChanged(); + } + public int Count { get { return threads.Count; diff --git a/src/xenia/debug/debugger.cc b/src/xenia/debug/debugger.cc index 8763e33b8..a73109de1 100644 --- a/src/xenia/debug/debugger.cc +++ b/src/xenia/debug/debugger.cc @@ -35,6 +35,7 @@ #include "xenia/debug/proto/control_generated.h" #include "xenia/debug/proto/messages_generated.h" #include "xenia/debug/proto/modules_generated.h" +#include "xenia/debug/proto/threads_generated.h" DEFINE_string(debug_session_path, "", "Debug output path."); DEFINE_int32(debug_port, 19000, "Port the debugger listens on."); @@ -400,6 +401,38 @@ void Debugger::OnMessage(std::vector buffer) { response_data_offset = response_data.Finish().Union(); } break; + case proto::RequestData_ListThreadsRequest: { + response_data_type = proto::ResponseData_ListThreadsResponse; + auto threads = + emulator()->kernel_state()->object_table()->GetObjectsByType( + XObject::kTypeThread); + std::vector> thread_list; + for (size_t i = 0; i < threads.size(); ++i) { + auto& thread = threads[i]; + auto thread_name_string = fbb.CreateString(thread->name()); + auto thread_builder = proto::ThreadBuilder(fbb); + // thread_builder.add_type(); + // thread_builder.add_stack_size(); + // thread_builder.add_xapi_thread_startup(); + // thread_builder.add_start_address(); + // thread_builder.add_start_context(); + // thread_builder.add_creation_flags(); + thread_builder.add_tls_address(thread->tls_ptr()); + thread_builder.add_pcr_address(thread->pcr_ptr()); + thread_builder.add_thread_state_address(thread->thread_state_ptr()); + thread_builder.add_thread_id(thread->thread_id()); + thread_builder.add_name(thread_name_string); + thread_builder.add_priority(thread->priority()); + thread_builder.add_affinity(thread->affinity()); + // thread_builder.add_state(thread->); + thread_list.push_back(thread_builder.Finish()); + } + auto threads_offset = fbb.CreateVector(thread_list); + auto response_data = proto::ListThreadsResponseBuilder(fbb); + response_data.add_thread(threads_offset); + response_data_offset = response_data.Finish().Union(); + } break; + case proto::RequestData_StopRequest: { response_data_type = proto::ResponseData_StopResponse; auto response_data = proto::StopResponseBuilder(fbb); diff --git a/src/xenia/debug/proto/messages.fbs b/src/xenia/debug/proto/messages.fbs index 8bd684e30..0d41ab3ed 100644 --- a/src/xenia/debug/proto/messages.fbs +++ b/src/xenia/debug/proto/messages.fbs @@ -31,6 +31,8 @@ union RequestData { ListFunctionsRequest, GetFunctionRequest, + ListThreadsRequest, + StopRequest, BreakRequest, ContinueRequest, @@ -55,6 +57,8 @@ union ResponseData { ListFunctionsResponse, GetFunctionResponse, + ListThreadsResponse, + StopResponse, BreakResponse, ContinueResponse, diff --git a/src/xenia/debug/proto/messages_generated.h b/src/xenia/debug/proto/messages_generated.h index 2e13c9166..ee0a0269c 100644 --- a/src/xenia/debug/proto/messages_generated.h +++ b/src/xenia/debug/proto/messages_generated.h @@ -91,14 +91,23 @@ enum RequestData { RequestData_GetModuleRequest = 7, RequestData_ListFunctionsRequest = 8, RequestData_GetFunctionRequest = 9, - RequestData_StopRequest = 10, - RequestData_BreakRequest = 11, - RequestData_ContinueRequest = 12, - RequestData_StepRequest = 13 + RequestData_ListThreadsRequest = 10, + RequestData_StopRequest = 11, + RequestData_BreakRequest = 12, + RequestData_ContinueRequest = 13, + RequestData_StepRequest = 14 }; inline const char **EnumNamesRequestData() { - static const char *names[] = { "NONE", "AttachRequest", "ListBreakpointsRequest", "AddBreakpointsRequest", "UpdateBreakpointsRequest", "RemoveBreakpointsRequest", "ListModulesRequest", "GetModuleRequest", "ListFunctionsRequest", "GetFunctionRequest", "StopRequest", "BreakRequest", "ContinueRequest", "StepRequest", nullptr }; + static const char *names[] = { + "NONE", "AttachRequest", + "ListBreakpointsRequest", "AddBreakpointsRequest", + "UpdateBreakpointsRequest", "RemoveBreakpointsRequest", + "ListModulesRequest", "GetModuleRequest", + "ListFunctionsRequest", "GetFunctionRequest", + "ListThreadsRequest", "StopRequest", + "BreakRequest", "ContinueRequest", + "StepRequest", nullptr}; return names; } @@ -117,16 +126,26 @@ enum ResponseData { ResponseData_GetModuleResponse = 7, ResponseData_ListFunctionsResponse = 8, ResponseData_GetFunctionResponse = 9, - ResponseData_StopResponse = 10, - ResponseData_BreakResponse = 11, - ResponseData_ContinueResponse = 12, - ResponseData_StepResponse = 13, - ResponseData_BreakpointEvent = 14, - ResponseData_AccessViolationEvent = 15 + ResponseData_ListThreadsResponse = 10, + ResponseData_StopResponse = 11, + ResponseData_BreakResponse = 12, + ResponseData_ContinueResponse = 13, + ResponseData_StepResponse = 14, + ResponseData_BreakpointEvent = 15, + ResponseData_AccessViolationEvent = 16 }; inline const char **EnumNamesResponseData() { - static const char *names[] = { "NONE", "AttachResponse", "ListBreakpointsResponse", "AddBreakpointsResponse", "UpdateBreakpointsResponse", "RemoveBreakpointsResponse", "ListModulesResponse", "GetModuleResponse", "ListFunctionsResponse", "GetFunctionResponse", "StopResponse", "BreakResponse", "ContinueResponse", "StepResponse", "BreakpointEvent", "AccessViolationEvent", nullptr }; + static const char *names[] = { + "NONE", "AttachResponse", + "ListBreakpointsResponse", "AddBreakpointsResponse", + "UpdateBreakpointsResponse", "RemoveBreakpointsResponse", + "ListModulesResponse", "GetModuleResponse", + "ListFunctionsResponse", "GetFunctionResponse", + "ListThreadsResponse", "StopResponse", + "BreakResponse", "ContinueResponse", + "StepResponse", "BreakpointEvent", + "AccessViolationEvent", nullptr}; return names; } @@ -304,6 +323,10 @@ inline bool VerifyRequestData(flatbuffers::Verifier &verifier, const void *union case RequestData_GetModuleRequest: return verifier.VerifyTable(reinterpret_cast(union_obj)); case RequestData_ListFunctionsRequest: return verifier.VerifyTable(reinterpret_cast(union_obj)); case RequestData_GetFunctionRequest: return verifier.VerifyTable(reinterpret_cast(union_obj)); + case RequestData_ListThreadsRequest: + return verifier.VerifyTable( + reinterpret_cast( + union_obj)); case RequestData_StopRequest: return verifier.VerifyTable(reinterpret_cast(union_obj)); case RequestData_BreakRequest: return verifier.VerifyTable(reinterpret_cast(union_obj)); case RequestData_ContinueRequest: return verifier.VerifyTable(reinterpret_cast(union_obj)); @@ -324,6 +347,10 @@ inline bool VerifyResponseData(flatbuffers::Verifier &verifier, const void *unio case ResponseData_GetModuleResponse: return verifier.VerifyTable(reinterpret_cast(union_obj)); case ResponseData_ListFunctionsResponse: return verifier.VerifyTable(reinterpret_cast(union_obj)); case ResponseData_GetFunctionResponse: return verifier.VerifyTable(reinterpret_cast(union_obj)); + case ResponseData_ListThreadsResponse: + return verifier.VerifyTable( + reinterpret_cast( + union_obj)); case ResponseData_StopResponse: return verifier.VerifyTable(reinterpret_cast(union_obj)); case ResponseData_BreakResponse: return verifier.VerifyTable(reinterpret_cast(union_obj)); case ResponseData_ContinueResponse: return verifier.VerifyTable(reinterpret_cast(union_obj)); diff --git a/src/xenia/debug/proto/threads.fbs b/src/xenia/debug/proto/threads.fbs index bbaa622f1..7b357c539 100644 --- a/src/xenia/debug/proto/threads.fbs +++ b/src/xenia/debug/proto/threads.fbs @@ -13,9 +13,26 @@ table Thread { // module_id:uint; // creation callstack + + stack_size:uint; + xapi_thread_startup:uint; + start_address:uint; + start_context:uint; + creation_flags:uint; + + tls_address:uint; + pcr_address:uint; + thread_state_address:uint; + thread_id:uint; + name:string; + + priority:uint; + affinity:uint; + state:uint; } table ListThreadsRequest { } table ListThreadsResponse { + thread:[Thread]; } diff --git a/src/xenia/debug/proto/threads_generated.h b/src/xenia/debug/proto/threads_generated.h index df7641048..3e0c530eb 100644 --- a/src/xenia/debug/proto/threads_generated.h +++ b/src/xenia/debug/proto/threads_generated.h @@ -36,10 +36,39 @@ inline const char *EnumNameThreadType(ThreadType e) { return EnumNamesThreadType struct Thread FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { const xe::debug::proto::XObject *object() const { return GetStruct(4); } ThreadType type() const { return static_cast(GetField(6, 0)); } + uint32_t stack_size() const { return GetField(8, 0); } + uint32_t xapi_thread_startup() const { return GetField(10, 0); } + uint32_t start_address() const { return GetField(12, 0); } + uint32_t start_context() const { return GetField(14, 0); } + uint32_t creation_flags() const { return GetField(16, 0); } + uint32_t tls_address() const { return GetField(18, 0); } + uint32_t pcr_address() const { return GetField(20, 0); } + uint32_t thread_state_address() const { return GetField(22, 0); } + uint32_t thread_id() const { return GetField(24, 0); } + const flatbuffers::String *name() const { + return GetPointer(26); + } + uint32_t priority() const { return GetField(28, 0); } + uint32_t affinity() const { return GetField(30, 0); } + uint32_t state() const { return GetField(32, 0); } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && VerifyField(verifier, 4 /* object */) && VerifyField(verifier, 6 /* type */) && + VerifyField(verifier, 8 /* stack_size */) && + VerifyField(verifier, 10 /* xapi_thread_startup */) && + VerifyField(verifier, 12 /* start_address */) && + VerifyField(verifier, 14 /* start_context */) && + VerifyField(verifier, 16 /* creation_flags */) && + VerifyField(verifier, 18 /* tls_address */) && + VerifyField(verifier, 20 /* pcr_address */) && + VerifyField(verifier, 22 /* thread_state_address */) && + VerifyField(verifier, 24 /* thread_id */) && + VerifyField(verifier, 26 /* name */) && + verifier.Verify(name()) && + VerifyField(verifier, 28 /* priority */) && + VerifyField(verifier, 30 /* affinity */) && + VerifyField(verifier, 32 /* state */) && verifier.EndTable(); } }; @@ -49,18 +78,75 @@ struct ThreadBuilder { flatbuffers::uoffset_t start_; void add_object(const xe::debug::proto::XObject *object) { fbb_.AddStruct(4, object); } void add_type(ThreadType type) { fbb_.AddElement(6, static_cast(type), 0); } + void add_stack_size(uint32_t stack_size) { + fbb_.AddElement(8, stack_size, 0); + } + void add_xapi_thread_startup(uint32_t xapi_thread_startup) { + fbb_.AddElement(10, xapi_thread_startup, 0); + } + void add_start_address(uint32_t start_address) { + fbb_.AddElement(12, start_address, 0); + } + void add_start_context(uint32_t start_context) { + fbb_.AddElement(14, start_context, 0); + } + void add_creation_flags(uint32_t creation_flags) { + fbb_.AddElement(16, creation_flags, 0); + } + void add_tls_address(uint32_t tls_address) { + fbb_.AddElement(18, tls_address, 0); + } + void add_pcr_address(uint32_t pcr_address) { + fbb_.AddElement(20, pcr_address, 0); + } + void add_thread_state_address(uint32_t thread_state_address) { + fbb_.AddElement(22, thread_state_address, 0); + } + void add_thread_id(uint32_t thread_id) { + fbb_.AddElement(24, thread_id, 0); + } + void add_name(flatbuffers::Offset name) { + fbb_.AddOffset(26, name); + } + void add_priority(uint32_t priority) { + fbb_.AddElement(28, priority, 0); + } + void add_affinity(uint32_t affinity) { + fbb_.AddElement(30, affinity, 0); + } + void add_state(uint32_t state) { fbb_.AddElement(32, state, 0); } ThreadBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } ThreadBuilder &operator=(const ThreadBuilder &); flatbuffers::Offset Finish() { - auto o = flatbuffers::Offset(fbb_.EndTable(start_, 2)); + auto o = flatbuffers::Offset(fbb_.EndTable(start_, 15)); return o; } }; -inline flatbuffers::Offset CreateThread(flatbuffers::FlatBufferBuilder &_fbb, - const xe::debug::proto::XObject *object = 0, - ThreadType type = ThreadType_Kernel) { +inline flatbuffers::Offset CreateThread( + flatbuffers::FlatBufferBuilder &_fbb, + const xe::debug::proto::XObject *object = 0, + ThreadType type = ThreadType_Kernel, uint32_t stack_size = 0, + uint32_t xapi_thread_startup = 0, uint32_t start_address = 0, + uint32_t start_context = 0, uint32_t creation_flags = 0, + uint32_t tls_address = 0, uint32_t pcr_address = 0, + uint32_t thread_state_address = 0, uint32_t thread_id = 0, + flatbuffers::Offset name = 0, uint32_t priority = 0, + uint32_t affinity = 0, uint32_t state = 0) { ThreadBuilder builder_(_fbb); + builder_.add_state(state); + builder_.add_affinity(affinity); + builder_.add_priority(priority); + builder_.add_name(name); + builder_.add_thread_id(thread_id); + builder_.add_thread_state_address(thread_state_address); + builder_.add_pcr_address(pcr_address); + builder_.add_tls_address(tls_address); + builder_.add_creation_flags(creation_flags); + builder_.add_start_context(start_context); + builder_.add_start_address(start_address); + builder_.add_xapi_thread_startup(xapi_thread_startup); + builder_.add_stack_size(stack_size); builder_.add_object(object); builder_.add_type(type); return builder_.Finish(); @@ -90,25 +176,39 @@ inline flatbuffers::Offset CreateListThreadsRequest(flatbuff } struct ListThreadsResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + const flatbuffers::Vector> *thread() const { + return GetPointer> *>( + 4); + } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && - verifier.EndTable(); + VerifyField(verifier, 4 /* thread */) && + verifier.Verify(thread()) && + verifier.VerifyVectorOfTables(thread()) && verifier.EndTable(); } }; struct ListThreadsResponseBuilder { flatbuffers::FlatBufferBuilder &fbb_; flatbuffers::uoffset_t start_; + void add_thread(flatbuffers::Offset< + flatbuffers::Vector>> thread) { + fbb_.AddOffset(4, thread); + } ListThreadsResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } ListThreadsResponseBuilder &operator=(const ListThreadsResponseBuilder &); flatbuffers::Offset Finish() { - auto o = flatbuffers::Offset(fbb_.EndTable(start_, 0)); + auto o = flatbuffers::Offset(fbb_.EndTable(start_, 1)); return o; } }; -inline flatbuffers::Offset CreateListThreadsResponse(flatbuffers::FlatBufferBuilder &_fbb) { +inline flatbuffers::Offset CreateListThreadsResponse( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset>> + thread = 0) { ListThreadsResponseBuilder builder_(_fbb); + builder_.add_thread(thread); return builder_.Finish(); } diff --git a/src/xenia/kernel/objects/xthread.cc b/src/xenia/kernel/objects/xthread.cc index 702e3a36a..cb8576438 100644 --- a/src/xenia/kernel/objects/xthread.cc +++ b/src/xenia/kernel/objects/xthread.cc @@ -46,6 +46,8 @@ XThread::XThread(KernelState* kernel_state, uint32_t stack_size, pcr_address_(0), thread_state_address_(0), thread_state_(0), + priority_(0), + affinity_(0), irql_(0) { creation_params_.stack_size = stack_size; creation_params_.xapi_thread_startup = xapi_thread_startup; @@ -613,6 +615,7 @@ void XThread::RundownAPCs() { int32_t XThread::QueryPriority() { return GetThreadPriority(thread_handle_); } void XThread::SetPriority(int32_t increment) { + priority_ = increment; int target_priority = 0; if (increment > 0x22) { target_priority = THREAD_PRIORITY_HIGHEST; @@ -647,11 +650,17 @@ void XThread::SetAffinity(uint32_t affinity) { XELOGW("Too few processors - scheduling will be wonky"); } SetActiveCpu(GetFakeCpuNumber(affinity)); + affinity_ = affinity; if (!FLAGS_ignore_thread_affinities) { SetThreadAffinityMask(reinterpret_cast(thread_handle_), affinity); } } +uint32_t XThread::active_cpu() const { + uint8_t* pcr = memory()->TranslateVirtual(pcr_address_); + return xe::load_and_swap(pcr + 0x10C); +} + void XThread::SetActiveCpu(uint32_t cpu_index) { uint8_t* pcr = memory()->TranslateVirtual(pcr_address_); xe::store_and_swap(pcr + 0x10C, cpu_index); diff --git a/src/xenia/kernel/objects/xthread.h b/src/xenia/kernel/objects/xthread.h index a97d85182..9cbb321eb 100644 --- a/src/xenia/kernel/objects/xthread.h +++ b/src/xenia/kernel/objects/xthread.h @@ -85,6 +85,7 @@ class XThread : public XObject { static uint32_t GetCurrentThreadHandle(); static uint32_t GetCurrentThreadId(const uint8_t* pcr); + uint32_t tls_ptr() const { return tls_address_; } uint32_t pcr_ptr() const { return pcr_address_; } uint32_t thread_state_ptr() const { return thread_state_address_; } @@ -112,9 +113,12 @@ class XThread : public XObject { void EnqueueApc(uint32_t normal_routine, uint32_t normal_context, uint32_t arg1, uint32_t arg2); + int32_t priority() const { return priority_; } int32_t QueryPriority(); void SetPriority(int32_t increment); + uint32_t affinity() const { return affinity_; } void SetAffinity(uint32_t affinity); + uint32_t active_cpu() const; void SetActiveCpu(uint32_t cpu_index); X_STATUS Resume(uint32_t* out_suspend_count = nullptr); @@ -151,6 +155,9 @@ class XThread : public XObject { std::string name_; + int32_t priority_; + uint32_t affinity_; + std::atomic irql_; xe::mutex apc_lock_; NativeList* apc_list_;