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
xtensa
include
asm
cmpxchg.h
Go to the documentation of this file.
1
/*
2
* Atomic xchg and cmpxchg operations.
3
*
4
* This file is subject to the terms and conditions of the GNU General Public
5
* License. See the file "COPYING" in the main directory of this archive
6
* for more details.
7
*
8
* Copyright (C) 2001 - 2005 Tensilica Inc.
9
*/
10
11
#ifndef _XTENSA_CMPXCHG_H
12
#define _XTENSA_CMPXCHG_H
13
14
#ifndef __ASSEMBLY__
15
16
#include <
linux/stringify.h
>
17
18
/*
19
* cmpxchg
20
*/
21
22
static
inline
unsigned
long
23
__cmpxchg_u32
(
volatile
int
*
p
,
int
old,
int
new
)
24
{
25
__asm__
__volatile__(
"rsil a15, "
__stringify
(
LOCKLEVEL
)
"\n\t"
26
"l32i %0, %1, 0 \n\t"
27
"bne %0, %2, 1f \n\t"
28
"s32i %3, %1, 0 \n\t"
29
"1: \n\t"
30
"wsr a15, ps \n\t"
31
"rsync \n\t"
32
:
"=&a"
(old)
33
:
"a"
(p),
"a"
(old),
"r"
(
new
)
34
:
"a15"
,
"memory"
);
35
return
old;
36
}
37
/* This function doesn't exist, so you'll get a linker error
38
* if something tries to do an invalid cmpxchg(). */
39
40
extern
void
__cmpxchg_called_with_bad_pointer
(
void
);
41
42
static
__inline__
unsigned
long
43
__cmpxchg
(
volatile
void
*
ptr
,
unsigned
long
old,
unsigned
long
new
,
int
size
)
44
{
45
switch
(size) {
46
case
4:
return
__cmpxchg_u32
(ptr, old,
new
);
47
default
:
__cmpxchg_called_with_bad_pointer
();
48
return
old;
49
}
50
}
51
52
#define cmpxchg(ptr,o,n) \
53
({ __typeof__(*(ptr)) _o_ = (o); \
54
__typeof__(*(ptr)) _n_ = (n); \
55
(__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \
56
(unsigned long)_n_, sizeof (*(ptr))); \
57
})
58
59
#include <
asm-generic/cmpxchg-local.h
>
60
61
static
inline
unsigned
long
__cmpxchg_local
(
volatile
void
*ptr,
62
unsigned
long
old,
63
unsigned
long
new
,
int
size)
64
{
65
switch
(size) {
66
case
4:
67
return
__cmpxchg_u32
(ptr, old,
new
);
68
default
:
69
return
__cmpxchg_local_generic(ptr, old,
new
, size);
70
}
71
72
return
old;
73
}
74
75
/*
76
* cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
77
* them available.
78
*/
79
#define cmpxchg_local(ptr, o, n) \
80
((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
81
(unsigned long)(n), sizeof(*(ptr))))
82
#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
83
84
/*
85
* xchg_u32
86
*
87
* Note that a15 is used here because the register allocation
88
* done by the compiler is not guaranteed and a window overflow
89
* may not occur between the rsil and wsr instructions. By using
90
* a15 in the rsil, the machine is guaranteed to be in a state
91
* where no register reference will cause an overflow.
92
*/
93
94
static
inline
unsigned
long
xchg_u32(
volatile
int
*
m
,
unsigned
long
val
)
95
{
96
unsigned
long
tmp
;
97
__asm__
__volatile__(
"rsil a15, "
__stringify
(
LOCKLEVEL
)
"\n\t"
98
"l32i %0, %1, 0 \n\t"
99
"s32i %2, %1, 0 \n\t"
100
"wsr a15, ps \n\t"
101
"rsync \n\t"
102
:
"=&a"
(tmp)
103
:
"a"
(m),
"a"
(val)
104
:
"a15"
,
"memory"
);
105
return
tmp
;
106
}
107
108
#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
109
110
/*
111
* This only works if the compiler isn't horribly bad at optimizing.
112
* gcc-2.5.8 reportedly can't handle this, but I define that one to
113
* be dead anyway.
114
*/
115
116
extern
void
__xchg_called_with_bad_pointer
(
void
);
117
118
static
__inline__
unsigned
long
119
__xchg
(
unsigned
long
x
,
volatile
void
* ptr,
int
size)
120
{
121
switch
(size) {
122
case
4:
123
return
xchg_u32(ptr, x);
124
}
125
__xchg_called_with_bad_pointer
();
126
return
x
;
127
}
128
129
#endif
/* __ASSEMBLY__ */
130
131
#endif
/* _XTENSA_CMPXCHG_H */
Generated on Thu Jan 10 2013 12:49:17 for Linux Kernel by
1.8.2