alsa-lib: heavy pcm atomics cleanup

The following patch comes from the realization that at least ARM code
for atomics is quite broken and nobody has cared for a decade.

A quick dive shows that only snd_atomic_{read,write}_{begin,end}
appear to be used widely. These are implemented using wmb/rmb.

Only other use of atomic functions is in pcm_meter.c.
The #SND_PCM_TYPE_METER plugin type appears rarely, if ever, used.
I presume these days anyone who wants a meter/scope will do in pulseaudio
layer instead of alsa.

It would seem better fit to have pcm_meter in alsa-plugins instead
of alsa-lib, but I guess that would be an ABI break...

So instead, I'm proposing here

1. Removal of all hand-crafted atomics from iatomic.h apart from barriers,
   which are used in snd_atomic_{read,write}_{begin,end}.

2. Using __sync_synchronize as the default fallback for barriers. This
   has been available since gcc 4.1, so it shouldn't be a problem.

3. Defining the few atomics used by pcm_meter.c withing pcm_meter.c
   itself, using gcc atomic builtins[1].

4. Since gcc atomic builtins are available only since gcc 4.7, add a check for
   that in gcc configure.in, and don't build pcm meter plugin if using
   older gcc.

The last point has the impact, that if there actually is someone who 1)
uses the meter plugin 2) wants to upgrade to 2014 alsa-lib 3) but
does not want to use a 2012+ gcc - that someone will be inconvenienced.

Finally remove the unneeded configure check for cpu type. We can
trust the gcc to set right flags for us.

[1] http://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html

Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Riku Voipio 2014-02-07 15:38:58 +02:00 committed by Takashi Iwai
parent 66f07aa3b7
commit 326c6802e4
3 changed files with 34 additions and 1074 deletions

View file

@ -309,40 +309,6 @@ fi
AC_SUBST(ALSA_DEPLIBS)
dnl Check for architecture
AC_MSG_CHECKING(for architecture)
case "$host" in
i?86*)
AC_MSG_RESULT(x86)
;;
x86_64*)
AC_MSG_RESULT(x86)
;;
alpha*)
AC_MSG_RESULT(alpha)
;;
powerpc*|ppc*)
AC_MSG_RESULT(ppc)
CPPFLAGS="$CPPFLAGS -D__ppc__"
;;
ia64*)
AC_MSG_RESULT(ia64)
CPPFLAGS="$CPPFLAGS -D__ia64__"
;;
mips*)
AC_MSG_RESULT(mips)
CPPFLAGS="$CPPFLAGS -D__mips__"
;;
arm*)
AC_MSG_RESULT(arm)
CPPFLAGS="$CPPFLAGS -D__arm__"
;;
*)
AC_MSG_RESULT($host_cpu)
echo "No atomic operations supported.."
;;
esac
dnl Check for wordexp.h
AC_CHECK_HEADERS([wordexp.h])
@ -488,6 +454,21 @@ else
pcm_plugins=""
fi
dnl check atomics for pcm_meter
AC_MSG_CHECKING([whether GCC supports builtin atomic intrinsics])
if test -z "$gcc_have_atomics"; then
gcc_have_atomics=no
AC_TRY_LINK([],
[int i;
__atomic_load_n(&i, __ATOMIC_SEQ_CST);
__atomic_add_fetch(&i, 0, __ATOMIC_SEQ_CST);
],
[gcc_have_atomics=yes],
[gcc_have_atomics=no])
fi
AC_MSG_RESULT($gcc_have_atomics)
PCM_PLUGIN_LIST="copy linear route mulaw alaw adpcm rate plug multi shm file null empty share meter hooks lfloat ladspa dmix dshare dsnoop asym iec958 softvol extplug ioplug mmap_emul"
build_pcm_plugin="no"
@ -531,6 +512,10 @@ if test "$softfloat" = "yes"; then
build_pcm_ladspa="no"
fi
if test "$gcc_have_atomics" != "yes"; then
build_pcm_meter="no"
fi
AM_CONDITIONAL([BUILD_PCM_PLUGIN], [test x$build_pcm_plugin = xyes])
AM_CONDITIONAL([BUILD_PCM_PLUGIN_COPY], [test x$build_pcm_copy = xyes])
AM_CONDITIONAL([BUILD_PCM_PLUGIN_LINEAR], [test x$build_pcm_linear = xyes])

File diff suppressed because it is too large Load diff

View file

@ -33,7 +33,10 @@
#include <dlfcn.h>
#include "pcm_local.h"
#include "pcm_plugin.h"
#include "iatomic.h"
#define atomic_read(ptr) __atomic_load_n(ptr, __ATOMIC_SEQ_CST )
#define atomic_add(ptr, n) __atomic_add_fetch(ptr, n, __ATOMIC_SEQ_CST)
#define atomic_dec(ptr) __atomic_sub_fetch(ptr, 1, __ATOMIC_SEQ_CST)
#ifndef PIC
/* entry for static linking */
@ -61,7 +64,7 @@ typedef struct _snd_pcm_meter {
struct list_head scopes;
int closed;
int running;
atomic_t reset;
int reset;
pthread_t thread;
pthread_mutex_t update_mutex;
pthread_mutex_t running_mutex;
@ -288,7 +291,7 @@ static int snd_pcm_meter_prepare(snd_pcm_t *pcm)
{
snd_pcm_meter_t *meter = pcm->private_data;
int err;
atomic_inc(&meter->reset);
atomic_add(&meter->reset, 1);
err = snd_pcm_prepare(meter->gen.slave);
if (err >= 0) {
if (pcm->stream == SND_PCM_STREAM_PLAYBACK)