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:
◱ PixelyIon 2019-11-15 19:49:24 +05:30 committed by ◱ PixelyIon
parent b3517357e1
commit 423540328a
6 changed files with 33 additions and 9 deletions

View File

@ -185,6 +185,7 @@ namespace skyline::kernel::svc {
std::vector<handle_t> waitHandles(numHandles); std::vector<handle_t> waitHandles(numHandles);
state.thisProcess->ReadMemory(waitHandles.data(), state.nce->GetRegister(Xreg::X1), numHandles * sizeof(handle_t)); state.thisProcess->ReadMemory(waitHandles.data(), state.nce->GetRegister(Xreg::X1), numHandles * sizeof(handle_t));
std::string handleStr; std::string handleStr;
uint index{};
for (const auto &handle : waitHandles) { for (const auto &handle : waitHandles) {
handleStr += fmt::format("* 0x{:X}\n", handle); handleStr += fmt::format("* 0x{:X}\n", handle);
auto object = state.thisProcess->handleTable.at(handle); auto object = state.thisProcess->handleTable.at(handle);
@ -194,19 +195,22 @@ namespace skyline::kernel::svc {
case type::KType::KEvent: case type::KType::KEvent:
case type::KType::KSession: case type::KType::KSession:
break; break;
default: default: {
state.nce->SetRegister(Wreg::W0, constant::status::InvHandle); state.nce->SetRegister(Wreg::W0, constant::status::InvHandle);
state.thisThread->ClearWaitObjects();
return; return;
}
} }
auto syncObject = std::static_pointer_cast<type::KSyncObject>(object); auto syncObject = std::static_pointer_cast<type::KSyncObject>(object);
if (syncObject->signalled) { if (syncObject->signalled) {
state.logger->Debug("Found signalled handle: 0x{:X}", handle); state.logger->Debug("Found signalled handle: 0x{:X}", handle);
state.nce->SetRegister(Wreg::W0, constant::status::Success); state.nce->SetRegister(Wreg::W0, constant::status::Success);
state.nce->SetRegister(Wreg::W1, handle); state.nce->SetRegister(Wreg::W1, index);
state.thisThread->ClearWaitObjects();
return; return;
} }
state.thisThread->waitObjects.push_back(syncObject); 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)); 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()) if (state.nce->GetRegister(Xreg::X3) != std::numeric_limits<u64>::max())

View File

@ -4,12 +4,13 @@
namespace skyline::kernel::type { namespace skyline::kernel::type {
KSyncObject::KSyncObject(const skyline::DeviceState &state, skyline::kernel::type::KType type) : KObject(state, 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() { void KSyncObject::Signal() {
for (const auto &info : waitThreads) { 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; state.os->processMap.at(info.process)->threadMap.at(info.process)->status = KThread::Status::Runnable;
} }
waitThreads.clear();
} }
} }

View File

@ -15,9 +15,9 @@ namespace skyline::kernel::type {
*/ */
struct threadInfo { struct threadInfo {
pid_t process; //!< The PID of the waiting thread 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 std::vector<threadInfo> waitThreads; //!< A vector of threads waiting on this object

View File

@ -37,4 +37,18 @@ namespace skyline::kernel::type {
if (status == Status::Sleeping) if (status == Status::Sleeping)
status = Status::Runnable; 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();
}
} }

View File

@ -22,7 +22,7 @@ namespace skyline::kernel::type {
WaitCondVar, //!< The thread is waiting on a Conditional Variable WaitCondVar, //!< The thread is waiting on a Conditional Variable
Runnable //!< The thread is ready to run after waiting Runnable //!< The thread is ready to run after waiting
} status = Status::Created; //!< The state of the thread } 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 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 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]) 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(); void WakeUp();
/**
* @brief This clears all the objects in the waitObjects vector
*/
void ClearWaitObjects();
/** /**
* @brief Update the priority level for the process. * @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. * @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.

View File

@ -78,7 +78,7 @@ namespace skyline {
} }
} }
if (state.thisThread->status == kernel::type::KThread::Status::Runnable) { if (state.thisThread->status == kernel::type::KThread::Status::Runnable) {
state.thisThread->waitObjects.clear(); state.thisThread->ClearWaitObjects();
state.thisThread->status = kernel::type::KThread::Status::Running; state.thisThread->status = kernel::type::KThread::Status::Running;
currRegs.pc += sizeof(u32); currRegs.pc += sizeof(u32);
WriteRegisters(currRegs); WriteRegisters(currRegs);