~ubuntu-branches/ubuntu/utopic/xen/utopic

« back to all changes in this revision

Viewing changes to xen/include/asm-i386/bitops.h

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Blank
  • Date: 2010-05-06 15:47:38 UTC
  • mto: (1.3.1) (15.1.1 sid) (4.1.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20100506154738-agoz0rlafrh1fnq7
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#ifndef _I386_BITOPS_H
2
 
#define _I386_BITOPS_H
3
 
 
4
 
/*
5
 
 * Copyright 1992, Linus Torvalds.
6
 
 */
7
 
 
8
 
#include <xeno/config.h>
9
 
 
10
 
/*
11
 
 * These have to be done with inline assembly: that way the bit-setting
12
 
 * is guaranteed to be atomic. All bit operations return 0 if the bit
13
 
 * was cleared before the operation and != 0 if it was not.
14
 
 *
15
 
 * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
16
 
 */
17
 
 
18
 
#ifdef CONFIG_SMP
19
 
#define LOCK_PREFIX "lock ; "
20
 
#else
21
 
#define LOCK_PREFIX ""
22
 
#endif
23
 
 
24
 
#define ADDR (*(volatile long *) addr)
25
 
 
26
 
/**
27
 
 * set_bit - Atomically set a bit in memory
28
 
 * @nr: the bit to set
29
 
 * @addr: the address to start counting from
30
 
 *
31
 
 * This function is atomic and may not be reordered.  See __set_bit()
32
 
 * if you do not require the atomic guarantees.
33
 
 * Note that @nr may be almost arbitrarily large; this function is not
34
 
 * restricted to acting on a single-word quantity.
35
 
 */
36
 
static __inline__ void set_bit(int nr, volatile void * addr)
37
 
{
38
 
        __asm__ __volatile__( LOCK_PREFIX
39
 
                "btsl %1,%0"
40
 
                :"=m" (ADDR)
41
 
                :"Ir" (nr));
42
 
}
43
 
 
44
 
/**
45
 
 * __set_bit - Set a bit in memory
46
 
 * @nr: the bit to set
47
 
 * @addr: the address to start counting from
48
 
 *
49
 
 * Unlike set_bit(), this function is non-atomic and may be reordered.
50
 
 * If it's called on the same region of memory simultaneously, the effect
51
 
 * may be that only one operation succeeds.
52
 
 */
53
 
static __inline__ void __set_bit(int nr, volatile void * addr)
54
 
{
55
 
        __asm__(
56
 
                "btsl %1,%0"
57
 
                :"=m" (ADDR)
58
 
                :"Ir" (nr));
59
 
}
60
 
 
61
 
/**
62
 
 * clear_bit - Clears a bit in memory
63
 
 * @nr: Bit to clear
64
 
 * @addr: Address to start counting from
65
 
 *
66
 
 * clear_bit() is atomic and may not be reordered.  However, it does
67
 
 * not contain a memory barrier, so if it is used for locking purposes,
68
 
 * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
69
 
 * in order to ensure changes are visible on other processors.
70
 
 */
71
 
static __inline__ void clear_bit(int nr, volatile void * addr)
72
 
{
73
 
        __asm__ __volatile__( LOCK_PREFIX
74
 
                "btrl %1,%0"
75
 
                :"=m" (ADDR)
76
 
                :"Ir" (nr));
77
 
}
78
 
#define smp_mb__before_clear_bit()      barrier()
79
 
#define smp_mb__after_clear_bit()       barrier()
80
 
 
81
 
/**
82
 
 * __change_bit - Toggle a bit in memory
83
 
 * @nr: the bit to set
84
 
 * @addr: the address to start counting from
85
 
 *
86
 
 * Unlike change_bit(), this function is non-atomic and may be reordered.
87
 
 * If it's called on the same region of memory simultaneously, the effect
88
 
 * may be that only one operation succeeds.
89
 
 */
90
 
static __inline__ void __change_bit(int nr, volatile void * addr)
91
 
{
92
 
        __asm__ __volatile__(
93
 
                "btcl %1,%0"
94
 
                :"=m" (ADDR)
95
 
                :"Ir" (nr));
96
 
}
97
 
 
98
 
/**
99
 
 * change_bit - Toggle a bit in memory
100
 
 * @nr: Bit to clear
101
 
 * @addr: Address to start counting from
102
 
 *
103
 
 * change_bit() is atomic and may not be reordered.
104
 
 * Note that @nr may be almost arbitrarily large; this function is not
105
 
 * restricted to acting on a single-word quantity.
106
 
 */
107
 
static __inline__ void change_bit(int nr, volatile void * addr)
108
 
{
109
 
        __asm__ __volatile__( LOCK_PREFIX
110
 
                "btcl %1,%0"
111
 
                :"=m" (ADDR)
112
 
                :"Ir" (nr));
113
 
}
114
 
 
115
 
/**
116
 
 * test_and_set_bit - Set a bit and return its old value
117
 
 * @nr: Bit to set
118
 
 * @addr: Address to count from
119
 
 *
120
 
 * This operation is atomic and cannot be reordered.  
121
 
 * It also implies a memory barrier.
122
 
 */
123
 
static __inline__ int test_and_set_bit(int nr, volatile void * addr)
124
 
{
125
 
        int oldbit;
126
 
 
127
 
        __asm__ __volatile__( LOCK_PREFIX
128
 
                "btsl %2,%1\n\tsbbl %0,%0"
129
 
                :"=r" (oldbit),"=m" (ADDR)
130
 
                :"Ir" (nr) : "memory");
131
 
        return oldbit;
132
 
}
133
 
 
134
 
/**
135
 
 * __test_and_set_bit - Set a bit and return its old value
136
 
 * @nr: Bit to set
137
 
 * @addr: Address to count from
138
 
 *
139
 
 * This operation is non-atomic and can be reordered.  
140
 
 * If two examples of this operation race, one can appear to succeed
141
 
 * but actually fail.  You must protect multiple accesses with a lock.
142
 
 */
143
 
static __inline__ int __test_and_set_bit(int nr, volatile void * addr)
144
 
{
145
 
        int oldbit;
146
 
 
147
 
        __asm__(
148
 
                "btsl %2,%1\n\tsbbl %0,%0"
149
 
                :"=r" (oldbit),"=m" (ADDR)
150
 
                :"Ir" (nr));
151
 
        return oldbit;
152
 
}
153
 
 
154
 
/**
155
 
 * test_and_clear_bit - Clear a bit and return its old value
156
 
 * @nr: Bit to set
157
 
 * @addr: Address to count from
158
 
 *
159
 
 * This operation is atomic and cannot be reordered.  
160
 
 * It also implies a memory barrier.
161
 
 */
162
 
static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
163
 
{
164
 
        int oldbit;
165
 
 
166
 
        __asm__ __volatile__( LOCK_PREFIX
167
 
                "btrl %2,%1\n\tsbbl %0,%0"
168
 
                :"=r" (oldbit),"=m" (ADDR)
169
 
                :"Ir" (nr) : "memory");
170
 
        return oldbit;
171
 
}
172
 
 
173
 
/**
174
 
 * __test_and_clear_bit - Clear a bit and return its old value
175
 
 * @nr: Bit to set
176
 
 * @addr: Address to count from
177
 
 *
178
 
 * This operation is non-atomic and can be reordered.  
179
 
 * If two examples of this operation race, one can appear to succeed
180
 
 * but actually fail.  You must protect multiple accesses with a lock.
181
 
 */
182
 
static __inline__ int __test_and_clear_bit(int nr, volatile void * addr)
183
 
{
184
 
        int oldbit;
185
 
 
186
 
        __asm__(
187
 
                "btrl %2,%1\n\tsbbl %0,%0"
188
 
                :"=r" (oldbit),"=m" (ADDR)
189
 
                :"Ir" (nr));
190
 
        return oldbit;
191
 
}
192
 
 
193
 
/* WARNING: non atomic and it can be reordered! */
194
 
static __inline__ int __test_and_change_bit(int nr, volatile void * addr)
195
 
{
196
 
        int oldbit;
197
 
 
198
 
        __asm__ __volatile__(
199
 
                "btcl %2,%1\n\tsbbl %0,%0"
200
 
                :"=r" (oldbit),"=m" (ADDR)
201
 
                :"Ir" (nr) : "memory");
202
 
        return oldbit;
203
 
}
204
 
 
205
 
/**
206
 
 * test_and_change_bit - Change a bit and return its new value
207
 
 * @nr: Bit to set
208
 
 * @addr: Address to count from
209
 
 *
210
 
 * This operation is atomic and cannot be reordered.  
211
 
 * It also implies a memory barrier.
212
 
 */
213
 
static __inline__ int test_and_change_bit(int nr, volatile void * addr)
214
 
{
215
 
        int oldbit;
216
 
 
217
 
        __asm__ __volatile__( LOCK_PREFIX
218
 
                "btcl %2,%1\n\tsbbl %0,%0"
219
 
                :"=r" (oldbit),"=m" (ADDR)
220
 
                :"Ir" (nr) : "memory");
221
 
        return oldbit;
222
 
}
223
 
 
224
 
 
225
 
static __inline__ int constant_test_bit(int nr, const volatile void * addr)
226
 
{
227
 
        return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
228
 
}
229
 
 
230
 
static __inline__ int variable_test_bit(int nr, volatile void * addr)
231
 
{
232
 
        int oldbit;
233
 
 
234
 
        __asm__ __volatile__(
235
 
                "btl %2,%1\n\tsbbl %0,%0"
236
 
                :"=r" (oldbit)
237
 
                :"m" (ADDR),"Ir" (nr));
238
 
        return oldbit;
239
 
}
240
 
 
241
 
#define test_bit(nr,addr) \
242
 
(__builtin_constant_p(nr) ? \
243
 
 constant_test_bit((nr),(addr)) : \
244
 
 variable_test_bit((nr),(addr)))
245
 
 
246
 
/**
247
 
 * find_first_zero_bit - find the first zero bit in a memory region
248
 
 * @addr: The address to start the search at
249
 
 * @size: The maximum size to search
250
 
 *
251
 
 * Returns the bit-number of the first zero bit, not the number of the byte
252
 
 * containing a bit.
253
 
 */
254
 
static __inline__ int find_first_zero_bit(void * addr, unsigned size)
255
 
{
256
 
        int d0, d1, d2;
257
 
        int res;
258
 
 
259
 
        if (!size)
260
 
                return 0;
261
 
        /* This looks at memory. Mark it volatile to tell gcc not to move it around */
262
 
        __asm__ __volatile__(
263
 
                "movl $-1,%%eax\n\t"
264
 
                "xorl %%edx,%%edx\n\t"
265
 
                "repe; scasl\n\t"
266
 
                "je 1f\n\t"
267
 
                "xorl -4(%%edi),%%eax\n\t"
268
 
                "subl $4,%%edi\n\t"
269
 
                "bsfl %%eax,%%edx\n"
270
 
                "1:\tsubl %%ebx,%%edi\n\t"
271
 
                "shll $3,%%edi\n\t"
272
 
                "addl %%edi,%%edx"
273
 
                :"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2)
274
 
                :"1" ((size + 31) >> 5), "2" (addr), "b" (addr));
275
 
        return res;
276
 
}
277
 
 
278
 
/**
279
 
 * find_next_zero_bit - find the first zero bit in a memory region
280
 
 * @addr: The address to base the search on
281
 
 * @offset: The bitnumber to start searching at
282
 
 * @size: The maximum size to search
283
 
 */
284
 
static __inline__ int find_next_zero_bit (void * addr, int size, int offset)
285
 
{
286
 
        unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
287
 
        int set = 0, bit = offset & 31, res;
288
 
        
289
 
        if (bit) {
290
 
                /*
291
 
                 * Look for zero in first byte
292
 
                 */
293
 
                __asm__("bsfl %1,%0\n\t"
294
 
                        "jne 1f\n\t"
295
 
                        "movl $32, %0\n"
296
 
                        "1:"
297
 
                        : "=r" (set)
298
 
                        : "r" (~(*p >> bit)));
299
 
                if (set < (32 - bit))
300
 
                        return set + offset;
301
 
                set = 32 - bit;
302
 
                p++;
303
 
        }
304
 
        /*
305
 
         * No zero yet, search remaining full bytes for a zero
306
 
         */
307
 
        res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr));
