]> git.sesse.net Git - casparcg/blob - tbb30_20100406oss/include/tbb/tbb_machine.h
aa130658338879a83a6dc49e5cfb75e759addc78
[casparcg] / tbb30_20100406oss / include / tbb / tbb_machine.h
1 /*
2     Copyright 2005-2010 Intel Corporation.  All Rights Reserved.
3
4     This file is part of Threading Building Blocks.
5
6     Threading Building Blocks is free software; you can redistribute it
7     and/or modify it under the terms of the GNU General Public License
8     version 2 as published by the Free Software Foundation.
9
10     Threading Building Blocks is distributed in the hope that it will be
11     useful, but WITHOUT ANY WARRANTY; without even the implied warranty
12     of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with Threading Building Blocks; if not, write to the Free Software
17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
19     As a special exception, you may use this file as part of a free software
20     library without restriction.  Specifically, if other files instantiate
21     templates or use macros or inline functions from this file, or you compile
22     this file and link it with other files to produce an executable, this
23     file does not by itself cause the resulting executable to be covered by
24     the GNU General Public License.  This exception does not however
25     invalidate any other reasons why the executable file might be covered by
26     the GNU General Public License.
27 */
28
29 #ifndef __TBB_machine_H
30 #define __TBB_machine_H
31
32 #include "tbb_stddef.h"
33
34 #if _WIN32||_WIN64
35
36 #ifdef _MANAGED
37 #pragma managed(push, off)
38 #endif
39
40 #if __MINGW32__
41 #include "machine/linux_ia32.h"
42 extern "C" __declspec(dllimport) int __stdcall SwitchToThread( void );
43 #define __TBB_Yield()  SwitchToThread()
44 #elif defined(_M_IX86)
45 #include "machine/windows_ia32.h"
46 #elif defined(_M_AMD64) 
47 #include "machine/windows_intel64.h"
48 #elif _XBOX 
49 #include "machine/xbox360_ppc.h"
50 #else
51 #error Unsupported platform
52 #endif
53
54 #ifdef _MANAGED
55 #pragma managed(pop)
56 #endif
57
58 #elif __linux__ || __FreeBSD__
59
60 #if __i386__
61 #include "machine/linux_ia32.h"
62 #elif __x86_64__
63 #include "machine/linux_intel64.h"
64 #elif __ia64__
65 #include "machine/linux_ia64.h"
66 #endif
67
68 #elif __APPLE__
69
70 #if __i386__
71 #include "machine/linux_ia32.h"
72 #elif __x86_64__
73 #include "machine/linux_intel64.h"
74 #elif __POWERPC__
75 #include "machine/mac_ppc.h"
76 #endif
77
78 #elif _AIX
79
80 #include "machine/ibm_aix51.h"
81
82 #elif __sun || __SUNPRO_CC
83
84 #define __asm__ asm 
85 #define __volatile__ volatile
86 #if __i386  || __i386__
87 #include "machine/linux_ia32.h"
88 #elif __x86_64__
89 #include "machine/linux_intel64.h"
90 #elif __sparc
91 #include "machine/sunos_sparc.h"
92 #endif
93
94 #endif
95
96 #if    !defined(__TBB_CompareAndSwap4) \
97     || !defined(__TBB_CompareAndSwap8) \
98     || !defined(__TBB_Yield)           \
99     || !defined(__TBB_release_consistency_helper)
100 #error Minimal requirements for tbb_machine.h not satisfied 
101 #endif
102
103 #ifndef __TBB_load_with_acquire
104     //! Load with acquire semantics; i.e., no following memory operation can move above the load.
105     template<typename T>
106     inline T __TBB_load_with_acquire(const volatile T& location) {
107         T temp = location;
108         __TBB_release_consistency_helper();
109         return temp;
110     }
111 #endif
112
113 #ifndef __TBB_store_with_release
114     //! Store with release semantics; i.e., no prior memory operation can move below the store.
115     template<typename T, typename V>
116     inline void __TBB_store_with_release(volatile T& location, V value) {
117         __TBB_release_consistency_helper();
118         location = T(value); 
119     }
120 #endif
121
122 #ifndef __TBB_Pause
123     inline void __TBB_Pause(int32_t) {
124         __TBB_Yield();
125     }
126 #endif
127
128 namespace tbb {
129 namespace internal {
130
131 //! Class that implements exponential backoff.
132 /** See implementation of spin_wait_while_eq for an example. */
133 class atomic_backoff {
134     //! Time delay, in units of "pause" instructions. 
135     /** Should be equal to approximately the number of "pause" instructions
136         that take the same time as an context switch. */
137     static const int32_t LOOPS_BEFORE_YIELD = 16;
138     int32_t count;
139 public:
140     atomic_backoff() : count(1) {}
141
142     //! Pause for a while.
143     void pause() {
144         if( count<=LOOPS_BEFORE_YIELD ) {
145             __TBB_Pause(count);
146             // Pause twice as long the next time.
147             count*=2;
148         } else {
149             // Pause is so long that we might as well yield CPU to scheduler.
150             __TBB_Yield();
151         }
152     }
153
154     // pause for a few times and then return false immediately.
155     bool bounded_pause() {
156         if( count<=LOOPS_BEFORE_YIELD ) {
157             __TBB_Pause(count);
158             // Pause twice as long the next time.
159             count*=2;
160             return true;
161         } else {
162             return false;
163         }
164     }
165
166     void reset() {
167         count = 1;
168     }
169 };
170
171 //! Spin WHILE the value of the variable is equal to a given value
172 /** T and U should be comparable types. */
173 template<typename T, typename U>
174 void spin_wait_while_eq( const volatile T& location, U value ) {
175     atomic_backoff backoff;
176     while( location==value ) backoff.pause();
177 }
178
179 //! Spin UNTIL the value of the variable is equal to a given value
180 /** T and U should be comparable types. */
181 template<typename T, typename U>
182 void spin_wait_until_eq( const volatile T& location, const U value ) {
183     atomic_backoff backoff;
184     while( location!=value ) backoff.pause();
185 }
186
187 // T should be unsigned, otherwise sign propagation will break correctness of bit manipulations.
188 // S should be either 1 or 2, for the mask calculation to work correctly.
189 // Together, these rules limit applicability of Masked CAS to unsigned char and unsigned short.
190 template<size_t S, typename T>
191 inline T __TBB_MaskedCompareAndSwap (volatile T *ptr, T value, T comparand ) {
192     volatile uint32_t * base = (uint32_t*)( (uintptr_t)ptr & ~(uintptr_t)0x3 );
193 #if __TBB_BIG_ENDIAN
194     const uint8_t bitoffset = uint8_t( 8*( 4-S - (uintptr_t(ptr) & 0x3) ) );
195 #else
196     const uint8_t bitoffset = uint8_t( 8*((uintptr_t)ptr & 0x3) );
197 #endif
198     const uint32_t mask = ( (1<<(S*8)) - 1 )<<bitoffset;
199     atomic_backoff b;
200     uint32_t result;
201     for(;;) {
202         result = *base; // reload the base value which might change during the pause
203         uint32_t old_value = ( result & ~mask ) | ( comparand << bitoffset );
204         uint32_t new_value = ( result & ~mask ) | ( value << bitoffset );
205         // __TBB_CompareAndSwap4 presumed to have full fence. 
206         result = __TBB_CompareAndSwap4( base, new_value, old_value );
207         if(  result==old_value               // CAS succeeded
208           || ((result^old_value)&mask)!=0 )  // CAS failed and the bits of interest have changed
209             break;
210         else                                 // CAS failed but the bits of interest left unchanged
211             b.pause();
212     }
213     return T((result & mask) >> bitoffset);
214 }
215
216 template<size_t S, typename T>
217 inline T __TBB_CompareAndSwapGeneric (volatile void *ptr, T value, T comparand ) { 
218     return __TBB_CompareAndSwapW((T *)ptr,value,comparand);
219 }
220
221 template<>
222 inline uint8_t __TBB_CompareAndSwapGeneric <1,uint8_t> (volatile void *ptr, uint8_t value, uint8_t comparand ) {
223 #ifdef __TBB_CompareAndSwap1
224     return __TBB_CompareAndSwap1(ptr,value,comparand);
225 #else
226     return __TBB_MaskedCompareAndSwap<1,uint8_t>((volatile uint8_t *)ptr,value,comparand);
227 #endif
228 }
229
230 template<>
231 inline uint16_t __TBB_CompareAndSwapGeneric <2,uint16_t> (volatile void *ptr, uint16_t value, uint16_t comparand ) {
232 #ifdef __TBB_CompareAndSwap2
233     return __TBB_CompareAndSwap2(ptr,value,comparand);
234 #else
235     return __TBB_MaskedCompareAndSwap<2,uint16_t>((volatile uint16_t *)ptr,value,comparand);
236 #endif
237 }
238
239 template<>
240 inline uint32_t __TBB_CompareAndSwapGeneric <4,uint32_t> (volatile void *ptr, uint32_t value, uint32_t comparand ) { 
241     return __TBB_CompareAndSwap4(ptr,value,comparand);
242 }
243
244 template<>
245 inline uint64_t __TBB_CompareAndSwapGeneric <8,uint64_t> (volatile void *ptr, uint64_t value, uint64_t comparand ) { 
246     return __TBB_CompareAndSwap8(ptr,value,comparand);
247 }
248
249 template<size_t S, typename T>
250 inline T __TBB_FetchAndAddGeneric (volatile void *ptr, T addend) {
251     atomic_backoff b;
252     T result;
253     for(;;) {
254         result = *reinterpret_cast<volatile T *>(ptr);
255         // __TBB_CompareAndSwapGeneric presumed to have full fence. 
256         if( __TBB_CompareAndSwapGeneric<S,T> ( ptr, result+addend, result )==result ) 
257             break;
258         b.pause();
259     }
260     return result;
261 }
262
263 template<size_t S, typename T>
264 inline T __TBB_FetchAndStoreGeneric (volatile void *ptr, T value) {
265     atomic_backoff b;
266     T result;
267     for(;;) {
268         result = *reinterpret_cast<volatile T *>(ptr);
269         // __TBB_CompareAndSwapGeneric presumed to have full fence.
270         if( __TBB_CompareAndSwapGeneric<S,T> ( ptr, value, result )==result ) 
271             break;
272         b.pause();
273     }
274     return result;
275 }
276
277 // Macro __TBB_TypeWithAlignmentAtLeastAsStrict(T) should be a type with alignment at least as 
278 // strict as type T.  Type type should have a trivial default constructor and destructor, so that
279 // arrays of that type can be declared without initializers.  
280 // It is correct (but perhaps a waste of space) if __TBB_TypeWithAlignmentAtLeastAsStrict(T) expands
281 // to a type bigger than T.
282 // The default definition here works on machines where integers are naturally aligned and the
283 // strictest alignment is 16.
284 #ifndef __TBB_TypeWithAlignmentAtLeastAsStrict
285
286 #if __GNUC__ || __SUNPRO_CC
287 struct __TBB_machine_type_with_strictest_alignment {
288     int member[4];
289 } __attribute__((aligned(16)));
290 #elif _MSC_VER
291 __declspec(align(16)) struct __TBB_machine_type_with_strictest_alignment {
292     int member[4];
293 };
294 #else
295 #error Must define __TBB_TypeWithAlignmentAtLeastAsStrict(T) or __TBB_machine_type_with_strictest_alignment
296 #endif
297
298 template<size_t N> struct type_with_alignment {__TBB_machine_type_with_strictest_alignment member;};
299 template<> struct type_with_alignment<1> { char member; };
300 template<> struct type_with_alignment<2> { uint16_t member; };
301 template<> struct type_with_alignment<4> { uint32_t member; };
302 template<> struct type_with_alignment<8> { uint64_t member; };
303
304 #if _MSC_VER||defined(__GNUC__)&&__GNUC__==3 && __GNUC_MINOR__<=2  
305 //! Work around for bug in GNU 3.2 and MSVC compilers.
306 /** Bug is that compiler sometimes returns 0 for __alignof(T) when T has not yet been instantiated.
307     The work-around forces instantiation by forcing computation of sizeof(T) before __alignof(T). */
308 template<size_t Size, typename T> 
309 struct work_around_alignment_bug {
310 #if _MSC_VER
311     static const size_t alignment = __alignof(T);
312 #else
313     static const size_t alignment = __alignof__(T);
314 #endif
315 };
316 #define __TBB_TypeWithAlignmentAtLeastAsStrict(T) tbb::internal::type_with_alignment<tbb::internal::work_around_alignment_bug<sizeof(T),T>::alignment>
317 #elif __GNUC__ || __SUNPRO_CC
318 #define __TBB_TypeWithAlignmentAtLeastAsStrict(T) tbb::internal::type_with_alignment<__alignof__(T)>
319 #else
320 #define __TBB_TypeWithAlignmentAtLeastAsStrict(T) __TBB_machine_type_with_strictest_alignment
321 #endif
322 #endif  /* ____TBB_TypeWithAlignmentAtLeastAsStrict */
323
324 // Template class here is to avoid instantiation of the static data for modules that don't use it
325 template<typename T>
326 struct reverse {
327     static const T byte_table[256];
328 };
329 // An efficient implementation of the reverse function utilizes a 2^8 lookup table holding the bit-reversed
330 // values of [0..2^8 - 1]. Those values can also be computed on the fly at a slightly higher cost.
331 template<typename T>
332 const T reverse<T>::byte_table[256] = {
333     0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
334     0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
335     0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
336     0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
337     0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
338     0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
339     0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
340     0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
341     0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
342     0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
343     0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
344     0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
345     0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
346     0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
347     0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
348     0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
349 };
350
351 } // namespace internal
352 } // namespace tbb
353
354 #ifndef __TBB_CompareAndSwap1
355 #define __TBB_CompareAndSwap1 tbb::internal::__TBB_CompareAndSwapGeneric<1,uint8_t>
356 #endif
357
358 #ifndef __TBB_CompareAndSwap2 
359 #define __TBB_CompareAndSwap2 tbb::internal::__TBB_CompareAndSwapGeneric<2,uint16_t>
360 #endif
361
362 #ifndef __TBB_CompareAndSwapW
363 #define __TBB_CompareAndSwapW tbb::internal::__TBB_CompareAndSwapGeneric<sizeof(ptrdiff_t),ptrdiff_t>
364 #endif
365
366 #ifndef __TBB_FetchAndAdd1
367 #define __TBB_FetchAndAdd1 tbb::internal::__TBB_FetchAndAddGeneric<1,uint8_t>
368 #endif
369
370 #ifndef __TBB_FetchAndAdd2
371 #define __TBB_FetchAndAdd2 tbb::internal::__TBB_FetchAndAddGeneric<2,uint16_t>
372 #endif
373
374 #ifndef __TBB_FetchAndAdd4
375 #define __TBB_FetchAndAdd4 tbb::internal::__TBB_FetchAndAddGeneric<4,uint32_t>
376 #endif
377
378 #ifndef __TBB_FetchAndAdd8
379 #define __TBB_FetchAndAdd8 tbb::internal::__TBB_FetchAndAddGeneric<8,uint64_t>
380 #endif
381
382 #ifndef __TBB_FetchAndAddW
383 #define __TBB_FetchAndAddW tbb::internal::__TBB_FetchAndAddGeneric<sizeof(ptrdiff_t),ptrdiff_t>
384 #endif
385
386 #ifndef __TBB_FetchAndStore1
387 #define __TBB_FetchAndStore1 tbb::internal::__TBB_FetchAndStoreGeneric<1,uint8_t>
388 #endif
389
390 #ifndef __TBB_FetchAndStore2
391 #define __TBB_FetchAndStore2 tbb::internal::__TBB_FetchAndStoreGeneric<2,uint16_t>
392 #endif
393
394 #ifndef __TBB_FetchAndStore4
395 #define __TBB_FetchAndStore4 tbb::internal::__TBB_FetchAndStoreGeneric<4,uint32_t>
396 #endif
397
398 #ifndef __TBB_FetchAndStore8
399 #define __TBB_FetchAndStore8 tbb::internal::__TBB_FetchAndStoreGeneric<8,uint64_t>
400 #endif
401
402 #ifndef __TBB_FetchAndStoreW
403 #define __TBB_FetchAndStoreW tbb::internal::__TBB_FetchAndStoreGeneric<sizeof(ptrdiff_t),ptrdiff_t>
404 #endif
405
406 #if __TBB_DECL_FENCED_ATOMICS
407
408 #ifndef __TBB_CompareAndSwap1__TBB_full_fence
409 #define __TBB_CompareAndSwap1__TBB_full_fence __TBB_CompareAndSwap1
410 #endif 
411 #ifndef __TBB_CompareAndSwap1acquire
412 #define __TBB_CompareAndSwap1acquire __TBB_CompareAndSwap1__TBB_full_fence
413 #endif 
414 #ifndef __TBB_CompareAndSwap1release
415 #define __TBB_CompareAndSwap1release __TBB_CompareAndSwap1__TBB_full_fence
416 #endif 
417
418 #ifndef __TBB_CompareAndSwap2__TBB_full_fence
419 #define __TBB_CompareAndSwap2__TBB_full_fence __TBB_CompareAndSwap2
420 #endif
421 #ifndef __TBB_CompareAndSwap2acquire
422 #define __TBB_CompareAndSwap2acquire __TBB_CompareAndSwap2__TBB_full_fence
423 #endif
424 #ifndef __TBB_CompareAndSwap2release
425 #define __TBB_CompareAndSwap2release __TBB_CompareAndSwap2__TBB_full_fence
426 #endif
427
428 #ifndef __TBB_CompareAndSwap4__TBB_full_fence
429 #define __TBB_CompareAndSwap4__TBB_full_fence __TBB_CompareAndSwap4
430 #endif 
431 #ifndef __TBB_CompareAndSwap4acquire
432 #define __TBB_CompareAndSwap4acquire __TBB_CompareAndSwap4__TBB_full_fence
433 #endif 
434 #ifndef __TBB_CompareAndSwap4release
435 #define __TBB_CompareAndSwap4release __TBB_CompareAndSwap4__TBB_full_fence
436 #endif 
437
438 #ifndef __TBB_CompareAndSwap8__TBB_full_fence
439 #define __TBB_CompareAndSwap8__TBB_full_fence __TBB_CompareAndSwap8
440 #endif
441 #ifndef __TBB_CompareAndSwap8acquire
442 #define __TBB_CompareAndSwap8acquire __TBB_CompareAndSwap8__TBB_full_fence
443 #endif
444 #ifndef __TBB_CompareAndSwap8release
445 #define __TBB_CompareAndSwap8release __TBB_CompareAndSwap8__TBB_full_fence
446 #endif
447
448 #ifndef __TBB_FetchAndAdd1__TBB_full_fence
449 #define __TBB_FetchAndAdd1__TBB_full_fence __TBB_FetchAndAdd1
450 #endif
451 #ifndef __TBB_FetchAndAdd1acquire
452 #define __TBB_FetchAndAdd1acquire __TBB_FetchAndAdd1__TBB_full_fence
453 #endif
454 #ifndef __TBB_FetchAndAdd1release
455 #define __TBB_FetchAndAdd1release __TBB_FetchAndAdd1__TBB_full_fence
456 #endif
457
458 #ifndef __TBB_FetchAndAdd2__TBB_full_fence
459 #define __TBB_FetchAndAdd2__TBB_full_fence __TBB_FetchAndAdd2
460 #endif
461 #ifndef __TBB_FetchAndAdd2acquire
462 #define __TBB_FetchAndAdd2acquire __TBB_FetchAndAdd2__TBB_full_fence
463 #endif
464 #ifndef __TBB_FetchAndAdd2release
465 #define __TBB_FetchAndAdd2release __TBB_FetchAndAdd2__TBB_full_fence
466 #endif
467
468 #ifndef __TBB_FetchAndAdd4__TBB_full_fence
469 #define __TBB_FetchAndAdd4__TBB_full_fence __TBB_FetchAndAdd4
470 #endif
471 #ifndef __TBB_FetchAndAdd4acquire
472 #define __TBB_FetchAndAdd4acquire __TBB_FetchAndAdd4__TBB_full_fence
473 #endif
474 #ifndef __TBB_FetchAndAdd4release
475 #define __TBB_FetchAndAdd4release __TBB_FetchAndAdd4__TBB_full_fence
476 #endif
477
478 #ifndef __TBB_FetchAndAdd8__TBB_full_fence
479 #define __TBB_FetchAndAdd8__TBB_full_fence __TBB_FetchAndAdd8
480 #endif
481 #ifndef __TBB_FetchAndAdd8acquire
482 #define __TBB_FetchAndAdd8acquire __TBB_FetchAndAdd8__TBB_full_fence
483 #endif
484 #ifndef __TBB_FetchAndAdd8release
485 #define __TBB_FetchAndAdd8release __TBB_FetchAndAdd8__TBB_full_fence
486 #endif
487
488 #ifndef __TBB_FetchAndStore1__TBB_full_fence
489 #define __TBB_FetchAndStore1__TBB_full_fence __TBB_FetchAndStore1
490 #endif
491 #ifndef __TBB_FetchAndStore1acquire
492 #define __TBB_FetchAndStore1acquire __TBB_FetchAndStore1__TBB_full_fence
493 #endif
494 #ifndef __TBB_FetchAndStore1release
495 #define __TBB_FetchAndStore1release __TBB_FetchAndStore1__TBB_full_fence
496 #endif
497
498 #ifndef __TBB_FetchAndStore2__TBB_full_fence
499 #define __TBB_FetchAndStore2__TBB_full_fence __TBB_FetchAndStore2
500 #endif
501 #ifndef __TBB_FetchAndStore2acquire
502 #define __TBB_FetchAndStore2acquire __TBB_FetchAndStore2__TBB_full_fence
503 #endif
504 #ifndef __TBB_FetchAndStore2release
505 #define __TBB_FetchAndStore2release __TBB_FetchAndStore2__TBB_full_fence
506 #endif
507
508 #ifndef __TBB_FetchAndStore4__TBB_full_fence
509 #define __TBB_FetchAndStore4__TBB_full_fence __TBB_FetchAndStore4
510 #endif
511 #ifndef __TBB_FetchAndStore4acquire
512 #define __TBB_FetchAndStore4acquire __TBB_FetchAndStore4__TBB_full_fence
513 #endif
514 #ifndef __TBB_FetchAndStore4release
515 #define __TBB_FetchAndStore4release __TBB_FetchAndStore4__TBB_full_fence
516 #endif
517
518 #ifndef __TBB_FetchAndStore8__TBB_full_fence
519 #define __TBB_FetchAndStore8__TBB_full_fence __TBB_FetchAndStore8
520 #endif
521 #ifndef __TBB_FetchAndStore8acquire
522 #define __TBB_FetchAndStore8acquire __TBB_FetchAndStore8__TBB_full_fence
523 #endif
524 #ifndef __TBB_FetchAndStore8release
525 #define __TBB_FetchAndStore8release __TBB_FetchAndStore8__TBB_full_fence
526 #endif
527
528 #endif // __TBB_DECL_FENCED_ATOMICS
529
530 // Special atomic functions
531 #ifndef __TBB_FetchAndAddWrelease
532 #define __TBB_FetchAndAddWrelease __TBB_FetchAndAddW
533 #endif
534
535 #ifndef __TBB_FetchAndIncrementWacquire
536 #define __TBB_FetchAndIncrementWacquire(P) __TBB_FetchAndAddW(P,1)
537 #endif
538
539 #ifndef __TBB_FetchAndDecrementWrelease
540 #define __TBB_FetchAndDecrementWrelease(P) __TBB_FetchAndAddW(P,(-1))
541 #endif
542
543 #if __TBB_WORDSIZE==4
544 // On 32-bit platforms, "atomic.h" requires definition of __TBB_Store8 and __TBB_Load8
545 #ifndef __TBB_Store8
546 inline void __TBB_Store8 (volatile void *ptr, int64_t value) {
547     tbb::internal::atomic_backoff b;
548     for(;;) {
549         int64_t result = *(int64_t *)ptr;
550         if( __TBB_CompareAndSwap8(ptr,value,result)==result ) break;
551         b.pause();
552     }
553 }
554 #endif
555
556 #ifndef __TBB_Load8
557 inline int64_t __TBB_Load8 (const volatile void *ptr) {
558     int64_t result = *(int64_t *)ptr;
559     result = __TBB_CompareAndSwap8((volatile void *)ptr,result,result);
560     return result;
561 }
562 #endif
563 #endif /* __TBB_WORDSIZE==4 */
564
565 #ifndef __TBB_Log2
566 inline intptr_t __TBB_Log2( uintptr_t x ) {
567     if( x==0 ) return -1;
568     intptr_t result = 0;
569     uintptr_t tmp;
570 #if __TBB_WORDSIZE>=8
571     if( (tmp = x>>32) ) { x=tmp; result += 32; }
572 #endif
573     if( (tmp = x>>16) ) { x=tmp; result += 16; }
574     if( (tmp = x>>8) )  { x=tmp; result += 8; }
575     if( (tmp = x>>4) )  { x=tmp; result += 4; }
576     if( (tmp = x>>2) )  { x=tmp; result += 2; }
577     return (x&2)? result+1: result;
578 }
579 #endif
580
581 #ifndef __TBB_AtomicOR
582 inline void __TBB_AtomicOR( volatile void *operand, uintptr_t addend ) {
583     tbb::internal::atomic_backoff b;
584     for(;;) {
585         uintptr_t tmp = *(volatile uintptr_t *)operand;
586         uintptr_t result = __TBB_CompareAndSwapW(operand, tmp|addend, tmp);
587         if( result==tmp ) break;
588         b.pause();
589     }
590 }
591 #endif
592
593 #ifndef __TBB_AtomicAND
594 inline void __TBB_AtomicAND( volatile void *operand, uintptr_t addend ) {
595     tbb::internal::atomic_backoff b;
596     for(;;) {
597         uintptr_t tmp = *(volatile uintptr_t *)operand;
598         uintptr_t result = __TBB_CompareAndSwapW(operand, tmp&addend, tmp);
599         if( result==tmp ) break;
600         b.pause();
601     }
602 }
603 #endif
604
605 #ifndef __TBB_TryLockByte
606 inline bool __TBB_TryLockByte( unsigned char &flag ) {
607     return __TBB_CompareAndSwap1(&flag,1,0)==0;
608 }
609 #endif
610
611 #ifndef __TBB_LockByte
612 inline uintptr_t __TBB_LockByte( unsigned char& flag ) {
613     if ( !__TBB_TryLockByte(flag) ) {
614         tbb::internal::atomic_backoff b;
615         do {
616             b.pause();
617         } while ( !__TBB_TryLockByte(flag) );
618     }
619     return 0;
620 }
621 #endif
622
623 #ifndef __TBB_ReverseByte
624 inline unsigned char __TBB_ReverseByte(unsigned char src) {
625     return tbb::internal::reverse<unsigned char>::byte_table[src];
626 }
627 #endif
628
629 template<typename T>
630 T __TBB_ReverseBits(T src)
631 {
632     T dst;
633     unsigned char *original = (unsigned char *) &src;
634     unsigned char *reversed = (unsigned char *) &dst;
635
636     for( int i = sizeof(T)-1; i >= 0; i-- )
637         reversed[i] = __TBB_ReverseByte( original[sizeof(T)-i-1] );
638
639     return dst;
640 }
641
642 #endif /* __TBB_machine_H */