~ubuntu-branches/ubuntu/oneiric/oss4/oneiric-proposed

« back to all changes in this revision

Viewing changes to debian/include-alsa/alsa/iatomic.h

  • Committer: Bazaar Package Importer
  • Author(s): Stefano Rivera
  • Date: 2011-06-16 20:37:48 UTC
  • mfrom: (5.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20110616203748-jbrxik6ql33z54co
Tags: 4.2-build2004-1ubuntu1
* Merge from Debian unstable.
  - Supports our current kernel (LP: #746048)
  Remaining changes:
  - debian/oss4-dkms.dkms.in: s/source/build/ in Kernel headers paths.
* ld-as-needed.patch: Re-order CC arguments to enable building with ld
  --as-needed (LP: #770972)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#ifndef __ALSA_IATOMIC_H
 
2
#define __ALSA_IATOMIC_H
 
3
 
 
4
#if defined(__i386__) || defined(__x86_64__)
 
5
 
 
6
/*
 
7
 * Atomic operations that C can't guarantee us.  Useful for
 
8
 * resource counting etc..
 
9
 */
 
10
 
 
11
#define ATOMIC_SMP_LOCK "lock ; "
 
12
 
 
13
/*
 
14
 * Make sure gcc doesn't try to be clever and move things around
 
15
 * on us. We need to use _exactly_ the address the user gave us,
 
16
 * not some alias that contains the same information.
 
17
 */
 
18
typedef struct { volatile int counter; } atomic_t;
 
19
 
 
20
#define ATOMIC_INIT(i)  { (i) }
 
21
 
 
22
/**
 
23
 * atomic_read - read atomic variable
 
24
 * @v: pointer of type atomic_t
 
25
 * 
 
26
 * Atomically reads the value of @v.  Note that the guaranteed
 
27
 * useful range of an atomic_t is only 24 bits.
 
28
 */ 
 
29
#define atomic_read(v)          ((v)->counter)
 
30
 
 
31
/**
 
32
 * atomic_set - set atomic variable
 
33
 * @v: pointer of type atomic_t
 
34
 * @i: required value
 
35
 * 
 
36
 * Atomically sets the value of @v to @i.  Note that the guaranteed
 
37
 * useful range of an atomic_t is only 24 bits.
 
38
 */ 
 
39
#define atomic_set(v,i)         (((v)->counter) = (i))
 
40
 
 
41
/**
 
42
 * atomic_add - add integer to atomic variable
 
43
 * @i: integer value to add
 
44
 * @v: pointer of type atomic_t
 
45
 * 
 
46
 * Atomically adds @i to @v.  Note that the guaranteed useful range
 
47
 * of an atomic_t is only 24 bits.
 
48
 */
 
49
static __inline__ void atomic_add(int i, atomic_t *v)
 
50
{
 
51
        __asm__ __volatile__(
 
52
                ATOMIC_SMP_LOCK "addl %1,%0"
 
53
                :"=m" (v->counter)
 
54
                :"ir" (i), "m" (v->counter));
 
55
}
 
56
 
 
57
/**
 
58
 * atomic_sub - subtract the atomic variable
 
59
 * @i: integer value to subtract
 
60
 * @v: pointer of type atomic_t
 
61
 * 
 
62
 * Atomically subtracts @i from @v.  Note that the guaranteed
 
63
 * useful range of an atomic_t is only 24 bits.
 
64
 */
 
65
static __inline__ void atomic_sub(int i, atomic_t *v)
 
66
{
 
67
        __asm__ __volatile__(
 
68
                ATOMIC_SMP_LOCK "subl %1,%0"
 
69
                :"=m" (v->counter)
 
70
                :"ir" (i), "m" (v->counter));
 
71
}
 
72
 
 
73
/**
 
74
 * atomic_sub_and_test - subtract value from variable and test result
 
75
 * @i: integer value to subtract
 
76
 * @v: pointer of type atomic_t
 
77
 * 
 
78
 * Atomically subtracts @i from @v and returns
 
79
 * true if the result is zero, or false for all
 
80
 * other cases.  Note that the guaranteed
 
81
 * useful range of an atomic_t is only 24 bits.
 
82
 */
 
83
static __inline__ int atomic_sub_and_test(int i, atomic_t *v)
 
84
{
 
85
        unsigned char c;
 
86
 
 
87
        __asm__ __volatile__(
 
88
                ATOMIC_SMP_LOCK "subl %2,%0; sete %1"
 
89
                :"=m" (v->counter), "=qm" (c)
 
90
                :"ir" (i), "m" (v->counter) : "memory");
 
91
        return c;
 
92
}
 
93
 
 
94
/**
 
95
 * atomic_inc - increment atomic variable
 
96
 * @v: pointer of type atomic_t
 
97
 * 
 
98
 * Atomically increments @v by 1.  Note that the guaranteed
 
99
 * useful range of an atomic_t is only 24 bits.
 
100
 */ 
 
101
static __inline__ void atomic_inc(atomic_t *v)
 
102
{
 
103
        __asm__ __volatile__(
 
104
                ATOMIC_SMP_LOCK "incl %0"
 
105
                :"=m" (v->counter)
 
106
                :"m" (v->counter));
 
107
}
 
108
 
 
109
/**
 
110
 * atomic_dec - decrement atomic variable
 
111
 * @v: pointer of type atomic_t
 
112
 * 
 
113
 * Atomically decrements @v by 1.  Note that the guaranteed
 
114
 * useful range of an atomic_t is only 24 bits.
 
115
 */ 
 
116
static __inline__ void atomic_dec(atomic_t *v)
 
117
{
 
118
        __asm__ __volatile__(
 
119
                ATOMIC_SMP_LOCK "decl %0"
 
120
                :"=m" (v->counter)
 
121
                :"m" (v->counter));
 
122
}
 
123
 
 
124
/**
 
125
 * atomic_dec_and_test - decrement and test
 
126
 * @v: pointer of type atomic_t
 
127
 * 
 
128
 * Atomically decrements @v by 1 and
 
129
 * returns true if the result is 0, or false for all other
 
130
 * cases.  Note that the guaranteed
 
131
 * useful range of an atomic_t is only 24 bits.
 
132
 */ 
 
133
static __inline__ int atomic_dec_and_test(atomic_t *v)
 
134
{
 
135
        unsigned char c;
 
136
 
 
137
        __asm__ __volatile__(
 
138
                ATOMIC_SMP_LOCK "decl %0; sete %1"
 
139
                :"=m" (v->counter), "=qm" (c)
 
140
                :"m" (v->counter) : "memory");
 
141
        return c != 0;
 
142
}
 
143
 
 
144
/**
 
145
 * atomic_inc_and_test - increment and test 
 
146
 * @v: pointer of type atomic_t
 
147
 * 
 
148
 * Atomically increments @v by 1
 
149
 * and returns true if the result is zero, or false for all
 
150
 * other cases.  Note that the guaranteed
 
151
 * useful range of an atomic_t is only 24 bits.
 
152
 */ 
 
153
static __inline__ int atomic_inc_and_test(atomic_t *v)
 
154
{
 
155
        unsigned char c;
 
156
 
 
157
        __asm__ __volatile__(
 
158
                ATOMIC_SMP_LOCK "incl %0; sete %1"
 
159
                :"=m" (v->counter), "=qm" (c)
 
160
                :"m" (v->counter) : "memory");
 
161
        return c != 0;
 
162
}
 
163
 
 
164
/**
 
165
 * atomic_add_negative - add and test if negative
 
166
 * @v: pointer of type atomic_t
 
167
 * @i: integer value to add
 
168
 * 
 
169
 * Atomically adds @i to @v and returns true
 
170
 * if the result is negative, or false when
 
171
 * result is greater than or equal to zero.  Note that the guaranteed
 
172
 * useful range of an atomic_t is only 24 bits.
 
173
 */ 
 
174
static __inline__ int atomic_add_negative(int i, atomic_t *v)
 
175
{
 
176
        unsigned char c;
 
177
 
 
178
        __asm__ __volatile__(
 
179
                ATOMIC_SMP_LOCK "addl %2,%0; sets %1"
 
180
                :"=m" (v->counter), "=qm" (c)
 
181
                :"ir" (i), "m" (v->counter) : "memory");
 
182
        return c;
 
183
}
 
184
 
 
185
/* These are x86-specific, used by some header files */
 
186
#define atomic_clear_mask(mask, addr) \
 
187
__asm__ __volatile__(ATOMIC_SMP_LOCK "andl %0,%1" \
 
188
: : "r" (~(mask)),"m" (*addr) : "memory")
 
189
 
 
190
#define atomic_set_mask(mask, addr) \
 
191
__asm__ __volatile__(ATOMIC_SMP_LOCK "orl %0,%1" \
 
192
: : "r" (mask),"m" (*addr) : "memory")
 
193
 
 
194
/*
 
195
 * Force strict CPU ordering.
 
196
 * And yes, this is required on UP too when we're talking
 
197
 * to devices.
 
198
 *
 
199
 * For now, "wmb()" doesn't actually do anything, as all
 
200
 * Intel CPU's follow what Intel calls a *Processor Order*,
 
201
 * in which all writes are seen in the program order even
 
202
 * outside the CPU.
 
203
 *
 
204
 * I expect future Intel CPU's to have a weaker ordering,
 
205
 * but I'd also expect them to finally get their act together
 
206
 * and add some real memory barriers if so.
 
207
 */
 
208
 
 
209
#ifdef __i386__
 
210
#define mb()    __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
 
211
#define rmb()   mb()
 
212
#define wmb()   __asm__ __volatile__ ("": : :"memory")
 
213
#else
 
214
#define mb()    asm volatile("mfence":::"memory")
 
215
#define rmb()   asm volatile("lfence":::"memory")
 
216
#define wmb()   asm volatile("sfence":::"memory")
 
217
#endif
 
218
 
 
219
#undef ATOMIC_SMP_LOCK
 
220
 
 
221
#define IATOMIC_DEFINED         1
 
222
 
 
223
#endif /* __i386__ */
 
224
 
 
225
#ifdef __ia64__
 
226
 
 
227
/*
 
228
 * On IA-64, counter must always be volatile to ensure that that the
 
229
 * memory accesses are ordered.
 
230
 */
 
231
typedef struct { volatile int counter; } atomic_t;
 
232
 
 
233
#define ATOMIC_INIT(i)          ((atomic_t) { (i) })
 
234
 
 
235
#define atomic_read(v)          ((v)->counter)
 
236
#define atomic_set(v,i)         (((v)->counter) = (i))
 
237
 
 
238
/* stripped version - we need only 4byte version */
 
239
#define ia64_cmpxchg(sem,ptr,old,new,size) \
 
240
({ \
 
241
        __typeof__(ptr) _p_ = (ptr); \
 
242
        __typeof__(new) _n_ = (new); \
 
243
        unsigned long _o_, _r_; \
 
244
        _o_ = (unsigned int) (long) (old); \
 
245
        __asm__ __volatile__ ("mov ar.ccv=%0;;" :: "rO"(_o_)); \
 
246
        __asm__ __volatile__ ("cmpxchg4."sem" %0=[%1],%2,ar.ccv" \
 
247
                              : "=r"(_r_) : "r"(_p_), "r"(_n_) : "memory"); \
 
248
        (__typeof__(old)) _r_; \
 
249
})
 
250
 
 
251
static __inline__ int
 
252
ia64_atomic_add (int i, atomic_t *v)
 
253
{
 
254
        int old, new;
 
255
        // CMPXCHG_BUGCHECK_DECL
 
256
 
 
257
        do {
 
258
                // CMPXCHG_BUGCHECK(v);
 
259
                old = atomic_read(v);
 
260
                new = old + i;
 
261
        } while (ia64_cmpxchg("acq", v, old, old + i, sizeof(atomic_t)) != old);
 
262
        return new;
 
263
}
 
264
 
 
265
static __inline__ int
 
266
ia64_atomic_sub (int i, atomic_t *v)
 
267
{
 
268
        int old, new;
 
269
        // CMPXCHG_BUGCHECK_DECL
 
270
 
 
271
        do {
 
272
                // CMPXCHG_BUGCHECK(v);
 
273
                old = atomic_read(v);
 
274
                new = old - i;
 
275
        } while (ia64_cmpxchg("acq", v, old, new, sizeof(atomic_t)) != old);
 
276
        return new;
 
277
}
 
278
 
 
279
#define IA64_FETCHADD(tmp,v,n,sz)                                               \
 
280
({                                                                              \
 
281
        switch (sz) {                                                           \
 
282
              case 4:                                                           \
 
283
                __asm__ __volatile__ ("fetchadd4.rel %0=[%1],%2"                \
 
284
                                      : "=r"(tmp) : "r"(v), "i"(n) : "memory"); \
 
285
                break;                                                          \
 
286
                                                                                \
 
287
              case 8:                                                           \
 
288
                __asm__ __volatile__ ("fetchadd8.rel %0=[%1],%2"                \
 
289
                                      : "=r"(tmp) : "r"(v), "i"(n) : "memory"); \
 
290
                break;                                                          \
 
291
        }                                                                       \
 
292
})
 
293
 
 
294
#define ia64_fetch_and_add(i,v)                                                 \
 
295
({                                                                              \
 
296
        unsigned long _tmp;                                                             \
 
297
        volatile __typeof__(*(v)) *_v = (v);                                    \
 
298
        switch (i) {                                                            \
 
299
              case -16: IA64_FETCHADD(_tmp, _v, -16, sizeof(*(v))); break;      \
 
300
              case  -8: IA64_FETCHADD(_tmp, _v,  -8, sizeof(*(v))); break;      \
 
301
              case  -4: IA64_FETCHADD(_tmp, _v,  -4, sizeof(*(v))); break;      \
 
302
              case  -1: IA64_FETCHADD(_tmp, _v,  -1, sizeof(*(v))); break;      \
 
303
              case   1: IA64_FETCHADD(_tmp, _v,   1, sizeof(*(v))); break;      \
 
304
              case   4: IA64_FETCHADD(_tmp, _v,   4, sizeof(*(v))); break;      \
 
305
              case   8: IA64_FETCHADD(_tmp, _v,   8, sizeof(*(v))); break;      \
 
306
              case  16: IA64_FETCHADD(_tmp, _v,  16, sizeof(*(v))); break;      \
 
307
        }                                                                       \
 
308
        (__typeof__(*v)) (_tmp + (i));  /* return new value */                  \
 
309
})
 
310
 
 
311
/*
 
312
 * Atomically add I to V and return TRUE if the resulting value is
 
313
 * negative.
 
314
 */
 
315
static __inline__ int
 
316
atomic_add_negative (int i, atomic_t *v)
 
317
{
 
318
        return ia64_atomic_add(i, v) < 0;
 
319
}
 
320
 
 
321
#define atomic_add_return(i,v)                                          \
 
322
        ((__builtin_constant_p(i) &&                                    \
 
323
          (   (i ==  1) || (i ==  4) || (i ==  8) || (i ==  16)         \
 
324
           || (i == -1) || (i == -4) || (i == -8) || (i == -16)))       \
 
325
         ? ia64_fetch_and_add(i, &(v)->counter)                         \
 
326
         : ia64_atomic_add(i, v))
 
327
 
 
328
#define atomic_sub_return(i,v)                                          \
 
329
        ((__builtin_constant_p(i) &&                                    \
 
330
          (   (i ==  1) || (i ==  4) || (i ==  8) || (i ==  16)         \
 
331
           || (i == -1) || (i == -4) || (i == -8) || (i == -16)))       \
 
332
         ? ia64_fetch_and_add(-(i), &(v)->counter)                      \
 
333
         : ia64_atomic_sub(i, v))
 
334
 
 
335
#define atomic_dec_return(v)            atomic_sub_return(1, (v))
 
336
#define atomic_inc_return(v)            atomic_add_return(1, (v))
 
337
 
 
338
#define atomic_sub_and_test(i,v)        (atomic_sub_return((i), (v)) == 0)
 
339
#define atomic_dec_and_test(v)          (atomic_sub_return(1, (v)) == 0)
 
340
#define atomic_inc_and_test(v)          (atomic_add_return(1, (v)) != 0)
 
341
 
 
342
#define atomic_add(i,v)                 atomic_add_return((i), (v))
 
343
#define atomic_sub(i,v)                 atomic_sub_return((i), (v))
 
344
#define atomic_inc(v)                   atomic_add(1, (v))
 
345
#define atomic_dec(v)                   atomic_sub(1, (v))
 
346
 
 
347
/*
 
348
 * Macros to force memory ordering.  In these descriptions, "previous"
 
349
 * and "subsequent" refer to program order; "visible" means that all
 
350
 * architecturally visible effects of a memory access have occurred
 
351
 * (at a minimum, this means the memory has been read or written).
 
352
 *
 
353
 *   wmb():     Guarantees that all preceding stores to memory-
 
354
 *              like regions are visible before any subsequent
 
355
 *              stores and that all following stores will be
 
356
 *              visible only after all previous stores.
 
357
 *   rmb():     Like wmb(), but for reads.
 
358
 *   mb():      wmb()/rmb() combo, i.e., all previous memory
 
359
 *              accesses are visible before all subsequent
 
360
 *              accesses and vice versa.  This is also known as
 
361
 *              a "fence."
 
362
 *
 
363
 * Note: "mb()" and its variants cannot be used as a fence to order
 
364
 * accesses to memory mapped I/O registers.  For that, mf.a needs to
 
365
 * be used.  However, we don't want to always use mf.a because (a)
 
366
 * it's (presumably) much slower than mf and (b) mf.a is supported for
 
367
 * sequential memory pages only.
 
368
 */
 
369
#define mb()    __asm__ __volatile__ ("mf" ::: "memory")
 
370
#define rmb()   mb()
 
371
#define wmb()   mb()
 
372
 
 
373
#define IATOMIC_DEFINED         1
 
374
 
 
375
#endif /* __ia64__ */
 
376
 
 
377
#ifdef __alpha__
 
378
 
 
379
/*
 
380
 * Atomic operations that C can't guarantee us.  Useful for
 
381
 * resource counting etc...
 
382
 *
 
383
 * But use these as seldom as possible since they are much slower
 
384
 * than regular operations.
 
385
 */
 
386
 
 
387
 
 
388
/*
 
389
 * Counter is volatile to make sure gcc doesn't try to be clever
 
390
 * and move things around on us. We need to use _exactly_ the address
 
391
 * the user gave us, not some alias that contains the same information.
 
392
 */
 
393
typedef struct { volatile int counter; } atomic_t;
 
394
 
 
395
#define ATOMIC_INIT(i)  ( (atomic_t) { (i) } )
 
396
 
 
397
#define atomic_read(v)          ((v)->counter)
 
398
#define atomic_set(v,i)         ((v)->counter = (i))
 
399
 
 
400
/*
 
401
 * To get proper branch prediction for the main line, we must branch
 
402
 * forward to code at the end of this object's .text section, then
 
403
 * branch back to restart the operation.
 
404
 */
 
405
 
 
406
static __inline__ void atomic_add(int i, atomic_t * v)
 
407
{
 
408
        unsigned long temp;
 
409
        __asm__ __volatile__(
 
410
        "1:     ldl_l %0,%1\n"
 
411
        "       addl %0,%2,%0\n"
 
412
        "       stl_c %0,%1\n"
 
413
        "       beq %0,2f\n"
 
414
        ".subsection 2\n"
 
415
        "2:     br 1b\n"
 
416
        ".previous"
 
417
        :"=&r" (temp), "=m" (v->counter)
 
418
        :"Ir" (i), "m" (v->counter));
 
419
}
 
420
 
 
421
static __inline__ void atomic_sub(int i, atomic_t * v)
 
422
{
 
423
        unsigned long temp;
 
424
        __asm__ __volatile__(
 
425
        "1:     ldl_l %0,%1\n"
 
426
        "       subl %0,%2,%0\n"
 
427
        "       stl_c %0,%1\n"
 
428
        "       beq %0,2f\n"
 
429
        ".subsection 2\n"
 
430
        "2:     br 1b\n"
 
431
        ".previous"
 
432
        :"=&r" (temp), "=m" (v->counter)
 
433
        :"Ir" (i), "m" (v->counter));
 
434
}
 
435
 
 
436
/*
 
437
 * Same as above, but return the result value
 
438
 */
 
439
static __inline__ long atomic_add_return(int i, atomic_t * v)
 
440
{
 
441
        long temp, result;
 
442
        __asm__ __volatile__(
 
443
        "1:     ldl_l %0,%1\n"
 
444
        "       addl %0,%3,%2\n"
 
445
        "       addl %0,%3,%0\n"
 
446
        "       stl_c %0,%1\n"
 
447
        "       beq %0,2f\n"
 
448
        "       mb\n"
 
449
        ".subsection 2\n"
 
450
        "2:     br 1b\n"
 
451
        ".previous"
 
452
        :"=&r" (temp), "=m" (v->counter), "=&r" (result)
 
453
        :"Ir" (i), "m" (v->counter) : "memory");
 
454
        return result;
 
455
}
 
456
 
 
457
static __inline__ long atomic_sub_return(int i, atomic_t * v)
 
458
{
 
459
        long temp, result;
 
460
        __asm__ __volatile__(
 
461
        "1:     ldl_l %0,%1\n"
 
462
        "       subl %0,%3,%2\n"
 
463
        "       subl %0,%3,%0\n"
 
464
        "       stl_c %0,%1\n"
 
465
        "       beq %0,2f\n"
 
466
        "       mb\n"
 
467
        ".subsection 2\n"
 
468
        "2:     br 1b\n"
 
469
        ".previous"
 
470
        :"=&r" (temp), "=m" (v->counter), "=&r" (result)
 
471
        :"Ir" (i), "m" (v->counter) : "memory");
 
472
        return result;
 
473
}
 
474
 
 
475
#define atomic_dec_return(v) atomic_sub_return(1,(v))
 
476
#define atomic_inc_return(v) atomic_add_return(1,(v))
 
477
 
 
478
#define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
 
479
#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
 
480
 
 
481
#define atomic_inc(v) atomic_add(1,(v))
 
482
#define atomic_dec(v) atomic_sub(1,(v))
 
483
 
 
484
#define mb() \
 
485
__asm__ __volatile__("mb": : :"memory")
 
486
 
 
487
#define rmb() \
 
488
__asm__ __volatile__("mb": : :"memory")
 
489
 
 
490
#define wmb() \
 
491
__asm__ __volatile__("wmb": : :"memory")
 
492
 
 
493
#define IATOMIC_DEFINED         1
 
494
 
 
495
#endif /* __alpha__ */
 
496
 
 
497
#ifdef __powerpc__
 
498
 
 
499
typedef struct { volatile int counter; } atomic_t;
 
500
 
 
501
#define ATOMIC_INIT(i)  { (i) }
 
502
 
 
503
#define atomic_read(v)          ((v)->counter)
 
504
#define atomic_set(v,i)         (((v)->counter) = (i))
 
505
 
 
506
extern void atomic_clear_mask(unsigned long mask, unsigned long *addr);
 
507
extern void atomic_set_mask(unsigned long mask, unsigned long *addr);
 
508
 
 
509
#define SMP_ISYNC       "\n\tisync"
 
510
 
 
511
static __inline__ void atomic_add(int a, atomic_t *v)
 
512
{
 
513
        int t;
 
514
 
 
515
        __asm__ __volatile__(
 
516
"1:     lwarx   %0,0,%3         # atomic_add\n\
 
517
        add     %0,%2,%0\n\
 
518
        stwcx.  %0,0,%3\n\
 
519
        bne-    1b"
 
520
        : "=&r" (t), "=m" (v->counter)
 
521
        : "r" (a), "r" (&v->counter), "m" (v->counter)
 
522
        : "cc");
 
523
}
 
524
 
 
525
static __inline__ int atomic_add_return(int a, atomic_t *v)
 
526
{
 
527
        int t;
 
528
 
 
529
        __asm__ __volatile__(
 
530
"1:     lwarx   %0,0,%2         # atomic_add_return\n\
 
531
        add     %0,%1,%0\n\
 
532
        stwcx.  %0,0,%2\n\
 
533
        bne-    1b"
 
534
        SMP_ISYNC
 
535
        : "=&r" (t)
 
536
        : "r" (a), "r" (&v->counter)
 
537
        : "cc", "memory");
 
538
 
 
539
        return t;
 
540
}
 
541
 
 
542
static __inline__ void atomic_sub(int a, atomic_t *v)
 
543
{
 
544
        int t;
 
545
 
 
546
        __asm__ __volatile__(
 
547
"1:     lwarx   %0,0,%3         # atomic_sub\n\
 
548
        subf    %0,%2,%0\n\
 
549
        stwcx.  %0,0,%3\n\
 
550
        bne-    1b"
 
551
        : "=&r" (t), "=m" (v->counter)
 
552
        : "r" (a), "r" (&v->counter), "m" (v->counter)
 
553
        : "cc");
 
554
}
 
555
 
 
556
static __inline__ int atomic_sub_return(int a, atomic_t *v)
 
557
{
 
558
        int t;
 
559
 
 
560
        __asm__ __volatile__(
 
561
"1:     lwarx   %0,0,%2         # atomic_sub_return\n\
 
562
        subf    %0,%1,%0\n\
 
563
        stwcx.  %0,0,%2\n\
 
564
        bne-    1b"
 
565
        SMP_ISYNC
 
566
        : "=&r" (t)
 
567
        : "r" (a), "r" (&v->counter)
 
568
        : "cc", "memory");
 
569
 
 
570
        return t;
 
571
}
 
572
 
 
573
static __inline__ void atomic_inc(atomic_t *v)
 
574
{
 
575
        int t;
 
576
 
 
577
        __asm__ __volatile__(
 
578
"1:     lwarx   %0,0,%2         # atomic_inc\n\
 
579
        addic   %0,%0,1\n\
 
580
        stwcx.  %0,0,%2\n\
 
581
        bne-    1b"
 
582
        : "=&r" (t), "=m" (v->counter)
 
583
        : "r" (&v->counter), "m" (v->counter)
 
584
        : "cc");
 
585
}
 
586
 
 
587
static __inline__ int atomic_inc_return(atomic_t *v)
 
588
{
 
589
        int t;
 
590
 
 
591
        __asm__ __volatile__(
 
592
"1:     lwarx   %0,0,%1         # atomic_inc_return\n\
 
593
        addic   %0,%0,1\n\
 
594
        stwcx.  %0,0,%1\n\
 
595
        bne-    1b"
 
596
        SMP_ISYNC
 
597
        : "=&r" (t)
 
598
        : "r" (&v->counter)
 
599
        : "cc", "memory");
 
600
 
 
601
        return t;
 
602
}
 
603
 
 
604
static __inline__ void atomic_dec(atomic_t *v)
 
605
{
 
606
        int t;
 
607
 
 
608
        __asm__ __volatile__(
 
609
"1:     lwarx   %0,0,%2         # atomic_dec\n\
 
610
        addic   %0,%0,-1\n\
 
611
        stwcx.  %0,0,%2\n\
 
612
        bne-    1b"
 
613
        : "=&r" (t), "=m" (v->counter)
 
614
        : "r" (&v->counter), "m" (v->counter)
 
615
        : "cc");
 
616
}
 
617
 
 
618
static __inline__ int atomic_dec_return(atomic_t *v)
 
619
{
 
620
        int t;
 
621
 
 
622
        __asm__ __volatile__(
 
623
"1:     lwarx   %0,0,%1         # atomic_dec_return\n\
 
624
        addic   %0,%0,-1\n\
 
625
        stwcx.  %0,0,%1\n\
 
626
        bne-    1b"
 
627
        SMP_ISYNC
 
628
        : "=&r" (t)
 
629
        : "r" (&v->counter)
 
630
        : "cc", "memory");
 
631
 
 
632
        return t;
 
633
}
 
634
 
 
635
#define atomic_sub_and_test(a, v)       (atomic_sub_return((a), (v)) == 0)
 
636
#define atomic_dec_and_test(v)          (atomic_dec_return((v)) == 0)
 
637
 
 
638
/*
 
639
 * Atomically test *v and decrement if it is greater than 0.
 
640
 * The function returns the old value of *v minus 1.
 
641
 */
 
642
static __inline__ int atomic_dec_if_positive(atomic_t *v)
 
643
{
 
644
        int t;
 
645
 
 
646
        __asm__ __volatile__(
 
647
"1:     lwarx   %0,0,%1         # atomic_dec_if_positive\n\
 
648
        addic.  %0,%0,-1\n\
 
649
        blt-    2f\n\
 
650
        stwcx.  %0,0,%1\n\
 
651
        bne-    1b"
 
652
        SMP_ISYNC
 
653
        "\n\
 
654
2:"     : "=&r" (t)
 
655
        : "r" (&v->counter)
 
656
        : "cc", "memory");
 
657
 
 
658
        return t;
 
659
}
 
660
 
 
661
/*
 
662
 * Memory barrier.
 
663
 * The sync instruction guarantees that all memory accesses initiated
 
664
 * by this processor have been performed (with respect to all other
 
665
 * mechanisms that access memory).  The eieio instruction is a barrier
 
666
 * providing an ordering (separately) for (a) cacheable stores and (b)
 
667
 * loads and stores to non-cacheable memory (e.g. I/O devices).
 
668
 *
 
669
 * mb() prevents loads and stores being reordered across this point.
 
670
 * rmb() prevents loads being reordered across this point.
 
671
 * wmb() prevents stores being reordered across this point.
 
672
 *
 
673
 * We can use the eieio instruction for wmb, but since it doesn't
 
674
 * give any ordering guarantees about loads, we have to use the
 
675
 * stronger but slower sync instruction for mb and rmb.
 
676
 */
 
677
#define mb()  __asm__ __volatile__ ("sync" : : : "memory")
 
678
#define rmb()  __asm__ __volatile__ ("sync" : : : "memory")
 
679
#define wmb()  __asm__ __volatile__ ("eieio" : : : "memory")
 
680
 
 
681
#define IATOMIC_DEFINED         1
 
682
 
 
683
#endif /* __powerpc__ */
 
684
 
 
685
#ifdef __mips__
 
686
 
 
687
typedef struct { volatile int counter; } atomic_t;
 
688
 
 
689
#define ATOMIC_INIT(i)    { (i) }
 
690
 
 
691
/*
 
692
 * atomic_read - read atomic variable
 
693
 * @v: pointer of type atomic_t
 
694
 *
 
695
 * Atomically reads the value of @v.  Note that the guaranteed
 
696
 * useful range of an atomic_t is only 24 bits.
 
697
 */
 
698
#define atomic_read(v)  ((v)->counter)
 
699
 
 
700
/*
 
701
 * atomic_set - set atomic variable
 
702
 * @v: pointer of type atomic_t
 
703
 * @i: required value
 
704
 *
 
705
 * Atomically sets the value of @v to @i.  Note that the guaranteed
 
706
 * useful range of an atomic_t is only 24 bits.
 
707
 */
 
708
#define atomic_set(v,i) ((v)->counter = (i))
 
709
 
 
710
/*
 
711
 * for MIPS II and better we can use ll/sc instruction, and kernel 2.4.3+
 
712
 * will emulate it on MIPS I.
 
713
 */
 
714
 
 
715
/*
 
716
 * atomic_add - add integer to atomic variable
 
717
 * @i: integer value to add
 
718
 * @v: pointer of type atomic_t
 
719
 *
 
720
 * Atomically adds @i to @v.  Note that the guaranteed useful range
 
721
 * of an atomic_t is only 24 bits.
 
722
 */
 
723
extern __inline__ void atomic_add(int i, atomic_t * v)
 
724
{
 
725
        unsigned long temp;
 
726
 
 
727
        __asm__ __volatile__(
 
728
                ".set push                            \n"
 
729
                ".set mips2                           \n"
 
730
                "1:   ll      %0, %1      # atomic_add\n"
 
731
                "     addu    %0, %2                  \n"
 
732
                "     sc      %0, %1                  \n"
 
733
                "     beqz    %0, 1b                  \n"
 
734
                ".set pop                             \n"
 
735
                : "=&r" (temp), "=m" (v->counter)
 
736
                : "Ir" (i), "m" (v->counter));
 
737
}
 
738
 
 
739
/*
 
740
 * atomic_sub - subtract the atomic variable
 
741
 * @i: integer value to subtract
 
742
 * @v: pointer of type atomic_t
 
743
 *
 
744
 * Atomically subtracts @i from @v.  Note that the guaranteed
 
745
 * useful range of an atomic_t is only 24 bits.
 
746
 */
 
747
extern __inline__ void atomic_sub(int i, atomic_t * v)
 
748
{
 
749
        unsigned long temp;
 
750
 
 
751
        __asm__ __volatile__(
 
752
                ".set push                            \n"
 
753
                ".set mips2                           \n"
 
754
                "1:   ll      %0, %1      # atomic_sub\n"
 
755
                "     subu    %0, %2                  \n"
 
756
                "     sc      %0, %1                  \n"
 
757
                "     beqz    %0, 1b                  \n"
 
758
                ".set pop                             \n"
 
759
                : "=&r" (temp), "=m" (v->counter)
 
760
                : "Ir" (i), "m" (v->counter));
 
761
}
 
762
 
 
763
/*
 
764
 * Same as above, but return the result value
 
765
 */
 
766
extern __inline__ int atomic_add_return(int i, atomic_t * v)
 
767
{
 
768
        unsigned long temp, result;
 
769
 
 
770
        __asm__ __volatile__(
 
771
                ".set push               # atomic_add_return\n"
 
772
                ".set noreorder                             \n"
 
773
                ".set mips2                                 \n"
 
774
                "1:   ll      %1, %2                        \n"
 
775
                "     addu    %0, %1, %3                    \n"
 
776
                "     sc      %0, %2                        \n"
 
777
                "     beqz    %0, 1b                        \n"
 
778
                "     addu    %0, %1, %3                    \n"
 
779
                ".set pop                                   \n"
 
780
                : "=&r" (result), "=&r" (temp), "=m" (v->counter)
 
781
                : "Ir" (i), "m" (v->counter)
 
782
                : "memory");
 
783
 
 
784
        return result;
 
785
}
 
786
 
 
787
extern __inline__ int atomic_sub_return(int i, atomic_t * v)
 
788
{
 
789
        unsigned long temp, result;
 
790
 
 
791
        __asm__ __volatile__(
 
792
                ".set push                                   \n"
 
793
                ".set mips2                                  \n"
 
794
                ".set noreorder           # atomic_sub_return\n"
 
795
                "1:   ll    %1, %2                           \n"
 
796
                "     subu  %0, %1, %3                       \n"
 
797
                "     sc    %0, %2                           \n"
 
798
                "     beqz  %0, 1b                           \n"
 
799
                "     subu  %0, %1, %3                       \n"
 
800
                ".set pop                                    \n"
 
801
                : "=&r" (result), "=&r" (temp), "=m" (v->counter)
 
802
                : "Ir" (i), "m" (v->counter)
 
803
                : "memory");
 
804
 
 
805
        return result;
 
806
}
 
807
 
 
808
#define atomic_dec_return(v) atomic_sub_return(1,(v))
 
809
#define atomic_inc_return(v) atomic_add_return(1,(v))
 
810
 
 
811
/*
 
812
 * atomic_sub_and_test - subtract value from variable and test result
 
813
 * @i: integer value to subtract
 
814
 * @v: pointer of type atomic_t
 
815
 *
 
816
 * Atomically subtracts @i from @v and returns
 
817
 * true if the result is zero, or false for all
 
818
 * other cases.  Note that the guaranteed
 
819
 * useful range of an atomic_t is only 24 bits.
 
820
 */
 
821
#define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
 
822
 
 
823
/*
 
824
 * atomic_inc_and_test - increment and test
 
825
 * @v: pointer of type atomic_t
 
826
 *
 
827
 * Atomically increments @v by 1
 
828
 * and returns true if the result is zero, or false for all
 
829
 * other cases.  Note that the guaranteed
 
830
 * useful range of an atomic_t is only 24 bits.
 
831
 */
 
832
#define atomic_inc_and_test(v) (atomic_inc_return(1, (v)) == 0)
 
833
 
 
834
/*
 
835
 * atomic_dec_and_test - decrement by 1 and test
 
836
 * @v: pointer of type atomic_t
 
837
 *
 
838
 * Atomically decrements @v by 1 and
 
839
 * returns true if the result is 0, or false for all other
 
840
 * cases.  Note that the guaranteed
 
841
 * useful range of an atomic_t is only 24 bits.
 
842
 */
 
843
#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
 
844
 
 
845
/*
 
846
 * atomic_inc - increment atomic variable
 
847
 * @v: pointer of type atomic_t
 
848
 *
 
849
 * Atomically increments @v by 1.  Note that the guaranteed
 
850
 * useful range of an atomic_t is only 24 bits.
 
851
 */
 
852
#define atomic_inc(v) atomic_add(1,(v))
 
853
 
 
854
/*
 
855
 * atomic_dec - decrement and test
 
856
 * @v: pointer of type atomic_t
 
857
 *
 
858
 * Atomically decrements @v by 1.  Note that the guaranteed
 
859
 * useful range of an atomic_t is only 24 bits.
 
860
 */
 
861
#define atomic_dec(v) atomic_sub(1,(v))
 
862
 
 
863
/*
 
864
 * atomic_add_negative - add and test if negative
 
865
 * @v: pointer of type atomic_t
 
866
 * @i: integer value to add
 
867
 *
 
868
 * Atomically adds @i to @v and returns true
 
869
 * if the result is negative, or false when
 
870
 * result is greater than or equal to zero.  Note that the guaranteed
 
871
 * useful range of an atomic_t is only 24 bits.
 
872
 *
 
873
 * Currently not implemented for MIPS.
 
874
 */
 
875
 
 
876
#define mb()                                            \
 
877
__asm__ __volatile__(                                   \
 
878
        "# prevent instructions being moved around\n\t" \
 
879
        ".set\tnoreorder\n\t"                           \
 
880
        "# 8 nops to fool the R4400 pipeline\n\t"       \
 
881
        "nop;nop;nop;nop;nop;nop;nop;nop\n\t"           \
 
882
        ".set\treorder"                                 \
 
883
        : /* no output */                               \
 
884
        : /* no input */                                \
 
885
        : "memory")
 
886
#define rmb() mb()
 
887
#define wmb() mb()
 
888
 
 
889
#define IATOMIC_DEFINED         1
 
890
 
 
891
#endif /* __mips__ */
 
892
 
 
893
#ifdef __arm__
 
894
 
 
895
/*
 
896
 * FIXME: bellow code is valid only for SA11xx
 
897
 */
 
898
 
 
899
/*
 
900
 * Save the current interrupt enable state & disable IRQs
 
901
 */
 
902
#define local_irq_save(x)                                       \
 
903
        ({                                                      \
 
904
                unsigned long temp;                             \
 
905
        __asm__ __volatile__(                                   \
 
906
        "mrs    %0, cpsr                @ local_irq_save\n"     \
 
907
"       orr     %1, %0, #128\n"                                 \
 
908
"       msr     cpsr_c, %1"                                     \
 
909
        : "=r" (x), "=r" (temp)                                 \
 
910
        :                                                       \
 
911
        : "memory");                                            \
 
912
        })
 
913
 
 
914
/*
 
915
 * restore saved IRQ & FIQ state
 
916
 */
 
917
#define local_irq_restore(x)                                    \
 
918
        __asm__ __volatile__(                                   \
 
919
        "msr    cpsr_c, %0              @ local_irq_restore\n"  \
 
920
        :                                                       \
 
921
        : "r" (x)                                               \
 
922
        : "memory")
 
923
 
 
924
#define __save_flags_cli(x) local_irq_save(x)
 
925
#define __restore_flags(x) local_irq_restore(x)
 
926
 
 
927
typedef struct { volatile int counter; } atomic_t;
 
928
 
 
929
#define ATOMIC_INIT(i)  { (i) }
 
930
 
 
931
#define atomic_read(v)  ((v)->counter)
 
932
#define atomic_set(v,i) (((v)->counter) = (i))
 
933
 
 
934
static __inline__ void atomic_add(int i, volatile atomic_t *v)
 
935
{
 
936
        unsigned long flags;
 
937
 
 
938
        __save_flags_cli(flags);
 
939
        v->counter += i;
 
940
        __restore_flags(flags);
 
941
}
 
942
 
 
943
static __inline__ void atomic_sub(int i, volatile atomic_t *v)
 
944
{
 
945
        unsigned long flags;
 
946
 
 
947
        __save_flags_cli(flags);
 
948
        v->counter -= i;
 
949
        __restore_flags(flags);
 
950
}
 
951
 
 
952
static __inline__ void atomic_inc(volatile atomic_t *v)
 
953
{
 
954
        unsigned long flags;
 
955
 
 
956
        __save_flags_cli(flags);
 
957
        v->counter += 1;
 
958
        __restore_flags(flags);
 
959
}
 
960
 
 
961
static __inline__ void atomic_dec(volatile atomic_t *v)
 
962
{
 
963
        unsigned long flags;
 
964
 
 
965
        __save_flags_cli(flags);
 
966
        v->counter -= 1;
 
967
        __restore_flags(flags);
 
968
}
 
969
 
 
970
static __inline__ int atomic_dec_and_test(volatile atomic_t *v)
 
971
{
 
972
        unsigned long flags;
 
973
        int result;
 
974
 
 
975
        __save_flags_cli(flags);
 
976
        v->counter -= 1;
 
977
        result = (v->counter == 0);
 
978
        __restore_flags(flags);
 
979
 
 
980
        return result;
 
981
}
 
982
 
 
983
static inline int atomic_add_negative(int i, volatile atomic_t *v)
 
984
{
 
985
        unsigned long flags;
 
986
        int result;
 
987
 
 
988
        __save_flags_cli(flags);
 
989
        v->counter += i;
 
990
        result = (v->counter < 0);
 
991
        __restore_flags(flags);
 
992
 
 
993
        return result;
 
994
}
 
995
 
 
996
static __inline__ void atomic_clear_mask(unsigned long mask, unsigned long *addr)
 
997
{
 
998
        unsigned long flags;
 
999
 
 
1000
        __save_flags_cli(flags);
 
1001
        *addr &= ~mask;
 
1002
        __restore_flags(flags);
 
1003
}
 
1004
 
 
1005
#define mb() __asm__ __volatile__ ("" : : : "memory")
 
1006
#define rmb() mb()
 
1007
#define wmb() mb()
 
1008
 
 
1009
#define IATOMIC_DEFINED         1
 
1010
 
 
1011
#endif /* __arm__ */
 
1012
 
 
1013
#ifndef IATOMIC_DEFINED
 
1014
/*
 
1015
 * non supported architecture.
 
1016
 */
 
1017
#warning "Atomic operations are not supported on this architecture."
 
1018
 
 
1019
typedef struct { volatile int counter; } atomic_t;
 
1020
 
 
1021
#define ATOMIC_INIT(i)  { (i) }
 
1022
 
 
1023
#define atomic_read(v)  ((v)->counter)
 
1024
#define atomic_set(v,i) (((v)->counter) = (i))
 
1025
#define atomic_add(i,v) (((v)->counter) += (i))
 
1026
#define atomic_sub(i,v) (((v)->counter) -= (i))
 
1027
#define atomic_inc(v)   (((v)->counter)++)
 
1028
#define atomic_dec(v)   (((v)->counter)--)
 
1029
 
 
1030
#define mb()
 
1031
#define rmb()
 
1032
#define wmb()
 
1033
 
 
1034
#define IATOMIC_DEFINED         1
 
1035
 
 
1036
#endif /* IATOMIC_DEFINED */
 
1037
 
 
1038
/*
 
1039
 *  Atomic read/write
 
1040
 *  Copyright (c) 2001 by Abramo Bagnara <abramo@alsa-project.org>
 
1041
 */
 
1042
 
 
1043
/* Max number of times we must spin on a spin-lock calling sched_yield().
 
1044
   After MAX_SPIN_COUNT iterations, we put the calling thread to sleep. */
 
1045
 
 
1046
#ifndef MAX_SPIN_COUNT
 
1047
#define MAX_SPIN_COUNT 50
 
1048
#endif
 
1049
 
 
1050
/* Duration of sleep (in nanoseconds) when we can't acquire a spin-lock
 
1051
   after MAX_SPIN_COUNT iterations of sched_yield().
 
1052
   This MUST BE > 2ms.
 
1053
   (Otherwise the kernel does busy-waiting for real-time threads,
 
1054
    giving other threads no chance to run.) */
 
1055
 
 
1056
#ifndef SPIN_SLEEP_DURATION
 
1057
#define SPIN_SLEEP_DURATION 2000001
 
1058
#endif
 
1059
 
 
1060
typedef struct {
 
1061
        unsigned int begin, end;
 
1062
} snd_atomic_write_t;
 
1063
 
 
1064
typedef struct {
 
1065
        volatile const snd_atomic_write_t *write;
 
1066
        unsigned int end;
 
1067
} snd_atomic_read_t;
 
1068
 
 
1069
void snd_atomic_read_wait(snd_atomic_read_t *t);
 
1070
 
 
1071
static inline void snd_atomic_write_init(snd_atomic_write_t *w)
 
1072
{
 
1073
        w->begin = 0;
 
1074
        w->end = 0;
 
1075
}
 
1076
 
 
1077
static inline void snd_atomic_write_begin(snd_atomic_write_t *w)
 
1078
{
 
1079
        w->begin++;
 
1080
        wmb();
 
1081
}
 
1082
 
 
1083
static inline void snd_atomic_write_end(snd_atomic_write_t *w)
 
1084
{
 
1085
        wmb();
 
1086
        w->end++;
 
1087
}
 
1088
 
 
1089
static inline void snd_atomic_read_init(snd_atomic_read_t *r, snd_atomic_write_t *w)
 
1090
{
 
1091
        r->write = w;
 
1092
}
 
1093
 
 
1094
static inline void snd_atomic_read_begin(snd_atomic_read_t *r)
 
1095
{
 
1096
        r->end = r->write->end;
 
1097
        rmb();
 
1098
}
 
1099
 
 
1100
static inline int snd_atomic_read_ok(snd_atomic_read_t *r)
 
1101
{
 
1102
        rmb();
 
1103
        return r->end == r->write->begin;
 
1104
}
 
1105
 
 
1106
#endif /* __ALSA_IATOMIC_H */