grpc 1.26.0 → 1.27.0.pre1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grpc might be problematic. Click here for more details.

Files changed (209) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +1654 -1519
  3. data/etc/roots.pem +44 -0
  4. data/include/grpc/grpc_security.h +37 -15
  5. data/include/grpc/grpc_security_constants.h +27 -0
  6. data/include/grpc/impl/codegen/grpc_types.h +14 -0
  7. data/include/grpc/impl/codegen/port_platform.h +1 -1
  8. data/src/core/ext/filters/client_channel/client_channel.cc +0 -20
  9. data/src/core/ext/filters/client_channel/http_proxy.cc +4 -4
  10. data/src/core/ext/filters/client_channel/lb_policy.cc +4 -3
  11. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +191 -201
  12. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_balancer_addresses.cc +89 -0
  13. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_balancer_addresses.h +40 -0
  14. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc +3 -2
  15. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc +88 -121
  16. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h +28 -57
  17. data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +0 -7
  18. data/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc +8 -9
  19. data/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +53 -34
  20. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +18 -5
  21. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +24 -19
  22. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +2 -1
  23. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc +4 -2
  24. data/src/core/ext/filters/client_channel/server_address.cc +6 -9
  25. data/src/core/ext/filters/client_channel/server_address.h +3 -10
  26. data/src/core/ext/filters/client_channel/xds/xds_api.cc +394 -150
  27. data/src/core/ext/filters/client_channel/xds/xds_api.h +75 -35
  28. data/src/core/ext/filters/client_channel/xds/xds_bootstrap.cc +59 -22
  29. data/src/core/ext/filters/client_channel/xds/xds_bootstrap.h +13 -9
  30. data/src/core/ext/filters/client_channel/xds/xds_channel_secure.cc +8 -6
  31. data/src/core/ext/filters/client_channel/xds/xds_client.cc +456 -175
  32. data/src/core/ext/filters/client_channel/xds/xds_client.h +33 -21
  33. data/src/core/ext/filters/client_channel/xds/xds_client_stats.cc +5 -8
  34. data/src/core/ext/filters/client_channel/xds/xds_client_stats.h +18 -24
  35. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +2 -2
  36. data/src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c +13 -5
  37. data/src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h +34 -0
  38. data/src/core/lib/channel/channelz.h +11 -1
  39. data/src/core/lib/gpr/time_precise.cc +1 -1
  40. data/src/core/lib/gprpp/optional.h +26 -0
  41. data/src/core/lib/gprpp/string_view.h +14 -10
  42. data/src/core/lib/iomgr/executor.cc +1 -1
  43. data/src/core/lib/iomgr/fork_posix.cc +4 -0
  44. data/src/core/lib/iomgr/poller/eventmanager_libuv.cc +87 -0
  45. data/src/core/lib/iomgr/poller/eventmanager_libuv.h +88 -0
  46. data/src/core/lib/iomgr/socket_utils_common_posix.cc +14 -0
  47. data/src/core/lib/iomgr/socket_utils_posix.h +12 -0
  48. data/src/core/lib/iomgr/tcp_custom.h +3 -0
  49. data/src/core/lib/iomgr/tcp_posix.cc +607 -56
  50. data/src/core/lib/iomgr/tcp_server_custom.cc +15 -2
  51. data/src/core/lib/iomgr/tcp_server_utils_posix_common.cc +8 -0
  52. data/src/core/lib/json/json.h +11 -1
  53. data/src/core/lib/json/json_reader.cc +206 -28
  54. data/src/core/lib/json/json_writer.cc +111 -24
  55. data/src/core/lib/security/credentials/composite/composite_credentials.cc +7 -0
  56. data/src/core/lib/security/credentials/composite/composite_credentials.h +5 -1
  57. data/src/core/lib/security/credentials/credentials.h +10 -1
  58. data/src/core/lib/security/credentials/fake/fake_credentials.h +2 -1
  59. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc +1 -1
  60. data/src/core/lib/security/credentials/plugin/plugin_credentials.cc +6 -4
  61. data/src/core/lib/security/credentials/plugin/plugin_credentials.h +2 -1
  62. data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc +20 -0
  63. data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h +8 -0
  64. data/src/core/lib/security/credentials/tls/{spiffe_credentials.cc → tls_credentials.cc} +23 -24
  65. data/src/core/lib/security/credentials/tls/{spiffe_credentials.h → tls_credentials.h} +9 -9
  66. data/src/core/lib/security/security_connector/alts/alts_security_connector.cc +13 -0
  67. data/src/core/lib/security/security_connector/fake/fake_security_connector.cc +22 -2
  68. data/src/core/lib/security/security_connector/load_system_roots_fallback.cc +2 -2
  69. data/src/core/lib/security/security_connector/load_system_roots_linux.cc +2 -2
  70. data/src/core/lib/security/security_connector/local/local_security_connector.cc +30 -3
  71. data/src/core/lib/security/security_connector/ssl_utils.cc +45 -3
  72. data/src/core/lib/security/security_connector/ssl_utils.h +12 -0
  73. data/src/core/lib/security/security_connector/tls/{spiffe_security_connector.cc → tls_security_connector.cc} +82 -69
  74. data/src/core/lib/security/security_connector/tls/{spiffe_security_connector.h → tls_security_connector.h} +17 -18
  75. data/src/core/lib/security/transport/client_auth_filter.cc +33 -0
  76. data/src/core/lib/surface/completion_queue.cc +22 -1
  77. data/src/core/lib/surface/version.cc +1 -1
  78. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc +11 -1
  79. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.h +1 -1
  80. data/src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc +3 -3
  81. data/src/core/tsi/fake_transport_security.cc +7 -3
  82. data/src/core/tsi/fake_transport_security.h +2 -0
  83. data/src/core/tsi/ssl_transport_security.cc +144 -8
  84. data/src/core/tsi/ssl_transport_security.h +15 -1
  85. data/src/core/tsi/transport_security.cc +13 -0
  86. data/src/core/tsi/transport_security_grpc.cc +2 -2
  87. data/src/core/tsi/transport_security_grpc.h +2 -2
  88. data/src/core/tsi/transport_security_interface.h +12 -0
  89. data/src/ruby/bin/math_pb.rb +5 -5
  90. data/src/ruby/ext/grpc/rb_call_credentials.c +4 -1
  91. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +2 -0
  92. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +4 -1
  93. data/src/ruby/lib/grpc/version.rb +1 -1
  94. data/src/ruby/pb/grpc/health/v1/health_pb.rb +3 -3
  95. data/src/ruby/pb/src/proto/grpc/testing/empty_pb.rb +1 -1
  96. data/src/ruby/pb/src/proto/grpc/testing/messages_pb.rb +23 -13
  97. data/third_party/abseil-cpp/absl/algorithm/algorithm.h +159 -0
  98. data/third_party/abseil-cpp/absl/base/attributes.h +609 -0
  99. data/third_party/abseil-cpp/absl/base/call_once.h +226 -0
  100. data/third_party/abseil-cpp/absl/base/casts.h +184 -0
  101. data/third_party/abseil-cpp/absl/base/config.h +622 -0
  102. data/third_party/abseil-cpp/absl/base/const_init.h +76 -0
  103. data/third_party/abseil-cpp/absl/base/dynamic_annotations.cc +129 -0
  104. data/third_party/abseil-cpp/absl/base/dynamic_annotations.h +389 -0
  105. data/third_party/abseil-cpp/absl/base/internal/atomic_hook.h +179 -0
  106. data/third_party/abseil-cpp/absl/base/internal/bits.h +218 -0
  107. data/third_party/abseil-cpp/absl/base/internal/cycleclock.cc +107 -0
  108. data/third_party/abseil-cpp/absl/base/internal/cycleclock.h +94 -0
  109. data/third_party/abseil-cpp/absl/base/internal/endian.h +266 -0
  110. data/third_party/abseil-cpp/absl/base/internal/hide_ptr.h +51 -0
  111. data/third_party/abseil-cpp/absl/base/internal/identity.h +37 -0
  112. data/third_party/abseil-cpp/absl/base/internal/inline_variable.h +107 -0
  113. data/third_party/abseil-cpp/absl/base/internal/invoke.h +187 -0
  114. data/third_party/abseil-cpp/absl/base/internal/low_level_scheduling.h +107 -0
  115. data/third_party/abseil-cpp/absl/base/internal/per_thread_tls.h +52 -0
  116. data/third_party/abseil-cpp/absl/base/internal/raw_logging.cc +237 -0
  117. data/third_party/abseil-cpp/absl/base/internal/raw_logging.h +179 -0
  118. data/third_party/abseil-cpp/absl/base/internal/scheduling_mode.h +58 -0
  119. data/third_party/abseil-cpp/absl/base/internal/spinlock.cc +233 -0
  120. data/third_party/abseil-cpp/absl/base/internal/spinlock.h +243 -0
  121. data/third_party/abseil-cpp/absl/base/internal/spinlock_akaros.inc +35 -0
  122. data/third_party/abseil-cpp/absl/base/internal/spinlock_linux.inc +67 -0
  123. data/third_party/abseil-cpp/absl/base/internal/spinlock_posix.inc +46 -0
  124. data/third_party/abseil-cpp/absl/base/internal/spinlock_wait.cc +81 -0
  125. data/third_party/abseil-cpp/absl/base/internal/spinlock_wait.h +93 -0
  126. data/third_party/abseil-cpp/absl/base/internal/spinlock_win32.inc +37 -0
  127. data/third_party/abseil-cpp/absl/base/internal/sysinfo.cc +414 -0
  128. data/third_party/abseil-cpp/absl/base/internal/sysinfo.h +66 -0
  129. data/third_party/abseil-cpp/absl/base/internal/thread_annotations.h +271 -0
  130. data/third_party/abseil-cpp/absl/base/internal/thread_identity.cc +140 -0
  131. data/third_party/abseil-cpp/absl/base/internal/thread_identity.h +250 -0
  132. data/third_party/abseil-cpp/absl/base/internal/throw_delegate.cc +108 -0
  133. data/third_party/abseil-cpp/absl/base/internal/throw_delegate.h +75 -0
  134. data/third_party/abseil-cpp/absl/base/internal/tsan_mutex_interface.h +66 -0
  135. data/third_party/abseil-cpp/absl/base/internal/unaligned_access.h +158 -0
  136. data/third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.cc +103 -0
  137. data/third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.h +124 -0
  138. data/third_party/abseil-cpp/absl/base/log_severity.cc +27 -0
  139. data/third_party/abseil-cpp/absl/base/log_severity.h +121 -0
  140. data/third_party/abseil-cpp/absl/base/macros.h +220 -0
  141. data/third_party/abseil-cpp/absl/base/optimization.h +181 -0
  142. data/third_party/abseil-cpp/absl/base/options.h +214 -0
  143. data/third_party/abseil-cpp/absl/base/policy_checks.h +111 -0
  144. data/third_party/abseil-cpp/absl/base/port.h +26 -0
  145. data/third_party/abseil-cpp/absl/base/thread_annotations.h +280 -0
  146. data/third_party/abseil-cpp/absl/container/inlined_vector.h +848 -0
  147. data/third_party/abseil-cpp/absl/container/internal/compressed_tuple.h +265 -0
  148. data/third_party/abseil-cpp/absl/container/internal/inlined_vector.h +892 -0
  149. data/third_party/abseil-cpp/absl/memory/memory.h +695 -0
  150. data/third_party/abseil-cpp/absl/meta/type_traits.h +759 -0
  151. data/third_party/abseil-cpp/absl/numeric/int128.cc +404 -0
  152. data/third_party/abseil-cpp/absl/numeric/int128.h +1091 -0
  153. data/third_party/abseil-cpp/absl/numeric/int128_have_intrinsic.inc +302 -0
  154. data/third_party/abseil-cpp/absl/numeric/int128_no_intrinsic.inc +308 -0
  155. data/third_party/abseil-cpp/absl/strings/ascii.cc +200 -0
  156. data/third_party/abseil-cpp/absl/strings/ascii.h +241 -0
  157. data/third_party/abseil-cpp/absl/strings/charconv.cc +985 -0
  158. data/third_party/abseil-cpp/absl/strings/charconv.h +119 -0
  159. data/third_party/abseil-cpp/absl/strings/escaping.cc +949 -0
  160. data/third_party/abseil-cpp/absl/strings/escaping.h +164 -0
  161. data/third_party/abseil-cpp/absl/strings/internal/char_map.h +156 -0
  162. data/third_party/abseil-cpp/absl/strings/internal/charconv_bigint.cc +359 -0
  163. data/third_party/abseil-cpp/absl/strings/internal/charconv_bigint.h +421 -0
  164. data/third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc +504 -0
  165. data/third_party/abseil-cpp/absl/strings/internal/charconv_parse.h +99 -0
  166. data/third_party/abseil-cpp/absl/strings/internal/escaping.cc +180 -0
  167. data/third_party/abseil-cpp/absl/strings/internal/escaping.h +58 -0
  168. data/third_party/abseil-cpp/absl/strings/internal/memutil.cc +112 -0
  169. data/third_party/abseil-cpp/absl/strings/internal/memutil.h +148 -0
  170. data/third_party/abseil-cpp/absl/strings/internal/ostringstream.cc +36 -0
  171. data/third_party/abseil-cpp/absl/strings/internal/ostringstream.h +89 -0
  172. data/third_party/abseil-cpp/absl/strings/internal/resize_uninitialized.h +73 -0
  173. data/third_party/abseil-cpp/absl/strings/internal/stl_type_traits.h +248 -0
  174. data/third_party/abseil-cpp/absl/strings/internal/str_join_internal.h +314 -0
  175. data/third_party/abseil-cpp/absl/strings/internal/str_split_internal.h +455 -0
  176. data/third_party/abseil-cpp/absl/strings/internal/utf8.cc +53 -0
  177. data/third_party/abseil-cpp/absl/strings/internal/utf8.h +50 -0
  178. data/third_party/abseil-cpp/absl/strings/match.cc +40 -0
  179. data/third_party/abseil-cpp/absl/strings/match.h +90 -0
  180. data/third_party/abseil-cpp/absl/strings/numbers.cc +916 -0
  181. data/third_party/abseil-cpp/absl/strings/numbers.h +263 -0
  182. data/third_party/abseil-cpp/absl/strings/str_cat.cc +246 -0
  183. data/third_party/abseil-cpp/absl/strings/str_cat.h +408 -0
  184. data/third_party/abseil-cpp/absl/strings/str_join.h +293 -0
  185. data/third_party/abseil-cpp/absl/strings/str_replace.cc +82 -0
  186. data/third_party/abseil-cpp/absl/strings/str_replace.h +219 -0
  187. data/third_party/abseil-cpp/absl/strings/str_split.cc +139 -0
  188. data/third_party/abseil-cpp/absl/strings/str_split.h +513 -0
  189. data/third_party/abseil-cpp/absl/strings/string_view.cc +235 -0
  190. data/third_party/abseil-cpp/absl/strings/string_view.h +615 -0
  191. data/third_party/abseil-cpp/absl/strings/strip.h +91 -0
  192. data/third_party/abseil-cpp/absl/strings/substitute.cc +171 -0
  193. data/third_party/abseil-cpp/absl/strings/substitute.h +693 -0
  194. data/third_party/abseil-cpp/absl/types/bad_optional_access.cc +48 -0
  195. data/third_party/abseil-cpp/absl/types/bad_optional_access.h +78 -0
  196. data/third_party/abseil-cpp/absl/types/internal/optional.h +396 -0
  197. data/third_party/abseil-cpp/absl/types/internal/span.h +128 -0
  198. data/third_party/abseil-cpp/absl/types/optional.h +776 -0
  199. data/third_party/abseil-cpp/absl/types/span.h +713 -0
  200. data/third_party/abseil-cpp/absl/utility/utility.h +350 -0
  201. data/third_party/upb/upb/decode.c +4 -0
  202. data/third_party/upb/upb/port.c +0 -1
  203. data/third_party/upb/upb/port_def.inc +1 -3
  204. data/third_party/upb/upb/table.c +2 -1
  205. metadata +147 -43
  206. data/src/core/lib/json/json_common.h +0 -34
  207. data/src/core/lib/json/json_reader.h +0 -146
  208. data/src/core/lib/json/json_string.cc +0 -367
  209. data/src/core/lib/json/json_writer.h +0 -84
