mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-30 05:34:18 +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);
|
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())
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user