Blame view

include/asm-arm26/bitops.h 5.84 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
  /*
   * Copyright 1995, Russell King.
   *
   * Based on the arm32 version by RMK (and others). Their copyrights apply to
   * Those parts.
   * Modified for arm26 by Ian Molton on 25/11/04
   *
   * bit 0 is the LSB of an "unsigned long" quantity.
   *
   * Please note that the code in this file should never be included
   * from user space.  Many of these are not implemented in assembler
   * since they would be too costly.  Also, they require privileged
   * instructions (which are not available from user mode) to ensure
   * that they are atomic.
   */
  
  #ifndef __ASM_ARM_BITOPS_H
  #define __ASM_ARM_BITOPS_H
  
  #ifdef __KERNEL__
  
  #include <linux/compiler.h>
  #include <asm/system.h>
  
  #define smp_mb__before_clear_bit()	do { } while (0)
  #define smp_mb__after_clear_bit()	do { } while (0)
  
  /*
   * These functions are the basis of our bit ops.
   *
   * First, the atomic bitops. These use native endian.
   */
  static inline void ____atomic_set_bit(unsigned int bit, volatile unsigned long *p)
  {
  	unsigned long flags;
  	unsigned long mask = 1UL << (bit & 31);
  
  	p += bit >> 5;
  
  	local_irq_save(flags);
  	*p |= mask;
  	local_irq_restore(flags);
  }
  
  static inline void ____atomic_clear_bit(unsigned int bit, volatile unsigned long *p)
  {
  	unsigned long flags;
  	unsigned long mask = 1UL << (bit & 31);
  
  	p += bit >> 5;
  
  	local_irq_save(flags);
  	*p &= ~mask;
  	local_irq_restore(flags);
  }
  
  static inline void ____atomic_change_bit(unsigned int bit, volatile unsigned long *p)
  {
  	unsigned long flags;
  	unsigned long mask = 1UL << (bit & 31);
  
  	p += bit >> 5;
  
  	local_irq_save(flags);
  	*p ^= mask;
  	local_irq_restore(flags);
  }
  
  static inline int
  ____atomic_test_and_set_bit(unsigned int bit, volatile unsigned long *p)
  {
  	unsigned long flags;
  	unsigned int res;
  	unsigned long mask = 1UL << (bit & 31);
  
  	p += bit >> 5;
  
  	local_irq_save(flags);
  	res = *p;
  	*p = res | mask;
  	local_irq_restore(flags);
  
  	return res & mask;
  }
  
  static inline int
  ____atomic_test_and_clear_bit(unsigned int bit, volatile unsigned long *p)
  {
  	unsigned long flags;
  	unsigned int res;
  	unsigned long mask = 1UL << (bit & 31);
  
  	p += bit >> 5;
  
  	local_irq_save(flags);
  	res = *p;
  	*p = res & ~mask;
  	local_irq_restore(flags);
  
  	return res & mask;
  }
  
  static inline int
  ____atomic_test_and_change_bit(unsigned int bit, volatile unsigned long *p)
  {
  	unsigned long flags;
  	unsigned int res;
  	unsigned long mask = 1UL << (bit & 31);
  
  	p += bit >> 5;
  
  	local_irq_save(flags);
  	res = *p;
  	*p = res ^ mask;
  	local_irq_restore(flags);
  
  	return res & mask;
  }
d142d8601   Akinobu Mita   [PATCH] bitops: a...
119
  #include <asm-generic/bitops/non-atomic.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
121
122
123
124
125
126
127
128
129
  
  /*
   * Little endian assembly bitops.  nr = 0 -> byte 0 bit 0.
   */
  extern void _set_bit_le(int nr, volatile unsigned long * p);
  extern void _clear_bit_le(int nr, volatile unsigned long * p);
  extern void _change_bit_le(int nr, volatile unsigned long * p);
  extern int _test_and_set_bit_le(int nr, volatile unsigned long * p);
  extern int _test_and_clear_bit_le(int nr, volatile unsigned long * p);
  extern int _test_and_change_bit_le(int nr, volatile unsigned long * p);
