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
frv
include
asm
cmpxchg.h
Go to the documentation of this file.
1
/* xchg and cmpxchg operation emulation for FR-V
2
*
3
* For an explanation of how atomic ops work in this arch, see:
4
* Documentation/frv/atomic-ops.txt
5
*
6
* Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
7
* Written by David Howells (
[email protected]
)
8
*
9
* This program is free software; you can redistribute it and/or
10
* modify it under the terms of the GNU General Public License
11
* as published by the Free Software Foundation; either version
12
* 2 of the License, or (at your option) any later version.
13
*/
14
#ifndef _ASM_CMPXCHG_H
15
#define _ASM_CMPXCHG_H
16
17
#include <linux/types.h>
18
19
/*****************************************************************************/
20
/*
21
* exchange value with memory
22
*/
23
extern
uint64_t
__xchg_64
(
uint64_t
i
,
volatile
void
*
v
);
24
25
#ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
26
27
#define xchg(ptr, x) \
28
({ \
29
__typeof__(ptr) __xg_ptr = (ptr); \
30
__typeof__(*(ptr)) __xg_orig; \
31
\
32
switch (sizeof(__xg_orig)) { \
33
case 4: \
34
asm volatile( \
35
"swap%I0 %M0,%1" \
36
: "+m"(*__xg_ptr), "=r"(__xg_orig) \
37
: "1"(x) \
38
: "memory" \
39
); \
40
break; \
41
\
42
default: \
43
__xg_orig = (__typeof__(__xg_orig))0; \
44
asm volatile("break"); \
45
break; \
46
} \
47
\
48
__xg_orig; \
49
})
50
51
#else
52
53
extern
uint32_t
__xchg_32(
uint32_t
i
,
volatile
void
*
v
);
54
55
#define xchg(ptr, x) \
56
({ \
57
__typeof__(ptr) __xg_ptr = (ptr); \
58
__typeof__(*(ptr)) __xg_orig; \
59
\
60
switch (sizeof(__xg_orig)) { \
61
case 4: __xg_orig = (__typeof__(*(ptr))) __xchg_32((uint32_t) x, __xg_ptr); break; \
62
default: \
63
__xg_orig = (__typeof__(__xg_orig))0; \
64
asm volatile("break"); \
65
break; \
66
} \
67
__xg_orig; \
68
})
69
70
#endif
71
72
#define tas(ptr) (xchg((ptr), 1))
73
74
/*****************************************************************************/
75
/*
76
* compare and conditionally exchange value with memory
77
* - if (*ptr == test) then orig = *ptr; *ptr = test;
78
* - if (*ptr != test) then orig = *ptr;
79
*/
80
extern
uint64_t
__cmpxchg_64
(
uint64_t
test
,
uint64_t
new
,
volatile
uint64_t
*
v
);
81
82
#ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
83
84
#define cmpxchg(ptr, test, new) \
85
({ \
86
__typeof__(ptr) __xg_ptr = (ptr); \
87
__typeof__(*(ptr)) __xg_orig, __xg_tmp; \
88
__typeof__(*(ptr)) __xg_test = (test); \
89
__typeof__(*(ptr)) __xg_new = (new); \
90
\
91
switch (sizeof(__xg_orig)) { \
92
case 4: \
93
asm volatile( \
94
"0: \n" \
95
" orcc gr0,gr0,gr0,icc3 \n" \
96
" ckeq icc3,cc7 \n" \
97
" ld.p %M0,%1 \n" \
98
" orcr cc7,cc7,cc3 \n" \
99
" sub%I4cc %1,%4,%2,icc0 \n" \
100
" bne icc0,#0,1f \n" \
101
" cst.p %3,%M0 ,cc3,#1 \n" \
102
" corcc gr29,gr29,gr0 ,cc3,#1 \n" \
103
" beq icc3,#0,0b \n" \
104
"1: \n" \
105
: "+U"(*__xg_ptr), "=&r"(__xg_orig), "=&r"(__xg_tmp) \
106
: "r"(__xg_new), "NPr"(__xg_test) \
107
: "memory", "cc7", "cc3", "icc3", "icc0" \
108
); \
109
break; \
110
\
111
default: \
112
__xg_orig = (__typeof__(__xg_orig))0; \
113
asm volatile("break"); \
114
break; \
115
} \
116
\
117
__xg_orig; \
118
})
119
120
#else
121
122
extern
uint32_t
__cmpxchg_32(
uint32_t
*
v
,
uint32_t
test
,
uint32_t
new
);
123
124
#define cmpxchg(ptr, test, new) \
125
({ \
126
__typeof__(ptr) __xg_ptr = (ptr); \
127
__typeof__(*(ptr)) __xg_orig; \
128
__typeof__(*(ptr)) __xg_test = (test); \
129
__typeof__(*(ptr)) __xg_new = (new); \
130
\
131
switch (sizeof(__xg_orig)) { \
132
case 4: __xg_orig = (__force __typeof__(*ptr)) \
133
__cmpxchg_32((__force uint32_t *)__xg_ptr, \
134
(__force uint32_t)__xg_test, \
135
(__force uint32_t)__xg_new); break; \
136
default: \
137
__xg_orig = (__typeof__(__xg_orig))0; \
138
asm volatile("break"); \
139
break; \
140
} \
141
\
142
__xg_orig; \
143
})
144
145
#endif
146
147
#include <
asm-generic/cmpxchg-local.h
>
148
149
static
inline
unsigned
long
__cmpxchg_local
(
volatile
void
*
ptr
,
150
unsigned
long
old,
151
unsigned
long
new
,
int
size
)
152
{
153
switch
(size) {
154
case
4:
155
return
cmpxchg
((
unsigned
long
*)ptr, old,
new
);
156
default
:
157
return
__cmpxchg_local_generic(ptr, old,
new
, size);
158
}
159
160
return
old;
161
}
162
163
/*
164
* cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
165
* them available.
166
*/
167
#define cmpxchg_local(ptr, o, n) \
168
((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \
169
(unsigned long)(n), sizeof(*(ptr))))
170
#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
171
172
#endif
/* _ASM_CMPXCHG_H */
Generated on Thu Jan 10 2013 12:49:17 for Linux Kernel by
1.8.2