Commit 59fb10d0 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Add atomic swap and compare-and-swap

parent 1af9f7d3
...@@ -47,4 +47,7 @@ static inline uintptr_t vlc_atomic_dec (vlc_atomic_t *atom) ...@@ -47,4 +47,7 @@ static inline uintptr_t vlc_atomic_dec (vlc_atomic_t *atom)
return vlc_atomic_sub (atom, 1); return vlc_atomic_sub (atom, 1);
} }
VLC_EXPORT(uintptr_t, vlc_atomic_swap, (vlc_atomic_t *, uintptr_t));
VLC_EXPORT(uintptr_t, vlc_atomic_compare_swap, (vlc_atomic_t *, uintptr_t, uintptr_t));
#endif #endif
...@@ -503,6 +503,8 @@ VLC_Compiler ...@@ -503,6 +503,8 @@ VLC_Compiler
vlc_atomic_get vlc_atomic_get
vlc_atomic_set vlc_atomic_set
vlc_atomic_add vlc_atomic_add
vlc_atomic_swap
vlc_atomic_compare_swap
vlc_cond_broadcast vlc_cond_broadcast
vlc_cond_destroy vlc_cond_destroy
vlc_cond_init vlc_cond_init
......
...@@ -46,6 +46,24 @@ uintptr_t vlc_atomic_add (vlc_atomic_t *atom, uintptr_t v) ...@@ -46,6 +46,24 @@ uintptr_t vlc_atomic_add (vlc_atomic_t *atom, uintptr_t v)
return __sync_add_and_fetch (&atom->u, v); return __sync_add_and_fetch (&atom->u, v);
} }
uintptr_t vlc_atomic_swap (vlc_atomic_t *atom, uintptr_t v)
{
/* grmbl, gcc does not provide an intrinsic for this! */
uintptr_t u;
do
u = vlc_atomic_get (atom);
while (vlc_atomic_compare_swap (atom, u, v) != u);
return u;
}
uintptr_t vlc_atomic_compare_swap (vlc_atomic_t *atom,
uintptr_t oldval, uintptr_t newval)
{
return __sync_val_compare_and_swap (&atom->u, oldval, newval);
}
#else #else
/* Worst-case fallback implementation with a mutex */ /* Worst-case fallback implementation with a mutex */
...@@ -78,4 +96,30 @@ uintptr_t vlc_atomic_add (vlc_atomic_t *atom, uintptr_t v) ...@@ -78,4 +96,30 @@ uintptr_t vlc_atomic_add (vlc_atomic_t *atom, uintptr_t v)
return v; return v;
} }
uintptr_t vlc_atomic_swap (vlc_atomic_t *atom, uintptr_t v)
{
uintptr_t u;
vlc_mutex_lock (&lock);
u = atom->u;
atom->u = v;
vlc_mutex_unlock (&lock);
return u;
}
uintptr_t vlc_atomic_compare_and_swap (vlc_atomic_t *atom,
uintptr_t oldval, uintptr_t newval)
{
uintptr_t u;
vlc_mutex_lock (&lock);
u = atom->u;
if (u == oldval)
atom->u = newval;
vlc_mutex_unlock (&lock);
return u;
}
#endif #endif
...@@ -50,3 +50,22 @@ uintptr_t vlc_atomic_add (vlc_atomic_t *atom, uintptr_t v) ...@@ -50,3 +50,22 @@ uintptr_t vlc_atomic_add (vlc_atomic_t *atom, uintptr_t v)
return InterlockedExchangeAdd (&atom->s, v) + v; return InterlockedExchangeAdd (&atom->s, v) + v;
#endif #endif
} }
uintptr_t vlc_atomic_swap (vlc_atomic_t *atom, uintptr_t v)
{
#if defined (WIN64)
return InterlockedExchange64 (&atom->s, v);
#else
return InterlockedExchange (&atom->s, v);
#endif
}
uintptr_t vlc_atomic_compare_swap (vlc_atomic_t *atom,
uintptr_t oldval, uintptr_t newval)
{
#if defined (WIN64)
return InterlockedCompareExchange64 (&atom->s, newval, oldval);
#else
return InterlockedCompareExchange (&atom->s, newval, oldval);
#endif
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment