14fee23f9Smrg // -*- C++ -*- 24fee23f9Smrg 3*b1e83836Smrg // Copyright (C) 2007-2022 Free Software Foundation, Inc. 44fee23f9Smrg // 54fee23f9Smrg // This file is part of the GNU ISO C++ Library. This library is free 64fee23f9Smrg // software; you can redistribute it and/or modify it under the terms 74fee23f9Smrg // of the GNU General Public License as published by the Free Software 84fee23f9Smrg // Foundation; either version 3, or (at your option) any later 94fee23f9Smrg // version. 104fee23f9Smrg 114fee23f9Smrg // This library is distributed in the hope that it will be useful, but 124fee23f9Smrg // WITHOUT ANY WARRANTY; without even the implied warranty of 134fee23f9Smrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 144fee23f9Smrg // General Public License for more details. 154fee23f9Smrg 164fee23f9Smrg // Under Section 7 of GPL version 3, you are granted additional 174fee23f9Smrg // permissions described in the GCC Runtime Library Exception, version 184fee23f9Smrg // 3.1, as published by the Free Software Foundation. 194fee23f9Smrg 204fee23f9Smrg // You should have received a copy of the GNU General Public License and 214fee23f9Smrg // a copy of the GCC Runtime Library Exception along with this program; 224fee23f9Smrg // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 234fee23f9Smrg // <http://www.gnu.org/licenses/>. 244fee23f9Smrg 254fee23f9Smrg /** @file parallel/compatibility.h 264fee23f9Smrg * @brief Compatibility layer, mostly concerned with atomic operations. 2748fb7bfaSmrg * 2848fb7bfaSmrg * This file is a GNU parallel extension to the Standard C++ Library 2948fb7bfaSmrg * and contains implementation details for the library's internal use. 304fee23f9Smrg */ 314fee23f9Smrg 324fee23f9Smrg // Written by Felix Putze. 334fee23f9Smrg 344fee23f9Smrg #ifndef _GLIBCXX_PARALLEL_COMPATIBILITY_H 354fee23f9Smrg #define _GLIBCXX_PARALLEL_COMPATIBILITY_H 1 364fee23f9Smrg 374fee23f9Smrg #include <parallel/types.h> 384fee23f9Smrg #include <parallel/base.h> 394fee23f9Smrg 404fee23f9Smrg #if !defined(_WIN32) || defined (__CYGWIN__) 414fee23f9Smrg #include <sched.h> 424fee23f9Smrg #endif 434fee23f9Smrg 444fee23f9Smrg #ifdef __MINGW32__ 454fee23f9Smrg // Including <windows.h> will drag in all the windows32 names. Since 464fee23f9Smrg // that can cause user code portability problems, we just declare the 474fee23f9Smrg // one needed function here. 484fee23f9Smrg extern "C" 494fee23f9Smrg __attribute((dllimport)) void __attribute__((stdcall)) Sleep (unsigned long); 504fee23f9Smrg #endif 514fee23f9Smrg 524fee23f9Smrg namespace __gnu_parallel 534fee23f9Smrg { 5448fb7bfaSmrg template<typename _Tp> 5548fb7bfaSmrg inline _Tp __add_omp(volatile _Tp * __ptr,_Tp __addend)5648fb7bfaSmrg __add_omp(volatile _Tp* __ptr, _Tp __addend) 574fee23f9Smrg { 584fee23f9Smrg int64_t __res; 594fee23f9Smrg #pragma omp critical 604fee23f9Smrg { 614fee23f9Smrg __res = *__ptr; 624fee23f9Smrg *(__ptr) += __addend; 634fee23f9Smrg } 644fee23f9Smrg return __res; 654fee23f9Smrg } 664fee23f9Smrg 674fee23f9Smrg /** @brief Add a value to a variable, atomically. 684fee23f9Smrg * 694fee23f9Smrg * @param __ptr Pointer to a signed integer. 704fee23f9Smrg * @param __addend Value to add. 714fee23f9Smrg */ 724fee23f9Smrg template<typename _Tp> 734fee23f9Smrg inline _Tp __fetch_and_add(volatile _Tp * __ptr,_Tp __addend)744fee23f9Smrg __fetch_and_add(volatile _Tp* __ptr, _Tp __addend) 754fee23f9Smrg { 7648fb7bfaSmrg if (__atomic_always_lock_free(sizeof(_Tp), __ptr)) 7748fb7bfaSmrg return __atomic_fetch_add(__ptr, __addend, __ATOMIC_ACQ_REL); 7848fb7bfaSmrg return __add_omp(__ptr, __addend); 794fee23f9Smrg } 804fee23f9Smrg 8148fb7bfaSmrg template<typename _Tp> 824fee23f9Smrg inline bool __cas_omp(volatile _Tp * __ptr,_Tp __comparand,_Tp __replacement)8348fb7bfaSmrg __cas_omp(volatile _Tp* __ptr, _Tp __comparand, _Tp __replacement) 844fee23f9Smrg { 854fee23f9Smrg bool __res = false; 864fee23f9Smrg #pragma omp critical 874fee23f9Smrg { 884fee23f9Smrg if (*__ptr == __comparand) 894fee23f9Smrg { 904fee23f9Smrg *__ptr = __replacement; 914fee23f9Smrg __res = true; 924fee23f9Smrg } 934fee23f9Smrg } 944fee23f9Smrg return __res; 954fee23f9Smrg } 964fee23f9Smrg 9748fb7bfaSmrg /** @brief Compare-and-swap 9848fb7bfaSmrg * 9948fb7bfaSmrg * Compare @c *__ptr and @c __comparand. If equal, let @c 1004fee23f9Smrg * *__ptr=__replacement and return @c true, return @c false otherwise. 1014fee23f9Smrg * 1024fee23f9Smrg * @param __ptr Pointer to signed integer. 1034fee23f9Smrg * @param __comparand Compare value. 10448fb7bfaSmrg * @param __replacement Replacement value. 10548fb7bfaSmrg */ 1064fee23f9Smrg template<typename _Tp> 1074fee23f9Smrg inline bool __compare_and_swap(volatile _Tp * __ptr,_Tp __comparand,_Tp __replacement)1084fee23f9Smrg __compare_and_swap(volatile _Tp* __ptr, _Tp __comparand, _Tp __replacement) 1094fee23f9Smrg { 11048fb7bfaSmrg if (__atomic_always_lock_free(sizeof(_Tp), __ptr)) 11148fb7bfaSmrg return __atomic_compare_exchange_n(__ptr, &__comparand, __replacement, 11248fb7bfaSmrg false, __ATOMIC_ACQ_REL, 11348fb7bfaSmrg __ATOMIC_RELAXED); 11448fb7bfaSmrg return __cas_omp(__ptr, __comparand, __replacement); 1154fee23f9Smrg } 1164fee23f9Smrg 11748fb7bfaSmrg /** @brief Yield control to another thread, without waiting for 11848fb7bfaSmrg * the end of the time slice. 11948fb7bfaSmrg */ 1204fee23f9Smrg inline void __yield()1214fee23f9Smrg __yield() 1224fee23f9Smrg { 1234fee23f9Smrg #if defined (_WIN32) && !defined (__CYGWIN__) 1244fee23f9Smrg Sleep(0); 1254fee23f9Smrg #else 1264fee23f9Smrg sched_yield(); 1274fee23f9Smrg #endif 1284fee23f9Smrg } 1294fee23f9Smrg } // end namespace 1304fee23f9Smrg 1314fee23f9Smrg #endif /* _GLIBCXX_PARALLEL_COMPATIBILITY_H */ 132