sync.c 5.7 KB

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