(root)/
gcc-13.2.0/
libgcc/
sync.c
       1  /* Out-of-line libgcc versions of __sync_* builtins.  */
       2  /* Copyright (C) 2008-2023 Free Software Foundation, Inc.
       3  
       4  This file is part of GCC.
       5  
       6  GCC is free software; you can redistribute it and/or modify it under
       7  the terms of the GNU General Public License as published by the Free
       8  Software Foundation; either version 3, or (at your option) any later
       9  version.
      10  
      11  GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      12  WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14  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  /* This file is used by targets whose makefiles define SYNC
      26     to "yes".  It is compiled with SYNC_CFLAGS and provides
      27     out-of-line versions of all relevant __sync_* primitives.
      28  
      29     These routines are intended for targets like MIPS that have two
      30     ISA encodings (the "normal" ISA and the MIPS16 ISA).  The normal
      31     ISA provides full synchronization capabilities but the MIPS16 ISA
      32     has no encoding for them.  MIPS16 code must therefore call external
      33     non-MIPS16 implementations of the __sync_* routines.
      34  
      35     The file is compiled once for each routine.  The following __foo
      36     routines are selected by defining a macro called L<foo>:
      37  
      38         __sync_synchronize
      39  
      40     The following __foo_N routines are selected by defining FN=foo
      41     and SIZE=N:
      42  
      43         __sync_fetch_and_add_N
      44         __sync_fetch_and_sub_N
      45         __sync_fetch_and_or_N
      46         __sync_fetch_and_and_N
      47         __sync_fetch_and_xor_N
      48         __sync_fetch_and_nand_N
      49         __sync_add_and_fetch_N
      50         __sync_sub_and_fetch_N
      51         __sync_or_and_fetch_N
      52         __sync_and_and_fetch_N
      53         __sync_xor_and_fetch_N
      54         __sync_nand_and_fetch_N
      55         __sync_bool_compare_and_swap_N
      56         __sync_val_compare_and_swap_N
      57         __sync_lock_test_and_set_N
      58  
      59     SIZE can be 1, 2, 4, 8 or 16.  __foo_N is omitted if the target does
      60     not provide __sync_compare_and_swap_N.
      61  
      62     Note that __sync_lock_release does not fall back on external
      63     __sync_lock_release_N functions.  The default implementation
      64     of __sync_lock_release is a call to __sync_synchronize followed
      65     by a store of zero, so we don't need separate library functions
      66     for it.  */
      67  
      68  #if defined FN
      69  
      70  /* Define functions called __sync_<NAME>_<UNITS>, with one macro per
      71     signature.  TYPE is a type that has UNITS bytes.  */
      72  
      73  #define DEFINE_V_PV(NAME, UNITS, TYPE)					\
      74    TYPE									\
      75    __##NAME##_##UNITS (TYPE *ptr, TYPE value)				\
      76    {									\
      77      return __##NAME (ptr, value);					\
      78    }
      79  
      80  #define DEFINE_V_PVV(NAME, UNITS, TYPE)					\
      81    TYPE									\
      82    __##NAME##_##UNITS (TYPE *ptr, TYPE value1, TYPE value2)		\
      83    {									\
      84      return __##NAME (ptr, value1, value2);				\
      85    }
      86  
      87  #define DEFINE_BOOL_PVV(NAME, UNITS, TYPE)				\
      88    _Bool									\
      89    __##NAME##_##UNITS (TYPE *ptr, TYPE value1, TYPE value2)		\
      90    {									\
      91      return __##NAME (ptr, value1, value2);				\
      92    }
      93  
      94  /* Map function names to the appropriate DEFINE_* macro.  */
      95  
      96  #define local_sync_fetch_and_add DEFINE_V_PV
      97  #define local_sync_fetch_and_sub DEFINE_V_PV
      98  #define local_sync_fetch_and_or DEFINE_V_PV
      99  #define local_sync_fetch_and_and DEFINE_V_PV
     100  #define local_sync_fetch_and_xor DEFINE_V_PV
     101  #define local_sync_fetch_and_nand DEFINE_V_PV
     102  
     103  #define local_sync_add_and_fetch DEFINE_V_PV
     104  #define local_sync_sub_and_fetch DEFINE_V_PV
     105  #define local_sync_or_and_fetch DEFINE_V_PV
     106  #define local_sync_and_and_fetch DEFINE_V_PV
     107  #define local_sync_xor_and_fetch DEFINE_V_PV
     108  #define local_sync_nand_and_fetch DEFINE_V_PV
     109  
     110  #define local_sync_bool_compare_and_swap DEFINE_BOOL_PVV
     111  #define local_sync_val_compare_and_swap DEFINE_V_PVV
     112  
     113  #define local_sync_lock_test_and_set DEFINE_V_PV
     114  
     115  /* Define the function __<NAME>_<UNITS>, given that TYPE is a type with
     116     UNITS bytes.  */
     117  #define DEFINE1(NAME, UNITS, TYPE) \
     118    static int unused[sizeof (TYPE) == UNITS ? 1 : -1]	\
     119      __attribute__((unused));				\
     120    local_##NAME (NAME, UNITS, TYPE);
     121  
     122  /* As above, but performing macro expansion on the arguments.  */
     123  #define DEFINE(NAME, UNITS, TYPE) DEFINE1 (NAME, UNITS, TYPE)
     124  
     125  /* Find an appropriate type TYPE for SIZE and invoke DEFINE (FN, SIZE, TYPE).
     126  
     127     The types chosen here may be incorrect for some targets.
     128     For example, targets with 16-byte atomicity support might not
     129     support OImode.  We would need some kind of target-specific
     130     override if that becomes a problem.  */
     131  
     132  #if SIZE == 1 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
     133  
     134  typedef unsigned int UQItype __attribute__((mode (QI)));
     135  DEFINE (FN, 1, UQItype)
     136  
     137  #elif SIZE == 2 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
     138  
     139  typedef unsigned int UHItype __attribute__((mode (HI)));
     140  DEFINE (FN, 2, UHItype)
     141  
     142  #elif SIZE == 4 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
     143  
     144  typedef unsigned int USItype __attribute__((mode (SI)));
     145  DEFINE (FN, 4, USItype)
     146  
     147  #elif SIZE == 8 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
     148  
     149  typedef unsigned int UDItype __attribute__((mode (DI)));
     150  DEFINE (FN, 8, UDItype)
     151  
     152  #elif SIZE == 16 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16
     153  
     154  typedef unsigned int UOItype __attribute__((mode (OI)));
     155  DEFINE (FN, 8, UOItype)
     156  
     157  #endif
     158  
     159  #elif __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 \
     160        || __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 \
     161        || __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 \
     162        || __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 \
     163        || __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16
     164  
     165  #if defined Lsync_synchronize
     166  
     167  void
     168  __sync_synchronize (void)
     169  {
     170    __sync_synchronize ();
     171  }
     172  
     173  #endif
     174  
     175  #endif