diff options
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/hle/kernel/errors.h | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 38 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 24 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.h | 14 | 
4 files changed, 72 insertions, 6 deletions
| diff --git a/src/core/hle/kernel/errors.h b/src/core/hle/kernel/errors.h index 8b58d701d..d8240ec6d 100644 --- a/src/core/hle/kernel/errors.h +++ b/src/core/hle/kernel/errors.h @@ -27,7 +27,7 @@ constexpr ResultCode ERR_SYNCHRONIZATION_CANCELED{ErrorModule::Kernel, 118};  constexpr ResultCode ERR_OUT_OF_RANGE{ErrorModule::Kernel, 119};  constexpr ResultCode ERR_INVALID_ENUM_VALUE{ErrorModule::Kernel, 120};  constexpr ResultCode ERR_NOT_FOUND{ErrorModule::Kernel, 121}; -constexpr ResultCode ERR_ALREADY_REGISTERED{ErrorModule::Kernel, 122}; +constexpr ResultCode ERR_BUSY{ErrorModule::Kernel, 122};  constexpr ResultCode ERR_SESSION_CLOSED_BY_REMOTE{ErrorModule::Kernel, 123};  constexpr ResultCode ERR_INVALID_STATE{ErrorModule::Kernel, 125};  constexpr ResultCode ERR_RESOURCE_LIMIT_EXCEEDED{ErrorModule::Kernel, 132}; diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 948989b31..72da3eb3d 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -851,8 +851,35 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)  }  /// Sets the thread activity -static ResultCode SetThreadActivity(Handle handle, u32 unknown) { -    LOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x{:08X}, unknown=0x{:08X}", handle, unknown); +static ResultCode SetThreadActivity(Handle handle, u32 activity) { +    LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", handle, activity); +    if (activity > static_cast<u32>(ThreadActivity::Paused)) { +        return ERR_INVALID_ENUM_VALUE; +    } + +    const auto* current_process = Core::CurrentProcess(); +    const SharedPtr<Thread> thread = current_process->GetHandleTable().Get<Thread>(handle); +    if (!thread) { +        LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", handle); +        return ERR_INVALID_HANDLE; +    } + +    if (thread->GetOwnerProcess() != current_process) { +        LOG_ERROR(Kernel_SVC, +                  "The current process does not own the current thread, thread_handle={:08X} " +                  "thread_pid={}, " +                  "current_process_pid={}", +                  handle, thread->GetOwnerProcess()->GetProcessID(), +                  current_process->GetProcessID()); +        return ERR_INVALID_HANDLE; +    } + +    if (thread == GetCurrentThread()) { +        LOG_ERROR(Kernel_SVC, "The thread handle specified is the current running thread"); +        return ERR_BUSY; +    } + +    thread->SetActivity(static_cast<ThreadActivity>(activity));      return RESULT_SUCCESS;  } @@ -879,7 +906,7 @@ static ResultCode GetThreadContext(VAddr thread_context, Handle handle) {      if (thread == GetCurrentThread()) {          LOG_ERROR(Kernel_SVC, "The thread handle specified is the current running thread"); -        return ERR_ALREADY_REGISTERED; +        return ERR_BUSY;      }      Core::ARM_Interface::ThreadContext ctx = thread->GetContext(); @@ -1157,7 +1184,10 @@ static ResultCode StartThread(Handle thread_handle) {      ASSERT(thread->GetStatus() == ThreadStatus::Dormant);      thread->ResumeFromWait(); -    Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule(); + +    if (thread->GetStatus() == ThreadStatus::Ready) { +        Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule(); +    }      return RESULT_SUCCESS;  } diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 4ffb76818..748c45dd7 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -50,7 +50,7 @@ void Thread::Stop() {      // Clean up thread from ready queue      // This is only needed when the thread is terminated forcefully (SVC TerminateProcess) -    if (status == ThreadStatus::Ready) { +    if (status == ThreadStatus::Ready || status == ThreadStatus::Paused) {          scheduler->UnscheduleThread(this, current_priority);      } @@ -140,6 +140,11 @@ void Thread::ResumeFromWait() {      wakeup_callback = nullptr; +    if (activity == ThreadActivity::Paused) { +        status = ThreadStatus::Paused; +        return; +    } +      status = ThreadStatus::Ready;      ChangeScheduler(); @@ -388,6 +393,23 @@ bool Thread::InvokeWakeupCallback(ThreadWakeupReason reason, SharedPtr<Thread> t      return wakeup_callback(reason, std::move(thread), std::move(object), index);  } +void Thread::SetActivity(ThreadActivity value) { +    activity = value; + +    if (value == ThreadActivity::Paused) { +        // Set status if not waiting +        if (status == ThreadStatus::Ready) { +            status = ThreadStatus::Paused; +        } else if (status == ThreadStatus::Running) { +            status = ThreadStatus::Paused; +            Core::System::GetInstance().CpuCore(processor_id).PrepareReschedule(); +        } +    } else if (status == ThreadStatus::Paused) { +        // Ready to reschedule +        ResumeFromWait(); +    } +} +  ////////////////////////////////////////////////////////////////////////////////////////////////////  /** diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index d384d50db..268bf845b 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -44,6 +44,7 @@ enum ThreadProcessorId : s32 {  enum class ThreadStatus {      Running,      ///< Currently running      Ready,        ///< Ready to run +    Paused,       ///< Paused by SetThreadActivity or debug      WaitHLEEvent, ///< Waiting for hle event to finish      WaitSleep,    ///< Waiting due to a SleepThread SVC      WaitIPC,      ///< Waiting for the reply from an IPC request @@ -60,6 +61,11 @@ enum class ThreadWakeupReason {      Timeout // The thread was woken up due to a wait timeout.  }; +enum class ThreadActivity : u32 { +    Normal = 0, +    Paused = 1, +}; +  class Thread final : public WaitObject {  public:      using TLSMemory = std::vector<u8>; @@ -370,6 +376,12 @@ public:          return affinity_mask;      } +    ThreadActivity GetActivity() const { +        return activity; +    } + +    void SetActivity(ThreadActivity value); +  private:      explicit Thread(KernelCore& kernel);      ~Thread() override; @@ -438,6 +450,8 @@ private:      TLSMemoryPtr tls_memory = std::make_shared<TLSMemory>();      std::string name; + +    ThreadActivity activity = ThreadActivity::Normal;  };  /** | 
