Library of Assembled Shared Sources
atomic_msvc_x86.h
Go to the documentation of this file.
1/** @file
2 * @author Bram de Greve (bram@cocamware.com)
3 * @author Tom De Muer (tom@cocamware.com)
4 *
5 * *** BEGIN LICENSE INFORMATION ***
6 *
7 * The contents of this file are subject to the Common Public Attribution License
8 * Version 1.0 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://lass.sourceforge.net/cpal-license. The License is based on the
11 * Mozilla Public License Version 1.1 but Sections 14 and 15 have been added to cover
12 * use of software over a computer network and provide for limited attribution for
13 * the Original Developer. In addition, Exhibit A has been modified to be consistent
14 * with Exhibit B.
15 *
16 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
17 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
18 * language governing rights and limitations under the License.
19 *
20 * The Original Code is LASS - Library of Assembled Shared Sources.
21 *
22 * The Initial Developer of the Original Code is Bram de Greve and Tom De Muer.
23 * The Original Developer is the Initial Developer.
24 *
25 * All portions of the code written by the Initial Developer are:
26 * Copyright (C) 2004-2023 the Initial Developer.
27 * All Rights Reserved.
28 *
29 * Contributor(s):
30 *
31 * Alternatively, the contents of this file may be used under the terms of the
32 * GNU General Public License Version 2 or later (the GPL), in which case the
33 * provisions of GPL are applicable instead of those above. If you wish to allow use
34 * of your version of this file only under the terms of the GPL and not to allow
35 * others to use your version of this file under the CPAL, indicate your decision by
36 * deleting the provisions above and replace them with the notice and other
37 * provisions required by the GPL License. If you do not delete the provisions above,
38 * a recipient may use your version of this file under either the CPAL or the GPL.
39 *
40 * *** END LICENSE INFORMATION ***
41 */
42
43#pragma warning(push)
44#pragma warning(disable: 4035)
45
46namespace lass
47{
48namespace util
49{
50namespace impl
51{
52
53template <>
54struct AtomicOperations<1>
55{
56 template <typename T> inline
57 static bool LASS_CALL compareAndSwap(volatile T& dest, T expectedValue, T newValue)
58 {
59 __asm
60 {
61 mov al, expectedValue
62 mov dl, newValue
63 mov edi, dest
64 lock cmpxchg [edi], dl
65 mov eax, 0
66 sete al
67 }
68 /* return eax */
69 }
70
71 template <typename T1, typename T2> inline
72 static bool LASS_CALL compareAndSwap(
73 volatile T1& dest1, T1 expected1, T2 expected2, T1 new1, T2 new2)
74 {
75 __asm
76 {
77 mov al, expected1
78 mov dl, new1
79 mov ah, expected2
80 mov dh, new2
81 mov edi, dest1
82 lock cmpxchg [edi], dx
83 mov eax, 0
84 sete al
85 }
86 /* return eax */
87 }
88
89 template <typename T> inline
90 static void LASS_CALL increment(volatile T& value)
91 {
92 __asm
93 {
94 mov edi, value
95 lock inc byte ptr [edi]
96 }
97 }
98
99 template <typename T> inline
100 static void LASS_CALL decrement(volatile T& value)
101 {
102 __asm
103 {
104 mov edi, value
105 lock dec byte ptr [edi]
106 }
107 }
108};
109
110
111
112template <>
113struct AtomicOperations<2>
114{
115 template <typename T> inline
116 static bool LASS_CALL compareAndSwap(volatile T& dest, T expectedValue, T newValue)
117 {
118 __asm
119 {
120 mov ax, expectedValue
121 mov dx, newValue
122 mov edi, dest
123 lock cmpxchg [edi], dx
124 mov eax, 0
125 sete al
126 }
127 /* return eax */
128 }
129
130 template <typename T1, typename T2> inline
131 static bool LASS_CALL compareAndSwap(
132 volatile T1& dest1, T1 expected1, T2 expected2, T1 new1, T2 new2)
133 {
134 __asm
135 {
136 mov ax, expected2
137 mov dx, new2
138 shl eax, 16
139 shl edx, 16
140 mov ax, expected1
141 mov dx, new1
142 mov edi, dest1
143 lock cmpxchg [edi], edx
144 mov eax, 0
145 sete al
146 }
147 /* return eax */
148 }
149
150 template <typename T> inline
151 static void LASS_CALL increment(volatile T& value)
152 {
153 __asm
154 {
155 mov edi, value
156 lock inc word ptr [edi]
157 }
158 }
159
160 template <typename T> inline
161 static void LASS_CALL decrement(volatile T& value)
162 {
163 __asm
164 {
165 mov edi, value
166 lock dec word ptr [edi]
167 }
168 }
169};
170
171
172
173template <>
174struct AtomicOperations<4>
175{
176 template <typename T> inline
177 static bool LASS_CALL compareAndSwap(volatile T& dest, T expectedValue, T newValue)
178 {
179 __asm
180 {
181 mov eax, expectedValue
182 mov edx, newValue
183 mov edi, dest
184 lock cmpxchg [edi], edx
185 mov eax, 0
186 sete al
187 }
188 /* return eax */
189 }
190
191 template <typename T1, typename T2> inline
192 static bool LASS_CALL compareAndSwap(
193 volatile T1& dest1, T1 expected1, T2 expected2, T1 new1, T2 new2)
194 {
195 // If you ever read this, because MSVC starts complaining with warnings like:
196 //
197 // frame pointer register 'ebx' modified by inline assembly code,
198 //
199 // then know we're doing okay.
200 // We're pushing and popping ebx but msvc doesn't realize it. Poor thing.
201 // Normally, you don't need to preserve ebx, except if you need dynamic stack-alignment
202 // code, and you're not doing frame pointer optimzation.
203 //
204 // Anyway, rest asure we heeded the warning, but we could not silence it.
205 // Not here anyway.
206 //
207 __asm
208 {
209 push ebx
210 mov eax, expected1
211 mov edx, expected2
212 mov ebx, new1
213 mov ecx, new2
214 mov edi, dest1
215 lock cmpxchg8b [edi]
216 mov eax, 0
217 sete al
218 pop ebx
219 }
220 /* return eax */
221 }
222
223 template <typename T> inline
224 static void LASS_CALL increment(volatile T& value)
225 {
226 __asm
227 {
228 mov edi, value
229 lock inc dword ptr [edi]
230 }
231 }
232
233 template <typename T> inline
234 static void LASS_CALL decrement(volatile T& value)
235 {
236 __asm
237 {
238 mov edi, value
239 lock dec dword ptr [edi]
240 }
241 }
242};
243
244
245
246template <>
247struct AtomicOperations<8>
248{
249 template <typename T> inline
250 static bool LASS_CALL compareAndSwap(volatile T& dest, T expectedValue, T newValue)
251 {
252 // If you ever read this, because MSVC starts complaining with warnings like:
253 //
254 // frame pointer register 'ebx' modified by inline assembly code,
255 //
256 // then know we're doing okay.
257 // We're pushing and popping ebx but msvc doesn't realize it. Poor thing.
258 // Normally, you don't need to preserve ebx, except if you need dynamic stack-alignment
259 // code, and you're not doing frame pointer optimzation.
260 //
261 // Anyway, rest asure we heeded the warning, but we could not silence it.
262 // Not here anyway.
263 //
264 __asm
265 {
266 push ebx
267 lea esi, expectedValue
268 lea edi, newValue
269 mov eax, [esi]
270 mov edx, 4[esi]
271 mov ebx, [edi]
272 mov ecx, 4[edi]
273 mov edi, dest
274 lock cmpxchg8b [edi]
275 mov eax, 0
276 sete al
277 pop ebx
278 }
279 /* return edx:eax */
280 }
281
282 template <typename T> inline
283 static void LASS_CALL increment(volatile T& value)
284 {
285 // not knowing any better, we emulate incq with cas loop
286 T old, fresh;
287 do
288 {
289 old = value;
290 fresh = old + 1;
291 }
292 while (!AtomicOperations<8>::compareAndSwap(value, old, fresh));
293 }
294
295 template <typename T> inline
296 static void LASS_CALL decrement(volatile T& value)
297 {
298 // not knowing any better, we emulate decq with cas loop
299 T old, fresh;
300 do
301 {
302 old = value;
303 fresh = old - 1;
304 }
305 while (!AtomicOperations<8>::compareAndSwap(value, old, fresh));
306 }
307};
308
309}
310}
311}
312
313#pragma warning(pop)
314
315// EOF
general utility, debug facilities, ...
Library for Assembled Shared Sources.
Definition config.h:53