Comment remaining unsolved bug.
[ardour.git] / libs / backends / wavesaudio / wavesapi / akupara / threading / atomic_ops_gcc_x86.hpp
1 /*
2  *  Akupara/threading/atomic_ops_gcc_x86.hpp
3  *
4  *
5  *  Created by Udi Barzilai on 06/06.
6  *  Copyright 2006 __MyCompanyName__. All rights reserved.
7  *
8  */
9 #if !defined(_AKUPARA_THREADING_ATOMIC_OPS_GCC_X86_HPP__INCLUDED_)
10 #       define _AKUPARA_THREADING_ATOMIC_OPS_GCC_X86_HPP__INCLUDED_
11 #       if defined(__GNUC__) && (defined(__i386__) ||  defined(__x86_64__))
12
13 namespace Akupara
14 {
15         namespace threading
16         {
17                 namespace atomic
18                 {
19                         namespace machine
20                         {
21                                 const unsigned int k_bytes_per_cache_line = 64;  // this is true for P4 & K8
22
23
24                                 // Flags for operations supported by this machine
25                                 //-------------------------------------
26                                 template<> struct implements_load         <4> : public true_type {};
27                                 template<> struct implements_store        <4> : public true_type {};
28                                 template<> struct implements_CAS          <4> : public true_type {};
29                                 template<> struct implements_CAS          <8> : public true_type {};
30                                 template<> struct implements_add          <4> : public true_type {};
31                                 template<> struct implements_fetch_and_add<4> : public true_type {};
32                                 //-------------------------------------
33
34
35
36                                 // CAS
37                                 //--------------------------------------------------------------------------------
38                                 template<>
39                                 inline bool compare_and_store<int64_t>(volatile int64_t * p, const int64_t & x, const int64_t & y)
40                                 {
41                                         register int32_t evh=int32_t(x>>32), evl=int32_t(x);
42                                         register const int32_t nvh=int32_t(y>>32), nvl=int32_t(y);
43                                         register bool result;
44                                         __asm__ __volatile__ (
45                                                         "# CAS64\n"
46                                                         "       lock                       \n"
47                                                         "       cmpxchg8b %[location]  \n"
48                                                         "       sete %[result]         \n"
49                                                         : [location] "+m" (*p), [result] "=qm" (result), [expected_value_high] "+d" (evh), [expected_value_low] "+a" (evl)
50                                                         : [new_value_high] "c" (nvh), [new_value_low] "b" (nvl)
51                                                         : "cc"
52                                         );
53                                         return result;
54                                 }
55                                 //--------------------------------------------------------------------------------
56                                 template<>
57                                 inline bool compare_and_store<int32_t>(volatile int32_t *p, const int32_t & x, const int32_t & y)
58                                 {
59                                         register int32_t expected_value = x;
60                                         register bool result;
61                                         __asm__ __volatile__ (
62                                                         "# CAS32\n"
63                                                         "       lock                             \n"
64                                                         "       cmpxchgl %[new_value],%[operand] \n"
65                                                         "       sete %[result]                   \n"
66                                                         : [operand] "+m" (*p), [result] "=qm" (result), [expected_value] "+a" (expected_value)
67                                                         : [new_value] "r" (y)
68                                                         : "cc"
69                                         );
70                                         return result;
71                                 }
72                                 //--------------------------------------------------------------------------------
73
74
75
76
77                                 // Atomic add/sub
78                                 //--------------------------------------------------------------------------------
79                                 inline void increment(volatile int32_t * operand_address)
80                                 {
81                                         __asm__ __volatile__ (
82                                         "# atomic_increment_32\n"
83                                         "       lock;             \n"
84                                         "       incl %[operand];  \n"
85                                         : [operand] "+m" (*operand_address)
86                                         :
87                                         : "cc"
88                                         );
89                                 }
90                                 //--------------------------------------------------------------------------------
91                                 inline void decrement(volatile int32_t * operand_address)
92                                 {
93                                         __asm__ __volatile__ (
94                                         "# atomic_decrement_32\n"
95                                         "       lock;             \n"
96                                         "       decl %[operand];  \n"
97                                         : [operand] "+m" (*operand_address)
98                                         :
99                                         : "cc"
100                                         );
101                                 }
102                                 //--------------------------------------------------------------------------------
103                                 template<>
104                                 inline void add<int32_t>(volatile int32_t * operand_address, const int32_t & addend)
105                                 {
106                                         if (__builtin_constant_p(addend) && addend==1)
107                                                 increment(operand_address);
108                                         else if (__builtin_constant_p(addend) && addend==-1)
109                                                 decrement(operand_address);
110                                         else
111                                                 __asm__ __volatile__ (
112                                                 "# atomic_add_32               \n"
113                                                 "       lock                       \n"
114                                                 "       addl %[addend], %[operand] \n"
115                                                 : [operand] "+m" (*operand_address)
116                                                 : [addend] "ir" (addend)
117                                                 : "cc"
118                                                 );
119                                 }
120                                 //--------------------------------------------------------------------------------
121                                 template<>
122                                 inline void subtract<int32_t>(volatile int32_t * operand_address, const int32_t & subtrahend)
123                                 {
124                                         if (__builtin_constant_p(subtrahend) && subtrahend==1)
125                                                 decrement(operand_address);
126                                         else if (__builtin_constant_p(subtrahend) && subtrahend==-1)
127                                                 increment(operand_address);
128                                         else
129                                                 __asm__ __volatile__ (
130                                                 "# atomic_subtract_32              \n"
131                                                 "       lock                           \n"
132                                                 "       subl %[subtrahend], %[operand] \n"
133                                                 : [operand] "+m" (*operand_address)
134                                                 : [subtrahend] "ir" (subtrahend)
135                                                 : "cc"
136                                                 );
137                                 }
138                                 //--------------------------------------------------------------------------------
139
140
141
142                                 // Atomic fetch and add/sub
143                                 //--------------------------------------------------------------------------------
144                                 template<>
145                                 inline int32_t fetch_and_add<int32_t>(volatile int32_t * operand_address, const int32_t & addend)
146                                 {
147                                         register int32_t addend_and_fetched = addend;
148                                         __asm__ __volatile__ (
149                                         "# atomic_fetch_and_add_32       \n"
150                                         "       lock;                        \n"
151                                         "       xaddl %[addend], %[operand]; \n"
152                                         : [operand] "+m" (*operand_address), [addend] "+r" (addend_and_fetched)
153                                         :
154                                         : "cc"
155                                         );
156                                         return addend_and_fetched;
157                                 }
158                                 //--------------------------------------------------------------------------------
159                                 template<>
160                                 inline int32_t fetch_and_subtract<int32_t>(volatile int32_t * operand_address, const int32_t & subtrahend)
161                                 {
162                                         return fetch_and_add(operand_address, -subtrahend);
163                                 }
164                                 //--------------------------------------------------------------------------------
165
166
167
168
169                                 // Memory barriers
170                                 //--------------------------------------------------------------------------------
171                                 inline void memory_barrier_readwrite()
172                                 {
173                                 #if _AKUPARA_X86_SSE_NOT_AVAILABLE
174                                         __asm__ __volatile__ (" lock; addl $0,0(%%esp); # memory_barrier_readwrite" : : : "memory");
175                                 #else
176                                         __asm__ __volatile__ (" mfence;   # memory_barrier_readwrite" : : : "memory");
177                                 #endif // _LOCKFREE_ATOMIC_OPS_X86_LFENCE_NOT_AVAILABLE
178                                 }
179                                 //--------------------------------------------------------------------------------
180                                 inline void memory_barrier_read()
181                                 {
182                                 #if _AKUPARA_X86_SSE_NOT_AVAILABLE
183                                         __asm__ __volatile__ (" lock; addl $0,0(%%esp); # memory_barrier_read" : : : "memory");
184                                 #else
185                                         __asm__ __volatile__ (" lfence;  # memory_barrier_read" : : : "memory");
186                                 #endif // _LOCKFREE_ATOMIC_OPS_X86_LFENCE_NOT_AVAILABLE
187                                 }
188                                 //--------------------------------------------------------------------------------
189                                 inline void memory_barrier_write()
190                                 {
191                                         __asm__ __volatile__ (" sfence;  # memory_barrier_write" : : : "memory");
192                                 }
193                                 //--------------------------------------------------------------------------------
194
195                         } // namespace machine
196                 } // namespace atomic
197         } // namespace threading
198 } // namespace Akupara
199
200 #       endif // defined(__GNUC__) && defined(__i386__)
201 #endif // _AKUPARA_THREADING_ATOMIC_OPS_GCC_X86_HPP__INCLUDED_