3
// ************************************************************************
5
// Kokkos: Manycore Performance-Portable Multidimensional Arrays
6
// Copyright (2012) Sandia Corporation
8
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9
// the U.S. Government retains certain rights in this software.
11
// Redistribution and use in source and binary forms, with or without
12
// modification, are permitted provided that the following conditions are
15
// 1. Redistributions of source code must retain the above copyright
16
// notice, this list of conditions and the following disclaimer.
18
// 2. Redistributions in binary form must reproduce the above copyright
19
// notice, this list of conditions and the following disclaimer in the
20
// documentation and/or other materials provided with the distribution.
22
// 3. Neither the name of the Corporation nor the names of the
23
// contributors may be used to endorse or promote products derived from
24
// this software without specific prior written permission.
26
// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38
// Questions? Contact H. Carter Edwards (hcedwar@sandia.gov)
40
// ************************************************************************
43
#if defined( KOKKOS_ATOMIC_HPP ) && ! defined( KOKKOS_ATOMIC_GENERIC_HPP )
44
#define KOKKOS_ATOMIC_GENERIC_HPP
45
#include <Kokkos_Macros.hpp>
47
// Combination operands to be used in an Compare and Exchange based atomic operation
51
template<class Scalar1, class Scalar2>
53
KOKKOS_FORCEINLINE_FUNCTION
54
static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
59
template<class Scalar1, class Scalar2>
61
KOKKOS_FORCEINLINE_FUNCTION
62
static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
67
template<class Scalar1, class Scalar2>
69
KOKKOS_FORCEINLINE_FUNCTION
70
static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
75
template<class Scalar1, class Scalar2>
77
KOKKOS_FORCEINLINE_FUNCTION
78
static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
83
template<class Scalar1, class Scalar2>
85
KOKKOS_FORCEINLINE_FUNCTION
86
static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
91
template<class Scalar1, class Scalar2>
93
KOKKOS_FORCEINLINE_FUNCTION
94
static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
99
template<class Scalar1, class Scalar2>
101
KOKKOS_FORCEINLINE_FUNCTION
102
static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
107
template<class Scalar1, class Scalar2>
109
KOKKOS_FORCEINLINE_FUNCTION
110
static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
115
template<class Scalar1, class Scalar2>
117
KOKKOS_FORCEINLINE_FUNCTION
118
static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
123
template<class Scalar1, class Scalar2>
125
KOKKOS_FORCEINLINE_FUNCTION
126
static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
131
template < class Oper, typename T >
132
KOKKOS_INLINE_FUNCTION
133
T atomic_fetch_oper( const Oper& op, volatile T * const dest ,
134
typename ::Kokkos::Impl::enable_if< sizeof(T) != sizeof(int) &&
135
sizeof(T) == sizeof(unsigned long long int) , const T >::type val )
137
union { unsigned long long int i ; T t ; } oldval , assume , newval ;
142
assume.i = oldval.i ;
143
newval.t = Oper::apply(assume.t, val) ;
144
oldval.i = ::Kokkos::atomic_compare_exchange( (unsigned long long int*)dest , assume.i , newval.i );
145
} while ( assume.i != oldval.i );
150
template < class Oper, typename T >
151
KOKKOS_INLINE_FUNCTION
152
T atomic_oper_fetch( const Oper& op, volatile T * const dest ,
153
typename ::Kokkos::Impl::enable_if< sizeof(T) != sizeof(int) &&
154
sizeof(T) == sizeof(unsigned long long int) , const T >::type val )
156
union { unsigned long long int i ; T t ; } oldval , assume , newval ;
161
assume.i = oldval.i ;
162
newval.t = Oper::apply(assume.t, val) ;
163
oldval.i = ::Kokkos::atomic_compare_exchange( (unsigned long long int*)dest , assume.i , newval.i );
164
} while ( assume.i != oldval.i );
169
template < class Oper, typename T >
170
KOKKOS_INLINE_FUNCTION
171
T atomic_fetch_oper( const Oper& op, volatile T * const dest ,
172
typename ::Kokkos::Impl::enable_if< sizeof(T) == sizeof(int) , const T >::type val )
174
union { int i ; T t ; } oldval , assume , newval ;
179
assume.i = oldval.i ;
180
newval.t = Oper::apply(assume.t, val) ;
181
oldval.i = ::Kokkos::atomic_compare_exchange( (int*)dest , assume.i , newval.i );
182
} while ( assume.i != oldval.i );
187
template < class Oper, typename T >
188
KOKKOS_INLINE_FUNCTION
189
T atomic_oper_fetch( const Oper& op, volatile T * const dest ,
190
typename ::Kokkos::Impl::enable_if< sizeof(T) == sizeof(int), const T >::type val )
192
union { int i ; T t ; } oldval , assume , newval ;
197
assume.i = oldval.i ;
198
newval.t = Oper::apply(assume.t, val) ;
199
oldval.i = ::Kokkos::atomic_compare_exchange( (int*)dest , assume.i , newval.i );
200
} while ( assume.i != oldval.i );
205
/*template < class Oper, typename T >
206
KOKKOS_INLINE_FUNCTION
207
T atomic_fetch_oper( const Oper& op, volatile T * const dest ,
208
typename ::Kokkos::Impl::enable_if< sizeof(T) == sizeof(short) , const T >::type val )
210
union { short i ; T t ; } oldval , assume , newval ;
215
assume.i = oldval.i ;
216
newval.t = Oper::apply(assume.t, val) ;
217
oldval.i = ::Kokkos::atomic_compare_exchange( (short*)dest , assume.i , newval.i );
218
} while ( assume.i != oldval.i );
223
template < class Oper, typename T >
224
KOKKOS_INLINE_FUNCTION
225
T atomic_oper_fetch( const Oper& op, volatile T * const dest ,
226
typename ::Kokkos::Impl::enable_if< sizeof(T) == sizeof(short), const T >::type val )
228
union { short i ; T t ; } oldval , assume , newval ;
233
assume.i = oldval.i ;
234
newval.t = Oper::apply(assume.t, val) ;
235
oldval.i = ::Kokkos::atomic_compare_exchange( (short*)dest , assume.i , newval.i );
236
} while ( assume.i != oldval.i );
241
template < class Oper, typename T >
242
KOKKOS_INLINE_FUNCTION
243
T atomic_fetch_oper( const Oper& op, volatile T * const dest ,
244
typename ::Kokkos::Impl::enable_if< sizeof(T) == sizeof(char) , const T >::type val )
246
union { char i ; T t ; } oldval , assume , newval ;
251
assume.i = oldval.i ;
252
newval.t = Oper::apply(assume.t, val) ;
253
oldval.i = ::Kokkos::atomic_compare_exchange( (char*)dest , assume.i , newval.i );
254
} while ( assume.i != oldval.i );
259
template < class Oper, typename T >
260
KOKKOS_INLINE_FUNCTION
261
T atomic_oper_fetch( const Oper& op, volatile T * const dest ,
262
typename ::Kokkos::Impl::enable_if< sizeof(T) == sizeof(char), const T >::type val )
264
union { char i ; T t ; } oldval , assume , newval ;
269
assume.i = oldval.i ;
270
newval.t = Oper::apply(assume.t, val) ;
271
oldval.i = ::Kokkos::atomic_compare_exchange( (char*)dest , assume.i , newval.i );
272
} while ( assume.i != oldval.i );
282
// Fetch_Oper atomics: return value before operation
283
template < typename T >
284
KOKKOS_INLINE_FUNCTION
285
T atomic_fetch_mul(volatile T * const dest, const T val) {
286
return Impl::atomic_fetch_oper(Impl::MulOper<T,const T>(),dest,val);
289
template < typename T >
290
KOKKOS_INLINE_FUNCTION
291
T atomic_fetch_div(volatile T * const dest, const T val) {
292
return Impl::atomic_fetch_oper(Impl::DivOper<T,const T>(),dest,val);
295
template < typename T >
296
KOKKOS_INLINE_FUNCTION
297
T atomic_fetch_mod(volatile T * const dest, const T val) {
298
return Impl::atomic_fetch_oper(Impl::ModOper<T,const T>(),dest,val);
301
template < typename T >
302
KOKKOS_INLINE_FUNCTION
303
T atomic_fetch_and(volatile T * const dest, const T val) {
304
return Impl::atomic_fetch_oper(Impl::AndOper<T,const T>(),dest,val);
307
template < typename T >
308
KOKKOS_INLINE_FUNCTION
309
T atomic_fetch_or(volatile T * const dest, const T val) {
310
return Impl::atomic_fetch_oper(Impl::OrOper<T,const T>(),dest,val);
313
template < typename T >
314
KOKKOS_INLINE_FUNCTION
315
T atomic_fetch_xor(volatile T * const dest, const T val) {
316
return Impl::atomic_fetch_oper(Impl::XorOper<T,const T>(),dest,val);
319
template < typename T >
320
KOKKOS_INLINE_FUNCTION
321
T atomic_fetch_lshift(volatile T * const dest, const unsigned int val) {
322
return Impl::atomic_fetch_oper(Impl::LShiftOper<T,const unsigned int>(),dest,val);
325
template < typename T >
326
KOKKOS_INLINE_FUNCTION
327
T atomic_fetch_rshift(volatile T * const dest, const unsigned int val) {
328
return Impl::atomic_fetch_oper(Impl::RShiftOper<T,const unsigned int>(),dest,val);
332
// Oper Fetch atomics: return value after operation
333
template < typename T >
334
KOKKOS_INLINE_FUNCTION
335
T atomic_mul_fetch(volatile T * const dest, const T val) {
336
return Impl::atomic_oper_fetch(Impl::MulOper<T,const T>(),dest,val);
339
template < typename T >
340
KOKKOS_INLINE_FUNCTION
341
T atomic_div_fetch(volatile T * const dest, const T val) {
342
return Impl::atomic_oper_fetch(Impl::DivOper<T,const T>(),dest,val);
345
template < typename T >
346
KOKKOS_INLINE_FUNCTION
347
T atomic_mod_fetch(volatile T * const dest, const T val) {
348
return Impl::atomic_oper_fetch(Impl::ModOper<T,const T>(),dest,val);
351
template < typename T >
352
KOKKOS_INLINE_FUNCTION
353
T atomic_and_fetch(volatile T * const dest, const T val) {
354
return Impl::atomic_oper_fetch(Impl::AndOper<T,const T>(),dest,val);
357
template < typename T >
358
KOKKOS_INLINE_FUNCTION
359
T atomic_or_fetch(volatile T * const dest, const T val) {
360
return Impl::atomic_oper_fetch(Impl::OrOper<T,const T>(),dest,val);
363
template < typename T >
364
KOKKOS_INLINE_FUNCTION
365
T atomic_xor_fetch(volatile T * const dest, const T val) {
366
return Impl::atomic_oper_fetch(Impl::XorOper<T,const T>(),dest,val);
369
template < typename T >
370
KOKKOS_INLINE_FUNCTION
371
T atomic_lshift_fetch(volatile T * const dest, const unsigned int val) {
372
return Impl::atomic_oper_fetch(Impl::LShiftOper<T,const unsigned int>(),dest,val);
375
template < typename T >
376
KOKKOS_INLINE_FUNCTION
377
T atomic_rshift_fetch(volatile T * const dest, const unsigned int val) {
378
return Impl::atomic_oper_fetch(Impl::RShiftOper<T,const unsigned int>(),dest,val);