From c522658d19f7e82748400731bddb4633847c2a40 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 15 May 2016 13:44:32 -0700 Subject: Avoid duplicate effect state objects in the freelist If an unapplied update was superceded, it would be placed in the freelist with its effect state object intact. This would cause another update with the same effect state object to be placed into the freelist as well, or worse, cause it to get deleted while in use when the container had its effect state cleared. --- OpenAL32/alAuxEffectSlot.c | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/OpenAL32/alAuxEffectSlot.c b/OpenAL32/alAuxEffectSlot.c index 0dd6a53f..9cc86563 100644 --- a/OpenAL32/alAuxEffectSlot.c +++ b/OpenAL32/alAuxEffectSlot.c @@ -549,12 +549,12 @@ ALenum InitEffectSlot(ALeffectslot *slot) void DeinitEffectSlot(ALeffectslot *slot) { struct ALeffectslotProps *props; + ALeffectState *state; size_t count = 0; props = ATOMIC_LOAD(&slot->Update); if(props) { - ALeffectState *state; state = ATOMIC_LOAD(&props->State, almemory_order_relaxed); if(state != slot->Params.EffectState) DELETE_OBJ(state); @@ -565,7 +565,6 @@ void DeinitEffectSlot(ALeffectslot *slot) while(props) { struct ALeffectslotProps *next; - ALeffectState *state; state = ATOMIC_LOAD(&props->State, almemory_order_relaxed); next = ATOMIC_LOAD(&props->next, almemory_order_relaxed); DELETE_OBJ(state); @@ -583,18 +582,32 @@ void UpdateEffectSlotProps(ALeffectslot *slot) struct ALeffectslotProps *props; ALeffectState *oldstate; - /* Get an unused property container, or allocate a new one as needed. */ - props = ATOMIC_LOAD(&slot->FreeList, almemory_order_acquire); - if(!props) - props = al_calloc(16, sizeof(*props)); + props = ATOMIC_EXCHANGE(struct ALeffectslotProps*, &slot->Update, NULL); + if(props) + { + /* If there was an unapplied update, check if its state object is the + * same as the current in-use one, or the one that will be set. If + * neither, delete it. + */ + oldstate = ATOMIC_EXCHANGE(ALeffectState*, &props->State, NULL, almemory_order_relaxed); + if(oldstate != slot->Params.EffectState && oldstate != slot->Effect.State) + DELETE_OBJ(oldstate); + } else { - struct ALeffectslotProps *next; - do { - next = ATOMIC_LOAD(&props->next, almemory_order_relaxed); - } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALeffectslotProps*, - &slot->FreeList, &props, next, almemory_order_seq_cst, - almemory_order_consume) == 0); + /* Get an unused property container, or allocate a new one as needed. */ + props = ATOMIC_LOAD(&slot->FreeList, almemory_order_relaxed); + if(!props) + props = al_calloc(16, sizeof(*props)); + else + { + struct ALeffectslotProps *next; + do { + next = ATOMIC_LOAD(&props->next, almemory_order_relaxed); + } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALeffectslotProps*, + &slot->FreeList, &props, next, almemory_order_seq_cst, + almemory_order_consume) == 0); + } } /* Copy in current property values. */ -- cgit v1.2.3