xref: /dflybsd-src/contrib/gcc-8.0/libstdc++-v3/include/parallel/compatibility.h (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
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