Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
atomic_gcc.h
00001 /****************************************************************************** 00002 The MIT License(MIT) 00003 00004 Embedded Template Library. 00005 https://github.com/ETLCPP/etl 00006 https://www.etlcpp.com 00007 00008 Copyright(c) 2017 jwellbelove 00009 00010 Permission is hereby granted, free of charge, to any person obtaining a copy 00011 of this software and associated documentation files(the "Software"), to deal 00012 in the Software without restriction, including without limitation the rights 00013 to use, copy, modify, merge, publish, distribute, sublicense, and / or sell 00014 copies of the Software, and to permit persons to whom the Software is 00015 furnished to do so, subject to the following conditions : 00016 00017 The above copyright notice and this permission notice shall be included in all 00018 copies or substantial portions of the Software. 00019 00020 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00021 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00022 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE 00023 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00024 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00025 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 00026 SOFTWARE. 00027 ******************************************************************************/ 00028 00029 #ifndef __ETL_ATOMIC_GCC__ 00030 #define __ETL_ATOMIC_GCC__ 00031 00032 #include "../platform.h" 00033 #include "../type_traits.h" 00034 #include "../char_traits.h" 00035 #include "../static_assert.h" 00036 #include "../nullptr.h" 00037 00038 #include <stdint.h> 00039 00040 namespace etl 00041 { 00042 //*************************************************************************** 00043 // Atomic type for pre C++11 GCC compilers that support the builtin 'fetch' functions. 00044 // Only integral and pointer types are supported. 00045 //*************************************************************************** 00046 template <typename T> 00047 class atomic 00048 { 00049 public: 00050 00051 STATIC_ASSERT(etl::is_integral<T>::value, "Only integral types are supported"); 00052 00053 atomic() 00054 : value(0) 00055 { 00056 } 00057 00058 atomic(T v) 00059 : value(v) 00060 { 00061 } 00062 00063 // Assignment 00064 T operator =(T v) 00065 { 00066 __sync_lock_test_and_set(&value, v); 00067 00068 return v; 00069 } 00070 00071 T operator =(T v) volatile 00072 { 00073 __sync_lock_test_and_set(&value, v); 00074 00075 return v; 00076 } 00077 00078 // Pre-increment 00079 T operator ++() 00080 { 00081 return fetch_add(1) + 1; 00082 } 00083 00084 T operator ++() volatile 00085 { 00086 return fetch_add(1) + 1; 00087 } 00088 00089 // Post-increment 00090 T operator ++(int) 00091 { 00092 return fetch_add(1); 00093 } 00094 00095 T operator ++(int) volatile 00096 { 00097 return fetch_add(1); 00098 } 00099 00100 // Pre-decrement 00101 T operator --() 00102 { 00103 return fetch_sub(1) + 1; 00104 } 00105 00106 T operator --() volatile 00107 { 00108 return fetch_sub(1) + 1; 00109 } 00110 00111 // Post-decrement 00112 T operator --(int) 00113 { 00114 return fetch_sub(1); 00115 } 00116 00117 T operator --(int) volatile 00118 { 00119 return fetch_sub(1); 00120 } 00121 00122 // Add 00123 T operator +=(T v) 00124 { 00125 return fetch_add(v) + v; 00126 } 00127 00128 T operator +=(T v) volatile 00129 { 00130 return fetch_add(v) + v; 00131 } 00132 00133 // Subtract 00134 T operator -=(T v) 00135 { 00136 return fetch_sub(v) - v; 00137 } 00138 00139 T operator -=(T v) volatile 00140 { 00141 return fetch_sub(v) - v; 00142 } 00143 00144 // And 00145 T operator &=(T v) 00146 { 00147 return fetch_and(v) & v; 00148 } 00149 00150 T operator &=(T v) volatile 00151 { 00152 return fetch_and(v) & v; 00153 } 00154 00155 // Or 00156 T operator |=(T v) 00157 { 00158 return fetch_or(v) | v; 00159 } 00160 00161 T operator |=(T v) volatile 00162 { 00163 return fetch_or(v) | v; 00164 } 00165 00166 // Exclusive or 00167 T operator ^=(T v) 00168 { 00169 return fetch_xor(v) ^ v; 00170 } 00171 00172 T operator ^=(T v) volatile 00173 { 00174 return fetch_xor(v) ^ v; 00175 } 00176 00177 // Conversion operator 00178 operator T () const 00179 { 00180 return __sync_fetch_and_add(const_cast<T*>(&value), 0); 00181 } 00182 00183 operator T() volatile const 00184 { 00185 return __sync_fetch_and_add(const_cast<T*>(&value), 0); 00186 } 00187 00188 // Is lock free? 00189 bool is_lock_free() const 00190 { 00191 return true; 00192 } 00193 00194 bool is_lock_free() const volatile 00195 { 00196 return true; 00197 } 00198 00199 // Store 00200 void store(T v) 00201 { 00202 __sync_lock_test_and_set(&value, v); 00203 } 00204 00205 void store(T v) volatile 00206 { 00207 __sync_lock_test_and_set(&value, v); 00208 } 00209 00210 // Load 00211 T load() 00212 { 00213 return __sync_fetch_and_add(&value, 0); 00214 } 00215 00216 T load() volatile 00217 { 00218 return __sync_fetch_and_add(&value, 0); 00219 } 00220 00221 // Fetch add 00222 T fetch_add(T v) 00223 { 00224 return __sync_fetch_and_add(&value, v); 00225 } 00226 00227 T fetch_add(T v) volatile 00228 { 00229 return __sync_fetch_and_add(&value, v); 00230 } 00231 00232 // Fetch subtract 00233 T fetch_sub(T v) 00234 { 00235 return __sync_fetch_and_sub(&value, v); 00236 } 00237 00238 T fetch_sub(T v) volatile 00239 { 00240 return __sync_fetch_and_sub(&value, v); 00241 } 00242 00243 // Fetch or 00244 T fetch_or(T v) 00245 { 00246 return __sync_fetch_and_or(&value, v); 00247 } 00248 00249 T fetch_or(T v) volatile 00250 { 00251 return __sync_fetch_and_or(&value, v); 00252 } 00253 00254 // Fetch and 00255 T fetch_and(T v) 00256 { 00257 return __sync_fetch_and_and(&value, v); 00258 } 00259 00260 T fetch_and(T v) volatile 00261 { 00262 return __sync_fetch_and_and(&value, v); 00263 } 00264 00265 // Fetch exclusive or 00266 T fetch_xor(T v) 00267 { 00268 return __sync_fetch_and_xor(&value, v); 00269 } 00270 00271 T fetch_xor(T v) volatile 00272 { 00273 return __sync_fetch_and_xor(&value, v); 00274 } 00275 00276 // Exchange 00277 T exchange(T v) 00278 { 00279 return __sync_lock_test_and_set(&value, v); 00280 } 00281 00282 T exchange(T v) volatile 00283 { 00284 return __sync_lock_test_and_set(&value, v); 00285 } 00286 00287 // Compare exchange weak 00288 bool compare_exchange_weak(T& expected, T desired) 00289 { 00290 T old = __sync_val_compare_and_swap(&value, expected, desired); 00291 00292 if (old == expected) 00293 { 00294 return true; 00295 } 00296 else 00297 { 00298 expected = old; 00299 return false; 00300 } 00301 } 00302 00303 bool compare_exchange_weak(T& expected, T desired) volatile 00304 { 00305 T old = __sync_val_compare_and_swap(&value, expected, desired); 00306 00307 if (old == expected) 00308 { 00309 return true; 00310 } 00311 else 00312 { 00313 expected = old; 00314 return false; 00315 } 00316 } 00317 00318 // Compare exchange strong 00319 bool compare_exchange_strong(T& expected, T desired) 00320 { 00321 T old = expected; 00322 00323 while (!compare_exchange_weak(old, desired)) 00324 { 00325 if (memcmp(&old, &expected, sizeof(T))) 00326 { 00327 expected = old; 00328 return false; 00329 } 00330 } 00331 00332 return true; 00333 } 00334 00335 bool compare_exchange_strong(T& expected, T desired) volatile 00336 { 00337 T old = expected; 00338 00339 while (!compare_exchange_weak(old, desired)) 00340 { 00341 if (memcmp(&old, &expected, sizeof(T))) 00342 { 00343 expected = old; 00344 return false; 00345 } 00346 } 00347 00348 return true; 00349 } 00350 00351 private: 00352 00353 atomic& operator =(const atomic&); 00354 atomic& operator =(const atomic&) volatile; 00355 00356 T value; 00357 }; 00358 00359 //*************************************************************************** 00360 // Specialisation for pointers. 00361 //*************************************************************************** 00362 template <typename T> 00363 class atomic<T*> 00364 { 00365 public: 00366 00367 atomic() 00368 : value(std::nullptr) 00369 { 00370 } 00371 00372 atomic(T v) 00373 : value(v) 00374 { 00375 } 00376 00377 // Assignment 00378 T operator =(T* v) 00379 { 00380 __sync_lock_test_and_set(&value, v); 00381 00382 return v; 00383 } 00384 00385 T operator =(T* v) volatile 00386 { 00387 __sync_lock_test_and_set(&value, v); 00388 00389 return v; 00390 } 00391 00392 // Pre-increment 00393 T operator ++() 00394 { 00395 return fetch_add(1) + 1; 00396 } 00397 00398 T operator ++() volatile 00399 { 00400 return fetch_add(1) + 1; 00401 } 00402 00403 // Post-increment 00404 T operator ++(int) 00405 { 00406 return fetch_add(1); 00407 } 00408 00409 T operator ++(int) volatile 00410 { 00411 return fetch_add(1); 00412 } 00413 00414 // Pre-decrement 00415 T operator --() 00416 { 00417 return fetch_sub(1) + 1; 00418 } 00419 00420 T operator --() volatile 00421 { 00422 return fetch_sub(1) + 1; 00423 } 00424 00425 // Post-decrement 00426 T operator --(int) 00427 { 00428 return fetch_sub(1); 00429 } 00430 00431 T operator --(int) volatile 00432 { 00433 return fetch_sub(1); 00434 } 00435 00436 // Add 00437 T* operator +=(std::ptrdiff_t v) 00438 { 00439 return fetch_add(v) + v; 00440 } 00441 00442 T* operator +=(std::ptrdiff_t v) volatile 00443 { 00444 return fetch_add(v) + v; 00445 } 00446 00447 // Subtract 00448 T* operator -=(std::ptrdiff_t v) 00449 { 00450 return fetch_sub(v) - v; 00451 } 00452 00453 T* operator -=(std::ptrdiff_t v) volatile 00454 { 00455 return fetch_sub(v) - v; 00456 } 00457 00458 // Conversion operator 00459 operator T () const 00460 { 00461 return __sync_fetch_and_add(const_cast<T**>(&value), 0); 00462 } 00463 00464 operator T() volatile const 00465 { 00466 return __sync_fetch_and_add(const_cast<T**>(&value), 0); 00467 } 00468 00469 // Is lock free? 00470 bool is_lock_free() const 00471 { 00472 return true; 00473 } 00474 00475 bool is_lock_free() const volatile 00476 { 00477 return true; 00478 } 00479 00480 // Store 00481 void store(T v) 00482 { 00483 __sync_lock_test_and_set(&value, v); 00484 } 00485 00486 void store(T v) volatile 00487 { 00488 __sync_lock_test_and_set(&value, v); 00489 } 00490 00491 // Load 00492 T load() 00493 { 00494 return __sync_fetch_and_add(&value, 0); 00495 } 00496 00497 T load() volatile 00498 { 00499 return __sync_fetch_and_add(&value, 0); 00500 } 00501 00502 // Fetch add 00503 T* fetch_add(std::ptrdiff_t v) 00504 { 00505 return __sync_fetch_and_add(&value, v); 00506 } 00507 00508 T* fetch_add(std::ptrdiff_t v) volatile 00509 { 00510 return __sync_fetch_and_add(&value, v); 00511 } 00512 00513 // Fetch subtract 00514 T* fetch_sub(std::ptrdiff_t v) 00515 { 00516 return __sync_fetch_and_sub(&value, v); 00517 } 00518 00519 T* fetch_sub(std::ptrdiff_t v) volatile 00520 { 00521 return __sync_fetch_and_sub(&value, v); 00522 } 00523 00524 // Exchange 00525 T exchange(T v) 00526 { 00527 return __sync_lock_test_and_set(&value, v); 00528 } 00529 00530 T exchange(T v) volatile 00531 { 00532 return __sync_lock_test_and_set(&value, v); 00533 } 00534 00535 // Compare exchange weak 00536 bool compare_exchange_weak(T& expected, T desired) 00537 { 00538 return __sync_bool_compare_and_swap(&value, expected, desired); 00539 } 00540 00541 bool compare_exchange_weak(T& expected, T desired) volatile 00542 { 00543 return __sync_bool_compare_and_swap(&value, expected, desired); 00544 } 00545 00546 // Compare exchange strong 00547 bool compare_exchange_strong(T& expected, T desired) 00548 { 00549 T old = expected; 00550 00551 while (!compare_exchange_weak(old, desired)) 00552 { 00553 if (memcmp(&old, &expected, sizeof(T))) 00554 { 00555 expected = old; 00556 return false; 00557 } 00558 } 00559 00560 return true; 00561 } 00562 00563 bool compare_exchange_strong(T& expected, T desired) volatile 00564 { 00565 T old = expected; 00566 00567 while (!compare_exchange_weak(old, desired)) 00568 { 00569 if (memcmp(&old, &expected, sizeof(T))) 00570 { 00571 expected = old; 00572 return false; 00573 } 00574 } 00575 00576 return true; 00577 } 00578 00579 private: 00580 00581 atomic& operator =(const atomic&); 00582 atomic& operator =(const atomic&) volatile; 00583 00584 T* value; 00585 }; 00586 00587 typedef etl::atomic<char> atomic_char; 00588 typedef etl::atomic<signed char> atomic_schar; 00589 typedef etl::atomic<unsigned char> atomic_uchar; 00590 typedef etl::atomic<short> atomic_short; 00591 typedef etl::atomic<unsigned short> atomic_ushort; 00592 typedef etl::atomic<int> atomic_int; 00593 typedef etl::atomic<unsigned int> atomic_uint; 00594 typedef etl::atomic<long> atomic_long; 00595 typedef etl::atomic<unsigned long> atomic_ulong; 00596 typedef etl::atomic<long long> atomic_llong; 00597 typedef etl::atomic<unsigned long long> atomic_ullong; 00598 typedef etl::atomic<wchar_t> atomic_wchar_t; 00599 typedef etl::atomic<char16_t> atomic_char16_t; 00600 typedef etl::atomic<char32_t> atomic_char32_t; 00601 typedef etl::atomic<uint8_t> atomic_uint8_t; 00602 typedef etl::atomic<int8_t> atomic_int8_t; 00603 typedef etl::atomic<uint16_t> atomic_uint16_t; 00604 typedef etl::atomic<int16_t> atomic_int16_t; 00605 typedef etl::atomic<uint32_t> atomic_uint32_t; 00606 typedef etl::atomic<int32_t> atomic_int32_t; 00607 typedef etl::atomic<uint64_t> atomic_uint64_t; 00608 typedef etl::atomic<int64_t> atomic_int64_t; 00609 typedef etl::atomic<int_least8_t> atomic_int_least8_t; 00610 typedef etl::atomic<uint_least8_t> atomic_uint_least8_t; 00611 typedef etl::atomic<int_least16_t> atomic_int_least16_t; 00612 typedef etl::atomic<uint_least16_t> atomic_uint_least16_t; 00613 typedef etl::atomic<int_least32_t> atomic_int_least32_t; 00614 typedef etl::atomic<uint_least32_t> atomic_uint_least32_t; 00615 typedef etl::atomic<int_least64_t> atomic_int_least64_t; 00616 typedef etl::atomic<uint_least64_t> atomic_uint_least64_t; 00617 typedef etl::atomic<int_fast8_t> atomic_int_fast8_t; 00618 typedef etl::atomic<uint_fast8_t> atomic_uint_fast8_t; 00619 typedef etl::atomic<int_fast16_t> atomic_int_fast16_t; 00620 typedef etl::atomic<uint_fast16_t> atomic_uint_fast16_t; 00621 typedef etl::atomic<int_fast32_t> atomic_int_fast32_t; 00622 typedef etl::atomic<uint_fast32_t> atomic_uint_fast32_t; 00623 typedef etl::atomic<int_fast64_t> atomic_int_fast64_t; 00624 typedef etl::atomic<uint_fast64_t> atomic_uint_fast64_t; 00625 typedef etl::atomic<intptr_t> atomic_intptr_t; 00626 typedef etl::atomic<uintptr_t> atomic_uintptr_t; 00627 typedef etl::atomic<size_t> atomic_size_t; 00628 typedef etl::atomic<ptrdiff_t> atomic_ptrdiff_t; 00629 typedef etl::atomic<intmax_t> atomic_intmax_t; 00630 typedef etl::atomic<uintmax_t> atomic_uintmax_t; 00631 } 00632 00633 #endif 00634
Generated on Tue Jul 12 2022 14:05:39 by
