Home | History | Annotate | Download | only in www
      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>
     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 &lt;= 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 &lt;= 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 &lt;class T&gt;
    173 T
    174 __atomic_load(T const volatile* obj)
    175 {
    176     unique_lock&lt;mutex&gt; _(some_mutex);
    177     return *obj;
    178 }
    179 
    180 template &lt;class T&gt;
    181 void
    182 __atomic_store(T volatile* obj, T desr)
    183 {
    184     unique_lock&lt;mutex&gt; _(some_mutex);
    185     *obj = desr;
    186 }
    187 
    188 template &lt;class T&gt;
    189 T
    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 
    198 template &lt;class T&gt;
    199 bool
    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>
    213 template &lt;class T&gt;
    214 bool
    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 
    227 template &lt;class T&gt;
    228 T
    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 
    237 template &lt;class T&gt;
    238 T
    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 
    247 template &lt;class T&gt;
    248 T
    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 
    257 template &lt;class T&gt;
    258 T
    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 
    267 template &lt;class T&gt;
    268 T
    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 
    277 void*
    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 
    286 void*
    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 
    295 void __atomic_thread_fence()
    296 {
    297     unique_lock&lt;mutex&gt; _(some_mutex);
    298 }
    299 
    300 void __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