fix a crash in debug builds where the compiler did not optimize
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Mon, 23 May 2011 09:41:52 +0000 (09:41 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Mon, 23 May 2011 09:41:52 +0000 (09:41 +0000)
ch->sfx-> to use a local variable holding the unchanging value of sfx
(the crash occurs when the mixer thread clears ch->sfx while the main
thread is deciding whether to merge a sound onto an existing channel -
if the channel dies during this code, the sfx pointer must be preserved)

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@11161 d7cf8633-e32d-0410-b094-e92efae38249

snd_main.c
snd_main.h
snd_mix.c

index fac45a4..9265cb6 100644 (file)
@@ -1200,6 +1200,7 @@ channel_t *SND_PickChannel(int entnum, int entchannel)
        int first_to_die;
        int first_life_left, life_left;
        channel_t* ch;
+       sfx_t *sfx; // use this instead of ch->sfx->, because that is volatile.
 
 // Check for replacement sound, or find the best one to replace
        first_to_die = -1;
@@ -1224,7 +1225,8 @@ channel_t *SND_PickChannel(int entnum, int entchannel)
        for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++)
        {
                ch = &channels[ch_idx];
-               if (!ch->sfx)
+               sfx = ch->sfx; // fetch the volatile variable
+               if (!sfx)
                {
                        // no sound on this channel
                        first_to_die = ch_idx;
@@ -1236,9 +1238,9 @@ channel_t *SND_PickChannel(int entnum, int entchannel)
                        continue;
 
                // don't override looped sounds
-               if ((ch->flags & CHANNELFLAG_FORCELOOP) || ch->sfx->loopstart < ch->sfx->total_length)
+               if ((ch->flags & CHANNELFLAG_FORCELOOP) || sfx->loopstart < sfx->total_length)
                        continue;
-               life_left = ch->sfx->total_length - ch->pos;
+               life_left = sfx->total_length - ch->pos;
 
                if (life_left < first_life_left)
                {
@@ -1852,6 +1854,7 @@ void S_UpdateAmbientSounds (void)
        int                     ambient_channel;
        channel_t       *chan;
        unsigned char           ambientlevels[NUM_AMBIENTS];
+       sfx_t           *sfx;
 
        memset(ambientlevels, 0, sizeof(ambientlevels));
        if (cl.worldmodel && cl.worldmodel->brush.AmbientSoundLevelsForPoint)
@@ -1861,7 +1864,8 @@ void S_UpdateAmbientSounds (void)
        for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++)
        {
                chan = &channels[ambient_channel];
-               if (chan->sfx == NULL || chan->sfx->fetcher == NULL)
+               sfx = chan->sfx; // fetch the volatile variable
+               if (sfx == NULL || sfx->fetcher == NULL)
                        continue;
 
                vol = (int)ambientlevels[ambient_channel];
index c7c631f..7419e9c 100644 (file)
@@ -86,7 +86,7 @@ typedef struct channel_s
 {
        int                     listener_volume [SND_LISTENERS];        // 0-65536 volume per speaker
        int                             master_vol;             // 0-65536 master volume
-       sfx_t                   *sfx;                   // sfx number
+       sfx_t                   *sfx;                   // pointer to sound sample being used
        unsigned int    flags;                  // cf CHANNELFLAG_* defines
        int                             pos;                    // sample position in sfx, negative values delay the start of the sound playback
        int                             entnum;                 // to allow overriding a specific sound
index 05abc83..cc425ba 100644 (file)
--- a/snd_mix.c
+++ b/snd_mix.c
@@ -186,6 +186,11 @@ static qboolean SND_PaintChannel (channel_t *ch, portable_sampleframe_t *paint,
        int vol[SND_LISTENERS];
        const snd_buffer_t *sb;
        unsigned int i, sb_offset;
+       sfx_t *sfx;
+
+       sfx = ch->sfx; // fetch the volatile variable
+       if (!sfx) // given that this is called by the mixer thread, this never happens, but...
+               return false;
 
        // move to the stack (do we need to?)
        for (i = 0;i < SND_LISTENERS;i++)
@@ -199,11 +204,11 @@ static qboolean SND_PaintChannel (channel_t *ch, portable_sampleframe_t *paint,
                return false;
 
        sb_offset = ch->pos;
-       sb = ch->sfx->fetcher->getsb (ch->sfx->fetcher_data, &ch->fetcher_data, &sb_offset, count);
+       sb = sfx->fetcher->getsb (sfx->fetcher_data, &ch->fetcher_data, &sb_offset, count);
        if (sb == NULL)
        {
                Con_DPrintf("SND_PaintChannel: ERROR: can't get sound buffer from sfx \"%s\"\n",
-                                       ch->sfx->name); // , count); // or add this? FIXME
+                                       sfx->name); // , count); // or add this? FIXME
                return false;
        }
        else