OSDN Git Service

ucm: implemented card list feature
[android-x86/external-alsa-lib.git] / test / code.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <sched.h>
6 #include <sys/time.h>
7
8 #ifndef __builtin_expect
9 #include <linux/compiler.h>
10 #endif
11
12 #define rdtscll(val) \
13      __asm__ __volatile__("rdtsc" : "=A" (val))
14
15 #define likely(x)       __builtin_expect((x),1)
16 #define unlikely(x)     __builtin_expect((x),0)
17
18 typedef short int s16;
19 typedef int s32;
20
21 #if 0
22 #define CONFIG_SMP
23 #endif
24
25 #ifdef CONFIG_SMP
26 #define LOCK_PREFIX "lock ; "
27 #else
28 #define LOCK_PREFIX ""
29 #endif
30
31 struct __xchg_dummy { unsigned long a[100]; };
32 #define __xg(x) ((struct __xchg_dummy *)(x))
33
34 static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
35                                       unsigned long new, int size)
36 {
37         unsigned long prev;
38         switch (size) {
39         case 1:
40                 __asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
41                                      : "=a"(prev)
42                                      : "q"(new), "m"(*__xg(ptr)), "0"(old)
43                                      : "memory");
44                 return prev;
45         case 2:
46                 __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
47                                      : "=a"(prev)
48                                      : "q"(new), "m"(*__xg(ptr)), "0"(old)
49                                      : "memory");
50                 return prev;
51         case 4:
52                 __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
53                                      : "=a"(prev)
54                                      : "q"(new), "m"(*__xg(ptr)), "0"(old)
55                                      : "memory");
56                 return prev;
57         }
58         return old;
59 }
60
61 #define cmpxchg(ptr,o,n)\
62         ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
63                                        (unsigned long)(n),sizeof(*(ptr))))
64
65 static inline void atomic_add(volatile int *dst, int v)
66 {
67         __asm__ __volatile__(
68                 LOCK_PREFIX "addl %1,%0"
69                 :"=m" (*dst)
70                 :"ir" (v), "m" (*dst));
71 }
72
73 static double detect_cpu_clock()
74 {
75         struct timeval tm_begin, tm_end;
76         unsigned long long tsc_begin, tsc_end;
77
78         /* Warm cache */
79         gettimeofday(&tm_begin, 0);
80
81         rdtscll(tsc_begin);
82         gettimeofday(&tm_begin, 0);
83
84         usleep(1000000);
85
86         rdtscll(tsc_end);
87         gettimeofday(&tm_end, 0);
88
89         return (tsc_end - tsc_begin) / (tm_end.tv_sec - tm_begin.tv_sec + (tm_end.tv_usec - tm_begin.tv_usec) / 1e6);
90 }
91
92 void mix_areas_srv(unsigned int size,
93                    const s16 *src,
94                    volatile s32 *sum,
95                    unsigned int src_step, unsigned int sum_step)
96 {
97         src_step /= sizeof(*src);
98         sum_step /= sizeof(*sum);
99         while (size-- > 0) {
100                 atomic_add(sum, *src);
101                 src += src_step;
102                 sum += sum_step;
103         }
104 }
105
106 void saturate(unsigned int size,
107               s16 *dst, const s32 *sum,
108               unsigned int dst_step, unsigned int sum_step)
109 {
110         dst_step /= sizeof(*dst);
111         sum_step /= sizeof(*sum);
112         while (size-- > 0) {
113                 s32 sample = *sum;
114                 if (unlikely(sample < -0x8000))
115                         *dst = -0x8000;
116                 else if (unlikely(sample > 0x7fff))
117                         *dst = 0x7fff;
118                 else
119                         *dst = sample;
120                 dst += dst_step;
121                 sum += sum_step;
122         }
123 }
124
125 void mix_areas0(unsigned int size,
126                 volatile s16 *dst, s16 *src,
127                 volatile s32 *sum,
128                 unsigned int dst_step,
129                 unsigned int src_step,
130                 unsigned int sum_step)
131 {
132         dst_step /= sizeof(*dst);
133         src_step /= sizeof(*src);
134         sum_step /= sizeof(*sum);
135         while (size-- > 0) {
136                 s32 sample = *dst + *src;
137                 if (unlikely(sample < -0x8000))
138                         *dst = -0x8000;
139                 else if (unlikely(sample > 0x7fff))
140                         *dst = 0x7fff;
141                 else
142                         *dst = sample;
143                 dst += dst_step;
144                 src += src_step;
145                 sum += sum_step;
146         }
147 }
148
149 #define MIX_AREAS1 mix_areas1
150 #define MIX_AREAS1_MMX mix_areas1_mmx
151 #include "../src/pcm/pcm_dmix_i386.h"
152 #undef MIX_AREAS1
153 #undef MIX_AREAS1_MMX
154
155 void mix_areas2(unsigned int size,
156                 volatile s16 *dst, const s16 *src,
157                 volatile s32 *sum,
158                 unsigned int dst_step,
159                 unsigned int src_step)
160 {
161         dst_step /= sizeof(*dst);
162         src_step /= sizeof(*src);
163         while (size-- > 0) {
164                 s32 sample = *src;
165                 s32 old_sample = *sum;
166                 if (cmpxchg(dst, 0, 1) == 0)
167                         sample -= old_sample;
168                 atomic_add(sum, sample);
169                 do {
170                         sample = *sum;
171                         if (unlikely(sample < -0x8000))
172                                 *dst = -0x8000;
173                         else if (unlikely(sample > 0x7fff))
174                                 *dst = 0x7fff;
175                         else
176                                 *dst = sample;
177                 } while (unlikely(sample != *sum));
178                 sum++;
179                 dst += dst_step;
180                 src += src_step;
181         }
182 }
183
184 void setscheduler(void)
185 {
186         struct sched_param sched_param;
187
188         if (sched_getparam(0, &sched_param) < 0) {
189                 printf("Scheduler getparam failed...\n");
190                 return;
191         }
192         sched_param.sched_priority = sched_get_priority_max(SCHED_RR);
193         if (!sched_setscheduler(0, SCHED_RR, &sched_param)) {
194                 printf("Scheduler set to Round Robin with priority %i...\n", sched_param.sched_priority);
195                 fflush(stdout);
196                 return;
197         }
198         printf("!!!Scheduler set to Round Robin with priority %i FAILED!!!\n", sched_param.sched_priority);
199 }
200
201 int cache_size = 1024*1024;
202
203 void init(s16 *dst, s32 *sum, int size)
204 {
205         int count;
206         char *a;
207         
208         for (count = size - 1; count >= 0; count--)
209                 *sum++ = 0;
210         for (count = size - 1; count >= 0; count--)
211                 *dst++ = 0;
212         a = malloc(cache_size);
213         for (count = cache_size - 1; count >= 0; count--) {
214                 a[count] = count & 0xff;
215                 a[count] ^= 0x55;
216                 a[count] ^= 0xaa;
217         }
218         free(a);
219 }
220
221 int main(int argc, char **argv)
222 {
223         int size = 2048, n = 4, max = 32267;
224         int LOOP = 100;
225         int i, t;
226         unsigned long long begin, end, diff, diffS, diff0, diff1, diff1_mmx, diff2;
227         double cpu_clock = detect_cpu_clock();
228         s16 *dst = malloc(sizeof(*dst) * size);
229         s32 *sum = calloc(size, sizeof(*sum));
230         s16 **srcs = malloc(sizeof(*srcs) * n);
231
232         setscheduler();
233 #ifndef CONFIG_SMP
234         printf("CPU clock: %fMhz (UP)\n\n", cpu_clock / 10e5);
235 #else
236         printf("CPU clock: %fMhz (SMP)\n\n", cpu_clock / 10e5);
237 #endif
238         if (argc > 3) {
239                 size = atoi(argv[1]);
240                 n = atoi(argv[2]);
241                 max = atoi(argv[3]);
242         }
243         if (argc > 4)
244                 cache_size = atoi(argv[4]) * 1024;
245         for (i = 0; i < n; i++) {
246                 int k;
247                 s16 *s;
248                 srcs[i] = s = malloc(sizeof(s16) * size);
249                 for (k = 0; k < size; ++k, ++s) {
250                         *s = (rand() % (max * 2)) - max;
251                 }
252         }
253
254         for (t = 0, diffS = -1; t < LOOP; t++) {
255                 init(dst, sum, size);
256                 rdtscll(begin);
257                 for (i = 0; i < n; i++) {
258                         mix_areas_srv(size, srcs[i], sum, 2, 4);
259                 }
260                 saturate(size, dst, sum, 2, 4);
261                 rdtscll(end);
262                 diff = end - begin;
263                 if (diff < diffS)
264                         diffS = diff;
265                 printf("mix_areas_srv : %lld               \r", diff); fflush(stdout);
266         }
267
268         for (t = 0, diff0 = -1; t < LOOP; t++) {
269                 init(dst, sum, size);
270                 rdtscll(begin);
271                 for (i = 0; i < n; i++) {
272                         mix_areas0(size, dst, srcs[i], sum, 2, 2, 4);
273                 }
274                 rdtscll(end);
275                 diff = end - begin;
276                 if (diff < diff0)
277                         diff0 = diff;
278                 printf("mix_areas0    : %lld               \r", diff); fflush(stdout);
279         }
280
281         for (t = 0, diff1 = -1; t < LOOP; t++) {
282                 init(dst, sum, size);
283                 rdtscll(begin);
284                 for (i = 0; i < n; i++) {
285                         mix_areas1(size, dst, srcs[i], sum, 2, 2, 4);
286                 }
287                 rdtscll(end);
288                 diff = end - begin;
289                 if (diff < diff1)
290                         diff1 = diff;
291                 printf("mix_areas1    : %lld              \r", diff); fflush(stdout);
292         }
293
294         for (t = 0, diff1_mmx = -1; t < LOOP; t++) {
295                 init(dst, sum, size);
296                 rdtscll(begin);
297                 for (i = 0; i < n; i++) {
298                         mix_areas1_mmx(size, dst, srcs[i], sum, 2, 2, 4);
299                 }
300                 rdtscll(end);
301                 diff = end - begin;
302                 if (diff < diff1_mmx)
303                         diff1_mmx = diff;
304                 printf("mix_areas1_mmx: %lld              \r", diff); fflush(stdout);
305         }
306
307         for (t = 0, diff2 = -1; t < LOOP; t++) {
308                 init(dst, sum, size);
309                 rdtscll(begin);
310                 for (i = 0; i < n; i++) {
311                         mix_areas2(size, dst, srcs[i], sum, 2, 2);
312                 }
313                 rdtscll(end);
314                 diff = end - begin;
315                 if (diff < diff2)
316                         diff2 = diff;
317                 printf("mix_areas2    : %lld              \r", diff); fflush(stdout);
318         }
319
320         printf("                                                                           \r");
321         printf("Summary (the best times):\n");
322         printf("mix_areas_srv : %lld %f%%\n", diffS, 100*2*44100.0*diffS/(size*n*cpu_clock));
323         printf("mix_areas0    : %lld %f%%\n", diff0, 100*2*44100.0*diff0/(size*n*cpu_clock));
324         printf("mix_areas1    : %lld %f%%\n", diff1, 100*2*44100.0*diff1/(size*n*cpu_clock));
325         printf("mix_areas1_mmx: %lld %f%%\n", diff1_mmx, 100*2*44100.0*diff1_mmx/(size*n*cpu_clock));
326         printf("mix_areas2    : %lld %f%%\n", diff2, 100*2*44100.0*diff2/(size*n*cpu_clock));
327
328         printf("\n");
329         printf("areas1/srv ratio     : %f\n", (double)diff1 / diffS);
330         printf("areas1_mmx/srv ratio : %f\n", (double)diff1_mmx / diffS);
331
332         return 0;
333 }