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