]> git.alsa-project.org Git - alsa-lib.git/commitdiff
Split arch-dependent codes of dmix
authorTakashi Iwai <tiwai@suse.de>
Tue, 8 Feb 2005 20:28:29 +0000 (20:28 +0000)
committerTakashi Iwai <tiwai@suse.de>
Tue, 8 Feb 2005 20:28:29 +0000 (20:28 +0000)
Split arch-dependent codes of dmix to separate files.

src/pcm/Makefile.am
src/pcm/pcm_dmix.c
src/pcm/pcm_dmix_generic.c [new file with mode: 0644]
src/pcm/pcm_dmix_i386.c [new file with mode: 0644]
src/pcm/pcm_dmix_x86_64.c [new file with mode: 0644]

index 8aaab406f145b2ded96f9ff82e3657ef10baf8c0..19c0882058c7c1f09fd1b890a484ae99006d8927 100644 (file)
@@ -12,6 +12,9 @@ libpcm_la_SOURCES = atomic.c mask.c interval.c \
                    pcm_meter.c pcm_hooks.c pcm_lfloat.c pcm_ladspa.c \
                    pcm_direct.c pcm_dmix.c pcm_dsnoop.c pcm_dshare.c \
                    pcm_asym.c pcm_iec958.c pcm_softvol.c pcm_symbols.c
+
+EXTRA_SOURCES = pcm_dmix_i386.c pcm_dmix_x86_64.c pcm_dmix_generic.c
+
 noinst_HEADERS = pcm_local.h pcm_plugin.h mask.h mask_inline.h \
                 interval.h interval_inline.h plugin_ops.h ladspa.h \
                 pcm_direct.h pcm_dmix_i386.h pcm_dmix_x86_64.h \
index 3add06450a3b8e6a88da3f1111e15c4543a01040..973483422e4d320a26d8cce2513a73c80f4887d4 100644 (file)
@@ -121,172 +121,12 @@ static void dmix_server_free(snd_pcm_direct_t *dmix)
  *  FIXME: optimize it for different architectures
  */
 