a1320ae31   Alexey Dobriyan   [PATCH] arm26: fi...
130
  extern int _find_first_zero_bit_le(const unsigned long * p, unsigned size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
  extern int _find_next_zero_bit_le(void * p, int size, int offset);
  extern int _find_first_bit_le(const unsigned long *p, unsigned size);
  extern int _find_next_bit_le(const unsigned long *p, int size, int offset);
  
  /*
   * The __* form of bitops are non-atomic and may be reordered.
   */
  #define	ATOMIC_BITOP_LE(name,nr,p)		\
  	(__builtin_constant_p(nr) ?		\
  	 ____atomic_##name(nr, p) :		\
  	 _##name##_le(nr,p))
  
  #define NONATOMIC_BITOP(name,nr,p)		\
  	(____nonatomic_##name(nr, p))
  
  /*
   * These are the little endian, atomic definitions.
   */
  #define set_bit(nr,p)			ATOMIC_BITOP_LE(set_bit,nr,p)
  #define clear_bit(nr,p)			ATOMIC_BITOP_LE(clear_bit,nr,p)
  #define change_bit(nr,p)		ATOMIC_BITOP_LE(change_bit,nr,p)
  #define test_and_set_bit(nr,p)		ATOMIC_BITOP_LE(test_and_set_bit,nr,p)
  #define test_and_clear_bit(nr,p)	ATOMIC_BITOP_LE(test_and_clear_bit,nr,p)
  #define test_and_change_bit(nr,p)	ATOMIC_BITOP_LE(test_and_change_bit,nr,p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
155
156
157
158
159
160
  #define find_first_zero_bit(p,sz)	_find_first_zero_bit_le(p,sz)
  #define find_next_zero_bit(p,sz,off)	_find_next_zero_bit_le(p,sz,off)
  #define find_first_bit(p,sz)		_find_first_bit_le(p,sz)
  #define find_next_bit(p,sz,off)		_find_next_bit_le(p,sz,off)
  
  #define WORD_BITOFF_TO_LE(x)		((x))
d142d8601   Akinobu Mita   [PATCH] bitops: a...
161
162
163
164
165
166
167
  #include <asm-generic/bitops/ffz.h>
  #include <asm-generic/bitops/__ffs.h>
  #include <asm-generic/bitops/fls.h>
  #include <asm-generic/bitops/fls64.h>
  #include <asm-generic/bitops/ffs.h>
  #include <asm-generic/bitops/sched.h>
  #include <asm-generic/bitops/hweight.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168
169
170
171
172
173
174
175
176
177
178
179
180
181
  
  /*
   * Ext2 is defined to use little-endian byte ordering.
   * These do not need to be atomic.
   */
  #define ext2_set_bit(nr,p)			\
  		__test_and_set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
  #define ext2_set_bit_atomic(lock,nr,p)          \
                  test_and_set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
  #define ext2_clear_bit(nr,p)			\
  		__test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
  #define ext2_clear_bit_atomic(lock,nr,p)        \
                  test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
  #define ext2_test_bit(nr,p)			\
d142d8601   Akinobu Mita   [PATCH] bitops: a...
182
  		test_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
184
185
186
187
188
189
190
191
192
193
194
  #define ext2_find_first_zero_bit(p,sz)		\
  		_find_first_zero_bit_le(p,sz)
  #define ext2_find_next_zero_bit(p,sz,off)	\
  		_find_next_zero_bit_le(p,sz,off)
  
  /*
   * Minix is defined to use little-endian byte ordering.
   * These do not need to be atomic.
   */
  #define minix_set_bit(nr,p)			\
  		__set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
  #define minix_test_bit(nr,p)			\
d142d8601   Akinobu Mita   [PATCH] bitops: a...
195
  		test_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
196
197
198
199
200
  #define minix_test_and_set_bit(nr,p)		\
  		__test_and_set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
  #define minix_test_and_clear_bit(nr,p)		\
  		__test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
  #define minix_find_first_zero_bit(p,sz)		\
a1320ae31   Alexey Dobriyan   [PATCH] arm26: fi...
201
  		_find_first_zero_bit_le((unsigned long *)(p),sz)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
203
204
205
  
  #endif /* __KERNEL__ */
  
  #endif /* _ARM_BITOPS_H */