mirror of
https://github.com/yuzu-emu/yuzu.git
synced 2024-07-04 23:31:19 +01:00
Merge pull request #1849 from encounter/svcSetThreadActivity
svc: Implement SetThreadActivity (thread suspension)
This commit is contained in:
commit
ae582b6669
5 changed files with 77 additions and 6 deletions
|
@ -27,7 +27,7 @@ constexpr ResultCode ERR_SYNCHRONIZATION_CANCELED{ErrorModule::Kernel, 118};
|
||||||
constexpr ResultCode ERR_OUT_OF_RANGE{ErrorModule::Kernel, 119};
|
constexpr ResultCode ERR_OUT_OF_RANGE{ErrorModule::Kernel, 119};
|
||||||
constexpr ResultCode ERR_INVALID_ENUM_VALUE{ErrorModule::Kernel, 120};
|
constexpr ResultCode ERR_INVALID_ENUM_VALUE{ErrorModule::Kernel, 120};
|
||||||
constexpr ResultCode ERR_NOT_FOUND{ErrorModule::Kernel, 121};
|
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_SESSION_CLOSED_BY_REMOTE{ErrorModule::Kernel, 123};
|
||||||
constexpr ResultCode ERR_INVALID_STATE{ErrorModule::Kernel, 125};
|
constexpr ResultCode ERR_INVALID_STATE{ErrorModule::Kernel, 125};
|
||||||
constexpr ResultCode ERR_RESOURCE_LIMIT_EXCEEDED{ErrorModule::Kernel, 132};
|
constexpr ResultCode ERR_RESOURCE_LIMIT_EXCEEDED{ErrorModule::Kernel, 132};
|
||||||
|
|
|
@ -932,8 +932,35 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the thread activity
|
/// Sets the thread activity
|
||||||
static ResultCode SetThreadActivity(Handle handle, u32 unknown) {
|
static ResultCode SetThreadActivity(Handle handle, u32 activity) {
|
||||||
LOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x{:08X}, unknown=0x{:08X}", handle, unknown);
|
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;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -960,7 +987,7 @@ static ResultCode GetThreadContext(VAddr thread_context, Handle handle) {
|
||||||
|
|
||||||
if (thread == GetCurrentThread()) {
|
if (thread == GetCurrentThread()) {
|
||||||
LOG_ERROR(Kernel_SVC, "The thread handle specified is the current running thread");
|
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();
|
Core::ARM_Interface::ThreadContext ctx = thread->GetContext();
|
||||||
|
@ -1245,7 +1272,10 @@ static ResultCode StartThread(Handle thread_handle) {
|
||||||
ASSERT(thread->GetStatus() == ThreadStatus::Dormant);
|
ASSERT(thread->GetStatus() == ThreadStatus::Dormant);
|
||||||
|
|
||||||
thread->ResumeFromWait();
|
thread->ResumeFromWait();
|
||||||
|
|
||||||
|
if (thread->GetStatus() == ThreadStatus::Ready) {
|
||||||
Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule();
|
Core::System::GetInstance().CpuCore(thread->GetProcessorID()).PrepareReschedule();
|
||||||
|
}
|
||||||
|
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ void Thread::Stop() {
|
||||||
|
|
||||||
// Clean up thread from ready queue
|
// Clean up thread from ready queue
|
||||||
// This is only needed when the thread is terminated forcefully (SVC TerminateProcess)
|
// 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);
|
scheduler->UnscheduleThread(this, current_priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,6 +140,11 @@ void Thread::ResumeFromWait() {
|
||||||
|
|
||||||
wakeup_callback = nullptr;
|
wakeup_callback = nullptr;
|
||||||
|
|
||||||
|
if (activity == ThreadActivity::Paused) {
|
||||||
|
status = ThreadStatus::Paused;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
status = ThreadStatus::Ready;
|
status = ThreadStatus::Ready;
|
||||||
|
|
||||||
ChangeScheduler();
|
ChangeScheduler();
|
||||||
|
@ -391,6 +396,23 @@ bool Thread::InvokeWakeupCallback(ThreadWakeupReason reason, SharedPtr<Thread> t
|
||||||
return wakeup_callback(reason, std::move(thread), std::move(object), index);
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -45,6 +45,7 @@ enum ThreadProcessorId : s32 {
|
||||||
enum class ThreadStatus {
|
enum class ThreadStatus {
|
||||||
Running, ///< Currently running
|
Running, ///< Currently running
|
||||||
Ready, ///< Ready to run
|
Ready, ///< Ready to run
|
||||||
|
Paused, ///< Paused by SetThreadActivity or debug
|
||||||
WaitHLEEvent, ///< Waiting for hle event to finish
|
WaitHLEEvent, ///< Waiting for hle event to finish
|
||||||
WaitSleep, ///< Waiting due to a SleepThread SVC
|
WaitSleep, ///< Waiting due to a SleepThread SVC
|
||||||
WaitIPC, ///< Waiting for the reply from an IPC request
|
WaitIPC, ///< Waiting for the reply from an IPC request
|
||||||
|
@ -61,6 +62,11 @@ enum class ThreadWakeupReason {
|
||||||
Timeout // The thread was woken up due to a wait timeout.
|
Timeout // The thread was woken up due to a wait timeout.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class ThreadActivity : u32 {
|
||||||
|
Normal = 0,
|
||||||
|
Paused = 1,
|
||||||
|
};
|
||||||
|
|
||||||
class Thread final : public WaitObject {
|
class Thread final : public WaitObject {
|
||||||
public:
|
public:
|
||||||
using TLSMemory = std::vector<u8>;
|
using TLSMemory = std::vector<u8>;
|
||||||
|
@ -371,6 +377,12 @@ public:
|
||||||
return affinity_mask;
|
return affinity_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ThreadActivity GetActivity() const {
|
||||||
|
return activity;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetActivity(ThreadActivity value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit Thread(KernelCore& kernel);
|
explicit Thread(KernelCore& kernel);
|
||||||
~Thread() override;
|
~Thread() override;
|
||||||
|
@ -439,6 +451,8 @@ private:
|
||||||
TLSMemoryPtr tls_memory = std::make_shared<TLSMemory>();
|
TLSMemoryPtr tls_memory = std::make_shared<TLSMemory>();
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
|
|
||||||
|
ThreadActivity activity = ThreadActivity::Normal;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -221,6 +221,9 @@ QString WaitTreeThread::GetText() const {
|
||||||
case Kernel::ThreadStatus::Ready:
|
case Kernel::ThreadStatus::Ready:
|
||||||
status = tr("ready");
|
status = tr("ready");
|
||||||
break;
|
break;
|
||||||
|
case Kernel::ThreadStatus::Paused:
|
||||||
|
status = tr("paused");
|
||||||
|
break;
|
||||||
case Kernel::ThreadStatus::WaitHLEEvent:
|
case Kernel::ThreadStatus::WaitHLEEvent:
|
||||||
status = tr("waiting for HLE return");
|
status = tr("waiting for HLE return");
|
||||||
break;
|
break;
|
||||||
|
@ -262,6 +265,8 @@ QColor WaitTreeThread::GetColor() const {
|
||||||
return QColor(Qt::GlobalColor::darkGreen);
|
return QColor(Qt::GlobalColor::darkGreen);
|
||||||
case Kernel::ThreadStatus::Ready:
|
case Kernel::ThreadStatus::Ready:
|
||||||
return QColor(Qt::GlobalColor::darkBlue);
|
return QColor(Qt::GlobalColor::darkBlue);
|
||||||
|
case Kernel::ThreadStatus::Paused:
|
||||||
|
return QColor(Qt::GlobalColor::lightGray);
|
||||||
case Kernel::ThreadStatus::WaitHLEEvent:
|
case Kernel::ThreadStatus::WaitHLEEvent:
|
||||||
case Kernel::ThreadStatus::WaitIPC:
|
case Kernel::ThreadStatus::WaitIPC:
|
||||||
return QColor(Qt::GlobalColor::darkRed);
|
return QColor(Qt::GlobalColor::darkRed);
|
||||||
|
|
Loading…
Reference in a new issue