1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" 2 "http://www.w3.org/TR/html4/strict.dtd"> 3 <!-- Material used from: HTML 4.01 specs: http://www.w3.org/TR/html401/ --> 4 <html> 5 <head> 6 <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> 7 <title><atomic> design</title> 8 <link type="text/css" rel="stylesheet" href="menu.css"> 9 <link type="text/css" rel="stylesheet" href="content.css"> 10 </head> 11 12 <body> 13 <div id="menu"> 14 <div> 15 <a href="http://llvm.org/">LLVM Home</a> 16 </div> 17 18 <div class="submenu"> 19 <label>libc++ Info</label> 20 <a href="/index.html">About</a> 21 </div> 22 23 <div class="submenu"> 24 <label>Quick Links</label> 25 <a href="http://lists.llvm.org/mailman/listinfo/cfe-dev">cfe-dev</a> 26 <a href="http://lists.llvm.org/mailman/listinfo/cfe-commits">cfe-commits</a> 27 <a href="http://llvm.org/bugs/">Bug Reports</a> 28 <a href="http://llvm.org/svn/llvm-project/libcxx/trunk/">Browse SVN</a> 29 <a href="http://llvm.org/viewvc/llvm-project/libcxx/trunk/">Browse ViewVC</a> 30 </div> 31 </div> 32 33 <div id="content"> 34 <!--*********************************************************************--> 35 <h1><atomic> design</h1> 36 <!--*********************************************************************--> 37 38 <p> 39 The compiler supplies all of the intrinsics as described below. This list of 40 intrinsics roughly parallels the requirements of the C and C++ atomics 41 proposals. The C and C++ library implementations simply drop through to these 42 intrinsics. Anything the platform does not support in hardware, the compiler 43 arranges for a (compiler-rt) library call to be made which will do the job with 44 a mutex, and in this case ignoring the memory ordering parameter (effectively 45 implementing <tt>memory_order_seq_cst</tt>). 46 </p> 47 48 <p> 49 Ultimate efficiency is preferred over run time error checking. Undefined 50 behavior is acceptable when the inputs do not conform as defined below. 51 </p> 52 53 <blockquote><pre> 54 <font color="#C80000">// In every intrinsic signature below, type* atomic_obj may be a pointer to a</font> 55 <font color="#C80000">// volatile-qualified type.</font> 56 <font color="#C80000">// Memory ordering values map to the following meanings:</font> 57 <font color="#C80000">// memory_order_relaxed == 0</font> 58 <font color="#C80000">// memory_order_consume == 1</font> 59 <font color="#C80000">// memory_order_acquire == 2</font> 60 <font color="#C80000">// memory_order_release == 3</font> 61 <font color="#C80000">// memory_order_acq_rel == 4</font> 62 <font color="#C80000">// memory_order_seq_cst == 5</font> 63 64 <font color="#C80000">// type must be trivially copyable</font> 65 <font color="#C80000">// type represents a "type argument"</font> 66 bool __atomic_is_lock_free(type); 67 68 <font color="#C80000">// type must be trivially copyable</font> 69 <font color="#C80000">// Behavior is defined for mem_ord = 0, 1, 2, 5</font> 70 type __atomic_load(const type* atomic_obj, int mem_ord); 71 72 <font color="#C80000">// type must be trivially copyable</font> 73 <font color="#C80000">// Behavior is defined for mem_ord = 0, 3, 5</font> 74 void __atomic_store(type* atomic_obj, type desired, int mem_ord); 75 76 <font color="#C80000">// type must be trivially copyable</font> 77 <font color="#C80000">// Behavior is defined for mem_ord = [0 ... 5]</font> 78 type __atomic_exchange(type* atomic_obj, type desired, int mem_ord); 79 80 <font color="#C80000">// type must be trivially copyable</font> 81 <font color="#C80000">// Behavior is defined for mem_success = [0 ... 5],</font> 82 <font color="#C80000">// mem_failure <= mem_success</font> 83 <font color="#C80000">// mem_failure != 3</font> 84 <font color="#C80000">// mem_failure != 4</font> 85 bool __atomic_compare_exchange_strong(type* atomic_obj, 86 type* expected, type desired, 87 int mem_success, int mem_failure); 88 89 <font color="#C80000">// type must be trivially copyable</font> 90 <font color="#C80000">// Behavior is defined for mem_success = [0 ... 5],</font> 91 <font color="#C80000">// mem_failure <= mem_success</font> 92 <font color="#C80000">// mem_failure != 3</font> 93 <font color="#C80000">// mem_failure != 4</font> 94 bool __atomic_compare_exchange_weak(type* atomic_obj, 95 type* expected, type desired, 96 int mem_success, int mem_failure); 97 98 <font color="#C80000">// type is one of: char, signed char, unsigned char, short, unsigned short, int,</font> 99 <font color="#C80000">// unsigned int, long, unsigned long, long long, unsigned long long,</font> 100 <font color="#C80000">// char16_t, char32_t, wchar_t</font> 101 <font color="#C80000">// Behavior is defined for mem_ord = [0 ... 5]</font> 102 type __atomic_fetch_add(type* atomic_obj, type operand, int mem_ord); 103 104 <font color="#C80000">// type is one of: char, signed char, unsigned char, short, unsigned short, int,</font> 105 <font color="#C80000">// unsigned int, long, unsigned long, long long, unsigned long long,</font> 106 <font color="#C80000">// char16_t, char32_t, wchar_t</font> 107 <font color="#C80000">// Behavior is defined for mem_ord = [0 ... 5]</font> 108 type __atomic_fetch_sub(type* atomic_obj, type operand, int mem_ord); 109 110 <font color="#C80000">// type is one of: char, signed char, unsigned char, short, unsigned short, int,</font> 111 <font color="#C80000">// unsigned int, long, unsigned long, long long, unsigned long long,</font> 112 <font color="#C80000">// char16_t, char32_t, wchar_t</font> 113 <font color="#C80000">// Behavior is defined for mem_ord = [0 ... 5]</font> 114 type __atomic_fetch_and(type* atomic_obj, type operand, int mem_ord); 115 116 <font color="#C80000">// type is one of: char, signed char, unsigned char, short, unsigned short, int,</font> 117 <font color="#C80000">// unsigned int, long, unsigned long, long long, unsigned long long,</font> 118 <font color="#C80000">// char16_t, char32_t, wchar_t</font> 119 <font color="#C80000">// Behavior is defined for mem_ord = [0 ... 5]</font> 120 type __atomic_fetch_or(type* atomic_obj, type operand, int mem_ord); 121 122 <font color="#C80000">// type is one of: char, signed char, unsigned char, short, unsigned short, int,</font> 123 <font color="#C80000">// unsigned int, long, unsigned long, long long, unsigned long long,</font> 124 <font color="#C80000">// char16_t, char32_t, wchar_t</font> 125 <font color="#C80000">// Behavior is defined for mem_ord = [0 ... 5]</font> 126 type __atomic_fetch_xor(type* atomic_obj, type operand, int mem_ord); 127 128 <font color="#C80000">// Behavior is defined for mem_ord = [0 ... 5]</font> 129 void* __atomic_fetch_add(void** atomic_obj, ptrdiff_t operand, int mem_ord); 130 void* __atomic_fetch_sub(void** atomic_obj, ptrdiff_t operand, int mem_ord); 131 132 <font color="#C80000">// Behavior is defined for mem_ord = [0 ... 5]</font> 133 void __atomic_thread_fence(int mem_ord); 134 void __atomic_signal_fence(int mem_ord); 135 </pre></blockquote> 136 137 <p> 138 If desired the intrinsics taking a single <tt>mem_ord</tt> parameter can default 139 this argument to 5. 140 </p> 141 142 <p> 143 If desired the intrinsics taking two ordering parameters can default 144 <tt>mem_success</tt> to 5, and <tt>mem_failure</tt> to 145 <tt>translate_memory_order(mem_success)</tt> where 146 <tt>translate_memory_order(mem_success)</tt> is defined as: 147 </p> 148 149 <blockquote><pre> 150 int 151 translate_memory_order(int o) 152 { 153 switch (o) 154 { 155 case 4: 156 return 2; 157 case 3: 158 return 0; 159 } 160 return o; 161 } 162 </pre></blockquote> 163 164 <p> 165 Below are representative C++ implementations of all of the operations. Their 166 purpose is to document the desired semantics of each operation, assuming 167 <tt>memory_order_seq_cst</tt>. This is essentially the code that will be called 168 if the front end calls out to compiler-rt. 169 </p> 170 171 <blockquote><pre> 172 template <class T> 173 T 174 __atomic_load(T const volatile* obj) 175 { 176 unique_lock<mutex> _(some_mutex); 177 return *obj; 178 } 179 180 template <class T> 181 void 182 __atomic_store(T volatile* obj, T desr) 183 { 184 unique_lock<mutex> _(some_mutex); 185 *obj = desr; 186 } 187 188 template <class T> 189 T 190 __atomic_exchange(T volatile* obj, T desr) 191 { 192 unique_lock<mutex> _(some_mutex); 193 T r = *obj; 194 *obj = desr; 195 return r; 196 } 197 198 template <class T> 199 bool 200 __atomic_compare_exchange_strong(T volatile* obj, T* exp, T desr) 201 { 202 unique_lock<mutex> _(some_mutex); 203 if (std::memcmp(const_cast<T*>(obj), exp, sizeof(T)) == 0) <font color="#C80000">// if (*obj == *exp)</font> 204 { 205 std::memcpy(const_cast<T*>(obj), &desr, sizeof(T)); <font color="#C80000">// *obj = desr;</font> 206 return true; 207 } 208 std::memcpy(exp, const_cast<T*>(obj), sizeof(T)); <font color="#C80000">// *exp = *obj;</font> 209 return false; 210 } 211 212 <font color="#C80000">// May spuriously return false (even if *obj == *exp)</font> 213 template <class T> 214 bool 215 __atomic_compare_exchange_weak(T volatile* obj, T* exp, T desr) 216 { 217 unique_lock<mutex> _(some_mutex); 218 if (std::memcmp(const_cast<T*>(obj), exp, sizeof(T)) == 0) <font color="#C80000">// if (*obj == *exp)</font> 219 { 220 std::memcpy(const_cast<T*>(obj), &desr, sizeof(T)); <font color="#C80000">// *obj = desr;</font> 221 return true; 222 } 223 std::memcpy(exp, const_cast<T*>(obj), sizeof(T)); <font color="#C80000">// *exp = *obj;</font> 224 return false; 225 } 226 227 template <class T> 228 T 229 __atomic_fetch_add(T volatile* obj, T operand) 230 { 231 unique_lock<mutex> _(some_mutex); 232 T r = *obj; 233 *obj += operand; 234 return r; 235 } 236 237 template <class T> 238 T 239 __atomic_fetch_sub(T volatile* obj, T operand) 240 { 241 unique_lock<mutex> _(some_mutex); 242 T r = *obj; 243 *obj -= operand; 244 return r; 245 } 246 247 template <class T> 248 T 249 __atomic_fetch_and(T volatile* obj, T operand) 250 { 251 unique_lock<mutex> _(some_mutex); 252 T r = *obj; 253 *obj &= operand; 254 return r; 255 } 256 257 template <class T> 258 T 259 __atomic_fetch_or(T volatile* obj, T operand) 260 { 261 unique_lock<mutex> _(some_mutex); 262 T r = *obj; 263 *obj |= operand; 264 return r; 265 } 266 267 template <class T> 268 T 269 __atomic_fetch_xor(T volatile* obj, T operand) 270 { 271 unique_lock<mutex> _(some_mutex); 272 T r = *obj; 273 *obj ^= operand; 274 return r; 275 } 276 277 void* 278 __atomic_fetch_add(void* volatile* obj, ptrdiff_t operand) 279 { 280 unique_lock<mutex> _(some_mutex); 281 void* r = *obj; 282 (char*&)(*obj) += operand; 283 return r; 284 } 285 286 void* 287 __atomic_fetch_sub(void* volatile* obj, ptrdiff_t operand) 288 { 289 unique_lock<mutex> _(some_mutex); 290 void* r = *obj; 291 (char*&)(*obj) -= operand; 292 return r; 293 } 294 295 void __atomic_thread_fence() 296 { 297 unique_lock<mutex> _(some_mutex); 298 } 299 300 void __atomic_signal_fence() 301 { 302 unique_lock<mutex> _(some_mutex); 303 } 304 </pre></blockquote> 305 306 307 </div> 308 </body> 309 </html> 310