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>&lt;atomic&gt; 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>&lt;atomic&gt; 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 &lt;= 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 &lt;= 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 &lt;class T&gt;
173T
174__atomic_load(T const volatile* obj)
175{
176    unique_lock&lt;mutex&gt; _(some_mutex);
177    return *obj;
178}
179
180template &lt;class T&gt;
181void
182__atomic_store(T volatile* obj, T desr)
183{
184    unique_lock&lt;mutex&gt; _(some_mutex);
185    *obj = desr;
186}
187
188template &lt;class T&gt;
189T
190__atomic_exchange(T volatile* obj, T desr)
191{
192    unique_lock&lt;mutex&gt; _(some_mutex);
193    T r = *obj;
194    *obj = desr;
195    return r;
196}
197
198template &lt;class T&gt;
199bool
200__atomic_compare_exchange_strong(T volatile* obj, T* exp, T desr)
201{
202    unique_lock&lt;mutex&gt; _(some_mutex);
203    if (std::memcmp(const_cast&lt;T*&gt;(obj), exp, sizeof(T)) == 0) <font color="#C80000">// if (*obj == *exp)</font>
204    {
205        std::memcpy(const_cast&lt;T*&gt;(obj), &amp;desr, sizeof(T)); <font color="#C80000">// *obj = desr;</font>
206        return true;
207    }
208    std::memcpy(exp, const_cast&lt;T*&gt;(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 &lt;class T&gt;
214bool
215__atomic_compare_exchange_weak(T volatile* obj, T* exp, T desr)
216{
217    unique_lock&lt;mutex&gt; _(some_mutex);
218    if (std::memcmp(const_cast&lt;T*&gt;(obj), exp, sizeof(T)) == 0) <font color="#C80000">// if (*obj == *exp)</font>
219    {
220        std::memcpy(const_cast&lt;T*&gt;(obj), &amp;desr, sizeof(T)); <font color="#C80000">// *obj = desr;</font>
221        return true;
222    }
223    std::memcpy(exp, const_cast&lt;T*&gt;(obj), sizeof(T)); <font color="#C80000">// *exp = *obj;</font>
224    return false;
225}
226
227template &lt;class T&gt;
228T
229__atomic_fetch_add(T volatile* obj, T operand)
230{
231    unique_lock&lt;mutex&gt; _(some_mutex);
232    T r = *obj;
233    *obj += operand;
234    return r;
235}
236
237template &lt;class T&gt;
238T
239__atomic_fetch_sub(T volatile* obj, T operand)
240{
241    unique_lock&lt;mutex&gt; _(some_mutex);
242    T r = *obj;
243    *obj -= operand;
244    return r;
245}
246
247template &lt;class T&gt;
248T
249__atomic_fetch_and(T volatile* obj, T operand)
250{
251    unique_lock&lt;mutex&gt; _(some_mutex);
252    T r = *obj;
253    *obj &amp;= operand;
254    return r;
255}
256
257template &lt;class T&gt;
258T
259__atomic_fetch_or(T volatile* obj, T operand)
260{
261    unique_lock&lt;mutex&gt; _(some_mutex);
262    T r = *obj;
263    *obj |= operand;
264    return r;
265}
266
267template &lt;class T&gt;
268T
269__atomic_fetch_xor(T volatile* obj, T operand)
270{
271    unique_lock&lt;mutex&gt; _(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&lt;mutex&gt; _(some_mutex);
281    void* r = *obj;
282    (char*&amp;)(*obj) += operand;
283    return r;
284}
285
286void*
287__atomic_fetch_sub(void* volatile* obj, ptrdiff_t operand)
288{
289    unique_lock&lt;mutex&gt; _(some_mutex);
290    void* r = *obj;
291    (char*&amp;)(*obj) -= operand;
292    return r;
293}
294
295void __atomic_thread_fence()
296{
297    unique_lock&lt;mutex&gt; _(some_mutex);
298}
299
300void __atomic_signal_fence()
301{
302    unique_lock&lt;mutex&gt; _(some_mutex);
303}
304</pre></blockquote>
305
306
307</div>
308</body>
309</html>
310