NVIDIA Iray: Math API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
atom.h
Go to the documentation of this file.
1 //*****************************************************************************
2 // Copyright 1986, 2014 NVIDIA Corporation. All rights reserved.
3 //*****************************************************************************
8 //*****************************************************************************
9 
10 #ifndef MI_BASE_ATOM_H
11 #define MI_BASE_ATOM_H
12 
13 #include <mi/base/config.h>
14 #include <mi/base/types.h>
15 
16 //
17 // Check what version of implementation we can use
18 //
19 
20 #if defined(MI_ARCH_X86) && defined(MI_COMPILER_MSC)
21 # define MI_ATOM32_X86MSC
22 # include <intrin.h>
23 # pragma intrinsic (_InterlockedExchangeAdd)
24 # pragma intrinsic (_InterlockedCompareExchange)
25 #elif defined(MI_ARCH_X86) && (defined(MI_COMPILER_GCC) || defined(MI_COMPILER_ICC))
26 # define MI_ATOM32_X86GCC
27 #else
28 # define MI_ATOM32_GENERIC
29 # include <mi/base/lock.h>
30 #endif
31 
32 namespace mi {
33 namespace base {
34 
39 class Atom32
42 {
43 public:
45  Atom32() : m_atom(0) {}
46 
48  Atom32(const Uint32 val) : m_atom(val) {}
49 
51  Uint32 operator = (const Uint32 val) {
52  m_atom = val;
53  return val;
54  }
55 
57  Uint32 operator += (const Uint32 val);
58 
60  Uint32 operator -= (const Uint32 val);
61 
64 
66  Uint32 operator ++(int);
67 
70 
72  Uint32 operator --(int);
73 
75  operator Uint32 () const {
76  return m_atom;
77  }
78 
80  Uint32 swap(const Uint32 val);
81 
82 private:
83  volatile Uint32 m_atom;
84 
85 #if defined(MI_ATOM32_GENERIC)
86  mi::base::Lock m_lock;
87 #endif
88 };
89 
90 #if defined(MI_ATOM32_X86MSC)
91 
92 //
93 // operator +=
94 //
95 __forceinline Uint32 Atom32::operator += ( const Uint32 rhs) {
96  return _InterlockedExchangeAdd(reinterpret_cast<volatile long *>(&m_atom),rhs) + rhs;
97 }
98 
99 //
100 // operator -=
101 //
102 __forceinline Uint32 Atom32::operator -= ( const Uint32 rhs) {
103  return _InterlockedExchangeAdd(
104  reinterpret_cast<volatile long *>(&m_atom), -static_cast<const Sint32>(rhs)) - rhs;
105 }
106 
107 //
108 // operator ++
109 //
110 __forceinline Uint32 Atom32::operator ++() {
111  return _InterlockedExchangeAdd(reinterpret_cast<volatile long *>(&m_atom),1L) + 1L;
112 }
113 
114 //
115 // operator --
116 //
117 __forceinline Uint32 Atom32::operator --() {
118  return _InterlockedExchangeAdd(reinterpret_cast<volatile long *>(&m_atom),-1L) - 1L;
119 }
120 
121 //
122 // operator ++
123 //
124 __forceinline Uint32 Atom32::operator ++(int) {
125  return _InterlockedExchangeAdd(reinterpret_cast<volatile long *>(&m_atom),1L);
126 }
127 
128 //
129 // operator --
130 //
131 __forceinline Uint32 Atom32::operator --(int) {
132  return _InterlockedExchangeAdd(reinterpret_cast<volatile long *>(&m_atom),-1L);
133 }
134 
135 //
136 // atomic value swapper
137 //
138 __forceinline Uint32 Atom32::swap( const Uint32 rhs) {
139  return _InterlockedExchange(reinterpret_cast<volatile long *>(&m_atom),rhs);
140 }
141 
142 #elif defined(MI_ATOM32_X86GCC) // defined(MI_ATOM32_X86MSC)
143 
144 //
145 // operator +=
146 //
147 inline Uint32 Atom32::operator += ( const Uint32 rhs) {
148  Uint32 retval;
149  asm volatile (
150  "movl %2,%0\n"
151  "lock; xaddl %0,%1\n"
152  "addl %2,%0\n"
153  : "=&r" (retval), "+m" (m_atom)
154  : "r" (rhs)
155  : "cc"
156  );
157  return retval;
158 }
159 
160 //
161 // operator -=
162 //
163 inline Uint32 Atom32::operator -= ( const Uint32 rhs) {
164  Uint32 retval;
165  asm volatile (
166  "neg %2\n"
167  "movl %2,%0\n"
168  "lock; xaddl %0,%1\n"
169  "addl %2,%0\n"
170  : "=&r" (retval), "+m" (m_atom)
171  : "r" (rhs)
172  : "cc", "%2"
173  );
174  return retval;
175 }
176 
177 //
178 // operator ++
179 //
180 inline Uint32 Atom32::operator ++() {
181  Uint32 retval;
182  asm volatile (
183  "movl $1,%0\n"
184  "lock; xaddl %0,%1\n"
185  "addl $1,%0\n"
186  : "=&r" (retval), "+m" (m_atom)
187  :
188  : "cc"
189  );
190  return retval;
191 }
192 
193 //
194 // operator --
195 //
196 inline Uint32 Atom32::operator --() {
197  Uint32 retval;
198  asm volatile (
199  "movl $-1,%0\n"
200  "lock; xaddl %0,%1\n"
201  "addl $-1,%0\n"
202  : "=&r" (retval), "+m" (m_atom)
203  :
204  : "cc"
205  );
206  return retval;
207 }
208 
209 //
210 // operator ++
211 //
212 inline Uint32 Atom32::operator ++(int) {
213  Uint32 retval;
214  asm volatile (
215  "movl $1,%0\n"
216  "lock; xaddl %0,%1\n"
217  : "=&r" (retval), "+m" (m_atom)
218  :
219  : "cc"
220  );
221  return retval;
222 }
223 
224 //
225 // operator --
226 //
227 inline Uint32 Atom32::operator --(int) {
228  Uint32 retval;
229  asm volatile (
230  "movl $-1,%0\n"
231  "lock; xaddl %0,%1\n"
232  : "=&r" (retval), "+m" (m_atom)
233  :
234  : "cc"
235  );
236  return retval;
237 }
238 
239 //
240 // atomic value swapper
241 //
242 inline Uint32 Atom32::swap( const Uint32 rhs) {
243  Uint32 retval;
244  asm volatile (
245  "0:\n"
246  "movl %1,%0\n"
247  "lock; cmpxchg %2,%1\n"
248  "jnz 0b\n"
249  : "=&a" (retval), "+m" (m_atom)
250  : "r" (rhs)
251  : "cc"
252  );
253  return retval;
254 }
255 
256 #elif defined(MI_ATOM32_GENERIC) // defined(MI_ATOM32_X86GCC)
257 
258 //
259 // operator +=
260 //
261 inline Uint32 Atom32::operator += ( const Uint32 rhs) {
262  mi::base::Lock::Block block(&m_lock);
263  return m_atom += rhs;
264 }
265 
266 //
267 // operator -=
268 //
269 inline Uint32 Atom32::operator -= ( const Uint32 rhs) {
270  mi::base::Lock::Block block(&m_lock);
271  return m_atom -= rhs;
272 }
273 
274 //
275 // operator ++
276 //
278  mi::base::Lock::Block block(&m_lock);
279  return ++m_atom;
280 }
281 
282 //
283 // operator --
284 //
286  mi::base::Lock::Block block(&m_lock);
287  return --m_atom;
288 }
289 
290 //
291 // operator ++
292 //
294  mi::base::Lock::Block block(&m_lock);
295  return m_atom++;
296 }
297 
298 //
299 // operator --
300 //
302  mi::base::Lock::Block block(&m_lock);
303  return m_atom--;
304 }
305 
306 //
307 // atomic value swap operation
308 //
309 inline Uint32 Atom32::swap( const Uint32 rhs) {
310  mi::base::Lock::Block block(&m_lock);
311  Uint32 retval = m_atom;
312  m_atom = rhs;
313  return retval;
314 }
315 
316 #else // MI_ATOM32_GENERIC
317 #error One of MI_ATOM32_X86MSC, MI_ATOM32_X86GCC, or MI_ATOM32_GENERIC must be defined.
318 #endif
319 
320 #undef MI_ATOM32_X86MSC
321 #undef MI_ATOM32_X86GCC
322 #undef MI_ATOM32_GENERIC
323  // end group mi_base_threads
325 
326 } // namespace base
327 } // namespace mi
328 
329 #endif // MI_BASE_ATOM_H