mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +00:00
kern: SvcGetDebugThreadParam
This commit is contained in:
parent
e1f3bb10a5
commit
3afd723b92
6 changed files with 140 additions and 3 deletions
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue