mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-29 22:54:16 +01:00
Ensure that threads are ready before their preemption timer can be
armed. It was discovered during testing of 'Hatsune Miku Project DIVA: Mega Mix' that if a thread was starting while preemption was being enabled a NULL pointer dereference could occur in the timer_settime call as timer_create may not have been called yet.
This commit is contained in:
parent
a7dc69223b
commit
af5ee96b9a
@ -231,6 +231,9 @@ namespace skyline::kernel::type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void KThread::ArmPreemptionTimer(std::chrono::nanoseconds timeToFire) {
|
void KThread::ArmPreemptionTimer(std::chrono::nanoseconds timeToFire) {
|
||||||
|
std::unique_lock lock(statusMutex);
|
||||||
|
statusCondition.wait(lock, [this]() { return ready || killed; });
|
||||||
|
if (!killed && running) {
|
||||||
struct itimerspec spec{.it_value = {
|
struct itimerspec spec{.it_value = {
|
||||||
.tv_nsec = std::min(timeToFire.count(), static_cast<long long>(constant::NsInSecond)),
|
.tv_nsec = std::min(timeToFire.count(), static_cast<long long>(constant::NsInSecond)),
|
||||||
.tv_sec = std::max(std::chrono::duration_cast<std::chrono::seconds>(timeToFire).count() - 1, 0LL),
|
.tv_sec = std::max(std::chrono::duration_cast<std::chrono::seconds>(timeToFire).count() - 1, 0LL),
|
||||||
@ -238,9 +241,15 @@ namespace skyline::kernel::type {
|
|||||||
timer_settime(preemptionTimer, 0, &spec, nullptr);
|
timer_settime(preemptionTimer, 0, &spec, nullptr);
|
||||||
isPreempted = true;
|
isPreempted = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void KThread::DisarmPreemptionTimer() {
|
void KThread::DisarmPreemptionTimer() {
|
||||||
if (isPreempted) {
|
if (!isPreempted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::unique_lock lock(statusMutex);
|
||||||
|
statusCondition.wait(lock, [this]() { return ready || killed; });
|
||||||
|
if (!killed && running) {
|
||||||
struct itimerspec spec{};
|
struct itimerspec spec{};
|
||||||
timer_settime(preemptionTimer, 0, &spec, nullptr);
|
timer_settime(preemptionTimer, 0, &spec, nullptr);
|
||||||
isPreempted = false;
|
isPreempted = false;
|
||||||
|
Loading…
Reference in New Issue
Block a user