v2.4.8 -> v2.4.8.1
[opensuse:kernel.git] / include / asm-arm / atomic.h
1 /*
2  *  linux/include/asm-arm/atomic.h
3  *
4  *  Copyright (c) 1996 Russell King.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  *  Changelog:
11  *   27-06-1996 RMK     Created
12  *   13-04-1997 RMK     Made functions atomic!
13  *   07-12-1997 RMK     Upgraded for v2.1.
14  *   26-08-1998 PJB     Added #ifdef __KERNEL__
15  */
16 #ifndef __ASM_ARM_ATOMIC_H
17 #define __ASM_ARM_ATOMIC_H
18
19 #include <linux/config.h>
20
21 #ifdef CONFIG_SMP
22 #error SMP not supported
23 #endif
24
25 #ifdef CONFIG_ARCH_CO285
26 typedef struct { volatile int counter; } atomic_t;
27 #else
28 typedef struct { int counter; } atomic_t;
29 #endif
30
31 #define ATOMIC_INIT(i)  { (i) }
32
33 #ifdef __KERNEL__
34 #include <asm/proc/system.h>
35
36 #define atomic_read(v)  ((v)->counter)
37 #define atomic_set(v,i) (((v)->counter) = (i))
38
39 static __inline__ void atomic_add(int i, volatile atomic_t *v)
40 {
41         unsigned long flags;
42
43         __save_flags_cli(flags);
44         v->counter += i;
45         __restore_flags(flags);
46 }
47
48 static __inline__ void atomic_sub(int i, volatile atomic_t *v)
49 {
50         unsigned long flags;
51
52         __save_flags_cli(flags);
53         v->counter -= i;
54         __restore_flags(flags);
55 }
56
57 static __inline__ void atomic_inc(volatile atomic_t *v)
58 {
59         unsigned long flags;
60
61         __save_flags_cli(flags);
62         v->counter += 1;
63         __restore_flags(flags);
64 }
65
66 static __inline__ void atomic_dec(volatile atomic_t *v)
67 {
68         unsigned long flags;
69
70         __save_flags_cli(flags);
71         v->counter -= 1;
72         __restore_flags(flags);
73 }
74
75 static __inline__ int atomic_dec_and_test(volatile atomic_t *v)
76 {
77         unsigned long flags;
78         int result;
79
80         __save_flags_cli(flags);
81         v->counter -= 1;
82         result = (v->counter == 0);
83         __restore_flags(flags);
84
85         return result;
86 }
87
88 static inline int atomic_add_negative(int i, volatile atomic_t *v)
89 {
90         unsigned long flags;
91         int result;
92
93         __save_flags_cli(flags);
94         v->counter += i;
95         result = (v->counter < 0);
96         __restore_flags(flags);
97
98         return result;
99 }
100
101 static __inline__ void atomic_clear_mask(unsigned long mask, unsigned long *addr)
102 {
103         unsigned long flags;
104
105         __save_flags_cli(flags);
106         *addr &= ~mask;
107         __restore_flags(flags);
108 }
109
110 /* Atomic operations are already serializing on ARM */
111 #define smp_mb__before_atomic_dec()     barrier()
112 #define smp_mb__after_atomic_dec()      barrier()
113 #define smp_mb__before_atomic_inc()     barrier()
114 #define smp_mb__after_atomic_inc()      barrier()
115
116 #endif
117 #endif