Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
arch
x86
include
asm
atomic64_32.h
Go to the documentation of this file.
1
#ifndef _ASM_X86_ATOMIC64_32_H
2
#define _ASM_X86_ATOMIC64_32_H
3
4
#include <linux/compiler.h>
5
#include <linux/types.h>
6
#include <asm/processor.h>
7
//#include <asm/cmpxchg.h>
8
9
/* An 64bit atomic type */
10
11
typedef
struct
{
12
u64
__aligned
(8)
counter
;
13
}
atomic64_t
;
14
15
#define ATOMIC64_INIT(val) { (val) }
16
17
#define __ATOMIC64_DECL(sym) void atomic64_##sym(atomic64_t *, ...)
18
#ifndef ATOMIC64_EXPORT
19
#define ATOMIC64_DECL_ONE __ATOMIC64_DECL
20
#else
21
#define ATOMIC64_DECL_ONE(sym) __ATOMIC64_DECL(sym); \
22
ATOMIC64_EXPORT(atomic64_##sym)
23
#endif
24
25
#ifdef CONFIG_X86_CMPXCHG64
26
#define __alternative_atomic64(f, g, out, in...) \
27
asm volatile("call %P[func]" \
28
: out : [func] "i" (atomic64_##g##_cx8), ## in)
29
30
#define ATOMIC64_DECL(sym) ATOMIC64_DECL_ONE(sym##_cx8)
31
#else
32
#define __alternative_atomic64(f, g, out, in...) \
33
alternative_call(atomic64_##f##_386, atomic64_##g##_cx8, \
34
X86_FEATURE_CX8, ASM_OUTPUT2(out), ## in)
35
36
#define ATOMIC64_DECL(sym) ATOMIC64_DECL_ONE(sym##_cx8); \
37
ATOMIC64_DECL_ONE(sym##_386)
38
39
ATOMIC64_DECL_ONE
(add_386);
40
ATOMIC64_DECL_ONE
(sub_386);
41
ATOMIC64_DECL_ONE
(inc_386);
42
ATOMIC64_DECL_ONE
(dec_386);
43
#endif
44
45
#define alternative_atomic64(f, out, in...) \
46
__alternative_atomic64(f, f, ASM_OUTPUT2(out), ## in)
47
48
ATOMIC64_DECL
(
read
);
49
ATOMIC64_DECL
(
set
);
50
ATOMIC64_DECL
(
xchg
);
51
ATOMIC64_DECL
(add_return);
52
ATOMIC64_DECL
(sub_return);
53
ATOMIC64_DECL
(inc_return);
54
ATOMIC64_DECL
(dec_return);
55
ATOMIC64_DECL
(dec_if_positive);
56
ATOMIC64_DECL
(inc_not_zero);
57
ATOMIC64_DECL
(add_unless);
58
59
#undef ATOMIC64_DECL
60
#undef ATOMIC64_DECL_ONE
61
#undef __ATOMIC64_DECL
62
#undef ATOMIC64_EXPORT
63
74
static
inline
long
long
atomic64_cmpxchg
(
atomic64_t
*
v
,
long
long
o,
long
long
n
)
75
{
76
return
cmpxchg64
(&v->
counter
, o, n);
77
}
78
87
static
inline
long
long
atomic64_xchg
(
atomic64_t
*
v
,
long
long
n
)
88
{
89
long
long
o;
90
unsigned
high
= (unsigned)(n >> 32);
91
unsigned
low
= (unsigned)n;
92
alternative_atomic64
(
xchg
,
"=&A"
(o),
93
"S"
(v),
"b"
(low),
"c"
(high)
94
:
"memory"
);
95
return
o;
96
}
97
105
static
inline
void
atomic64_set
(
atomic64_t
*v,
long
long
i
)
106
{
107
unsigned
high = (unsigned)(i >> 32);
108
unsigned
low = (unsigned)i;
109
alternative_atomic64
(
set
,
/* no output */
,
110
"S"
(v),
"b"
(low),
"c"
(high)
111
:
"eax"
,
"edx"
,
"memory"
);
112
}
113
120
static
inline
long
long
atomic64_read
(
const
atomic64_t
*v)
121
{
122
long
long
r
;
123
alternative_atomic64
(
read
,
"=&A"
(r),
"c"
(v) :
"memory"
);
124
return
r
;
125
}
126
134
static
inline
long
long
atomic64_add_return
(
long
long
i,
atomic64_t
*v)
135
{
136
alternative_atomic64
(add_return,
137
ASM_OUTPUT2
(
"+A"
(i),
"+c"
(v)),
138
ASM_NO_INPUT_CLOBBER
(
"memory"
));
139
return
i
;
140
}
141
142
/*
143
* Other variants with different arithmetic operators:
144
*/
145
static
inline
long
long
atomic64_sub_return
(
long
long
i,
atomic64_t
*v)
146
{
147
alternative_atomic64
(sub_return,
148
ASM_OUTPUT2
(
"+A"
(i),
"+c"
(v)),
149
ASM_NO_INPUT_CLOBBER
(
"memory"
));
150
return
i
;
151
}
152
153
static
inline
long
long
atomic64_inc_return
(
atomic64_t
*v)
154
{
155
long
long
a
;
156
alternative_atomic64
(inc_return,
"=&A"
(a),
157
"S"
(v) :
"memory"
,
"ecx"
);
158
return
a
;
159
}
160
161
static
inline
long
long
atomic64_dec_return
(
atomic64_t
*v)
162
{
163
long
long
a
;
164
alternative_atomic64
(dec_return,
"=&A"
(a),
165
"S"
(v) :
"memory"
,
"ecx"
);
166
return
a
;
167
}
168
176
static
inline
long
long
atomic64_add
(
long
long
i,
atomic64_t
*v)
177
{
178
__alternative_atomic64
(
add
, add_return,
179
ASM_OUTPUT2
(
"+A"
(i),
"+c"
(v)),
180
ASM_NO_INPUT_CLOBBER
(
"memory"
));
181
return
i
;
182
}
183
191
static
inline
long
long
atomic64_sub
(
long
long
i,
atomic64_t
*v)
192
{
193
__alternative_atomic64
(sub, sub_return,
194
ASM_OUTPUT2
(
"+A"
(i),
"+c"
(v)),
195
ASM_NO_INPUT_CLOBBER
(
"memory"
));
196
return
i
;
197
}
198
208
static
inline
int
atomic64_sub_and_test
(
long
long
i,
atomic64_t
*v)
209
{
210
return
atomic64_sub_return
(i, v) == 0;
211
}
212
219
static
inline
void
atomic64_inc
(
atomic64_t
*v)
220
{
221
__alternative_atomic64
(
inc
, inc_return,
/* no output */
,
222
"S"
(v) :
"memory"
,
"eax"
,
"ecx"
,
"edx"
);
223
}
224
231
static
inline
void
atomic64_dec
(
atomic64_t
*v)
232
{
233
__alternative_atomic64
(dec, dec_return,
/* no output */
,
234
"S"
(v) :
"memory"
,
"eax"
,
"ecx"
,
"edx"
);
235
}
236
245
static
inline
int
atomic64_dec_and_test
(
atomic64_t
*v)
246
{
247
return
atomic64_dec_return
(v) == 0;
248
}
249
258
static
inline
int
atomic64_inc_and_test
(
atomic64_t
*v)
259
{
260
return
atomic64_inc_return
(v) == 0;
261
}
262
272
static
inline
int
atomic64_add_negative
(
long
long
i,
atomic64_t
*v)
273
{
274
return
atomic64_add_return
(i, v) < 0;
275
}
276
286
static
inline
int
atomic64_add_unless(
atomic64_t
*v,
long
long
a,
long
long
u
)
287
{
288
unsigned
low = (unsigned)u;
289
unsigned
high = (unsigned)(u >> 32);
290
alternative_atomic64
(add_unless,
291
ASM_OUTPUT2
(
"+A"
(a),
"+c"
(low),
"+D"
(high)),
292
"S"
(v) :
"memory"
);
293
return
(
int
)
a
;
294
}
295
296
297
static
inline
int
atomic64_inc_not_zero
(
atomic64_t
*v)
298
{
299
int
r
;
300
alternative_atomic64
(inc_not_zero,
"=&a"
(r),
301
"S"
(v) :
"ecx"
,
"edx"
,
"memory"
);
302
return
r
;
303
}
304
305
static
inline
long
long
atomic64_dec_if_positive
(
atomic64_t
*v)
306
{
307
long
long
r
;
308
alternative_atomic64
(dec_if_positive,
"=&A"
(r),
309
"S"
(v) :
"ecx"
,
"memory"
);
310
return
r
;
311
}
312
313
#undef alternative_atomic64
314
#undef __alternative_atomic64
315
316
#endif
/* _ASM_X86_ATOMIC64_32_H */
Generated on Thu Jan 10 2013 13:19:58 for Linux Kernel by
1.8.2