]> git.sesse.net Git - vlc/commitdiff
Rewrite vlc_atomic_* using the new atomic operations
authorRémi Denis-Courmont <remi@remlab.net>
Fri, 11 May 2012 17:43:32 +0000 (20:43 +0300)
committerRémi Denis-Courmont <remi@remlab.net>
Fri, 11 May 2012 17:55:38 +0000 (20:55 +0300)
This way, the official atomic functions will be used when available,
rather than VLC's own implementation.

This commit also enables proper atomic operations on some platforms
or with some toolchains. __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 is not
defined on some platforms such as ARM Linux, nor by other compilers
than GCC such as LLVM/clang. Then atomic operations wrongly fell
back to the lame mutex-based implementation.

This will break support for some old compilers and old or irrelevant
instruction set architectures. They would need to provide replacement
for the Intel-originated __sync_* builtin functions.

include/vlc_atomic.h
src/Makefile.am
src/libvlccore.sym
src/misc/atomic.c [deleted file]
src/win32/atomic.c [deleted file]

index 11b2711e76cd02a1313336c11591b21ad1bf7201..8e891e7d42a20889b82cc9ea8ed1a20b91b739cc 100644 (file)
@@ -189,14 +189,25 @@ bool vlc_atomic_compare_exchange(volatile void *object, void *expected,
 # define VLC_ATOMIC_INIT(val) { (val) }
 
 /* All functions return the atom value _after_ the operation. */
+static inline uintptr_t vlc_atomic_get(const vlc_atomic_t *atom)
+{
+    return atomic_load(&atom->u);
+}
+
+static inline uintptr_t vlc_atomic_set(vlc_atomic_t *atom, uintptr_t v)
+{
+    atomic_store(&atom->u, v);
+    return v;
+}
 
-VLC_API uintptr_t vlc_atomic_get(const vlc_atomic_t *);
-VLC_API uintptr_t vlc_atomic_set(vlc_atomic_t *, uintptr_t);
-VLC_API uintptr_t vlc_atomic_add(vlc_atomic_t *, uintptr_t);
+static inline uintptr_t vlc_atomic_add(vlc_atomic_t *atom, uintptr_t v)
+{
+    return atomic_fetch_add(&atom->u, v) + v;
+}
 
 static inline uintptr_t vlc_atomic_sub (vlc_atomic_t *atom, uintptr_t v)
 {
-    return vlc_atomic_add (atom, -v);
+    return atomic_fetch_sub (&atom->u, v) - v;
 }
 
 static inline uintptr_t vlc_atomic_inc (vlc_atomic_t *atom)
@@ -209,8 +220,16 @@ static inline uintptr_t vlc_atomic_dec (vlc_atomic_t *atom)
     return vlc_atomic_sub (atom, 1);
 }
 
-VLC_API uintptr_t vlc_atomic_swap(vlc_atomic_t *, uintptr_t);
-VLC_API uintptr_t vlc_atomic_compare_swap(vlc_atomic_t *, uintptr_t, uintptr_t);
+static inline uintptr_t vlc_atomic_swap(vlc_atomic_t *atom, uintptr_t v)
+{
+    return atomic_exchange(&atom->u, v);
+}
+
+static inline uintptr_t vlc_atomic_compare_swap(vlc_atomic_t *atom,
+                                                uintptr_t u, uintptr_t v)
+{
+    return atomic_compare_exchange_strong(&atom->u, &u, v);
+}
 
 /** Helper to retrieve a single precision from an atom. */
 static inline float vlc_atomic_getf(const vlc_atomic_t *atom)
index 69357d74a3e2083707c99e60f6d21af71dfcf9c4..d6d083ec7a0761ce2d0ef4eeaf598e172542ed5a 100644 (file)
@@ -239,7 +239,6 @@ endif
 
 SOURCES_libvlc_darwin = \
        posix/darwin_dirs.c \
-       misc/atomic.c \
        posix/filesystem.c \
        posix/plugin.c \
        posix/thread.c \
@@ -249,7 +248,6 @@ SOURCES_libvlc_darwin = \
 
 SOURCES_libvlc_linux = \
        posix/dirs.c \
-       misc/atomic.c \
        posix/filesystem.c \
        posix/plugin.c \
        posix/thread.c \
@@ -261,7 +259,6 @@ SOURCES_libvlc_linux = \
 
 SOURCES_libvlc_win32 = \
        win32/dirs.c \