@@ -0,0 +1,233 @@
1
+ // Copyright 2017 The Abseil Authors.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // https://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ #include "absl/base/internal/spinlock.h"
16
+
17
+ #include <algorithm>
18
+ #include <atomic>
19
+ #include <limits>
20
+
21
+ #include "absl/base/attributes.h"
22
+ #include "absl/base/internal/atomic_hook.h"
23
+ #include "absl/base/internal/cycleclock.h"
24
+ #include "absl/base/internal/spinlock_wait.h"
25
+ #include "absl/base/internal/sysinfo.h" /* For NumCPUs() */
26
+ #include "absl/base/call_once.h"
27
+
28
+ // Description of lock-word:
29
+ // 31..00: [............................3][2][1][0]
30
+ //
31
+ // [0]: kSpinLockHeld
32
+ // [1]: kSpinLockCooperative
33
+ // [2]: kSpinLockDisabledScheduling
34
+ // [31..3]: ONLY kSpinLockSleeper OR
35
+ // Wait time in cycles >> PROFILE_TIMESTAMP_SHIFT
36
+ //
37
+ // Detailed descriptions:
38
+ //
39
+ // Bit [0]: The lock is considered held iff kSpinLockHeld is set.
40
+ //
41
+ // Bit [1]: Eligible waiters (e.g. Fibers) may co-operatively reschedule when
42
+ // contended iff kSpinLockCooperative is set.
43
+ //
44
+ // Bit [2]: This bit is exclusive from bit [1]. It is used only by a
45
+ // non-cooperative lock. When set, indicates that scheduling was
46
+ // successfully disabled when the lock was acquired. May be unset,
47
+ // even if non-cooperative, if a ThreadIdentity did not yet exist at
48
+ // time of acquisition.
49
+ //
50
+ // Bit [3]: If this is the only upper bit ([31..3]) set then this lock was
51
+ // acquired without contention, however, at least one waiter exists.
52
+ //
53
+ // Otherwise, bits [31..3] represent the time spent by the current lock
54
+ // holder to acquire the lock. There may be outstanding waiter(s).
55
+
56
+ namespace absl {
57
+ ABSL_NAMESPACE_BEGIN
58
+ namespace base_internal {
59
+
60
+ ABSL_CONST_INIT static base_internal::AtomicHook<void (*)(const void *lock,
61
+ int64_t wait_cycles)>
62
+ submit_profile_data;
63
+
64
+ void RegisterSpinLockProfiler(void (*fn)(const void *contendedlock,
65
+ int64_t wait_cycles)) {
66
+ submit_profile_data.Store(fn);
67
+ }
68
+
69
+ // Uncommon constructors.
70
+ SpinLock::SpinLock(base_internal::SchedulingMode mode)
71
+ : lockword_(IsCooperative(mode) ? kSpinLockCooperative : 0) {
72
+ ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static);
73
+ }
74
+
75
+ SpinLock::SpinLock(base_internal::LinkerInitialized,
76
+ base_internal::SchedulingMode mode) {
77
+ ABSL_TSAN_MUTEX_CREATE(this, 0);
78
+ if (IsCooperative(mode)) {
79
+ InitLinkerInitializedAndCooperative();
80
+ }
81
+ // Otherwise, lockword_ is already initialized.
82
+ }
83
+
84
+ // Static (linker initialized) spinlocks always start life as functional
85
+ // non-cooperative locks. When their static constructor does run, it will call
86
+ // this initializer to augment the lockword with the cooperative bit. By
87
+ // actually taking the lock when we do this we avoid the need for an atomic
88
+ // operation in the regular unlock path.
89
+ //
90
+ // SlowLock() must be careful to re-test for this bit so that any outstanding
91
+ // waiters may be upgraded to cooperative status.
92
+ void SpinLock::InitLinkerInitializedAndCooperative() {
93
+ Lock();
94
+ lockword_.fetch_or(kSpinLockCooperative, std::memory_order_relaxed);
95
+ Unlock();
96
+ }
97
+
98
+ // Monitor the lock to see if its value changes within some time period
99
+ // (adaptive_spin_count loop iterations). The last value read from the lock
100
+ // is returned from the method.
101
+ uint32_t SpinLock::SpinLoop() {
102
+ // We are already in the slow path of SpinLock, initialize the
103
+ // adaptive_spin_count here.
104
+ ABSL_CONST_INIT static absl::once_flag init_adaptive_spin_count;
105
+ ABSL_CONST_INIT static int adaptive_spin_count = 0;
106
+ base_internal::LowLevelCallOnce(&init_adaptive_spin_count, []() {
107
+ adaptive_spin_count = base_internal::NumCPUs() > 1 ? 1000 : 1;
108
+ });
109
+
110
+ int c = adaptive_spin_count;
111
+ uint32_t lock_value;
112
+ do {
113
+ lock_value = lockword_.load(std::memory_order_relaxed);
114
+ } while ((lock_value & kSpinLockHeld) != 0 && --c > 0);
115
+ return lock_value;
116
+ }
117
+
118
+ void SpinLock::SlowLock() {
119
+ uint32_t lock_value = SpinLoop();
120
+ lock_value = TryLockInternal(lock_value, 0);
121
+ if ((lock_value & kSpinLockHeld) == 0) {
122
+ return;
123
+ }
124
+ // The lock was not obtained initially, so this thread needs to wait for
125
+ // it. Record the current timestamp in the local variable wait_start_time
126
+ // so the total wait time can be stored in the lockword once this thread
127
+ // obtains the lock.
128
+ int64_t wait_start_time = CycleClock::Now();
129
+ uint32_t wait_cycles = 0;
130
+ int lock_wait_call_count = 0;
131
+ while ((lock_value & kSpinLockHeld) != 0) {
132
+ // If the lock is currently held, but not marked as having a sleeper, mark
133
+ // it as having a sleeper.
134
+ if ((lock_value & kWaitTimeMask) == 0) {
135
+ // Here, just "mark" that the thread is going to sleep. Don't store the
136
+ // lock wait time in the lock as that will cause the current lock
137
+ // owner to think it experienced contention.
138
+ if (lockword_.compare_exchange_strong(
139
+ lock_value, lock_value | kSpinLockSleeper,
140
+ std::memory_order_relaxed, std::memory_order_relaxed)) {
141
+ // Successfully transitioned to kSpinLockSleeper. Pass
142
+ // kSpinLockSleeper to the SpinLockWait routine to properly indicate
143
+ // the last lock_value observed.
144
+ lock_value |= kSpinLockSleeper;
145
+ } else if ((lock_value & kSpinLockHeld) == 0) {
146
+ // Lock is free again, so try and acquire it before sleeping. The
147
+ // new lock state will be the number of cycles this thread waited if
148
+ // this thread obtains the lock.
149
+ lock_value = TryLockInternal(lock_value, wait_cycles);
150
+ continue; // Skip the delay at the end of the loop.
151
+ }
152
+ }
153
+
154
+ base_internal::SchedulingMode scheduling_mode;
155
+ if ((lock_value & kSpinLockCooperative) != 0) {
156
+ scheduling_mode = base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL;
157
+ } else {
158
+ scheduling_mode = base_internal::SCHEDULE_KERNEL_ONLY;
159
+ }
160
+ // SpinLockDelay() calls into fiber scheduler, we need to see
161
+ // synchronization there to avoid false positives.
162
+ ABSL_TSAN_MUTEX_PRE_DIVERT(this, 0);
163
+ // Wait for an OS specific delay.
164
+ base_internal::SpinLockDelay(&lockword_, lock_value, ++lock_wait_call_count,
165
+ scheduling_mode);
166
+ ABSL_TSAN_MUTEX_POST_DIVERT(this, 0);
167
+ // Spin again after returning from the wait routine to give this thread
168
+ // some chance of obtaining the lock.
169
+ lock_value = SpinLoop();
170
+ wait_cycles = EncodeWaitCycles(wait_start_time, CycleClock::Now());
171
+ lock_value = TryLockInternal(lock_value, wait_cycles);
172
+ }
173
+ }
174
+
175
+ void SpinLock::SlowUnlock(uint32_t lock_value) {
176
+ base_internal::SpinLockWake(&lockword_,
177
+ false); // wake waiter if necessary
178
+
179
+ // If our acquisition was contended, collect contentionz profile info. We
180
+ // reserve a unitary wait time to represent that a waiter exists without our
181
+ // own acquisition having been contended.
182
+ if ((lock_value & kWaitTimeMask) != kSpinLockSleeper) {
183
+ const uint64_t wait_cycles = DecodeWaitCycles(lock_value);
184
+ ABSL_TSAN_MUTEX_PRE_DIVERT(this, 0);
185
+ submit_profile_data(this, wait_cycles);
186
+ ABSL_TSAN_MUTEX_POST_DIVERT(this, 0);
187
+ }
188
+ }
189
+
190
+ // We use the upper 29 bits of the lock word to store the time spent waiting to
191
+ // acquire this lock. This is reported by contentionz profiling. Since the
192
+ // lower bits of the cycle counter wrap very quickly on high-frequency
193
+ // processors we divide to reduce the granularity to 2^PROFILE_TIMESTAMP_SHIFT
194
+ // sized units. On a 4Ghz machine this will lose track of wait times greater
195
+ // than (2^29/4 Ghz)*128 =~ 17.2 seconds. Such waits should be extremely rare.
196
+ enum { PROFILE_TIMESTAMP_SHIFT = 7 };
197
+ enum { LOCKWORD_RESERVED_SHIFT = 3 }; // We currently reserve the lower 3 bits.
198
+
199
+ uint32_t SpinLock::EncodeWaitCycles(int64_t wait_start_time,
200
+ int64_t wait_end_time) {
201
+ static const int64_t kMaxWaitTime =
202
+ std::numeric_limits<uint32_t>::max() >> LOCKWORD_RESERVED_SHIFT;
203
+ int64_t scaled_wait_time =
204
+ (wait_end_time - wait_start_time) >> PROFILE_TIMESTAMP_SHIFT;
205
+
206
+ // Return a representation of the time spent waiting that can be stored in
207
+ // the lock word's upper bits.
208
+ uint32_t clamped = static_cast<uint32_t>(
209
+ std::min(scaled_wait_time, kMaxWaitTime) << LOCKWORD_RESERVED_SHIFT);
210
+
211
+ if (clamped == 0) {
212
+ return kSpinLockSleeper; // Just wake waiters, but don't record contention.
213
+ }
214
+ // Bump up value if necessary to avoid returning kSpinLockSleeper.
215
+ const uint32_t kMinWaitTime =
216
+ kSpinLockSleeper + (1 << LOCKWORD_RESERVED_SHIFT);
217
+ if (clamped == kSpinLockSleeper) {
218
+ return kMinWaitTime;
219
+ }
220
+ return clamped;
221
+ }
222
+
223
+ uint64_t SpinLock::DecodeWaitCycles(uint32_t lock_value) {
224
+ // Cast to uint32_t first to ensure bits [63:32] are cleared.
225
+ const uint64_t scaled_wait_time =
226
+ static_cast<uint32_t>(lock_value & kWaitTimeMask);
227
+ return scaled_wait_time
228
+ << (PROFILE_TIMESTAMP_SHIFT - LOCKWORD_RESERVED_SHIFT);
229
+ }
230
+
231
+ } // namespace base_internal
232
+ ABSL_NAMESPACE_END
233
+ } // namespace absl
@@ -0,0 +1,243 @@
1
+ //
2
+ // Copyright 2017 The Abseil Authors.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // https://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+ //
16
+
17
+ // Most users requiring mutual exclusion should use Mutex.
18
+ // SpinLock is provided for use in three situations:
19
+ // - for use in code that Mutex itself depends on
20
+ // - to get a faster fast-path release under low contention (without an
21
+ // atomic read-modify-write) In return, SpinLock has worse behaviour under
22
+ // contention, which is why Mutex is preferred in most situations.
23
+ // - for async signal safety (see below)
24
+
25
+ // SpinLock is async signal safe. If a spinlock is used within a signal
26
+ // handler, all code that acquires the lock must ensure that the signal cannot
27
+ // arrive while they are holding the lock. Typically, this is done by blocking
28
+ // the signal.
29
+
30
+ #ifndef ABSL_BASE_INTERNAL_SPINLOCK_H_
31
+ #define ABSL_BASE_INTERNAL_SPINLOCK_H_
32
+
33
+ #include <stdint.h>
34
+ #include <sys/types.h>
35
+
36
+ #include <atomic>
37
+
38
+ #include "absl/base/attributes.h"
39
+ #include "absl/base/dynamic_annotations.h"
40
+ #include "absl/base/internal/low_level_scheduling.h"
41
+ #include "absl/base/internal/raw_logging.h"
42
+ #include "absl/base/internal/scheduling_mode.h"
43
+ #include "absl/base/internal/tsan_mutex_interface.h"
44
+ #include "absl/base/macros.h"
45
+ #include "absl/base/port.h"
46
+ #include "absl/base/thread_annotations.h"
47
+
48
+ namespace absl {
49
+ ABSL_NAMESPACE_BEGIN
50
+ namespace base_internal {
51
+
52
+ class ABSL_LOCKABLE SpinLock {
53
+ public:
54
+ SpinLock() : lockword_(kSpinLockCooperative) {
55
+ ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static);
56
+ }
57
+
58
+ // Special constructor for use with static SpinLock objects. E.g.,
59
+ //
60
+ // static SpinLock lock(base_internal::kLinkerInitialized);
61
+ //
62
+ // When initialized using this constructor, we depend on the fact
63
+ // that the linker has already initialized the memory appropriately. The lock
64
+ // is initialized in non-cooperative mode.
65
+ //
66
+ // A SpinLock constructed like this can be freely used from global
67
+ // initializers without worrying about the order in which global
68
+ // initializers run.
69
+ explicit SpinLock(base_internal::LinkerInitialized) {
70
+ // Does nothing; lockword_ is already initialized
71
+ ABSL_TSAN_MUTEX_CREATE(this, 0);
72
+ }
73
+
74
+ // Constructors that allow non-cooperative spinlocks to be created for use
75
+ // inside thread schedulers. Normal clients should not use these.
76
+ explicit SpinLock(base_internal::SchedulingMode mode);
77
+ SpinLock(base_internal::LinkerInitialized,
78
+ base_internal::SchedulingMode mode);
79
+
80
+ ~SpinLock() { ABSL_TSAN_MUTEX_DESTROY(this, __tsan_mutex_not_static); }
81
+
82
+ // Acquire this SpinLock.
83
+ inline void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION() {
84
+ ABSL_TSAN_MUTEX_PRE_LOCK(this, 0);
85
+ if (!TryLockImpl()) {
86
+ SlowLock();
87
+ }
88
+ ABSL_TSAN_MUTEX_POST_LOCK(this, 0, 0);
89
+ }
90
+
91
+ // Try to acquire this SpinLock without blocking and return true if the
92
+ // acquisition was successful. If the lock was not acquired, false is
93
+ // returned. If this SpinLock is free at the time of the call, TryLock
94
+ // will return true with high probability.
95
+ inline bool TryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true) {
96
+ ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_try_lock);
97
+ bool res = TryLockImpl();
98
+ ABSL_TSAN_MUTEX_POST_LOCK(
99
+ this, __tsan_mutex_try_lock | (res ? 0 : __tsan_mutex_try_lock_failed),
100
+ 0);
101
+ return res;
102
+ }
103
+
104
+ // Release this SpinLock, which must be held by the calling thread.
105
+ inline void Unlock() ABSL_UNLOCK_FUNCTION() {
106
+ ABSL_TSAN_MUTEX_PRE_UNLOCK(this, 0);
107
+ uint32_t lock_value = lockword_.load(std::memory_order_relaxed);
108
+ lock_value = lockword_.exchange(lock_value & kSpinLockCooperative,
109
+ std::memory_order_release);
110
+
111
+ if ((lock_value & kSpinLockDisabledScheduling) != 0) {
112
+ base_internal::SchedulingGuard::EnableRescheduling(true);
113
+ }
114
+ if ((lock_value & kWaitTimeMask) != 0) {
115
+ // Collect contentionz profile info, and speed the wakeup of any waiter.
116
+ // The wait_cycles value indicates how long this thread spent waiting
117
+ // for the lock.
118
+ SlowUnlock(lock_value);
119
+ }
120
+ ABSL_TSAN_MUTEX_POST_UNLOCK(this, 0);
121
+ }
122
+
123
+ // Determine if the lock is held. When the lock is held by the invoking
124
+ // thread, true will always be returned. Intended to be used as
125
+ // CHECK(lock.IsHeld()).
126
+ inline bool IsHeld() const {
127
+ return (lockword_.load(std::memory_order_relaxed) & kSpinLockHeld) != 0;
128
+ }
129
+
130
+ protected:
131
+ // These should not be exported except for testing.
132
+
133
+ // Store number of cycles between wait_start_time and wait_end_time in a
134
+ // lock value.
135
+ static uint32_t EncodeWaitCycles(int64_t wait_start_time,
136
+ int64_t wait_end_time);
137
+
138
+ // Extract number of wait cycles in a lock value.
139
+ static uint64_t DecodeWaitCycles(uint32_t lock_value);
140
+
141
+ // Provide access to protected method above. Use for testing only.
142
+ friend struct SpinLockTest;
143
+
144
+ private:
145
+ // lockword_ is used to store the following:
146
+ //
147
+ // bit[0] encodes whether a lock is being held.
148
+ // bit[1] encodes whether a lock uses cooperative scheduling.
149
+ // bit[2] encodes whether a lock disables scheduling.
150
+ // bit[3:31] encodes time a lock spent on waiting as a 29-bit unsigned int.
151
+ enum { kSpinLockHeld = 1 };
152
+ enum { kSpinLockCooperative = 2 };
153
+ enum { kSpinLockDisabledScheduling = 4 };
154
+ enum { kSpinLockSleeper = 8 };
155
+ enum { kWaitTimeMask = // Includes kSpinLockSleeper.
156
+ ~(kSpinLockHeld | kSpinLockCooperative | kSpinLockDisabledScheduling) };
157
+
158
+ // Returns true if the provided scheduling mode is cooperative.
159
+ static constexpr bool IsCooperative(
160
+ base_internal::SchedulingMode scheduling_mode) {
161
+ return scheduling_mode == base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL;
162
+ }
163
+
164
+ uint32_t TryLockInternal(uint32_t lock_value, uint32_t wait_cycles);
165
+ void InitLinkerInitializedAndCooperative();
166
+ void SlowLock() ABSL_ATTRIBUTE_COLD;
167
+ void SlowUnlock(uint32_t lock_value) ABSL_ATTRIBUTE_COLD;
168
+ uint32_t SpinLoop();
169
+
170
+ inline bool TryLockImpl() {
171
+ uint32_t lock_value = lockword_.load(std::memory_order_relaxed);
172
+ return (TryLockInternal(lock_value, 0) & kSpinLockHeld) == 0;
173
+ }
174
+
175
+ std::atomic<uint32_t> lockword_;
176
+
177
+ SpinLock(const SpinLock&) = delete;
178
+ SpinLock& operator=(const SpinLock&) = delete;
179
+ };
180
+
181
+ // Corresponding locker object that arranges to acquire a spinlock for
182
+ // the duration of a C++ scope.
183
+ class ABSL_SCOPED_LOCKABLE SpinLockHolder {
184
+ public:
185
+ inline explicit SpinLockHolder(SpinLock* l) ABSL_EXCLUSIVE_LOCK_FUNCTION(l)
186
+ : lock_(l) {
187
+ l->Lock();
188
+ }
189
+ inline ~SpinLockHolder() ABSL_UNLOCK_FUNCTION() { lock_->Unlock(); }
190
+
191
+ SpinLockHolder(const SpinLockHolder&) = delete;
192
+ SpinLockHolder& operator=(const SpinLockHolder&) = delete;
193
+
194
+ private:
195
+ SpinLock* lock_;
196
+ };
197
+
198
+ // Register a hook for profiling support.
199
+ //
200
+ // The function pointer registered here will be called whenever a spinlock is
201
+ // contended. The callback is given an opaque handle to the contended spinlock
202
+ // and the number of wait cycles. This is thread-safe, but only a single
203
+ // profiler can be registered. It is an error to call this function multiple
204
+ // times with different arguments.
205
+ void RegisterSpinLockProfiler(void (*fn)(const void* lock,
206
+ int64_t wait_cycles));
207
+
208
+ //------------------------------------------------------------------------------
209
+ // Public interface ends here.
210
+ //------------------------------------------------------------------------------
211
+
212
+ // If (result & kSpinLockHeld) == 0, then *this was successfully locked.
213
+ // Otherwise, returns last observed value for lockword_.
214
+ inline uint32_t SpinLock::TryLockInternal(uint32_t lock_value,
215
+ uint32_t wait_cycles) {
216
+ if ((lock_value & kSpinLockHeld) != 0) {
217
+ return lock_value;
218
+ }
219
+
220
+ uint32_t sched_disabled_bit = 0;
221
+ if ((lock_value & kSpinLockCooperative) == 0) {
222
+ // For non-cooperative locks we must make sure we mark ourselves as
223
+ // non-reschedulable before we attempt to CompareAndSwap.
224
+ if (base_internal::SchedulingGuard::DisableRescheduling()) {
225
+ sched_disabled_bit = kSpinLockDisabledScheduling;
226
+ }
227
+ }
228
+
229
+ if (!lockword_.compare_exchange_strong(
230
+ lock_value,
231
+ kSpinLockHeld | lock_value | wait_cycles | sched_disabled_bit,
232
+ std::memory_order_acquire, std::memory_order_relaxed)) {
233
+ base_internal::SchedulingGuard::EnableRescheduling(sched_disabled_bit != 0);
234
+ }
235
+
236
+ return lock_value;
237
+ }
238
+
239
+ } // namespace base_internal
240
+ ABSL_NAMESPACE_END
241
+ } // namespace absl
242
+
243
+ #endif // ABSL_BASE_INTERNAL_SPINLOCK_H_