-#ifdef __i386__
-
-#define ADD_AND_SATURATE
-
-#define MIX_AREAS1 mix_areas1
-#define MIX_AREAS1_MMX mix_areas1_mmx
-#define MIX_AREAS2 mix_areas2
-#define LOCK_PREFIX ""
-#include "pcm_dmix_i386.h"
-#undef MIX_AREAS1
-#undef MIX_AREAS1_MMX
-#undef MIX_AREAS2
-#undef LOCK_PREFIX
-
-#define MIX_AREAS1 mix_areas1_smp
-#define MIX_AREAS1_MMX mix_areas1_smp_mmx
-#define MIX_AREAS2 mix_areas2_smp
-#define LOCK_PREFIX "lock ; "
-#include "pcm_dmix_i386.h"
-#undef MIX_AREAS1
-#undef MIX_AREAS1_MMX
-#undef MIX_AREAS2
-#undef LOCK_PREFIX
-static void mix_select_callbacks(snd_pcm_direct_t *dmix)
-{
-       FILE *in;
-       char line[255];
-       int smp = 0, mmx = 0;
-       
-       /* try to determine, if we have a MMX capable CPU */
-       in = fopen("/proc/cpuinfo", "r");
-       if (in) {
-               while (!feof(in)) {
-                       fgets(line, sizeof(line), in);
-                       if (!strncmp(line, "processor", 9))
-                               smp++;
-                       else if (!strncmp(line, "flags", 5)) {
-                               if (strstr(line, " mmx"))
-                                       mmx = 1;
-                       }
-               }
-               fclose(in);
-       }
-       // printf("MMX: %i, SMP: %i\n", mmx, smp);
-       if (mmx) {
-               dmix->u.dmix.mix_areas1 = smp > 1 ? mix_areas1_smp_mmx : mix_areas1_mmx;
-       } else {
-               dmix->u.dmix.mix_areas1 = smp > 1 ? mix_areas1_smp : mix_areas1;
-       }
-       dmix->u.dmix.mix_areas2 = smp > 1 ? mix_areas2_smp : mix_areas2;
-}
-#endif
-
-#ifdef __x86_64__
-#define ADD_AND_SATURATE
-
-#define MIX_AREAS1 mix_areas1
-#define MIX_AREAS2 mix_areas2
-#define LOCK_PREFIX ""
-#include "pcm_dmix_x86_64.h"
-#undef MIX_AREAS1
-#undef MIX_AREAS2
-#undef LOCK_PREFIX
-
-#define MIX_AREAS1 mix_areas1_smp
-#define MIX_AREAS2 mix_areas2_smp
-#define LOCK_PREFIX "lock ; "
-#include "pcm_dmix_x86_64.h"
-#undef MIX_AREAS1
-#undef MIX_AREAS2
-#undef LOCK_PREFIX
-static void mix_select_callbacks(snd_pcm_direct_t *dmix)
-{
-       FILE *in;
-       char line[255];
-       int smp = 0;
-       
-       /* try to determine, if we have SMP */
-       in = fopen("/proc/cpuinfo", "r");
-       if (in) {
-               while (!feof(in)) {
-                       fgets(line, sizeof(line), in);
-                       if (!strncmp(line, "processor", 9))
-                               smp++;
-               }
-               fclose(in);
-       }
-       // printf("SMP: %i\n", smp);
-       dmix->u.dmix.mix_areas1 = smp > 1 ? mix_areas1_smp : mix_areas1;
-       dmix->u.dmix.mix_areas2 = smp > 1 ? mix_areas2_smp : mix_areas2;
-}
-#endif
-
-
-#ifndef ADD_AND_SATURATE
-#warning Please, recode mix_areas1() routine to your architecture...
-static void mix_areas1(unsigned int size,
-                      volatile signed short *dst, signed short *src,
-                      volatile signed int *sum, size_t dst_step,
-                      size_t src_step, size_t sum_step)
-{
-       register signed int sample, old_sample;
-
-       for (;;) {
-               sample = *src;
-               old_sample = *sum;
-               if (*dst == 0)
-                       sample -= old_sample;
-               *sum += sample;
-               do {
-                       old_sample = *sum;
-                       if (old_sample > 0x7fff)
-                               sample = 0x7fff;
-                       else if (old_sample < -0x8000)
-                               sample = -0x8000;
-                       else
-                               sample = old_sample;
-                       *dst = sample;
-               } while (*sum != old_sample);
-               if (!--size)
-                       return;
-               ((char *)src) += src_step;
-               ((char *)dst) += dst_step;
-               ((char *)sum) += sum_step;
-       }
-}
-
-#warning Please, recode mix_areas2() routine to your architecture...
-static void mix_areas2(unsigned int size,
-                      volatile signed int *dst, signed int *src,
-                      volatile signed int *sum, size_t dst_step,
-                      size_t src_step, size_t sum_step)
-{
-       register signed int sample, old_sample;
-
-       for (;;) {
-               sample = *src / 256;
-               old_sample = *sum;
-               if (*dst == 0)
-                       sample -= old_sample;
-               *sum += sample;
-               do {
-                       old_sample = *sum;
-                       if (old_sample > 0x7fffff)
-                               sample = 0x7fffffff;
-                       else if (old_sample < -0x800000)
-                               sample = -0x80000000;
-                       else
-                               sample = old_sample * 256;
-                       *dst = sample;
-               } while (*sum != old_sample);
-               if (!--size)
-                       return;
-               ((char *)src) += src_step;
-               ((char *)dst) += dst_step;
-               ((char *)sum) += sum_step;
-       }
-}
-
-static void mix_select_callbacks(snd_pcm_direct_t *dmix)
-{
-       dmix->u.dmix.mix_areas1 = mix_areas1;
-       dmix->u.dmix.mix_areas2 = mix_areas2;
-}
+#if defined(__i386__)
+#include "pcm_dmix_i386.c"
+#elif defined(__x86_64__)
+#include "pcm_dmix_x86_64.c"
+#else
+#include "pcm_dmix_generic.c"
 #endif
 
 static void mix_areas(snd_pcm_direct_t *dmix,
diff --git a/src/pcm/pcm_dmix_generic.c b/src/pcm/pcm_dmix_generic.c
new file mode 100644 (file)
index 0000000..4ce7759
--- /dev/null
@@ -0,0 +1,119 @@
+#if defined(__i386__) || defined(__x86_64__)
+#define LOCK_PREFIX "lock ; "
+#define ARCH_ADD(p,a)                                  \
+       __asm__ __volatile__(LOCK_PREFIX "addl %1,%0"   \
+                            :"=m" (*p)                 \
+                            :"ir" (a), "m" (*p))
+struct __xchg_dummy { unsigned long a[100]; };
+#define __xg(x) ((struct __xchg_dummy *)(x))
+static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
+                                     unsigned long new, int size)
+{
+       unsigned long prev;
+       switch (size) {
+       case 1:
+               __asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
+                                    : "=a"(prev)
+                                    : "q"(new), "m"(*__xg(ptr)), "0"(old)
+                                    : "memory");
+               return prev;
+       case 2:
+               __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
+                                    : "=a"(prev)
+                                    : "q"(new), "m"(*__xg(ptr)), "0"(old)
+                                    : "memory");
+               return prev;
+       case 4:
+               __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
+                                    : "=a"(prev)
+                                    : "q"(new), "m"(*__xg(ptr)), "0"(old)
+                                    : "memory");
+               return prev;
+       }
+       return old;
+}
+
+#define ARCH_CMPXCHG(ptr,o,n)\
+       ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
+                                       (unsigned long)(n),sizeof(*(ptr))))
+#endif
+
+#ifndef ARCH_ADD
+#warning Please, define atomic ADD and CMPXCHG for your architecture...
+#define ARCH_ADD(p,a) (*(p) += (a))
+#define ARCH_CMPXCHG(p,a,b) (*(p)) /* fake */
+#endif
+
+static void mix_areas1(unsigned int size,
+                      volatile signed short *dst, signed short *src,
+                      volatile signed int *sum, size_t dst_step,
+                      size_t src_step, size_t sum_step)
+{
+       register signed int sample, old_sample;
+       src_step /= sizeof(*src);
+       dst_step /= sizeof(*dst);
+       sum_step /= sizeof(*sum);
+
+       for (;;) {
+               sample = *src;
+               old_sample = *sum;
+               if (ARCH_CMPXCHG(dst, 0, 1) == 0)
+                       sample -= old_sample;
+               ARCH_ADD(sum, sample);
+               do {
+                       old_sample = *sum;
+                       if (old_sample > 0x7fff)
+                               sample = 0x7fff;
+                       else if (old_sample < -0x8000)
+                               sample = -0x8000;
+                       else
+                               sample = old_sample;
+                       *dst = sample;
+               } while (*sum != old_sample);
+               if (!--size)
+                       return;
+               src += src_step;
+               dst += dst_step;
+               sum += sum_step;
+       }
+}
+
+static void mix_areas2(unsigned int size,
+                      volatile signed int *dst, signed int *src,
+                      volatile signed int *sum, size_t dst_step,
+                      size_t src_step, size_t sum_step)
+{
+       register signed int sample, old_sample;
+       src_step /= sizeof(*src);
+       dst_step /= sizeof(*dst);
+       sum_step /= sizeof(*sum);
+
+       for (;;) {
+               sample = *src / 256;
+               old_sample = *sum;
+               if (ARCH_CMPXCHG(dst, 0, 1) == 0)
+                       sample -= old_sample;
+               ARCH_ADD(sum, sample);
+               do {
+                       old_sample = *sum;
+                       if (old_sample > 0x7fffff)
+                               sample = 0x7fffffff;
+                       else if (old_sample < -0x800000)
+                               sample = -0x80000000;
+                       else
+                               sample = old_sample * 256;
+                       *dst = sample;
+               } while (*sum != old_sample);
+               if (!--size)
+                       return;
+               src += src_step;
+               dst += dst_step;
+               sum += sum_step;
+       }
+}
+
+static void mix_select_callbacks(snd_pcm_direct_t *dmix)
+{
+       dmix->u.dmix.mix_areas1 = mix_areas1;
+       dmix->u.dmix.mix_areas2 = mix_areas2;
+}
diff --git a/src/pcm/pcm_dmix_i386.c b/src/pcm/pcm_dmix_i386.c
new file mode 100644 (file)
index 0000000..758a582
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * optimized mixing code for i386
+ */
+
+#define MIX_AREAS1 mix_areas1
+#define MIX_AREAS1_MMX mix_areas1_mmx
+#define MIX_AREAS2 mix_areas2
+#define LOCK_PREFIX ""
+#include "pcm_dmix_i386.h"
+#undef MIX_AREAS1
+#undef MIX_AREAS1_MMX
+#undef MIX_AREAS2
+#undef LOCK_PREFIX
+
+#define MIX_AREAS1 mix_areas1_smp
+#define MIX_AREAS1_MMX mix_areas1_smp_mmx
+#define MIX_AREAS2 mix_areas2_smp
+#define LOCK_PREFIX "lock ; "
+#include "pcm_dmix_i386.h"
+#undef MIX_AREAS1
+#undef MIX_AREAS1_MMX
+#undef MIX_AREAS2
+#undef LOCK_PREFIX
+static void mix_select_callbacks(snd_pcm_direct_t *dmix)
+{
+       FILE *in;
+       char line[255];
+       int smp = 0, mmx = 0;
+       
+       /* try to determine, if we have a MMX capable CPU */
+       in = fopen("/proc/cpuinfo", "r");
+       if (in) {
+               while (!feof(in)) {
+                       fgets(line, sizeof(line), in);
+                       if (!strncmp(line, "processor", 9))
+                               smp++;
+                       else if (!strncmp(line, "flags", 5)) {
+                               if (strstr(line, " mmx"))
+                                       mmx = 1;
+                       }
+               }
+               fclose(in);
+       }
+       // printf("MMX: %i, SMP: %i\n", mmx, smp);
+       if (mmx) {
+               dmix->u.dmix.mix_areas1 = smp > 1 ? mix_areas1_smp_mmx : mix_areas1_mmx;
+       } else {
+               dmix->u.dmix.mix_areas1 = smp > 1 ? mix_areas1_smp : mix_areas1;
+       }
+       dmix->u.dmix.mix_areas2 = smp > 1 ? mix_areas2_smp : mix_areas2;
+}
diff --git a/src/pcm/pcm_dmix_x86_64.c b/src/pcm/pcm_dmix_x86_64.c
new file mode 100644 (file)
index 0000000..2e9a521
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * optimized mixing code for x86-64
+ */
+
+#define MIX_AREAS1 mix_areas1
+#define MIX_AREAS2 mix_areas2
+#define LOCK_PREFIX ""
+#include "pcm_dmix_x86_64.h"
+#undef MIX_AREAS1
+#undef MIX_AREAS2
+#undef LOCK_PREFIX
+
+#define MIX_AREAS1 mix_areas1_smp
+#define MIX_AREAS2 mix_areas2_smp
+#define LOCK_PREFIX "lock ; "
+#include "pcm_dmix_x86_64.h"
+#undef MIX_AREAS1
+#undef MIX_AREAS2
+#undef LOCK_PREFIX
+static void mix_select_callbacks(snd_pcm_direct_t *dmix)
+{
+       FILE *in;
+       char line[255];
+       int smp = 0;
+       
+       /* try to determine, if we have SMP */
+       in = fopen("/proc/cpuinfo", "r");
+       if (in) {
+               while (!feof(in)) {
+                       fgets(line, sizeof(line), in);
+                       if (!strncmp(line, "processor", 9))
+                               smp++;
+               }
+               fclose(in);
+       }
+       // printf("SMP: %i\n", smp);
+       dmix->u.dmix.mix_areas1 = smp > 1 ? mix_areas1_smp : mix_areas1;
+       dmix->u.dmix.mix_areas2 = smp > 1 ? mix_areas2_smp : mix_areas2;
+}