-       win32/atomic.c \
        win32/filesystem.c \
        win32/plugin.c \
        win32/thread.c \
@@ -273,7 +270,6 @@ SOURCES_libvlc_win32 = \
 SOURCES_libvlc_symbian = \
        symbian/path.cpp \
        symbian/dirs.c \
-       misc/atomic.c \
        win32/plugin.c \
        posix/rand.c \
        $(NULL)
@@ -281,7 +277,6 @@ SOURCES_libvlc_symbian = \
 SOURCES_libvlc_os2 = \
        os2/getaddrinfo.c \
        os2/dirs.c \
-       misc/atomic.c \
        os2/filesystem.c \
        os2/plugin.c \
        os2/thread.c \
@@ -291,7 +286,6 @@ SOURCES_libvlc_os2 = \
 
 SOURCES_libvlc_other = \
        posix/dirs.c \
-       misc/atomic.c \
        posix/filesystem.c \
        posix/thread.c \
        posix/plugin.c \
index 5d35457b5c351904db79209501ed2ce8559e9861..921e5136b72b2d7264e717e3f6d92c27c9fff489 100644 (file)
@@ -489,11 +489,6 @@ vlc_clone
 VLC_CompileBy
 VLC_CompileHost
 VLC_Compiler
-vlc_atomic_get
-vlc_atomic_set
-vlc_atomic_add
-vlc_atomic_swap
-vlc_atomic_compare_swap
 vlc_cond_broadcast
 vlc_cond_destroy
 vlc_cond_init
diff --git a/src/misc/atomic.c b/src/misc/atomic.c
deleted file mode 100644 (file)
index f79a491..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/*****************************************************************************
- * atomic.c:
- *****************************************************************************
- * Copyright (C) 2010 Rémi Denis-Courmont
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <vlc_common.h>
-#include <vlc_atomic.h>
-
-#if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
-/* GCC intrinsics */
-
-uintptr_t vlc_atomic_get (const vlc_atomic_t *atom)
-{
-    __sync_synchronize ();
-    return atom->u;
-}
-
-uintptr_t vlc_atomic_set (vlc_atomic_t *atom, uintptr_t v)
-{
-    atom->u = v;
-    __sync_synchronize ();
-    return v;
-}
-
-uintptr_t vlc_atomic_add (vlc_atomic_t *atom, uintptr_t 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
-/* Worst-case fallback implementation with a mutex */
-
-static vlc_mutex_t lock = VLC_STATIC_MUTEX;
-
-uintptr_t vlc_atomic_get (const vlc_atomic_t *atom)
-{
-    uintptr_t v;
-
-    vlc_mutex_lock (&lock);
-    v = atom->u;
-    vlc_mutex_unlock (&lock);
-    return v;
-}
-
-uintptr_t vlc_atomic_set (vlc_atomic_t *atom, uintptr_t v)
-{
-    vlc_mutex_lock (&lock);
-    atom->u = v;
-    vlc_mutex_unlock (&lock);
-    return v;
-}
-
-uintptr_t vlc_atomic_add (vlc_atomic_t *atom, uintptr_t v)
-{
-    vlc_mutex_lock (&lock);
-    atom->u += v;
-    v = atom->u;
-    vlc_mutex_unlock (&lock);
-    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_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
diff --git a/src/win32/atomic.c b/src/win32/atomic.c
deleted file mode 100644 (file)
index cb2bc84..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*****************************************************************************
- * atomic.c:
- *****************************************************************************
- * Copyright (C) 2010 Rémi Denis-Courmont
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <vlc_common.h>
-#include <vlc_atomic.h>
-
-#include <windows.h>
-
-uintptr_t vlc_atomic_get (const vlc_atomic_t *atom)
-{
-    return atom->u;
-}
-
-uintptr_t vlc_atomic_set (vlc_atomic_t *atom, uintptr_t v)
-{
-#if defined (WIN64)
-    InterlockedExchange64 (&atom->u, v);
-#else
-    InterlockedExchange (&atom->u, v);
-#endif
-    return v;
-}
-
-uintptr_t vlc_atomic_add (vlc_atomic_t *atom, uintptr_t v)
-{
-#if defined (WIN64)
-    return InterlockedExchangeAdd64 (&atom->s, v) + v;
-#else
-    return InterlockedExchangeAdd (&atom->s, v) + v;
-#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
-}