308
 
        return (offset + set + res);
309
 
}
310
 
 
311
 
/**
312
 
 * ffz - find first zero in word.
313
 
 * @word: The word to search
314
 
 *
315
 
 * Undefined if no zero exists, so code should check against ~0UL first.
316
 
 */
317
 
static __inline__ unsigned long ffz(unsigned long word)
318
 
{
319
 
        __asm__("bsfl %1,%0"
320
 
                :"=r" (word)
321
 
                :"r" (~word));
322
 
        return word;
323
 
}
324
 
 
325
 
/**
326
 
 * ffs - find first bit set
327
 
 * @x: the word to search
328
 
 *
329
 
 * This is defined the same way as
330
 
 * the libc and compiler builtin ffs routines, therefore
331
 
 * differs in spirit from the above ffz (man ffs).
332
 
 */
333
 
static __inline__ int ffs(int x)
334
 
{
335
 
        int r;
336
 
 
337
 
        __asm__("bsfl %1,%0\n\t"
338
 
                "jnz 1f\n\t"
339
 
                "movl $-1,%0\n"
340
 
                "1:" : "=r" (r) : "g" (x));
341
 
        return r+1;
342
 
}
343
 
 
344
 
/**
345
 
 * hweightN - returns the hamming weight of a N-bit word
346
 
 * @x: the word to weigh
347
 
 *
348
 
 * The Hamming Weight of a number is the total number of bits set in it.
349
 
 */
350
 
 
351
 
#define hweight32(x) generic_hweight32(x)
352
 
#define hweight16(x) generic_hweight16(x)
353
 
#define hweight8(x) generic_hweight8(x)
354
 
 
355
 
#define ext2_set_bit                 __test_and_set_bit
356
 
#define ext2_clear_bit               __test_and_clear_bit
357
 
#define ext2_test_bit                test_bit
358
 
#define ext2_find_first_zero_bit     find_first_zero_bit
359
 
#define ext2_find_next_zero_bit      find_next_zero_bit
360
 
 
361
 
/* Bitmap functions for the minix filesystem.  */
362
 
#define minix_test_and_set_bit(nr,addr) __test_and_set_bit(nr,addr)
363
 
#define minix_set_bit(nr,addr) __set_bit(nr,addr)
364
 
#define minix_test_and_clear_bit(nr,addr) __test_and_clear_bit(nr,addr)
365
 
#define minix_test_bit(nr,addr) test_bit(nr,addr)
366
 
#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
367
 
 
368
 
#endif /* _I386_BITOPS_H */