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> 39The compiler supplies all of the intrinsics as described below. This list of 40intrinsics roughly parallels the requirements of the C and C++ atomics 41proposals. The C and C++ library implementations simply drop through to these 42intrinsics. Anything the platform does not support in hardware, the compiler 43arranges for a (compiler-rt) library call to be made which will do the job with 44a mutex, and in this case ignoring the memory ordering parameter (effectively 45implementing <tt>memory_order_seq_cst</tt>). 46</p> 47 48<p> 49Ultimate efficiency is preferred over run time error checking. Undefined 50behavior 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> 66bool __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> 70type __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> 74void __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> 78type __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> 85bool __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> 94bool __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> 102type __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> 108type __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> 114type __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> 120type __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> 126type __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> 129void* __atomic_fetch_add(void** atomic_obj, ptrdiff_t operand, int mem_ord); 130void* __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> 133void __atomic_thread_fence(int mem_ord); 134void __atomic_signal_fence(int mem_ord); 135</pre></blockquote> 136 137<p> 138If desired the intrinsics taking a single <tt>mem_ord</tt> parameter can default 139this argument to 5. 140</p> 141 142<p> 143If 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> 150int 151translate_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> 165Below are representative C++ implementations of all of the operations. Their 166purpose 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 168if the front end calls out to compiler-rt. 169</p> 170 171<blockquote><pre> 172template <class T> 173T 174__atomic_load(T const volatile* obj) 175{ 176 unique_lock<mutex> _(some_mutex); 177 return *obj; 178} 179 180template <class T> 181void 182__atomic_store(T volatile* obj, T desr) 183{ 184 unique_lock<mutex> _(some_mutex); 185 *obj = desr; 186} 187 188template <class T> 189T 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 198template <class T> 199bool 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> 213template <class T> 214bool 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 227template <class T> 228T 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 237template <class T> 238T 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 247template <class T> 248T 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 257template <class T> 258T 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 267template <class T> 268T 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 277void* 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 286void* 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 295void __atomic_thread_fence() 296{ 297 unique_lock<mutex> _(some_mutex); 298} 299 300void __atomic_signal_fence() 301{ 302 unique_lock<mutex> _(some_mutex); 303} 304</pre></blockquote> 305 306 307</div> 308</body> 309</html> 310