~ubuntu-branches/debian/sid/lammps/sid

« back to all changes in this revision

Viewing changes to lib/kokkos/core/src/impl/Kokkos_Atomic_Generic.hpp

  • Committer: Package Import Robot
  • Author(s): Anton Gladky
  • Date: 2015-04-29 23:44:49 UTC
  • mfrom: (5.1.3 experimental)
  • Revision ID: package-import@ubuntu.com-20150429234449-mbhy9utku6hp6oq8
Tags: 0~20150313.gitfa668e1-1
Upload into unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
//@HEADER
 
3
// ************************************************************************
 
4
//
 
5
//   Kokkos: Manycore Performance-Portable Multidimensional Arrays
 
6
//              Copyright (2012) Sandia Corporation
 
7
//
 
8
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
 
9
// the U.S. Government retains certain rights in this software.
 
10
//
 
11
// Redistribution and use in source and binary forms, with or without
 
12
// modification, are permitted provided that the following conditions are
 
13
// met:
 
14
//
 
15
// 1. Redistributions of source code must retain the above copyright
 
16
// notice, this list of conditions and the following disclaimer.
 
17
//
 
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.
 
21
//
 
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.
 
25
//
 
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.
 
37
//
 
38
// Questions?  Contact  H. Carter Edwards (hcedwar@sandia.gov)
 
39
//
 
40
// ************************************************************************
 
41
//@HEADER
 
42
*/
 
43
#if defined( KOKKOS_ATOMIC_HPP ) && ! defined( KOKKOS_ATOMIC_GENERIC_HPP )
 
44
#define KOKKOS_ATOMIC_GENERIC_HPP
 
45
#include <Kokkos_Macros.hpp>
 
46
 
 
47
// Combination operands to be used in an Compare and Exchange based atomic operation
 
48
namespace Kokkos {
 
49
namespace Impl {
 
50
 
 
51
template<class Scalar1, class Scalar2>
 
52
struct AddOper {
 
53
  KOKKOS_FORCEINLINE_FUNCTION
 
54
  static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
 
55
    return val1+val2;
 
56
  }
 
57
};
 
58
 
 
59
template<class Scalar1, class Scalar2>
 
60
struct SubOper {
 
61
  KOKKOS_FORCEINLINE_FUNCTION
 
62
  static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
 
63
    return val1-val2;
 
64
  }
 
65
};
 
66
 
 
67
template<class Scalar1, class Scalar2>
 
68
struct MulOper {
 
69
  KOKKOS_FORCEINLINE_FUNCTION
 
70
  static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
 
71
    return val1*val2;
 
72
  }
 
73
};
 
74
 
 
75
template<class Scalar1, class Scalar2>
 
76
struct DivOper {
 
77
  KOKKOS_FORCEINLINE_FUNCTION
 
78
  static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
 
79
    return val1/val2;
 
80
  }
 
81
};
 
82
 
 
83
template<class Scalar1, class Scalar2>
 
84
struct ModOper {
 
85
  KOKKOS_FORCEINLINE_FUNCTION
 
86
  static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
 
87
    return val1%val2;
 
88
  }
 
89
};
 
90
 
 
91
template<class Scalar1, class Scalar2>
 
92
struct AndOper {
 
93
  KOKKOS_FORCEINLINE_FUNCTION
 
94
  static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
 
95
    return val1&val2;
 
96
  }
 
97
};
 
98
 
 
99
template<class Scalar1, class Scalar2>
 
100
struct OrOper {
 
101
  KOKKOS_FORCEINLINE_FUNCTION
 
102
  static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
 
103
    return val1|val2;
 
104
  }
 
105
};
 
106
 
 
107
template<class Scalar1, class Scalar2>
 
108
struct XorOper {
 
109
  KOKKOS_FORCEINLINE_FUNCTION
 
110
  static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
 
111
    return val1^val2;
 
112
  }
 
113
};
 
114
 
 
115
template<class Scalar1, class Scalar2>
 
116
struct LShiftOper {
 
117
  KOKKOS_FORCEINLINE_FUNCTION
 
118
  static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
 
119
    return val1<<val2;
 
120
  }
 
121
};
 
122
 
 
123
template<class Scalar1, class Scalar2>
 
124
struct RShiftOper {
 
125
  KOKKOS_FORCEINLINE_FUNCTION
 
126
  static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
 
127
    return val1>>val2;
 
128
  }
 
129
};
 
130
 
 
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 )
 
136
{
 
137
  union { unsigned long long int i ; T t ; } oldval , assume , newval ;
 
138
 
 
139
  oldval.t = *dest ;
 
140
 
 
141
  do {
 
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 );
 
146
 
 
147
  return oldval.t ;
 
148
}
 
149
 
 
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 )
 
155
{
 
156
  union { unsigned long long int i ; T t ; } oldval , assume , newval ;
 
157
 
 
158
  oldval.t = *dest ;
 
159
 
 
160
  do {
 
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 );
 
165
 
 
166
  return newval.t ;
 
167
}
 
168
 
 
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 )
 
173
{
 
174
  union { int i ; T t ; } oldval , assume , newval ;
 
175
 
 
176
  oldval.t = *dest ;
 
177
 
 
178
  do {
 
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 );
 
183
 
 
184
  return oldval.t ;
 
185
}
 
186
 
 
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 )
 
191
{
 
192
  union { int i ; T t ; } oldval , assume , newval ;
 
193
 
 
194
  oldval.t = *dest ;
 
195
 
 
196
  do {
 
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 );
 
201
 
 
202
  return newval.t ;
 
203
}
 
204
 
 
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 )
 
209
{
 
210
  union { short i ; T t ; } oldval , assume , newval ;
 
211
 
 
212
  oldval.t = *dest ;
 
213
 
 
214
  do {
 
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 );
 
219
 
 
220
  return oldval.t ;
 
221
}
 
222
 
 
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 )
 
227
{
 
228
  union { short i ; T t ; } oldval , assume , newval ;
 
229
 
 
230
  oldval.t = *dest ;
 
231
 
 
232
  do {
 
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 );
 
237
 
 
238
  return newval.t ;
 
239
}
 
240
 
 
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 )
 
245
{
 
246
  union { char i ; T t ; } oldval , assume , newval ;
 
247
 
 
248
  oldval.t = *dest ;
 
249
 
 
250
  do {
 
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 );
 
255
 
 
256
  return oldval.t ;
 
257
}
 
258
 
 
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 )
 
263
{
 
264
  union { char i ; T t ; } oldval , assume , newval ;
 
265
 
 
266
  oldval.t = *dest ;
 
267
 
 
268
  do {
 
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 );
 
273
 
 
274
  return newval.t ;
 
275
}*/
 
276
 
 
277
}
 
278
}
 
279
 
 
280
namespace Kokkos {
 
281
 
 
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);
 
287
}
 
288
 
 
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);
 
293
}
 
294
 
 
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);
 
299
}
 
300
 
 
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);
 
305
}
 
306
 
 
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);
 
311
}
 
312
 
 
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);
 
317
}
 
318
 
 
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);
 
323
}
 
324
 
 
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);
 
329
}
 
330
 
 
331
 
 
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);
 
337
}
 
338
 
 
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);
 
343
}
 
344
 
 
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);
 
349
}
 
350
 
 
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);
 
355
}
 
356
 
 
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);
 
361
}
 
362
 
 
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);
 
367
}
 
368
 
 
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);
 
373
}
 
374
 
 
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);
 
379
}
 
380
 
 
381
 
 
382
}
 
383
#endif