fix: use a mutex to pause emu thread

still not ideal imo
This commit is contained in:
Rekai Nyangadzayi Musuka 2023-12-15 04:10:51 -06:00
parent d54202bf8b
commit 9183e6850d
2 changed files with 14 additions and 32 deletions

View File

@ -17,13 +17,10 @@ const Timer = std.time.Timer;
pub const Synchro = struct { pub const Synchro = struct {
const AtomicBool = std.atomic.Atomic(bool); const AtomicBool = std.atomic.Atomic(bool);
// UI -> Emulator
ui_busy: AtomicBool = AtomicBool.init(false),
paused: AtomicBool = AtomicBool.init(true), // FIXME: can ui_busy and paused be the same? paused: AtomicBool = AtomicBool.init(true), // FIXME: can ui_busy and paused be the same?
should_quit: AtomicBool = AtomicBool.init(false), should_quit: AtomicBool = AtomicBool.init(false),
// Emulator -> UI emu_access: std.Thread.Mutex = .{},
did_pause: AtomicBool = AtomicBool.init(false),
}; };
/// 4 Cycles in 1 dot /// 4 Cycles in 1 dot
@ -71,18 +68,16 @@ fn inner(comptime kind: RunKind, audio_sync: bool, cpu: *Arm7tdmi, scheduler: *S
const bus_ptr: *Bus = @ptrCast(@alignCast(cpu.bus.ptr)); const bus_ptr: *Bus = @ptrCast(@alignCast(cpu.bus.ptr));
// FIXME: audioSync accesses emulator state without any guarantees
switch (kind) { switch (kind) {
.Unlimited, .UnlimitedFPS => { .Unlimited, .UnlimitedFPS => {
log.info("Emulation w/out video sync", .{}); log.info("Emulation w/out video sync", .{});
while (!sync.should_quit.load(.Monotonic)) { while (!sync.should_quit.load(.Monotonic)) {
if (sync.ui_busy.load(.Monotonic) or sync.paused.load(.Monotonic)) { if (sync.paused.load(.Monotonic)) continue;
sync.did_pause.store(true, .Monotonic);
continue; runFrame(sync, scheduler, cpu);
}
runFrame(scheduler, cpu);
audioSync(audio_sync, bus_ptr.apu.stream, &bus_ptr.apu.is_buffer_full); audioSync(audio_sync, bus_ptr.apu.stream, &bus_ptr.apu.is_buffer_full);
if (kind == .UnlimitedFPS) tracker.?.tick(); if (kind == .UnlimitedFPS) tracker.?.tick();
@ -94,13 +89,9 @@ fn inner(comptime kind: RunKind, audio_sync: bool, cpu: *Arm7tdmi, scheduler: *S
var wake_time: u64 = frame_period; var wake_time: u64 = frame_period;
while (!sync.should_quit.load(.Monotonic)) { while (!sync.should_quit.load(.Monotonic)) {
if (sync.ui_busy.load(.Monotonic) or sync.paused.load(.Monotonic)) { if (sync.paused.load(.Monotonic)) continue;
sync.did_pause.store(true, .Release);
continue; runFrame(sync, scheduler, cpu);
}
runFrame(scheduler, cpu);
const new_wake_time = videoSync(&timer, wake_time); const new_wake_time = videoSync(&timer, wake_time);
// Spin to make up the difference of OS scheduler innacuracies // Spin to make up the difference of OS scheduler innacuracies
@ -118,7 +109,10 @@ fn inner(comptime kind: RunKind, audio_sync: bool, cpu: *Arm7tdmi, scheduler: *S
} }
} }
pub fn runFrame(sched: *Scheduler, cpu: *Arm7tdmi) void { pub fn runFrame(sync: *Synchro, sched: *Scheduler, cpu: *Arm7tdmi) void {
sync.emu_access.lock();
defer sync.emu_access.unlock();
const frame_end = sched.tick + cycles_per_frame; const frame_end = sched.tick + cycles_per_frame;
while (sched.tick < frame_end) { while (sched.tick < frame_end) {

View File

@ -206,21 +206,9 @@ pub const Gui = struct {
self.state.emulation = .Inactive; self.state.emulation = .Inactive;
}, },
}, },
.Active => blk: { .Active => {
sync.ui_busy.store(true, .Monotonic); sync.emu_access.lock();
defer sync.ui_busy.store(false, .Monotonic); defer sync.emu_access.unlock();
// spin until we know the emu is paused :)
const timeout = 0x100000;
wait_loop: for (0..timeout) |i| {
const ret = sync.did_pause.compareAndSwap(true, false, .Acquire, .Monotonic);
if (ret == null) break :wait_loop;
if (i == timeout - 1) break :blk;
}
// while (sync.did_pause.compareAndSwap(true, false, .Acquire, .Acquire) != null) std.atomic.spinLoopHint();
// Add FPS count to the histogram // Add FPS count to the histogram
if (tracker) |t| self.state.fps_hist.push(t.value()) catch {}; if (tracker) |t| self.state.fps_hist.push(t.value()) catch {};