136ac495dSmrg // -*- C++ -*- 236ac495dSmrg 3*8feb0f0bSmrg // Copyright (C) 2007-2020 Free Software Foundation, Inc. 436ac495dSmrg // 536ac495dSmrg // This file is part of the GNU ISO C++ Library. This library is free 636ac495dSmrg // software; you can redistribute it and/or modify it under the terms 736ac495dSmrg // of the GNU General Public License as published by the Free Software 836ac495dSmrg // Foundation; either version 3, or (at your option) any later 936ac495dSmrg // version. 1036ac495dSmrg 1136ac495dSmrg // This library is distributed in the hope that it will be useful, but 1236ac495dSmrg // WITHOUT ANY WARRANTY; without even the implied warranty of 1336ac495dSmrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1436ac495dSmrg // General Public License for more details. 1536ac495dSmrg 1636ac495dSmrg // Under Section 7 of GPL version 3, you are granted additional 1736ac495dSmrg // permissions described in the GCC Runtime Library Exception, version 1836ac495dSmrg // 3.1, as published by the Free Software Foundation. 1936ac495dSmrg 2036ac495dSmrg // You should have received a copy of the GNU General Public License and 2136ac495dSmrg // a copy of the GCC Runtime Library Exception along with this program; 2236ac495dSmrg // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 2336ac495dSmrg // <http://www.gnu.org/licenses/>. 2436ac495dSmrg 2536ac495dSmrg /** @file parallel/compatibility.h 2636ac495dSmrg * @brief Compatibility layer, mostly concerned with atomic operations. 2736ac495dSmrg * 2836ac495dSmrg * This file is a GNU parallel extension to the Standard C++ Library 2936ac495dSmrg * and contains implementation details for the library's internal use. 3036ac495dSmrg */ 3136ac495dSmrg 3236ac495dSmrg // Written by Felix Putze. 3336ac495dSmrg 3436ac495dSmrg #ifndef _GLIBCXX_PARALLEL_COMPATIBILITY_H 3536ac495dSmrg #define _GLIBCXX_PARALLEL_COMPATIBILITY_H 1 3636ac495dSmrg 3736ac495dSmrg #include <parallel/types.h> 3836ac495dSmrg #include <parallel/base.h> 3936ac495dSmrg 4036ac495dSmrg #if !defined(_WIN32) || defined (__CYGWIN__) 4136ac495dSmrg #include <sched.h> 4236ac495dSmrg #endif 4336ac495dSmrg 4436ac495dSmrg #ifdef __MINGW32__ 4536ac495dSmrg // Including <windows.h> will drag in all the windows32 names. Since 4636ac495dSmrg // that can cause user code portability problems, we just declare the 4736ac495dSmrg // one needed function here. 4836ac495dSmrg extern "C" 4936ac495dSmrg __attribute((dllimport)) void __attribute__((stdcall)) Sleep (unsigned long); 5036ac495dSmrg #endif 5136ac495dSmrg 5236ac495dSmrg namespace __gnu_parallel 5336ac495dSmrg { 5436ac495dSmrg template<typename _Tp> 5536ac495dSmrg inline _Tp __add_omp(volatile _Tp * __ptr,_Tp __addend)5636ac495dSmrg __add_omp(volatile _Tp* __ptr, _Tp __addend) 5736ac495dSmrg { 5836ac495dSmrg int64_t __res; 5936ac495dSmrg #pragma omp critical 6036ac495dSmrg { 6136ac495dSmrg __res = *__ptr; 6236ac495dSmrg *(__ptr) += __addend; 6336ac495dSmrg } 6436ac495dSmrg return __res; 6536ac495dSmrg } 6636ac495dSmrg 6736ac495dSmrg /** @brief Add a value to a variable, atomically. 6836ac495dSmrg * 6936ac495dSmrg * @param __ptr Pointer to a signed integer. 7036ac495dSmrg * @param __addend Value to add. 7136ac495dSmrg */ 7236ac495dSmrg template<typename _Tp> 7336ac495dSmrg inline _Tp __fetch_and_add(volatile _Tp * __ptr,_Tp __addend)7436ac495dSmrg __fetch_and_add(volatile _Tp* __ptr, _Tp __addend) 7536ac495dSmrg { 7636ac495dSmrg if (__atomic_always_lock_free(sizeof(_Tp), __ptr)) 7736ac495dSmrg return __atomic_fetch_add(__ptr, __addend, __ATOMIC_ACQ_REL); 7836ac495dSmrg return __add_omp(__ptr, __addend); 7936ac495dSmrg } 8036ac495dSmrg 8136ac495dSmrg template<typename _Tp> 8236ac495dSmrg inline bool __cas_omp(volatile _Tp * __ptr,_Tp __comparand,_Tp __replacement)8336ac495dSmrg __cas_omp(volatile _Tp* __ptr, _Tp __comparand, _Tp __replacement) 8436ac495dSmrg { 8536ac495dSmrg bool __res = false; 8636ac495dSmrg #pragma omp critical 8736ac495dSmrg { 8836ac495dSmrg if (*__ptr == __comparand) 8936ac495dSmrg { 9036ac495dSmrg *__ptr = __replacement; 9136ac495dSmrg __res = true; 9236ac495dSmrg } 9336ac495dSmrg } 9436ac495dSmrg return __res; 9536ac495dSmrg } 9636ac495dSmrg 9736ac495dSmrg /** @brief Compare-and-swap 9836ac495dSmrg * 9936ac495dSmrg * Compare @c *__ptr and @c __comparand. If equal, let @c 10036ac495dSmrg * *__ptr=__replacement and return @c true, return @c false otherwise. 10136ac495dSmrg * 10236ac495dSmrg * @param __ptr Pointer to signed integer. 10336ac495dSmrg * @param __comparand Compare value. 10436ac495dSmrg * @param __replacement Replacement value. 10536ac495dSmrg */ 10636ac495dSmrg template<typename _Tp> 10736ac495dSmrg inline bool __compare_and_swap(volatile _Tp * __ptr,_Tp __comparand,_Tp __replacement)10836ac495dSmrg __compare_and_swap(volatile _Tp* __ptr, _Tp __comparand, _Tp __replacement) 10936ac495dSmrg { 11036ac495dSmrg if (__atomic_always_lock_free(sizeof(_Tp), __ptr)) 11136ac495dSmrg return __atomic_compare_exchange_n(__ptr, &__comparand, __replacement, 11236ac495dSmrg false, __ATOMIC_ACQ_REL, 11336ac495dSmrg __ATOMIC_RELAXED); 11436ac495dSmrg return __cas_omp(__ptr, __comparand, __replacement); 11536ac495dSmrg } 11636ac495dSmrg 11736ac495dSmrg /** @brief Yield control to another thread, without waiting for 11836ac495dSmrg * the end of the time slice. 11936ac495dSmrg */ 12036ac495dSmrg inline void __yield()12136ac495dSmrg __yield() 12236ac495dSmrg { 12336ac495dSmrg #if defined (_WIN32) && !defined (__CYGWIN__) 12436ac495dSmrg Sleep(0); 12536ac495dSmrg #else 12636ac495dSmrg sched_yield(); 12736ac495dSmrg #endif 12836ac495dSmrg } 12936ac495dSmrg } // end namespace 13036ac495dSmrg 13136ac495dSmrg #endif /* _GLIBCXX_PARALLEL_COMPATIBILITY_H */ 132