kern: SvcGetDebugThreadParam

This commit is contained in:
Michael Scire 2020-07-31 01:59:46 -07:00 committed by SciresM
parent e1f3bb10a5
commit 3afd723b92
6 changed files with 140 additions and 3 deletions

View file

@ -23,7 +23,7 @@ namespace ams::kern {
class KAutoObjectWithListContainer {
NON_COPYABLE(KAutoObjectWithListContainer);
NON_MOVEABLE(KAutoObjectWithListContainer);
private:
public:
using ListType = util::IntrusiveRedBlackTreeMemberTraits<&KAutoObjectWithList::list_node>::TreeType<KAutoObjectWithList>;
public:
class ListAccessor : public KScopedLightLock {

View file

@ -522,6 +522,7 @@ namespace ams::kern {
return ConditionVariableThreadTreeTraits::IsValid();
}
static KThread *GetThreadFromId(u64 thread_id);
static Result GetThreadList(s32 *out_num_threads, ams::kern::svc::KUserPointer<u64 *> out_thread_ids, s32 max_out_count);
using ConditionVariableThreadTreeType = ConditionVariableThreadTree;

View file

@ -71,6 +71,7 @@ namespace ams::kern::svc {
/* 260 */ using ::ams::svc::ResultMessageTooLarge;
/* 517 */ using ::ams::svc::ResultInvalidProcessId;
/* 518 */ using ::ams::svc::ResultInvalidThreadId;
/* 520 */ using ::ams::svc::ResultProcessTerminated;
}

View file

@ -1190,6 +1190,41 @@ namespace ams::kern {
return std::addressof(this->GetContext());
}
KThread *KThread::GetThreadFromId(u64 thread_id) {
/* Lock the list. */
KThread::ListAccessor accessor;
const auto end = accessor.end();
/* Define helper object to find the thread. */
class IdObjectHelper : public KAutoObjectWithListContainer::ListType::value_type {
private:
u64 id;
public:
constexpr explicit IdObjectHelper(u64 id) : id(id) { /* ... */ }
virtual u64 GetId() const override { return this->id; }
};
/* Find the object with the right id. */
const auto it = accessor.find(IdObjectHelper(thread_id));
/* Check to make sure we found the thread. */
if (it == end) {
return nullptr;
}
/* Get the thread. */
KThread *thread = static_cast<KThread *>(std::addressof(*it));
/* Open the thread. */
if (AMS_LIKELY(thread->Open())) {
MESOSPHERE_ASSERT(thread->GetId() == thread_id);
return thread;
}
/* We failed to find the thread. */
return nullptr;
}
Result KThread::GetThreadList(s32 *out_num_threads, ams::kern::svc::KUserPointer<u64 *> out_thread_ids, s32 max_out_count) {
/* Lock the list. */
KThread::ListAccessor accessor;

View file

@ -246,6 +246,105 @@ namespace ams::kern::svc {
return ResultSuccess();
}
Result GetDebugThreadParam(uint64_t *out_64, uint32_t *out_32, ams::svc::Handle debug_handle, uint64_t thread_id, ams::svc::DebugThreadParam param) {
/* Get the debug object. */
KScopedAutoObject debug = GetCurrentProcess().GetHandleTable().GetObject<KDebug>(debug_handle);
R_UNLESS(debug.IsNotNull(), svc::ResultInvalidHandle());
/* Get the thread from its id. */
KScopedAutoObject thread = KThread::GetThreadFromId(thread_id);
R_UNLESS(thread.IsNotNull(), svc::ResultInvalidThreadId());
/* Get the process from the debug object. */
KScopedAutoObject process = debug->GetProcess();
R_UNLESS(process.IsNotNull(), svc::ResultProcessTerminated());
/* Verify that the process is the thread's parent. */
R_UNLESS(process.GetPointerUnsafe() == thread->GetOwnerProcess(), svc::ResultInvalidThreadId());
/* Get the parameter. */
switch (param) {
case ams::svc::DebugThreadParam_Priority:
{
/* Get the priority. */
*out_32 = thread->GetPriority();
}
break;
case ams::svc::DebugThreadParam_State:
{
/* Get the thread state and suspend status. */
KThread::ThreadState state;
bool suspended_user;
bool suspended_debug;
{
KScopedSchedulerLock sl;
state = thread->GetState();
suspended_user = thread->IsSuspendRequested(KThread::SuspendType_Thread);
suspended_debug = thread->IsSuspendRequested(KThread::SuspendType_Debug);
}
/* Set the suspend flags. */
*out_32 = 0;
if (suspended_user) {
*out_32 |= ams::svc::ThreadSuspend_User;
}
if (suspended_debug) {
*out_32 |= ams::svc::ThreadSuspend_Debug;
}
/* Set the state. */
switch (state) {
case KThread::ThreadState_Initialized:
{
*out_64 = ams::svc::ThreadState_Initializing;
}
break;
case KThread::ThreadState_Waiting:
{
*out_64 = ams::svc::ThreadState_Waiting;
}
break;
case KThread::ThreadState_Runnable:
{
*out_64 = ams::svc::ThreadState_Running;
}
break;
case KThread::ThreadState_Terminated:
{
*out_64 = ams::svc::ThreadState_Terminated;
}
break;
default:
return svc::ResultInvalidState();
}
}
break;
case ams::svc::DebugThreadParam_IdealCore:
{
/* Get the ideal core. */
*out_32 = thread->GetIdealCore();
}
break;
case ams::svc::DebugThreadParam_CurrentCore:
{
/* Get the current core. */
*out_32 = thread->GetActiveCore();
}
break;
case ams::svc::DebugThreadParam_AffinityMask:
{
/* Get the affinity mask. */
*out_32 = thread->GetAffinityMask().GetAffinityMask();
}
break;
default:
return ams::svc::ResultInvalidEnumValue();
}
return ResultSuccess();
}
}
/* ============================= 64 ABI ============================= */
@ -299,7 +398,7 @@ namespace ams::kern::svc {
}
Result GetDebugThreadParam64(uint64_t *out_64, uint32_t *out_32, ams::svc::Handle debug_handle, uint64_t thread_id, ams::svc::DebugThreadParam param) {
MESOSPHERE_PANIC("Stubbed SvcGetDebugThreadParam64 was called.");
return GetDebugThreadParam(out_64, out_32, debug_handle, thread_id, param);
}
/* ============================= 64From32 ABI ============================= */
@ -353,7 +452,7 @@ namespace ams::kern::svc {
}
Result GetDebugThreadParam64From32(uint64_t *out_64, uint32_t *out_32, ams::svc::Handle debug_handle, uint64_t thread_id, ams::svc::DebugThreadParam param) {
MESOSPHERE_PANIC("Stubbed SvcGetDebugThreadParam64From32 was called.");
return GetDebugThreadParam(out_64, out_32, debug_handle, thread_id, param);
}
}

View file

@ -74,6 +74,7 @@ namespace ams::svc {
R_DEFINE_ERROR_RESULT(MessageTooLarge, 260);
R_DEFINE_ERROR_RESULT(InvalidProcessId, 517);
R_DEFINE_ERROR_RESULT(InvalidThreadId, 518);
R_DEFINE_ERROR_RESULT(ProcessTerminated, 520);
}