2 * Akupara/threading/atomic_ops_gcc_x86.hpp
5 * Created by Udi Barzilai on 06/06.
6 * Copyright 2006 __MyCompanyName__. All rights reserved.
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__))
21 const unsigned int k_bytes_per_cache_line = 64; // this is true for P4 & K8
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 //-------------------------------------
37 //--------------------------------------------------------------------------------
39 inline bool compare_and_store<int64_t>(volatile int64_t * p, const int64_t & x, const int64_t & y)
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);
44 __asm__ __volatile__ (
47 " cmpxchg8b %[location] \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)
55 //--------------------------------------------------------------------------------
57 inline bool compare_and_store<int32_t>(volatile int32_t *p, const int32_t & x, const int32_t & y)
59 register int32_t expected_value = x;
61 __asm__ __volatile__ (
64 " cmpxchgl %[new_value],%[operand] \n"
66 : [operand] "+m" (*p), [result] "=qm" (result), [expected_value] "+a" (expected_value)
72 //--------------------------------------------------------------------------------
78 //--------------------------------------------------------------------------------
79 inline void increment(volatile int32_t * operand_address)
81 __asm__ __volatile__ (
82 "# atomic_increment_32\n"
84 " incl %[operand]; \n"
85 : [operand] "+m" (*operand_address)
90 //--------------------------------------------------------------------------------
91 inline void decrement(volatile int32_t * operand_address)
93 __asm__ __volatile__ (
94 "# atomic_decrement_32\n"
96 " decl %[operand]; \n"
97 : [operand] "+m" (*operand_address)
102 //--------------------------------------------------------------------------------
104 inline void add<int32_t>(volatile int32_t * operand_address, const int32_t & addend)
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);
111 __asm__ __volatile__ (
114 " addl %[addend], %[operand] \n"
115 : [operand] "+m" (*operand_address)
116 : [addend] "ir" (addend)
120 //--------------------------------------------------------------------------------
122 inline void subtract<int32_t>(volatile int32_t * operand_address, const int32_t & subtrahend)
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);
129 __asm__ __volatile__ (
130 "# atomic_subtract_32 \n"
132 " subl %[subtrahend], %[operand] \n"
133 : [operand] "+m" (*operand_address)
134 : [subtrahend] "ir" (subtrahend)
138 //--------------------------------------------------------------------------------
142 // Atomic fetch and add/sub
143 //--------------------------------------------------------------------------------
145 inline int32_t fetch_and_add<int32_t>(volatile int32_t * operand_address, const int32_t & addend)
147 register int32_t addend_and_fetched = addend;
148 __asm__ __volatile__ (
149 "# atomic_fetch_and_add_32 \n"
151 " xaddl %[addend], %[operand]; \n"
152 : [operand] "+m" (*operand_address), [addend] "+r" (addend_and_fetched)
156 return addend_and_fetched;
158 //--------------------------------------------------------------------------------
160 inline int32_t fetch_and_subtract<int32_t>(volatile int32_t * operand_address, const int32_t & subtrahend)
162 return fetch_and_add(operand_address, -subtrahend);
164 //--------------------------------------------------------------------------------
170 //--------------------------------------------------------------------------------
171 inline void memory_barrier_readwrite()
173 #if _AKUPARA_X86_SSE_NOT_AVAILABLE
174 __asm__ __volatile__ (" lock; addl $0,0(%%esp); # memory_barrier_readwrite" : : : "memory");
176 __asm__ __volatile__ (" mfence; # memory_barrier_readwrite" : : : "memory");
177 #endif // _LOCKFREE_ATOMIC_OPS_X86_LFENCE_NOT_AVAILABLE
179 //--------------------------------------------------------------------------------
180 inline void memory_barrier_read()
182 #if _AKUPARA_X86_SSE_NOT_AVAILABLE
183 __asm__ __volatile__ (" lock; addl $0,0(%%esp); # memory_barrier_read" : : : "memory");
185 __asm__ __volatile__ (" lfence; # memory_barrier_read" : : : "memory");
186 #endif // _LOCKFREE_ATOMIC_OPS_X86_LFENCE_NOT_AVAILABLE
188 //--------------------------------------------------------------------------------
189 inline void memory_barrier_write()
191 __asm__ __volatile__ (" sfence; # memory_barrier_write" : : : "memory");
193 //--------------------------------------------------------------------------------
195 } // namespace machine
196 } // namespace atomic
197 } // namespace threading
198 } // namespace Akupara
200 # endif // defined(__GNUC__) && defined(__i386__)
201 #endif // _AKUPARA_THREADING_ATOMIC_OPS_GCC_X86_HPP__INCLUDED_