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);
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())

View File

@ -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();
}
}

View File

@ -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

View File

@ -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();
}
}

View File

@ -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.

View File

@ -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);