mirror of
https://github.com/Vita3K/Vita3K.git
synced 2026-07-25 00:14:33 +02:00
kernel/thread: Fix data race on to_do field
The inner execution loop in run_loop() reads and writes to_do without holding the mutex, while exit_delete() and suspend() modify it from other threads. This is a data race. Restructure the inner loop so that every access to to_do is under the mutex. The lock is acquired briefly to snapshot or modify to_do, then released before guest execution. The lock is held when the loop breaks out, matching the original post-loop lock state.
This commit is contained in:
@@ -258,21 +258,27 @@ bool ThreadState::run_loop() {
|
||||
}
|
||||
|
||||
// Run the cpu
|
||||
do {
|
||||
if (to_do == ThreadToDo::step) {
|
||||
res = step(*cpu);
|
||||
while (true) {
|
||||
lock.lock();
|
||||
if (to_do != ThreadToDo::run && to_do != ThreadToDo::step)
|
||||
break;
|
||||
if (res != 0 || call_level != run_level || hit_breakpoint(*cpu))
|
||||
break;
|
||||
const bool do_step = (to_do == ThreadToDo::step);
|
||||
if (do_step)
|
||||
to_do = ThreadToDo::suspend;
|
||||
lock.unlock();
|
||||
|
||||
} else
|
||||
if (do_step)
|
||||
res = step(*cpu);
|
||||
else
|
||||
res = run(*cpu);
|
||||
|
||||
// handle svc call if this was what stopped the cpu
|
||||
if (cpu->svc_called) {
|
||||
cpu->protocol->call_svc(*cpu, cpu->svc, read_pc(*cpu), *this);
|
||||
}
|
||||
} while (to_do == ThreadToDo::run && res == 0 && call_level == run_level && !hit_breakpoint(*cpu));
|
||||
|
||||
lock.lock();
|
||||
}
|
||||
|
||||
// Handle errors
|
||||
if (to_do == ThreadToDo::remove)
|
||||
|
||||
Reference in New Issue
Block a user