1*38fd1498Szrj // -*- C++ -*- 2*38fd1498Szrj 3*38fd1498Szrj // Copyright (C) 2007-2018 Free Software Foundation, Inc. 4*38fd1498Szrj // 5*38fd1498Szrj // This file is part of the GNU ISO C++ Library. This library is free 6*38fd1498Szrj // software; you can redistribute it and/or modify it under the terms 7*38fd1498Szrj // of the GNU General Public License as published by the Free Software 8*38fd1498Szrj // Foundation; either version 3, or (at your option) any later 9*38fd1498Szrj // version. 10*38fd1498Szrj 11*38fd1498Szrj // This library is distributed in the hope that it will be useful, but 12*38fd1498Szrj // WITHOUT ANY WARRANTY; without even the implied warranty of 13*38fd1498Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14*38fd1498Szrj // General Public License for more details. 15*38fd1498Szrj 16*38fd1498Szrj // Under Section 7 of GPL version 3, you are granted additional 17*38fd1498Szrj // permissions described in the GCC Runtime Library Exception, version 18*38fd1498Szrj // 3.1, as published by the Free Software Foundation. 19*38fd1498Szrj 20*38fd1498Szrj // You should have received a copy of the GNU General Public License and 21*38fd1498Szrj // a copy of the GCC Runtime Library Exception along with this program; 22*38fd1498Szrj // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23*38fd1498Szrj // <http://www.gnu.org/licenses/>. 24*38fd1498Szrj 25*38fd1498Szrj /** @file parallel/compatibility.h 26*38fd1498Szrj * @brief Compatibility layer, mostly concerned with atomic operations. 27*38fd1498Szrj * 28*38fd1498Szrj * This file is a GNU parallel extension to the Standard C++ Library 29*38fd1498Szrj * and contains implementation details for the library's internal use. 30*38fd1498Szrj */ 31*38fd1498Szrj 32*38fd1498Szrj // Written by Felix Putze. 33*38fd1498Szrj 34*38fd1498Szrj #ifndef _GLIBCXX_PARALLEL_COMPATIBILITY_H 35*38fd1498Szrj #define _GLIBCXX_PARALLEL_COMPATIBILITY_H 1 36*38fd1498Szrj 37*38fd1498Szrj #include <parallel/types.h> 38*38fd1498Szrj #include <parallel/base.h> 39*38fd1498Szrj 40*38fd1498Szrj #if !defined(_WIN32) || defined (__CYGWIN__) 41*38fd1498Szrj #include <sched.h> 42*38fd1498Szrj #endif 43*38fd1498Szrj 44*38fd1498Szrj #ifdef __MINGW32__ 45*38fd1498Szrj // Including <windows.h> will drag in all the windows32 names. Since 46*38fd1498Szrj // that can cause user code portability problems, we just declare the 47*38fd1498Szrj // one needed function here. 48*38fd1498Szrj extern "C" 49*38fd1498Szrj __attribute((dllimport)) void __attribute__((stdcall)) Sleep (unsigned long); 50*38fd1498Szrj #endif 51*38fd1498Szrj 52*38fd1498Szrj namespace __gnu_parallel 53*38fd1498Szrj { 54*38fd1498Szrj template<typename _Tp> 55*38fd1498Szrj inline _Tp __add_omp(volatile _Tp * __ptr,_Tp __addend)56*38fd1498Szrj __add_omp(volatile _Tp* __ptr, _Tp __addend) 57*38fd1498Szrj { 58*38fd1498Szrj int64_t __res; 59*38fd1498Szrj #pragma omp critical 60*38fd1498Szrj { 61*38fd1498Szrj __res = *__ptr; 62*38fd1498Szrj *(__ptr) += __addend; 63*38fd1498Szrj } 64*38fd1498Szrj return __res; 65*38fd1498Szrj } 66*38fd1498Szrj 67*38fd1498Szrj /** @brief Add a value to a variable, atomically. 68*38fd1498Szrj * 69*38fd1498Szrj * @param __ptr Pointer to a signed integer. 70*38fd1498Szrj * @param __addend Value to add. 71*38fd1498Szrj */ 72*38fd1498Szrj template<typename _Tp> 73*38fd1498Szrj inline _Tp __fetch_and_add(volatile _Tp * __ptr,_Tp __addend)74*38fd1498Szrj __fetch_and_add(volatile _Tp* __ptr, _Tp __addend) 75*38fd1498Szrj { 76*38fd1498Szrj if (__atomic_always_lock_free(sizeof(_Tp), __ptr)) 77*38fd1498Szrj return __atomic_fetch_add(__ptr, __addend, __ATOMIC_ACQ_REL); 78*38fd1498Szrj return __add_omp(__ptr, __addend); 79*38fd1498Szrj } 80*38fd1498Szrj 81*38fd1498Szrj template<typename _Tp> 82*38fd1498Szrj inline bool __cas_omp(volatile _Tp * __ptr,_Tp __comparand,_Tp __replacement)83*38fd1498Szrj __cas_omp(volatile _Tp* __ptr, _Tp __comparand, _Tp __replacement) 84*38fd1498Szrj { 85*38fd1498Szrj bool __res = false; 86*38fd1498Szrj #pragma omp critical 87*38fd1498Szrj { 88*38fd1498Szrj if (*__ptr == __comparand) 89*38fd1498Szrj { 90*38fd1498Szrj *__ptr = __replacement; 91*38fd1498Szrj __res = true; 92*38fd1498Szrj } 93*38fd1498Szrj } 94*38fd1498Szrj return __res; 95*38fd1498Szrj } 96*38fd1498Szrj 97*38fd1498Szrj /** @brief Compare-and-swap 98*38fd1498Szrj * 99*38fd1498Szrj * Compare @c *__ptr and @c __comparand. If equal, let @c 100*38fd1498Szrj * *__ptr=__replacement and return @c true, return @c false otherwise. 101*38fd1498Szrj * 102*38fd1498Szrj * @param __ptr Pointer to signed integer. 103*38fd1498Szrj * @param __comparand Compare value. 104*38fd1498Szrj * @param __replacement Replacement value. 105*38fd1498Szrj */ 106*38fd1498Szrj template<typename _Tp> 107*38fd1498Szrj inline bool __compare_and_swap(volatile _Tp * __ptr,_Tp __comparand,_Tp __replacement)108*38fd1498Szrj __compare_and_swap(volatile _Tp* __ptr, _Tp __comparand, _Tp __replacement) 109*38fd1498Szrj { 110*38fd1498Szrj if (__atomic_always_lock_free(sizeof(_Tp), __ptr)) 111*38fd1498Szrj return __atomic_compare_exchange_n(__ptr, &__comparand, __replacement, 112*38fd1498Szrj false, __ATOMIC_ACQ_REL, 113*38fd1498Szrj __ATOMIC_RELAXED); 114*38fd1498Szrj return __cas_omp(__ptr, __comparand, __replacement); 115*38fd1498Szrj } 116*38fd1498Szrj 117*38fd1498Szrj /** @brief Yield control to another thread, without waiting for 118*38fd1498Szrj * the end of the time slice. 119*38fd1498Szrj */ 120*38fd1498Szrj inline void __yield()121*38fd1498Szrj __yield() 122*38fd1498Szrj { 123*38fd1498Szrj #if defined (_WIN32) && !defined (__CYGWIN__) 124*38fd1498Szrj Sleep(0); 125*38fd1498Szrj #else 126*38fd1498Szrj sched_yield(); 127*38fd1498Szrj #endif 128*38fd1498Szrj } 129*38fd1498Szrj } // end namespace 130*38fd1498Szrj 131*38fd1498Szrj #endif /* _GLIBCXX_PARALLEL_COMPATIBILITY_H */ 132