Work around a crashing race condition, proper fix needed

This commit is contained in:
Lior Halphon 2019-01-28 20:56:37 +02:00
parent b996ed9220
commit dde06e7cae
1 changed files with 12 additions and 8 deletions

View File

@ -472,33 +472,37 @@ void GB_apu_copy_buffer(GB_gameboy_t *gb, GB_sample_t *dest, size_t count)
} }
gb->apu_output.copy_in_progress = true; gb->apu_output.copy_in_progress = true;
/* TODO: Rewrite this as a proper cyclic buffer. This is a workaround to avoid a very rare crashing race condition */
size_t buffer_position = gb->apu_output.buffer_position;
if (!gb->apu_output.stream_started) { if (!gb->apu_output.stream_started) {
// Intentionally fail the first copy to sync the stream with the Gameboy. // Intentionally fail the first copy to sync the stream with the Gameboy.
gb->apu_output.stream_started = true; gb->apu_output.stream_started = true;
gb->apu_output.buffer_position = 0; gb->apu_output.buffer_position = 0;
buffer_position = 0;
} }
if (count > gb->apu_output.buffer_position) { if (count > buffer_position) {
// GB_log(gb, "Audio underflow: %d\n", count - gb->apu_output.buffer_position); // GB_log(gb, "Audio underflow: %d\n", count - gb->apu_output.buffer_position);
GB_sample_t output; GB_sample_t output;
render(gb, true, &output); render(gb, true, &output);
for (unsigned i = 0; i < count - gb->apu_output.buffer_position; i++) { for (unsigned i = 0; i < count - buffer_position; i++) {
dest[gb->apu_output.buffer_position + i] = output; dest[buffer_position + i] = output;
} }
if (gb->apu_output.buffer_position) { if (buffer_position) {
if (gb->apu_output.buffer_size + (count - gb->apu_output.buffer_position) < count * 3) { if (gb->apu_output.buffer_size + (count - buffer_position) < count * 3) {
gb->apu_output.buffer_size += count - gb->apu_output.buffer_position; gb->apu_output.buffer_size += count - buffer_position;
gb->apu_output.buffer = realloc(gb->apu_output.buffer, gb->apu_output.buffer = realloc(gb->apu_output.buffer,
gb->apu_output.buffer_size * sizeof(*gb->apu_output.buffer)); gb->apu_output.buffer_size * sizeof(*gb->apu_output.buffer));
gb->apu_output.stream_started = false; gb->apu_output.stream_started = false;
} }
} }
count = gb->apu_output.buffer_position; count = buffer_position;
} }
memcpy(dest, gb->apu_output.buffer, count * sizeof(*gb->apu_output.buffer)); memcpy(dest, gb->apu_output.buffer, count * sizeof(*gb->apu_output.buffer));
memmove(gb->apu_output.buffer, gb->apu_output.buffer + count, (gb->apu_output.buffer_position - count) * sizeof(*gb->apu_output.buffer)); memmove(gb->apu_output.buffer, gb->apu_output.buffer + count, (buffer_position - count) * sizeof(*gb->apu_output.buffer));
gb->apu_output.buffer_position -= count; gb->apu_output.buffer_position -= count;
gb->apu_output.copy_in_progress = false; gb->apu_output.copy_in_progress = false;