Library of Assembled Shared Sources
atomic_msvc_x64.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-2011 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#include <intrin.h>
44#pragma intrinsic(_InterlockedCompareExchange)
45#pragma intrinsic(_InterlockedCompareExchange16)
46#pragma intrinsic(_InterlockedCompareExchange64)
47#if LASS_COMPILER_VERSION >= 1500
48# pragma intrinsic(_InterlockedCompareExchange128)
49#endif
50#pragma intrinsic(_InterlockedIncrement)
51#pragma intrinsic(_InterlockedIncrement16)
52#pragma intrinsic(_InterlockedIncrement64)
53#pragma intrinsic(_InterlockedDecrement)
54#pragma intrinsic(_InterlockedDecrement16)
55#pragma intrinsic(_InterlockedDecrement64)
56#pragma intrinsic(__ll_rshift)
57
58extern "C"
59{
60 bool lass_cas8(volatile lass::num::Tuint8*, lass::num::Tuint8, lass::num::Tuint8);
61 void lass_inc8(volatile lass::num::Tuint8*);
62 void lass_dec8(volatile lass::num::Tuint8*);
63 bool lass_dcas8(volatile lass::num::Tuint8*, lass::num::Tuint8, lass::num::Tuint8, lass::num::Tuint8, lass::num::Tuint8);
64 bool lass_dcas16(volatile lass::num::Tuint16*, lass::num::Tuint16, lass::num::Tuint16, lass::num::Tuint16, lass::num::Tuint16);
65 bool lass_dcas32(volatile lass::num::Tuint32*, lass::num::Tuint32, lass::num::Tuint32, lass::num::Tuint32, lass::num::Tuint32);
66 bool lass_dcas64(volatile lass::num::Tuint64*, lass::num::Tuint64, lass::num::Tuint64, lass::num::Tuint64, lass::num::Tuint64);
67}
68
69namespace lass
70{
71namespace util
72{
73namespace impl
74{
75
76template <>
77struct AtomicOperations<1>
78{
79 template <typename T> inline
80 static bool LASS_CALL compareAndSwap(volatile T& dest, T expectedValue, T newValue)
81 {
82 return lass_cas8(reinterpret_cast<volatile num::Tuint8*>(&dest),
83 *reinterpret_cast<num::Tuint8*>(&newValue), *reinterpret_cast<num::Tuint8*>(&expectedValue));
84 }
85
86 template <typename T1, typename T2> inline
87 static bool LASS_CALL compareAndSwap(
88 volatile T1& dest1, T1 expected1, T2 expected2, T1 new1, T2 new2)
89 {
90 return lass_dcas8(
91 reinterpret_cast<volatile num::Tuint8*>(&dest1),
92 *reinterpret_cast<num::Tuint8*>(&new1), *reinterpret_cast<num::Tuint8*>(&new2),
93 *reinterpret_cast<num::Tuint8*>(&expected1), *reinterpret_cast<num::Tuint8*>(&expected2));
94 }
95
96 template <typename T> inline
97 static void LASS_CALL increment(volatile T& value)
98 {
99 lass_inc8(reinterpret_cast<volatile num::Tuint8*>(&value));
100 }
101
102 template <typename T> inline
103 static void LASS_CALL decrement(volatile T& value)
104 {
105 lass_dec8(reinterpret_cast<volatile num::Tuint8*>(&value));
106 }
107};
108
109
110
111template <>
112struct AtomicOperations<2>
113{
114 template <typename T> inline
115 static bool LASS_CALL compareAndSwap(volatile T& dest, T expectedValue, T newValue)
116 {
117 const short expected = *reinterpret_cast<short*>(&expectedValue);
118 return _InterlockedCompareExchange16(reinterpret_cast<volatile short*>(&dest),
119 *reinterpret_cast<short*>(&newValue), expected) == expected;
120 }
121
122 template <typename T1, typename T2> inline
123 static bool LASS_CALL compareAndSwap(
124 volatile T1& dest1, T1 expected1, T2 expected2, T1 new1, T2 new2)
125 {
126 return lass_dcas16(
127 reinterpret_cast<volatile num::Tuint16*>(&dest1),
128 *reinterpret_cast<num::Tuint16*>(&new1), *reinterpret_cast<num::Tuint16*>(&new2),
129 *reinterpret_cast<num::Tuint16*>(&expected1), *reinterpret_cast<num::Tuint16*>(&expected2));
130 }
131
132 template <typename T> inline
133 static void LASS_CALL increment(volatile T& value)
134 {
135 _InterlockedIncrement16(reinterpret_cast<volatile short*>(&value));
136 }
137
138 template <typename T> inline
139 static void LASS_CALL decrement(volatile T& value)
140 {
141 _InterlockedDecrement16(reinterpret_cast<volatile short*>(&value));
142 }
143};
144
145
146
147template <>
148struct AtomicOperations<4>
149{
150 template <typename T> inline
151 static bool LASS_CALL compareAndSwap(volatile T& dest, T expectedValue, T newValue)
152 {
153 const long expected = *reinterpret_cast<long*>(&expectedValue);
154 return _InterlockedCompareExchange(reinterpret_cast<volatile long*>(&dest),
155 *reinterpret_cast<long*>(&newValue), expected) == expected;
156 }
157
158 template <typename T1, typename T2> inline
159 static bool LASS_CALL compareAndSwap(
160 volatile T1& dest1, T1 expected1, T2 expected2, T1 new1, T2 new2)
161 {
162 return lass_dcas32(
163 reinterpret_cast<volatile num::Tuint32*>(&dest1),
164 *reinterpret_cast<num::Tuint32*>(&new1), *reinterpret_cast<num::Tuint32*>(&new2),
165 *reinterpret_cast<num::Tuint32*>(&expected1), *reinterpret_cast<num::Tuint32*>(&expected2));
166 }
167
168 template <typename T> inline
169 static void LASS_CALL increment(volatile T& value)
170 {
171 _InterlockedIncrement(reinterpret_cast<volatile long*>(&value));
172 }
173
174 template <typename T> inline
175 static void LASS_CALL decrement(volatile T& value)
176 {
177 _InterlockedDecrement(reinterpret_cast<volatile long*>(&value));
178 }
179};
180
181
182
183template <>
184struct AtomicOperations<8>
185{
186 template <typename T> inline
187 static bool LASS_CALL compareAndSwap(volatile T& dest, T expectedValue, T newValue)
188 {
189 const __int64 expected = *reinterpret_cast<__int64*>(&expectedValue);
190 return _InterlockedCompareExchange64(reinterpret_cast<volatile __int64*>(&dest),
191 *reinterpret_cast<__int64*>(&newValue), expected) == expected;
192 }
193
194 template <typename T1, typename T2> inline
195 static bool LASS_CALL compareAndSwap(
196 volatile T1& dest1, T1 expected1, T2 expected2, T1 new1, T2 new2)
197 {
198 LASS_ASSERT((reinterpret_cast<num::Tuint64>(&dest1) & 0xf) == 0); // dest needs to be 16-byte aligned.
199#if LASS_COMPILER_VERSION >= 1500
200 __int64 expected[2] = { *reinterpret_cast<__int64*>(&expected1), *reinterpret_cast<__int64*>(&expected2) };
201 return _InterlockedCompareExchange128(
202 reinterpret_cast<volatile __int64*>(&dest1),
203 *reinterpret_cast<__int64*>(&new2), *reinterpret_cast<__int64*>(&new1),
204 expected) != 0;
205#else
206 return lass_dcas64(
207 reinterpret_cast<volatile num::Tuint64*>(&dest1),
208 *reinterpret_cast<num::Tuint64*>(&new1), *reinterpret_cast<num::Tuint64*>(&new2),
209 *reinterpret_cast<num::Tuint64*>(&expected1), *reinterpret_cast<num::Tuint64*>(&expected2));
210#endif
211 }
212
213 template <typename T> inline
214 static void LASS_CALL increment(volatile T& value)
215 {
216 _InterlockedIncrement64(reinterpret_cast<volatile __int64*>(&value));
217 }
218
219 template <typename T> inline
220 static void LASS_CALL decrement(volatile T& value)
221 {
222 _InterlockedDecrement64(reinterpret_cast<volatile __int64*>(&value));
223 }
224};
225
226
227
228}
229}
230}
231
232// EOF
general utility, debug facilities, ...
Library for Assembled Shared Sources.
Definition config.h:53