forked from kamailio/kamailio
-
Notifications
You must be signed in to change notification settings - Fork 0
/
bit_test.h
163 lines (142 loc) · 4.41 KB
/
bit_test.h
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/*
* $Id$
*
* Copyright (C) 2010 iptelorg GmbH
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* History
* -------
* 2010-04-26 Initial version (Miklos)
* 2011-01-05 bit_test_and_reset added (Miklos)
*/
/* Bit test functions:
* - int bit_test(int offset, unsigned int *addr)
* Returns the bit found at offset position
* in a bitstring pointed by addr.
*
* - int bit_test_and_set(int offset, unsigned int *addr)
* Returns the bit found at offset position
* in a bitstring pointed by addr, and sets
* the bit at the given offset.
*
* - int bit_test_and_reset(int offset, unsigned int *addr)
* Returns the bit found at offset position
* in a bitstring pointed by addr, and resets
* the bit at the given offset.
*
* Note that 0 <= offset <= 128, Make sure that addr points to
* a large enough memory area.
*/
#ifndef _BIT_TEST_H
#define _BIT_TEST_H
/* fix __CPU_i386 -> __CPU_x86 */
#if defined __CPU_i386 && ! defined __CPU_x86
#define __CPU_x86
#endif
#ifdef CC_GCC_LIKE_ASM
#if defined __CPU_x86 || defined __CPU_x86_64
#define BIT_TEST_ASM
#endif
#endif
#ifdef BIT_TEST_ASM
/* Returns the bit found at offset position in the bitstring
* pointed by addr.
* Note that the CPU can access 4 bytes starting from addr,
* hence 0 <= offset < 128 holds. Make sure that addr points
* to a memory area that is large enough.
*/
static inline int bit_test(int offset, unsigned int *addr)
{
unsigned char v;
asm volatile(
" bt %2, %1 \n\t"
" setc %0 \n\t"
: "=qm" (v) : "m" (*addr), "r" (offset)
);
return (int)v;
}
/* Returns the bit found at offset position in the bitstring
* pointed by addr and sets it to 1.
* Note that the CPU can access 4 bytes starting from addr,
* hence 0 <= offset < 128 holds. Make sure that addr points
* to a memory area that is large enough.
*/
static inline int bit_test_and_set(int offset, unsigned int *addr)
{
unsigned char v;
asm volatile(
" bts %2, %1 \n\t"
" setc %0 \n\t"
: "=qm" (v) : "m" (*addr), "r" (offset)
);
return (int)v;
}
/* Returns the bit found at offset position in the bitstring
* pointed by addr and resets it to 0.
* Note that the CPU can access 4 bytes starting from addr,
* hence 0 <= offset < 128 holds. Make sure that addr points
* to a memory area that is large enough.
*/
static inline int bit_test_and_reset(int offset, unsigned int *addr)
{
unsigned char v;
asm volatile(
" btr %2, %1 \n\t"
" setc %0 \n\t"
: "=qm" (v) : "m" (*addr), "r" (offset)
);
return (int)v;
}
#else /* BIT_TEST_ASM */
/* Returns the bit found at offset position in the bitstring
* pointed by addr.
* Note that offset can be grater than 32, make sure that addr points
* to a memory area that is large enough.
*/
static inline int bit_test(int offset, unsigned int *addr)
{
return ((*(addr + offset/32)) & (1U << (offset % 32))) ? 1 : 0;
}
/* Returns the bit found at offset position in the bitstring
* pointed by addr and sets it to 1.
* Note that offset can be grater than 32, make sure that addr points
* to a memory area that is large enough.
*/
static inline int bit_test_and_set(int offset, unsigned int *addr)
{
unsigned int *i;
int mask, res;
i = addr + offset/32;
mask = 1U << (offset % 32);
res = ((*i) & mask) ? 1 : 0;
(*i) |= mask;
return res;
}
/* Returns the bit found at offset position in the bitstring
* pointed by addr and resets it to 0.
* Note that offset can be grater than 32, make sure that addr points
* to a memory area that is large enough.
*/
static inline int bit_test_and_reset(int offset, unsigned int *addr)
{
unsigned int *i;
int mask, res;
i = addr + offset/32;
mask = 1U << (offset % 32);
res = ((*i) & mask) ? 1 : 0;
(*i) &= ~mask;
return res;
}
#endif /* BIT_TEST_ASM */
#endif /* #ifndef _BIT_TEST_H */