1
0
Fork 0

Fix: Data races on MixerChannel active states

pull/8425/head
Jonathan G Rennison 2022-11-07 21:19:06 +00:00 committed by Michael Lutz
parent 5d6cdf4385
commit a962d7476b
1 changed files with 24 additions and 24 deletions

View File

@ -10,6 +10,7 @@
#include "stdafx.h" #include "stdafx.h"
#include <math.h> #include <math.h>
#include <mutex> #include <mutex>
#include <atomic>
#include "core/math_func.hpp" #include "core/math_func.hpp"
#include "framerate_type.h" #include "framerate_type.h"
#include "settings_type.h" #include "settings_type.h"
@ -18,8 +19,6 @@
#include "mixer.h" #include "mixer.h"
struct MixerChannel { struct MixerChannel {
bool active;
/* pointer to allocated buffer memory */ /* pointer to allocated buffer memory */
int8 *memory; int8 *memory;
@ -36,6 +35,7 @@ struct MixerChannel {
bool is16bit; bool is16bit;
}; };
static std::atomic<uint8> _active_channels;
static MixerChannel _channels[8]; static MixerChannel _channels[8];
static uint32 _play_rate = 11025; static uint32 _play_rate = 11025;
static uint32 _max_size = UINT_MAX; static uint32 _max_size = UINT_MAX;
@ -135,9 +135,9 @@ static void mix_int8_to_int16(MixerChannel *sc, int16 *buffer, uint samples, uin
sc->pos = b - sc->memory; sc->pos = b - sc->memory;
} }
static void MxCloseChannel(MixerChannel *mc) static void MxCloseChannel(uint8 channel_index)
{ {
mc->active = false; _active_channels.fetch_and(~(1 << channel_index), std::memory_order_release);
} }
void MxMixSamples(void *buffer, uint samples) void MxMixSamples(void *buffer, uint samples)
@ -149,8 +149,6 @@ void MxMixSamples(void *buffer, uint samples)
last_samples = samples; last_samples = samples;
} }
MixerChannel *mc;
/* Clear the buffer */ /* Clear the buffer */
memset(buffer, 0, sizeof(int16) * 2 * samples); memset(buffer, 0, sizeof(int16) * 2 * samples);
@ -169,30 +167,31 @@ void MxMixSamples(void *buffer, uint samples)
_settings_client.music.effect_vol) / (127 * 127); _settings_client.music.effect_vol) / (127 * 127);
/* Mix each channel */ /* Mix each channel */
for (mc = _channels; mc != endof(_channels); mc++) { uint8 active = _active_channels.load(std::memory_order_acquire);
if (mc->active) { for (uint8 idx : SetBitIterator(active)) {
MixerChannel *mc = &_channels[idx];
if (mc->is16bit) { if (mc->is16bit) {
mix_int16(mc, (int16*)buffer, samples, effect_vol); mix_int16(mc, (int16*)buffer, samples, effect_vol);
} else { } else {
mix_int8_to_int16(mc, (int16*)buffer, samples, effect_vol); mix_int8_to_int16(mc, (int16*)buffer, samples, effect_vol);
} }
if (mc->samples_left == 0) MxCloseChannel(mc); if (mc->samples_left == 0) MxCloseChannel(idx);
}
} }
} }
MixerChannel *MxAllocateChannel() MixerChannel *MxAllocateChannel()
{ {
MixerChannel *mc; uint8 currently_active = _active_channels.load(std::memory_order_acquire);
for (mc = _channels; mc != endof(_channels); mc++) { uint8 available = ~currently_active;
if (!mc->active) { if (available == 0) return nullptr;
uint8 channel_index = FindFirstBit(available);
MixerChannel *mc = &_channels[channel_index];
free(mc->memory); free(mc->memory);
mc->memory = nullptr; mc->memory = nullptr;
return mc; return mc;
} }
}
return nullptr;
}
void MxSetChannelRawSrc(MixerChannel *mc, int8 *mem, size_t size, uint rate, bool is16bit) void MxSetChannelRawSrc(MixerChannel *mc, int8 *mem, size_t size, uint rate, bool is16bit)
{ {
@ -231,7 +230,8 @@ void MxSetChannelVolume(MixerChannel *mc, uint volume, float pan)
void MxActivateChannel(MixerChannel *mc) void MxActivateChannel(MixerChannel *mc)
{ {
mc->active = true; uint8 channel_index = mc - _channels;
_active_channels.fetch_or((1 << channel_index), std::memory_order_release);
} }
/** /**