mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-26 15:04:16 +01:00
Fix svcWaitSynchronization
svcWaitSynchronization would return the handle of the object instead of the index of it's handle earlier, this is now fixed.
This commit is contained in:
parent
b3517357e1
commit
423540328a
@ -185,6 +185,7 @@ namespace skyline::kernel::svc {
|
||||
std::vector<handle_t> waitHandles(numHandles);
|
||||
state.thisProcess->ReadMemory(waitHandles.data(), state.nce->GetRegister(Xreg::X1), numHandles * sizeof(handle_t));
|
||||
std::string handleStr;
|
||||
uint index{};
|
||||
for (const auto &handle : waitHandles) {
|
||||
handleStr += fmt::format("* 0x{:X}\n", handle);
|
||||
auto object = state.thisProcess->handleTable.at(handle);
|
||||
@ -194,19 +195,22 @@ namespace skyline::kernel::svc {
|
||||
case type::KType::KEvent:
|
||||
case type::KType::KSession:
|
||||
break;
|
||||
default:
|
||||
default: {
|
||||
state.nce->SetRegister(Wreg::W0, constant::status::InvHandle);
|
||||
state.thisThread->ClearWaitObjects();
|
||||
return;
|
||||
}
|
||||
}
|
||||
auto syncObject = std::static_pointer_cast<type::KSyncObject>(object);
|
||||
if (syncObject->signalled) {
|
||||
state.logger->Debug("Found signalled handle: 0x{:X}", handle);
|
||||
state.nce->SetRegister(Wreg::W0, constant::status::Success);
|
||||
state.nce->SetRegister(Wreg::W1, handle);
|
||||
state.nce->SetRegister(Wreg::W1, index);
|
||||
state.thisThread->ClearWaitObjects();
|
||||
return;
|
||||
}
|
||||
state.thisThread->waitObjects.push_back(syncObject);
|
||||
syncObject->waitThreads.emplace_back(state.thisThread->pid, handle);
|
||||
syncObject->waitThreads.emplace_back(state.thisThread->pid, index);
|
||||
}
|
||||
state.logger->Debug("Waiting on handles:\n{}Timeout: 0x{:X} ns", handleStr, state.nce->GetRegister(Xreg::X3));
|
||||
if (state.nce->GetRegister(Xreg::X3) != std::numeric_limits<u64>::max())
|
||||
|
@ -4,12 +4,13 @@
|
||||
namespace skyline::kernel::type {
|
||||
KSyncObject::KSyncObject(const skyline::DeviceState &state, skyline::kernel::type::KType type) : KObject(state, type) {}
|
||||
|
||||
KSyncObject::threadInfo::threadInfo(pid_t process, handle_t handle) : process(process), handle(handle) {}
|
||||
KSyncObject::threadInfo::threadInfo(pid_t process, u32 index) : process(process), index(index) {}
|
||||
|
||||
void KSyncObject::Signal() {
|
||||
for (const auto &info : waitThreads) {
|
||||
state.nce->SetRegister(Wreg::W1, info.handle);
|
||||
state.nce->SetRegister(Wreg::W1, info.index);
|
||||
state.os->processMap.at(info.process)->threadMap.at(info.process)->status = KThread::Status::Runnable;
|
||||
}
|
||||
waitThreads.clear();
|
||||
}
|
||||
}
|
||||
|
@ -15,9 +15,9 @@ namespace skyline::kernel::type {
|
||||
*/
|
||||
struct threadInfo {
|
||||
pid_t process; //!< The PID of the waiting thread
|
||||
handle_t handle; //!< The handle in the process's handle table
|
||||
u32 index; //!< The index of the object in the wait list
|
||||
|
||||
threadInfo(pid_t process, handle_t handle);
|
||||
threadInfo(pid_t process, u32 index);
|
||||
};
|
||||
std::vector<threadInfo> waitThreads; //!< A vector of threads waiting on this object
|
||||
|
||||
|
@ -37,4 +37,18 @@ namespace skyline::kernel::type {
|
||||
if (status == Status::Sleeping)
|
||||
status = Status::Runnable;
|
||||
}
|
||||
|
||||
void KThread::ClearWaitObjects() {
|
||||
for (auto &object : waitObjects) {
|
||||
auto iter = object->waitThreads.begin();
|
||||
while (iter != object->waitThreads.end()) {
|
||||
if (iter->process == pid) {
|
||||
object->waitThreads.erase(iter);
|
||||
break;
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
waitObjects.clear();
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ namespace skyline::kernel::type {
|
||||
WaitCondVar, //!< The thread is waiting on a Conditional Variable
|
||||
Runnable //!< The thread is ready to run after waiting
|
||||
} status = Status::Created; //!< The state of the thread
|
||||
std::vector<std::shared_ptr<KSyncObject>> waitObjects; //!< A vector holding handles this thread is waiting for
|
||||
std::vector<std::shared_ptr<KSyncObject>> waitObjects; //!< A vector holding the objects this thread is waiting for
|
||||
u64 timeout{}; //!< The end of a timeout for svcWaitSynchronization or the end of the sleep period for svcSleepThread
|
||||
handle_t handle; // The handle of the object in the handle table
|
||||
pid_t pid; //!< The PID of the current thread (As in kernel PID and not PGID [In short, Linux implements threads as processes that share a lot of stuff at the kernel level])
|
||||
@ -63,6 +63,11 @@ namespace skyline::kernel::type {
|
||||
*/
|
||||
void WakeUp();
|
||||
|
||||
/**
|
||||
* @brief This clears all the objects in the waitObjects vector
|
||||
*/
|
||||
void ClearWaitObjects();
|
||||
|
||||
/**
|
||||
* @brief Update the priority level for the process.
|
||||
* @details Set the priority of the current thread to `priority` using setpriority [https://linux.die.net/man/3/setpriority]. We rescale the priority from Nintendo scale to that of Android.
|
||||
|
@ -78,7 +78,7 @@ namespace skyline {
|
||||
}
|
||||
}
|
||||
if (state.thisThread->status == kernel::type::KThread::Status::Runnable) {
|
||||
state.thisThread->waitObjects.clear();
|
||||
state.thisThread->ClearWaitObjects();
|
||||
state.thisThread->status = kernel::type::KThread::Status::Running;
|
||||
currRegs.pc += sizeof(u32);
|
||||
WriteRegisters(currRegs);
|
||||
|
Loading…
Reference in New Issue
Block a user