grpc 1.31.1 → 1.32.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 (431) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +595 -15723
  3. data/include/grpc/grpc_security.h +31 -14
  4. data/include/grpc/impl/codegen/README.md +22 -0
  5. data/include/grpc/impl/codegen/port_platform.h +6 -1
  6. data/src/core/ext/filters/client_channel/backup_poller.cc +3 -2
  7. data/src/core/ext/filters/client_channel/client_channel.cc +64 -20
  8. data/src/core/ext/filters/client_channel/client_channel.h +1 -1
  9. data/src/core/ext/filters/client_channel/client_channel_channelz.h +0 -3
  10. data/src/core/ext/filters/client_channel/health/health_check_client.cc +6 -1
  11. data/src/core/ext/filters/client_channel/http_connect_handshaker.cc +2 -3
  12. data/src/core/ext/filters/client_channel/lb_policy.h +2 -0
  13. data/src/core/ext/filters/client_channel/lb_policy/child_policy_handler.cc +6 -4
  14. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +20 -13
  15. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_balancer_addresses.cc +0 -13
  16. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_balancer_addresses.h +0 -3
  17. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc +1 -37
  18. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +19 -13
  19. data/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc +29 -10
  20. data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +5 -4
  21. data/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc +20 -9
  22. data/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc +18 -12
  23. data/src/core/ext/filters/client_channel/lb_policy/xds/eds.cc +22 -14
  24. data/src/core/ext/filters/client_channel/lb_policy/xds/lrs.cc +18 -9
  25. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc +54 -56
  26. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +3 -3
  27. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_libuv.cc +1 -1
  28. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc +1 -1
  29. data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc +1 -1
  30. data/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc +1 -1
  31. data/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc +363 -14
  32. data/src/core/ext/filters/client_channel/resolver_result_parsing.h +0 -1
  33. data/src/core/ext/filters/client_channel/resolving_lb_policy.cc +5 -4
  34. data/src/core/ext/filters/client_channel/server_address.cc +40 -7
  35. data/src/core/ext/filters/client_channel/server_address.h +42 -4
  36. data/src/core/ext/filters/client_channel/subchannel.cc +64 -23
  37. data/src/core/ext/filters/client_channel/subchannel.h +16 -4
  38. data/src/core/ext/filters/max_age/max_age_filter.cc +2 -1
  39. data/src/core/ext/transport/chttp2/client/chttp2_connector.cc +87 -31
  40. data/src/core/ext/transport/chttp2/client/chttp2_connector.h +18 -1
  41. data/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc +10 -35
  42. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +19 -25
  43. data/src/core/ext/transport/chttp2/server/chttp2_server.h +2 -1
  44. data/src/core/ext/transport/chttp2/server/insecure/server_chttp2.cc +2 -2
  45. data/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc +6 -6
  46. data/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.cc +3 -2
  47. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +239 -277
  48. data/src/core/ext/transport/chttp2/transport/flow_control.cc +1 -1
  49. data/src/core/ext/transport/chttp2/transport/frame_settings.cc +2 -2
  50. data/src/core/ext/transport/chttp2/transport/internal.h +5 -1
  51. data/src/core/ext/transport/chttp2/transport/parsing.cc +1 -28
  52. data/src/core/ext/transport/chttp2/transport/writing.cc +6 -5
  53. data/src/core/ext/transport/inproc/inproc_transport.cc +12 -12
  54. data/src/core/ext/upb-generated/envoy/config/accesslog/v3/accesslog.upb.c +224 -0
  55. data/src/core/ext/upb-generated/envoy/config/accesslog/v3/accesslog.upb.h +700 -0
  56. data/src/core/ext/upb-generated/envoy/config/cluster/v3/circuit_breaker.upb.c +74 -0
  57. data/src/core/ext/upb-generated/envoy/config/cluster/v3/circuit_breaker.upb.h +226 -0
  58. data/src/core/ext/upb-generated/envoy/config/cluster/v3/cluster.upb.c +380 -0
  59. data/src/core/ext/upb-generated/envoy/config/cluster/v3/cluster.upb.h +1378 -0
  60. data/src/core/ext/upb-generated/envoy/{api/v2/cluster → config/cluster/v3}/filter.upb.c +8 -8
  61. data/src/core/ext/upb-generated/envoy/config/cluster/v3/filter.upb.h +69 -0
  62. data/src/core/ext/upb-generated/envoy/{api/v2/cluster → config/cluster/v3}/outlier_detection.upb.c +8 -8
  63. data/src/core/ext/upb-generated/envoy/config/cluster/v3/outlier_detection.upb.h +323 -0
  64. data/src/core/ext/upb-generated/envoy/config/core/v3/address.upb.c +112 -0
  65. data/src/core/ext/upb-generated/envoy/config/core/v3/address.upb.h +334 -0
  66. data/src/core/ext/upb-generated/envoy/{api/v2/core → config/core/v3}/backoff.upb.c +8 -8
  67. data/src/core/ext/upb-generated/envoy/config/core/v3/backoff.upb.h +79 -0
  68. data/src/core/ext/upb-generated/envoy/config/core/v3/base.upb.c +309 -0
  69. data/src/core/ext/upb-generated/envoy/config/core/v3/base.upb.h +869 -0
  70. data/src/core/ext/upb-generated/envoy/config/core/v3/config_source.upb.c +96 -0
  71. data/src/core/ext/upb-generated/envoy/config/core/v3/config_source.upb.h +328 -0
  72. data/src/core/ext/upb-generated/envoy/config/core/v3/event_service_config.upb.c +34 -0
  73. data/src/core/ext/upb-generated/envoy/config/core/v3/event_service_config.upb.h +71 -0
  74. data/src/core/ext/upb-generated/envoy/config/core/v3/grpc_service.upb.c +195 -0
  75. data/src/core/ext/upb-generated/envoy/config/core/v3/grpc_service.upb.h +634 -0
  76. data/src/core/ext/upb-generated/envoy/config/core/v3/health_check.upb.c +170 -0
  77. data/src/core/ext/upb-generated/envoy/config/core/v3/health_check.upb.h +684 -0
  78. data/src/core/ext/upb-generated/envoy/{api/v2/core → config/core/v3}/http_uri.upb.c +8 -8
  79. data/src/core/ext/upb-generated/envoy/config/core/v3/http_uri.upb.h +80 -0
  80. data/src/core/ext/upb-generated/envoy/config/core/v3/protocol.upb.c +152 -0
  81. data/src/core/ext/upb-generated/envoy/config/core/v3/protocol.upb.h +536 -0
  82. data/src/core/ext/upb-generated/envoy/config/core/v3/proxy_protocol.upb.c +28 -0
  83. data/src/core/ext/upb-generated/envoy/config/core/v3/proxy_protocol.upb.h +58 -0
  84. data/src/core/ext/upb-generated/envoy/{api/v2/core → config/core/v3}/socket_option.upb.c +6 -6
  85. data/src/core/ext/upb-generated/envoy/config/core/v3/socket_option.upb.h +88 -0
  86. data/src/core/ext/upb-generated/envoy/config/endpoint/v3/endpoint.upb.c +91 -0
  87. data/src/core/ext/upb-generated/envoy/config/endpoint/v3/endpoint.upb.h +220 -0
  88. data/src/core/ext/upb-generated/envoy/config/endpoint/v3/endpoint_components.upb.c +91 -0
  89. data/src/core/ext/upb-generated/envoy/config/endpoint/v3/endpoint_components.upb.h +273 -0
  90. data/src/core/ext/upb-generated/envoy/config/endpoint/v3/load_report.upb.c +112 -0
  91. data/src/core/ext/upb-generated/envoy/config/endpoint/v3/load_report.upb.h +332 -0
  92. data/src/core/ext/upb-generated/envoy/config/listener/{v2 → v3}/api_listener.upb.c +8 -8
  93. data/src/core/ext/upb-generated/envoy/config/listener/v3/api_listener.upb.h +65 -0
  94. data/src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.c +108 -0
  95. data/src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.h +401 -0
  96. data/src/core/ext/upb-generated/envoy/config/listener/v3/listener_components.upb.c +138 -0
  97. data/src/core/ext/upb-generated/envoy/config/listener/v3/listener_components.upb.h +490 -0
  98. data/src/core/ext/upb-generated/envoy/config/listener/v3/udp_listener_config.upb.c +41 -0
  99. data/src/core/ext/upb-generated/envoy/config/listener/v3/udp_listener_config.upb.h +94 -0
  100. data/src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.c +174 -0
  101. data/src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.h +599 -0
  102. data/src/core/ext/upb-generated/envoy/config/route/v3/route.upb.c +63 -0
  103. data/src/core/ext/upb-generated/envoy/config/route/v3/route.upb.h +204 -0
  104. data/src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.c +773 -0
  105. data/src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.h +2855 -0
  106. data/src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.c +59 -0
  107. data/src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.h +135 -0
  108. data/src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.c +50 -0
  109. data/src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.h +108 -0
  110. data/src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c +312 -0
  111. data/src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h +1125 -0
  112. data/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c +20 -0
  113. data/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.h +34 -0
  114. data/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.c +111 -0
  115. data/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/common.upb.h +401 -0
  116. data/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/secret.upb.c +72 -0
  117. data/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/secret.upb.h +198 -0
  118. data/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/tls.upb.c +105 -0
  119. data/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/tls.upb.h +388 -0
  120. data/src/core/ext/upb-generated/envoy/{api/v2 → service/cluster/v3}/cds.upb.c +5 -6
  121. data/src/core/ext/upb-generated/envoy/service/cluster/v3/cds.upb.h +49 -0
  122. data/src/core/ext/upb-generated/envoy/service/discovery/{v2 → v3}/ads.upb.c +5 -4
  123. data/src/core/ext/upb-generated/envoy/service/discovery/v3/ads.upb.h +49 -0
  124. data/src/core/ext/upb-generated/envoy/service/discovery/v3/discovery.upb.c +129 -0
  125. data/src/core/ext/upb-generated/envoy/service/discovery/v3/discovery.upb.h +386 -0
  126. data/src/core/ext/upb-generated/envoy/{api/v2 → service/endpoint/v3}/eds.upb.c +5 -6
  127. data/src/core/ext/upb-generated/envoy/service/endpoint/v3/eds.upb.h +49 -0
  128. data/src/core/ext/upb-generated/envoy/{api/v2 → service/listener/v3}/lds.upb.c +5 -6
  129. data/src/core/ext/upb-generated/envoy/service/listener/v3/lds.upb.h +49 -0
  130. data/src/core/ext/upb-generated/envoy/service/load_stats/v3/lrs.upb.c +55 -0
  131. data/src/core/ext/upb-generated/envoy/service/load_stats/v3/lrs.upb.h +136 -0
  132. data/src/core/ext/upb-generated/envoy/{api/v2 → service/route/v3}/rds.upb.c +5 -6
  133. data/src/core/ext/upb-generated/envoy/service/route/v3/rds.upb.h +49 -0
  134. data/src/core/ext/upb-generated/envoy/{api/v2 → service/route/v3}/srds.upb.c +5 -6
  135. data/src/core/ext/upb-generated/envoy/service/route/v3/srds.upb.h +49 -0
  136. data/src/core/ext/upb-generated/envoy/type/matcher/v3/metadata.upb.c +47 -0
  137. data/src/core/ext/upb-generated/envoy/type/matcher/v3/metadata.upb.h +114 -0
  138. data/src/core/ext/upb-generated/envoy/type/matcher/v3/number.upb.c +35 -0
  139. data/src/core/ext/upb-generated/envoy/type/matcher/v3/number.upb.h +77 -0
  140. data/src/core/ext/upb-generated/envoy/type/matcher/v3/path.upb.c +34 -0
  141. data/src/core/ext/upb-generated/envoy/type/matcher/v3/path.upb.h +71 -0
  142. data/src/core/ext/upb-generated/envoy/type/matcher/v3/regex.upb.c +64 -0
  143. data/src/core/ext/upb-generated/envoy/type/matcher/v3/regex.upb.h +145 -0
  144. data/src/core/ext/upb-generated/envoy/type/matcher/v3/string.upb.c +53 -0
  145. data/src/core/ext/upb-generated/envoy/type/matcher/v3/string.upb.h +127 -0
  146. data/src/core/ext/upb-generated/envoy/type/matcher/v3/value.upb.c +63 -0
  147. data/src/core/ext/upb-generated/envoy/type/matcher/v3/value.upb.h +188 -0
  148. data/src/core/ext/upb-generated/envoy/type/metadata/v3/metadata.upb.c +88 -0
  149. data/src/core/ext/upb-generated/envoy/type/metadata/v3/metadata.upb.h +258 -0
  150. data/src/core/ext/upb-generated/envoy/type/tracing/v3/custom_tag.upb.c +90 -0
  151. data/src/core/ext/upb-generated/envoy/type/tracing/v3/custom_tag.upb.h +250 -0
  152. data/src/core/ext/upb-generated/envoy/type/{http.upb.c → v3/http.upb.c} +2 -2
  153. data/src/core/ext/upb-generated/envoy/type/{http.upb.h → v3/http.upb.h} +8 -8
  154. data/src/core/ext/upb-generated/envoy/type/{percent.upb.c → v3/percent.upb.c} +9 -8
  155. data/src/core/ext/upb-generated/envoy/type/v3/percent.upb.h +86 -0
  156. data/src/core/ext/upb-generated/envoy/type/{range.upb.c → v3/range.upb.c} +12 -11
  157. data/src/core/ext/upb-generated/envoy/type/v3/range.upb.h +111 -0
  158. data/src/core/ext/upb-generated/envoy/type/{semantic_version.upb.c → v3/semantic_version.upb.c} +6 -5
  159. data/src/core/ext/upb-generated/envoy/type/v3/semantic_version.upb.h +61 -0
  160. data/src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.c +234 -0
  161. data/src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.h +759 -0
  162. data/src/core/ext/upb-generated/google/protobuf/descriptor.upb.c +36 -36
  163. data/src/core/ext/upb-generated/google/protobuf/struct.upb.h +1 -1
  164. data/src/core/ext/upb-generated/udpa/annotations/versioning.upb.c +27 -0
  165. data/src/core/ext/upb-generated/udpa/annotations/versioning.upb.h +53 -0
  166. data/src/core/ext/upb-generated/validate/validate.upb.c +11 -11
  167. data/src/core/ext/upb-generated/validate/validate.upb.h +1 -1
  168. data/src/core/ext/{filters/client_channel/xds → xds}/xds_api.cc +1045 -767
  169. data/src/core/ext/{filters/client_channel/xds → xds}/xds_api.h +114 -99
  170. data/src/core/ext/{filters/client_channel/xds → xds}/xds_bootstrap.cc +44 -2
  171. data/src/core/ext/{filters/client_channel/xds → xds}/xds_bootstrap.h +8 -3
  172. data/src/core/ext/{filters/client_channel/xds → xds}/xds_channel.h +4 -4
  173. data/src/core/ext/{filters/client_channel/xds → xds}/xds_channel_args.h +3 -3
  174. data/src/core/ext/{filters/client_channel/xds → xds}/xds_channel_secure.cc +2 -5
  175. data/src/core/ext/{filters/client_channel/xds → xds}/xds_client.cc +85 -417
  176. data/src/core/ext/{filters/client_channel/xds → xds}/xds_client.h +12 -45
  177. data/src/core/ext/{filters/client_channel/xds → xds}/xds_client_stats.cc +2 -2
  178. data/src/core/ext/{filters/client_channel/xds → xds}/xds_client_stats.h +3 -3
  179. data/src/core/lib/channel/channelz.cc +14 -15
  180. data/src/core/lib/channel/channelz.h +1 -1
  181. data/src/core/lib/channel/channelz_registry.cc +3 -1
  182. data/src/core/lib/gpr/sync_posix.cc +2 -8
  183. data/src/core/lib/iomgr/endpoint.cc +5 -1
  184. data/src/core/lib/iomgr/endpoint.h +7 -3
  185. data/src/core/lib/iomgr/endpoint_cfstream.cc +32 -11
  186. data/src/core/lib/iomgr/ev_posix.cc +0 -2
  187. data/src/core/lib/iomgr/iomgr.cc +0 -10
  188. data/src/core/lib/iomgr/iomgr.h +0 -10
  189. data/src/core/{ext/filters/client_channel → lib/iomgr}/parse_address.cc +1 -1
  190. data/src/core/{ext/filters/client_channel → lib/iomgr}/parse_address.h +3 -3
  191. data/src/core/lib/iomgr/sockaddr_utils.cc +2 -1
  192. data/src/core/lib/iomgr/sockaddr_utils.h +2 -1
  193. data/src/core/lib/iomgr/tcp_custom.cc +32 -16
  194. data/src/core/lib/iomgr/tcp_posix.cc +31 -13
  195. data/src/core/lib/iomgr/tcp_windows.cc +26 -10
  196. data/src/core/lib/security/authorization/authorization_engine.cc +177 -0
  197. data/src/core/lib/security/authorization/authorization_engine.h +84 -0
  198. data/src/core/lib/security/authorization/evaluate_args.cc +153 -0
  199. data/src/core/lib/security/authorization/evaluate_args.h +59 -0
  200. data/src/core/lib/security/authorization/mock_cel/activation.h +57 -0
  201. data/src/core/lib/security/authorization/mock_cel/cel_expr_builder_factory.h +42 -0
  202. data/src/core/lib/security/authorization/mock_cel/cel_expression.h +68 -0
  203. data/src/core/lib/security/authorization/mock_cel/cel_value.h +93 -0
  204. data/src/core/lib/security/authorization/mock_cel/evaluator_core.h +67 -0
  205. data/src/core/lib/security/authorization/mock_cel/flat_expr_builder.h +56 -0
  206. data/src/core/lib/security/authorization/mock_cel/statusor.h +50 -0
  207. data/src/core/lib/security/credentials/google_default/google_default_credentials.cc +56 -38
  208. data/src/core/lib/security/security_connector/fake/fake_security_connector.cc +1 -2
  209. data/src/core/lib/security/transport/secure_endpoint.cc +7 -1
  210. data/src/core/lib/surface/call.cc +12 -12
  211. data/src/core/lib/surface/call.h +2 -1
  212. data/src/core/lib/surface/channel.cc +28 -20
  213. data/src/core/lib/surface/channel.h +12 -2
  214. data/src/core/lib/surface/completion_queue.cc +10 -272
  215. data/src/core/lib/surface/completion_queue.h +0 -8
  216. data/src/core/lib/surface/init.cc +1 -3
  217. data/src/core/lib/surface/server.cc +1066 -1244
  218. data/src/core/lib/surface/server.h +363 -87
  219. data/src/core/lib/surface/version.cc +2 -2
  220. data/src/core/lib/transport/authority_override.cc +38 -0
  221. data/src/core/lib/transport/authority_override.h +32 -0
  222. data/src/core/lib/transport/connectivity_state.cc +18 -13
  223. data/src/core/lib/transport/connectivity_state.h +18 -6
  224. data/src/core/lib/transport/error_utils.cc +13 -0
  225. data/src/core/lib/transport/error_utils.h +6 -0
  226. data/src/core/lib/transport/static_metadata.cc +295 -276
  227. data/src/core/lib/transport/static_metadata.h +80 -73
  228. data/src/core/lib/transport/transport.h +7 -0
  229. data/src/core/lib/uri/uri_parser.cc +23 -21
  230. data/src/core/lib/uri/uri_parser.h +3 -1
  231. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc +22 -0
  232. data/src/core/tsi/ssl_transport_security.cc +3 -9
  233. data/src/ruby/ext/grpc/rb_channel_credentials.c +9 -0
  234. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +2 -2
  235. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +4 -4
  236. data/src/ruby/lib/grpc/version.rb +1 -1
  237. data/src/ruby/spec/channel_credentials_spec.rb +10 -0
  238. data/src/ruby/spec/generic/active_call_spec.rb +19 -8
  239. data/third_party/abseil-cpp/absl/algorithm/container.h +1727 -0
  240. data/third_party/abseil-cpp/absl/base/internal/direct_mmap.h +161 -0
  241. data/third_party/abseil-cpp/absl/base/internal/exponential_biased.cc +93 -0
  242. data/third_party/abseil-cpp/absl/base/internal/exponential_biased.h +130 -0
  243. data/third_party/abseil-cpp/absl/base/internal/low_level_alloc.cc +620 -0
  244. data/third_party/abseil-cpp/absl/base/internal/low_level_alloc.h +126 -0
  245. data/third_party/abseil-cpp/absl/container/fixed_array.h +515 -0
  246. data/third_party/abseil-cpp/absl/container/flat_hash_set.h +503 -0
  247. data/third_party/abseil-cpp/absl/container/internal/common.h +202 -0
  248. data/third_party/abseil-cpp/absl/container/internal/container_memory.h +440 -0
  249. data/third_party/abseil-cpp/absl/container/internal/hash_function_defaults.h +146 -0
  250. data/third_party/abseil-cpp/absl/container/internal/hash_policy_traits.h +191 -0
  251. data/third_party/abseil-cpp/absl/container/internal/hashtable_debug_hooks.h +85 -0
  252. data/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.cc +269 -0
  253. data/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.h +297 -0
  254. data/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler_force_weak_definition.cc +30 -0
  255. data/third_party/abseil-cpp/absl/container/internal/have_sse.h +49 -0
  256. data/third_party/abseil-cpp/absl/container/internal/layout.h +741 -0
  257. data/third_party/abseil-cpp/absl/container/internal/raw_hash_set.cc +48 -0
  258. data/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h +1882 -0
  259. data/third_party/abseil-cpp/absl/debugging/internal/address_is_readable.cc +138 -0
  260. data/third_party/abseil-cpp/absl/debugging/internal/address_is_readable.h +32 -0
  261. data/third_party/abseil-cpp/absl/debugging/internal/demangle.cc +1895 -0
  262. data/third_party/abseil-cpp/absl/debugging/internal/demangle.h +71 -0
  263. data/third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.cc +382 -0
  264. data/third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.h +134 -0
  265. data/third_party/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc +192 -0
  266. data/third_party/abseil-cpp/absl/debugging/internal/stacktrace_arm-inl.inc +125 -0
  267. data/third_party/abseil-cpp/absl/debugging/internal/stacktrace_config.h +70 -0
  268. data/third_party/abseil-cpp/absl/debugging/internal/stacktrace_generic-inl.inc +99 -0
  269. data/third_party/abseil-cpp/absl/debugging/internal/stacktrace_powerpc-inl.inc +248 -0
  270. data/third_party/abseil-cpp/absl/debugging/internal/stacktrace_unimplemented-inl.inc +24 -0
  271. data/third_party/abseil-cpp/absl/debugging/internal/stacktrace_win32-inl.inc +85 -0
  272. data/third_party/abseil-cpp/absl/debugging/internal/stacktrace_x86-inl.inc +346 -0
  273. data/third_party/abseil-cpp/absl/debugging/internal/symbolize.h +128 -0
  274. data/third_party/abseil-cpp/absl/debugging/internal/vdso_support.cc +194 -0
  275. data/third_party/abseil-cpp/absl/debugging/internal/vdso_support.h +158 -0
  276. data/third_party/abseil-cpp/absl/debugging/stacktrace.cc +140 -0
  277. data/third_party/abseil-cpp/absl/debugging/stacktrace.h +231 -0
  278. data/third_party/abseil-cpp/absl/debugging/symbolize.cc +25 -0
  279. data/third_party/abseil-cpp/absl/debugging/symbolize.h +99 -0
  280. data/third_party/abseil-cpp/absl/debugging/symbolize_elf.inc +1480 -0
  281. data/third_party/abseil-cpp/absl/debugging/symbolize_unimplemented.inc +40 -0
  282. data/third_party/abseil-cpp/absl/debugging/symbolize_win32.inc +81 -0
  283. data/third_party/abseil-cpp/absl/functional/function_ref.h +139 -0
  284. data/third_party/abseil-cpp/absl/functional/internal/function_ref.h +106 -0
  285. data/third_party/abseil-cpp/absl/hash/hash.h +324 -0
  286. data/third_party/abseil-cpp/absl/hash/internal/city.cc +346 -0
  287. data/third_party/abseil-cpp/absl/hash/internal/city.h +96 -0
  288. data/third_party/abseil-cpp/absl/hash/internal/hash.cc +55 -0
  289. data/third_party/abseil-cpp/absl/hash/internal/hash.h +988 -0
  290. data/third_party/abseil-cpp/absl/status/status.cc +447 -0
  291. data/third_party/abseil-cpp/absl/status/status.h +428 -0
  292. data/third_party/abseil-cpp/absl/status/status_payload_printer.cc +43 -0
  293. data/third_party/abseil-cpp/absl/status/status_payload_printer.h +51 -0
  294. data/third_party/abseil-cpp/absl/strings/cord.cc +2019 -0
  295. data/third_party/abseil-cpp/absl/strings/cord.h +1121 -0
  296. data/third_party/abseil-cpp/absl/strings/internal/cord_internal.h +151 -0
  297. data/third_party/abseil-cpp/absl/synchronization/barrier.cc +52 -0
  298. data/third_party/abseil-cpp/absl/synchronization/barrier.h +79 -0
  299. data/third_party/abseil-cpp/absl/synchronization/blocking_counter.cc +57 -0
  300. data/third_party/abseil-cpp/absl/synchronization/blocking_counter.h +99 -0
  301. data/third_party/abseil-cpp/absl/synchronization/internal/create_thread_identity.cc +140 -0
  302. data/third_party/abseil-cpp/absl/synchronization/internal/create_thread_identity.h +60 -0
  303. data/third_party/abseil-cpp/absl/synchronization/internal/graphcycles.cc +697 -0
  304. data/third_party/abseil-cpp/absl/synchronization/internal/graphcycles.h +141 -0
  305. data/third_party/abseil-cpp/absl/synchronization/internal/kernel_timeout.h +155 -0
  306. data/third_party/abseil-cpp/absl/synchronization/internal/mutex_nonprod.inc +261 -0
  307. data/third_party/abseil-cpp/absl/synchronization/internal/per_thread_sem.cc +106 -0
  308. data/third_party/abseil-cpp/absl/synchronization/internal/per_thread_sem.h +115 -0
  309. data/third_party/abseil-cpp/absl/synchronization/internal/waiter.cc +484 -0
  310. data/third_party/abseil-cpp/absl/synchronization/internal/waiter.h +159 -0
  311. data/third_party/abseil-cpp/absl/synchronization/mutex.cc +2728 -0
  312. data/third_party/abseil-cpp/absl/synchronization/mutex.h +1056 -0
  313. data/third_party/abseil-cpp/absl/synchronization/notification.cc +78 -0
  314. data/third_party/abseil-cpp/absl/synchronization/notification.h +123 -0
  315. data/third_party/abseil-cpp/absl/types/bad_variant_access.cc +64 -0
  316. data/third_party/abseil-cpp/absl/types/bad_variant_access.h +82 -0
  317. data/third_party/abseil-cpp/absl/types/internal/variant.h +1646 -0
  318. data/third_party/abseil-cpp/absl/types/variant.h +861 -0
  319. data/third_party/boringssl-with-bazel/err_data.c +263 -257
  320. data/third_party/boringssl-with-bazel/src/crypto/evp/evp_asn1.c +16 -0
  321. data/third_party/boringssl-with-bazel/src/crypto/hpke/hpke.c +456 -0
  322. data/third_party/boringssl-with-bazel/src/crypto/hpke/internal.h +192 -0
  323. data/third_party/boringssl-with-bazel/src/crypto/x509/x_sig.c +20 -0
  324. data/third_party/boringssl-with-bazel/src/include/openssl/arm_arch.h +52 -0
  325. data/third_party/boringssl-with-bazel/src/include/openssl/base.h +1 -1
  326. data/third_party/boringssl-with-bazel/src/include/openssl/ssl.h +39 -7
  327. data/third_party/boringssl-with-bazel/src/include/openssl/tls1.h +2 -3
  328. data/third_party/boringssl-with-bazel/src/include/openssl/x509.h +11 -0
  329. data/third_party/boringssl-with-bazel/src/ssl/internal.h +4 -0
  330. data/third_party/boringssl-with-bazel/src/ssl/ssl_cert.cc +3 -6
  331. data/third_party/boringssl-with-bazel/src/ssl/ssl_lib.cc +10 -0
  332. data/third_party/boringssl-with-bazel/src/ssl/t1_lib.cc +34 -9
  333. data/third_party/boringssl-with-bazel/src/ssl/tls13_server.cc +5 -0
  334. data/third_party/boringssl-with-bazel/src/ssl/tls_record.cc +5 -3
  335. data/third_party/upb/upb/decode.c +64 -15
  336. data/third_party/upb/upb/encode.c +2 -2
  337. data/third_party/upb/upb/msg.h +2 -2
  338. data/third_party/upb/upb/port_def.inc +1 -1
  339. data/third_party/upb/upb/table.c +0 -11
  340. data/third_party/upb/upb/table.int.h +0 -9
  341. data/third_party/upb/upb/upb.c +16 -14
  342. data/third_party/upb/upb/upb.h +26 -0
  343. data/third_party/upb/upb/upb.hpp +2 -0
  344. metadata +257 -155
  345. data/src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c +0 -21
  346. data/src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.h +0 -34
  347. data/src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.c +0 -114
  348. data/src/core/ext/upb-generated/envoy/api/v2/auth/common.upb.h +0 -429
  349. data/src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.c +0 -72
  350. data/src/core/ext/upb-generated/envoy/api/v2/auth/secret.upb.h +0 -198
  351. data/src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.c +0 -105
  352. data/src/core/ext/upb-generated/envoy/api/v2/auth/tls.upb.h +0 -388
  353. data/src/core/ext/upb-generated/envoy/api/v2/cds.upb.h +0 -52
  354. data/src/core/ext/upb-generated/envoy/api/v2/cluster.upb.c +0 -403
  355. data/src/core/ext/upb-generated/envoy/api/v2/cluster.upb.h +0 -1453
  356. data/src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.c +0 -74
  357. data/src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.h +0 -226
  358. data/src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.h +0 -69
  359. data/src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.h +0 -323
  360. data/src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c +0 -112
  361. data/src/core/ext/upb-generated/envoy/api/v2/core/address.upb.h +0 -334
  362. data/src/core/ext/upb-generated/envoy/api/v2/core/backoff.upb.h +0 -79
  363. data/src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c +0 -313
  364. data/src/core/ext/upb-generated/envoy/api/v2/core/base.upb.h +0 -891
  365. data/src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c +0 -96
  366. data/src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.h +0 -328
  367. data/src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.c +0 -34
  368. data/src/core/ext/upb-generated/envoy/api/v2/core/event_service_config.upb.h +0 -71
  369. data/src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c +0 -197
  370. data/src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.h +0 -649
  371. data/src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c +0 -172
  372. data/src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.h +0 -693
  373. data/src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.h +0 -80
  374. data/src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c +0 -152
  375. data/src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.h +0 -536
  376. data/src/core/ext/upb-generated/envoy/api/v2/core/socket_option.upb.h +0 -88
  377. data/src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c +0 -129
  378. data/src/core/ext/upb-generated/envoy/api/v2/discovery.upb.h +0 -386
  379. data/src/core/ext/upb-generated/envoy/api/v2/eds.upb.h +0 -52
  380. data/src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.c +0 -92
  381. data/src/core/ext/upb-generated/envoy/api/v2/endpoint.upb.h +0 -224
  382. data/src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.c +0 -18
  383. data/src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.h +0 -32
  384. data/src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upb.c +0 -91
  385. data/src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint_components.upb.h +0 -273
  386. data/src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.c +0 -112
  387. data/src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.h +0 -332
  388. data/src/core/ext/upb-generated/envoy/api/v2/lds.upb.h +0 -52
  389. data/src/core/ext/upb-generated/envoy/api/v2/listener.upb.c +0 -109
  390. data/src/core/ext/upb-generated/envoy/api/v2/listener.upb.h +0 -415
  391. data/src/core/ext/upb-generated/envoy/api/v2/listener/listener.upb.c +0 -18
  392. data/src/core/ext/upb-generated/envoy/api/v2/listener/listener.upb.h +0 -32
  393. data/src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upb.c +0 -145
  394. data/src/core/ext/upb-generated/envoy/api/v2/listener/listener_components.upb.h +0 -538
  395. data/src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upb.c +0 -43
  396. data/src/core/ext/upb-generated/envoy/api/v2/listener/udp_listener_config.upb.h +0 -111
  397. data/src/core/ext/upb-generated/envoy/api/v2/rds.upb.h +0 -52
  398. data/src/core/ext/upb-generated/envoy/api/v2/route.upb.c +0 -63
  399. data/src/core/ext/upb-generated/envoy/api/v2/route.upb.h +0 -204
  400. data/src/core/ext/upb-generated/envoy/api/v2/route/route.upb.c +0 -18
  401. data/src/core/ext/upb-generated/envoy/api/v2/route/route.upb.h +0 -32
  402. data/src/core/ext/upb-generated/envoy/api/v2/route/route_components.upb.c +0 -815
  403. data/src/core/ext/upb-generated/envoy/api/v2/route/route_components.upb.h +0 -2984
  404. data/src/core/ext/upb-generated/envoy/api/v2/scoped_route.upb.c +0 -59
  405. data/src/core/ext/upb-generated/envoy/api/v2/scoped_route.upb.h +0 -135
  406. data/src/core/ext/upb-generated/envoy/api/v2/srds.upb.h +0 -52
  407. data/src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.c +0 -228
  408. data/src/core/ext/upb-generated/envoy/config/filter/accesslog/v2/accesslog.upb.h +0 -732
  409. data/src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.c +0 -316
  410. data/src/core/ext/upb-generated/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.upb.h +0 -1167
  411. data/src/core/ext/upb-generated/envoy/config/listener/v2/api_listener.upb.h +0 -65
  412. data/src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.c +0 -51
  413. data/src/core/ext/upb-generated/envoy/config/trace/v2/http_tracer.upb.h +0 -125
  414. data/src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.h +0 -49
  415. data/src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c +0 -54
  416. data/src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.h +0 -136
  417. data/src/core/ext/upb-generated/envoy/type/matcher/regex.upb.c +0 -63
  418. data/src/core/ext/upb-generated/envoy/type/matcher/regex.upb.h +0 -145
  419. data/src/core/ext/upb-generated/envoy/type/matcher/string.upb.c +0 -53
  420. data/src/core/ext/upb-generated/envoy/type/matcher/string.upb.h +0 -133
  421. data/src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upb.c +0 -88
  422. data/src/core/ext/upb-generated/envoy/type/metadata/v2/metadata.upb.h +0 -258
  423. data/src/core/ext/upb-generated/envoy/type/percent.upb.h +0 -86
  424. data/src/core/ext/upb-generated/envoy/type/range.upb.h +0 -111
  425. data/src/core/ext/upb-generated/envoy/type/semantic_version.upb.h +0 -61
  426. data/src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upb.c +0 -89
  427. data/src/core/ext/upb-generated/envoy/type/tracing/v2/custom_tag.upb.h +0 -250
  428. data/src/core/lib/security/transport/target_authority_table.cc +0 -75
  429. data/src/core/lib/security/transport/target_authority_table.h +0 -40
  430. data/src/core/lib/slice/slice_hash_table.h +0 -199
  431. data/src/core/lib/slice/slice_weak_hash_table.h +0 -102
@@ -0,0 +1,159 @@
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
+
16
+ #ifndef ABSL_SYNCHRONIZATION_INTERNAL_WAITER_H_
17
+ #define ABSL_SYNCHRONIZATION_INTERNAL_WAITER_H_
18
+
19
+ #include "absl/base/config.h"
20
+
21
+ #ifdef _WIN32
22
+ #include <sdkddkver.h>
23
+ #else
24
+ #include <pthread.h>
25
+ #endif
26
+
27
+ #ifdef __linux__
28
+ #include <linux/futex.h>
29
+ #endif
30
+
31
+ #ifdef ABSL_HAVE_SEMAPHORE_H
32
+ #include <semaphore.h>
33
+ #endif
34
+
35
+ #include <atomic>
36
+ #include <cstdint>
37
+
38
+ #include "absl/base/internal/thread_identity.h"
39
+ #include "absl/synchronization/internal/kernel_timeout.h"
40
+
41
+ // May be chosen at compile time via -DABSL_FORCE_WAITER_MODE=<index>
42
+ #define ABSL_WAITER_MODE_FUTEX 0
43
+ #define ABSL_WAITER_MODE_SEM 1
44
+ #define ABSL_WAITER_MODE_CONDVAR 2
45
+ #define ABSL_WAITER_MODE_WIN32 3
46
+
47
+ #if defined(ABSL_FORCE_WAITER_MODE)
48
+ #define ABSL_WAITER_MODE ABSL_FORCE_WAITER_MODE
49
+ #elif defined(_WIN32) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
50
+ #define ABSL_WAITER_MODE ABSL_WAITER_MODE_WIN32
51
+ #elif defined(__BIONIC__)
52
+ // Bionic supports all the futex operations we need even when some of the futex
53
+ // definitions are missing.
54
+ #define ABSL_WAITER_MODE ABSL_WAITER_MODE_FUTEX
55
+ #elif defined(__linux__) && defined(FUTEX_CLOCK_REALTIME)
56
+ // FUTEX_CLOCK_REALTIME requires Linux >= 2.6.28.
57
+ #define ABSL_WAITER_MODE ABSL_WAITER_MODE_FUTEX
58
+ #elif defined(ABSL_HAVE_SEMAPHORE_H)
59
+ #define ABSL_WAITER_MODE ABSL_WAITER_MODE_SEM
60
+ #else
61
+ #define ABSL_WAITER_MODE ABSL_WAITER_MODE_CONDVAR
62
+ #endif
63
+
64
+ namespace absl {
65
+ ABSL_NAMESPACE_BEGIN
66
+ namespace synchronization_internal {
67
+
68
+ // Waiter is an OS-specific semaphore.
69
+ class Waiter {
70
+ public:
71
+ // Prepare any data to track waits.
72
+ Waiter();
73
+
74
+ // Not copyable or movable
75
+ Waiter(const Waiter&) = delete;
76
+ Waiter& operator=(const Waiter&) = delete;
77
+
78
+ // Destroy any data to track waits.
79
+ ~Waiter();
80
+
81
+ // Blocks the calling thread until a matching call to `Post()` or
82
+ // `t` has passed. Returns `true` if woken (`Post()` called),
83
+ // `false` on timeout.
84
+ bool Wait(KernelTimeout t);
85
+
86
+ // Restart the caller of `Wait()` as with a normal semaphore.
87
+ void Post();
88
+
89
+ // If anyone is waiting, wake them up temporarily and cause them to
90
+ // call `MaybeBecomeIdle()`. They will then return to waiting for a
91
+ // `Post()` or timeout.
92
+ void Poke();
93
+
94
+ // Returns the Waiter associated with the identity.
95
+ static Waiter* GetWaiter(base_internal::ThreadIdentity* identity) {
96
+ static_assert(
97
+ sizeof(Waiter) <= sizeof(base_internal::ThreadIdentity::WaiterState),
98
+ "Insufficient space for Waiter");
99
+ return reinterpret_cast<Waiter*>(identity->waiter_state.data);
100
+ }
101
+
102
+ // How many periods to remain idle before releasing resources
103
+ #ifndef THREAD_SANITIZER
104
+ static const int kIdlePeriods = 60;
105
+ #else
106
+ // Memory consumption under ThreadSanitizer is a serious concern,
107
+ // so we release resources sooner. The value of 1 leads to 1 to 2 second
108
+ // delay before marking a thread as idle.
109
+ static const int kIdlePeriods = 1;
110
+ #endif
111
+
112
+ private:
113
+ #if ABSL_WAITER_MODE == ABSL_WAITER_MODE_FUTEX
114
+ // Futexes are defined by specification to be 32-bits.
115
+ // Thus std::atomic<int32_t> must be just an int32_t with lockfree methods.
116
+ std::atomic<int32_t> futex_;
117
+ static_assert(sizeof(int32_t) == sizeof(futex_), "Wrong size for futex");
118
+
119
+ #elif ABSL_WAITER_MODE == ABSL_WAITER_MODE_CONDVAR
120
+ // REQUIRES: mu_ must be held.
121
+ void InternalCondVarPoke();
122
+
123
+ pthread_mutex_t mu_;
124
+ pthread_cond_t cv_;
125
+ int waiter_count_;
126
+ int wakeup_count_; // Unclaimed wakeups.
127
+
128
+ #elif ABSL_WAITER_MODE == ABSL_WAITER_MODE_SEM
129
+ sem_t sem_;
130
+ // This seems superfluous, but for Poke() we need to cause spurious
131
+ // wakeups on the semaphore. Hence we can't actually use the
132
+ // semaphore's count.
133
+ std::atomic<int> wakeups_;
134
+
135
+ #elif ABSL_WAITER_MODE == ABSL_WAITER_MODE_WIN32
136
+ // WinHelper - Used to define utilities for accessing the lock and
137
+ // condition variable storage once the types are complete.
138
+ class WinHelper;
139
+
140
+ // REQUIRES: WinHelper::GetLock(this) must be held.
141
+ void InternalCondVarPoke();
142
+
143
+ // We can't include Windows.h in our headers, so we use aligned charachter
144
+ // buffers to define the storage of SRWLOCK and CONDITION_VARIABLE.
145
+ alignas(void*) unsigned char mu_storage_[sizeof(void*)];
146
+ alignas(void*) unsigned char cv_storage_[sizeof(void*)];
147
+ int waiter_count_;
148
+ int wakeup_count_;
149
+
150
+ #else
151
+ #error Unknown ABSL_WAITER_MODE
152
+ #endif
153
+ };
154
+
155
+ } // namespace synchronization_internal
156
+ ABSL_NAMESPACE_END
157
+ } // namespace absl
158
+
159
+ #endif // ABSL_SYNCHRONIZATION_INTERNAL_WAITER_H_
@@ -0,0 +1,2728 @@
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/synchronization/mutex.h"
16
+
17
+ #ifdef _WIN32
18
+ #include <windows.h>
19
+ #ifdef ERROR
20
+ #undef ERROR
21
+ #endif
22
+ #else
23
+ #include <fcntl.h>
24
+ #include <pthread.h>
25
+ #include <sched.h>
26
+ #include <sys/time.h>
27
+ #endif
28
+
29
+ #include <assert.h>
30
+ #include <errno.h>
31
+ #include <stdio.h>
32
+ #include <stdlib.h>
33
+ #include <string.h>
34
+ #include <time.h>
35
+
36
+ #include <algorithm>
37
+ #include <atomic>
38
+ #include <cinttypes>
39
+ #include <thread> // NOLINT(build/c++11)
40
+
41
+ #include "absl/base/attributes.h"
42
+ #include "absl/base/config.h"
43
+ #include "absl/base/dynamic_annotations.h"
44
+ #include "absl/base/internal/atomic_hook.h"
45
+ #include "absl/base/internal/cycleclock.h"
46
+ #include "absl/base/internal/hide_ptr.h"
47
+ #include "absl/base/internal/low_level_alloc.h"
48
+ #include "absl/base/internal/raw_logging.h"
49
+ #include "absl/base/internal/spinlock.h"
50
+ #include "absl/base/internal/sysinfo.h"
51
+ #include "absl/base/internal/thread_identity.h"
52
+ #include "absl/base/port.h"
53
+ #include "absl/debugging/stacktrace.h"
54
+ #include "absl/debugging/symbolize.h"
55
+ #include "absl/synchronization/internal/graphcycles.h"
56
+ #include "absl/synchronization/internal/per_thread_sem.h"
57
+ #include "absl/time/time.h"
58
+
59
+ using absl::base_internal::CurrentThreadIdentityIfPresent;
60
+ using absl::base_internal::PerThreadSynch;
61
+ using absl::base_internal::ThreadIdentity;
62
+ using absl::synchronization_internal::GetOrCreateCurrentThreadIdentity;
63
+ using absl::synchronization_internal::GraphCycles;
64
+ using absl::synchronization_internal::GraphId;
65
+ using absl::synchronization_internal::InvalidGraphId;
66
+ using absl::synchronization_internal::KernelTimeout;
67
+ using absl::synchronization_internal::PerThreadSem;
68
+
69
+ extern "C" {
70
+ ABSL_ATTRIBUTE_WEAK void AbslInternalMutexYield() { std::this_thread::yield(); }
71
+ } // extern "C"
72
+
73
+ namespace absl {
74
+ ABSL_NAMESPACE_BEGIN
75
+
76
+ namespace {
77
+
78
+ #if defined(THREAD_SANITIZER)
79
+ constexpr OnDeadlockCycle kDeadlockDetectionDefault = OnDeadlockCycle::kIgnore;
80
+ #else
81
+ constexpr OnDeadlockCycle kDeadlockDetectionDefault = OnDeadlockCycle::kAbort;
82
+ #endif
83
+
84
+ ABSL_CONST_INIT std::atomic<OnDeadlockCycle> synch_deadlock_detection(
85
+ kDeadlockDetectionDefault);
86
+ ABSL_CONST_INIT std::atomic<bool> synch_check_invariants(false);
87
+
88
+ // ------------------------------------------ spinlock support
89
+
90
+ // Make sure read-only globals used in the Mutex code are contained on the
91
+ // same cacheline and cacheline aligned to eliminate any false sharing with
92
+ // other globals from this and other modules.
93
+ static struct MutexGlobals {
94
+ MutexGlobals() {
95
+ // Find machine-specific data needed for Delay() and
96
+ // TryAcquireWithSpinning(). This runs in the global constructor
97
+ // sequence, and before that zeros are safe values.
98
+ num_cpus = absl::base_internal::NumCPUs();
99
+ spinloop_iterations = num_cpus > 1 ? 1500 : 0;
100
+ }
101
+ int num_cpus;
102
+ int spinloop_iterations;
103
+ // Pad this struct to a full cacheline to prevent false sharing.
104
+ char padding[ABSL_CACHELINE_SIZE - 2 * sizeof(int)];
105
+ } ABSL_CACHELINE_ALIGNED mutex_globals;
106
+ static_assert(
107
+ sizeof(MutexGlobals) == ABSL_CACHELINE_SIZE,
108
+ "MutexGlobals must occupy an entire cacheline to prevent false sharing");
109
+
110
+ ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
111
+ absl::base_internal::AtomicHook<void (*)(int64_t wait_cycles)>
112
+ submit_profile_data;
113
+ ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES absl::base_internal::AtomicHook<void (*)(
114
+ const char *msg, const void *obj, int64_t wait_cycles)>
115
+ mutex_tracer;
116
+ ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
117
+ absl::base_internal::AtomicHook<void (*)(const char *msg, const void *cv)>
118
+ cond_var_tracer;
119
+ ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES absl::base_internal::AtomicHook<
120
+ bool (*)(const void *pc, char *out, int out_size)>
121
+ symbolizer(absl::Symbolize);
122
+
123
+ } // namespace
124
+
125
+ static inline bool EvalConditionAnnotated(const Condition *cond, Mutex *mu,
126
+ bool locking, bool trylock,
127
+ bool read_lock);
128
+
129
+ void RegisterMutexProfiler(void (*fn)(int64_t wait_timestamp)) {
130
+ submit_profile_data.Store(fn);
131
+ }
132
+
133
+ void RegisterMutexTracer(void (*fn)(const char *msg, const void *obj,
134
+ int64_t wait_cycles)) {
135
+ mutex_tracer.Store(fn);
136
+ }
137
+
138
+ void RegisterCondVarTracer(void (*fn)(const char *msg, const void *cv)) {
139
+ cond_var_tracer.Store(fn);
140
+ }
141
+
142
+ void RegisterSymbolizer(bool (*fn)(const void *pc, char *out, int out_size)) {
143
+ symbolizer.Store(fn);
144
+ }
145
+
146
+ // spinlock delay on iteration c. Returns new c.
147
+ namespace {
148
+ enum DelayMode { AGGRESSIVE, GENTLE };
149
+ };
150
+ static int Delay(int32_t c, DelayMode mode) {
151
+ // If this a uniprocessor, only yield/sleep. Otherwise, if the mode is
152
+ // aggressive then spin many times before yielding. If the mode is
153
+ // gentle then spin only a few times before yielding. Aggressive spinning is
154
+ // used to ensure that an Unlock() call, which must get the spin lock for
155
+ // any thread to make progress gets it without undue delay.
156
+ int32_t limit = (mutex_globals.num_cpus > 1) ?
157
+ ((mode == AGGRESSIVE) ? 5000 : 250) : 0;
158
+ if (c < limit) {
159
+ c++; // spin
160
+ } else {
161
+ ABSL_TSAN_MUTEX_PRE_DIVERT(nullptr, 0);
162
+ if (c == limit) { // yield once
163
+ AbslInternalMutexYield();
164
+ c++;
165
+ } else { // then wait
166
+ absl::SleepFor(absl::Microseconds(10));
167
+ c = 0;
168
+ }
169
+ ABSL_TSAN_MUTEX_POST_DIVERT(nullptr, 0);
170
+ }
171
+ return (c);
172
+ }
173
+
174
+ // --------------------------Generic atomic ops
175
+ // Ensure that "(*pv & bits) == bits" by doing an atomic update of "*pv" to
176
+ // "*pv | bits" if necessary. Wait until (*pv & wait_until_clear)==0
177
+ // before making any change.
178
+ // This is used to set flags in mutex and condition variable words.
179
+ static void AtomicSetBits(std::atomic<intptr_t>* pv, intptr_t bits,
180
+ intptr_t wait_until_clear) {
181
+ intptr_t v;
182
+ do {
183
+ v = pv->load(std::memory_order_relaxed);
184
+ } while ((v & bits) != bits &&
185
+ ((v & wait_until_clear) != 0 ||
186
+ !pv->compare_exchange_weak(v, v | bits,
187
+ std::memory_order_release,
188
+ std::memory_order_relaxed)));
189
+ }
190
+
191
+ // Ensure that "(*pv & bits) == 0" by doing an atomic update of "*pv" to
192
+ // "*pv & ~bits" if necessary. Wait until (*pv & wait_until_clear)==0
193
+ // before making any change.
194
+ // This is used to unset flags in mutex and condition variable words.
195
+ static void AtomicClearBits(std::atomic<intptr_t>* pv, intptr_t bits,
196
+ intptr_t wait_until_clear) {
197
+ intptr_t v;
198
+ do {
199
+ v = pv->load(std::memory_order_relaxed);
200
+ } while ((v & bits) != 0 &&
201
+ ((v & wait_until_clear) != 0 ||
202
+ !pv->compare_exchange_weak(v, v & ~bits,
203
+ std::memory_order_release,
204
+ std::memory_order_relaxed)));
205
+ }
206
+
207
+ //------------------------------------------------------------------
208
+
209
+ // Data for doing deadlock detection.
210
+ static absl::base_internal::SpinLock deadlock_graph_mu(
211
+ absl::base_internal::kLinkerInitialized);
212
+
213
+ // graph used to detect deadlocks.
214
+ static GraphCycles *deadlock_graph ABSL_GUARDED_BY(deadlock_graph_mu)
215
+ ABSL_PT_GUARDED_BY(deadlock_graph_mu);
216
+
217
+ //------------------------------------------------------------------
218
+ // An event mechanism for debugging mutex use.
219
+ // It also allows mutexes to be given names for those who can't handle
220
+ // addresses, and instead like to give their data structures names like
221
+ // "Henry", "Fido", or "Rupert IV, King of Yondavia".
222
+
223
+ namespace { // to prevent name pollution
224
+ enum { // Mutex and CondVar events passed as "ev" to PostSynchEvent
225
+ // Mutex events
226
+ SYNCH_EV_TRYLOCK_SUCCESS,
227
+ SYNCH_EV_TRYLOCK_FAILED,
228
+ SYNCH_EV_READERTRYLOCK_SUCCESS,
229
+ SYNCH_EV_READERTRYLOCK_FAILED,
230
+ SYNCH_EV_LOCK,
231
+ SYNCH_EV_LOCK_RETURNING,
232
+ SYNCH_EV_READERLOCK,
233
+ SYNCH_EV_READERLOCK_RETURNING,
234
+ SYNCH_EV_UNLOCK,
235
+ SYNCH_EV_READERUNLOCK,
236
+
237
+ // CondVar events
238
+ SYNCH_EV_WAIT,
239
+ SYNCH_EV_WAIT_RETURNING,
240
+ SYNCH_EV_SIGNAL,
241
+ SYNCH_EV_SIGNALALL,
242
+ };
243
+
244
+ enum { // Event flags
245
+ SYNCH_F_R = 0x01, // reader event
246
+ SYNCH_F_LCK = 0x02, // PostSynchEvent called with mutex held
247
+ SYNCH_F_TRY = 0x04, // TryLock or ReaderTryLock
248
+ SYNCH_F_UNLOCK = 0x08, // Unlock or ReaderUnlock
249
+
250
+ SYNCH_F_LCK_W = SYNCH_F_LCK,
251
+ SYNCH_F_LCK_R = SYNCH_F_LCK | SYNCH_F_R,
252
+ };
253
+ } // anonymous namespace
254
+
255
+ // Properties of the events.
256
+ static const struct {
257
+ int flags;
258
+ const char *msg;
259
+ } event_properties[] = {
260
+ {SYNCH_F_LCK_W | SYNCH_F_TRY, "TryLock succeeded "},
261
+ {0, "TryLock failed "},
262
+ {SYNCH_F_LCK_R | SYNCH_F_TRY, "ReaderTryLock succeeded "},
263
+ {0, "ReaderTryLock failed "},
264
+ {0, "Lock blocking "},
265
+ {SYNCH_F_LCK_W, "Lock returning "},
266
+ {0, "ReaderLock blocking "},
267
+ {SYNCH_F_LCK_R, "ReaderLock returning "},
268
+ {SYNCH_F_LCK_W | SYNCH_F_UNLOCK, "Unlock "},
269
+ {SYNCH_F_LCK_R | SYNCH_F_UNLOCK, "ReaderUnlock "},
270
+ {0, "Wait on "},
271
+ {0, "Wait unblocked "},
272
+ {0, "Signal on "},
273
+ {0, "SignalAll on "},
274
+ };
275
+
276
+ static absl::base_internal::SpinLock synch_event_mu(
277
+ absl::base_internal::kLinkerInitialized);
278
+ // protects synch_event
279
+
280
+ // Hash table size; should be prime > 2.
281
+ // Can't be too small, as it's used for deadlock detection information.
282
+ static const uint32_t kNSynchEvent = 1031;
283
+
284
+ static struct SynchEvent { // this is a trivial hash table for the events
285
+ // struct is freed when refcount reaches 0
286
+ int refcount ABSL_GUARDED_BY(synch_event_mu);
287
+
288
+ // buckets have linear, 0-terminated chains
289
+ SynchEvent *next ABSL_GUARDED_BY(synch_event_mu);
290
+
291
+ // Constant after initialization
292
+ uintptr_t masked_addr; // object at this address is called "name"
293
+
294
+ // No explicit synchronization used. Instead we assume that the
295
+ // client who enables/disables invariants/logging on a Mutex does so
296
+ // while the Mutex is not being concurrently accessed by others.
297
+ void (*invariant)(void *arg); // called on each event
298
+ void *arg; // first arg to (*invariant)()
299
+ bool log; // logging turned on
300
+
301
+ // Constant after initialization
302
+ char name[1]; // actually longer---NUL-terminated std::string
303
+ } * synch_event[kNSynchEvent] ABSL_GUARDED_BY(synch_event_mu);
304
+
305
+ // Ensure that the object at "addr" has a SynchEvent struct associated with it,
306
+ // set "bits" in the word there (waiting until lockbit is clear before doing
307
+ // so), and return a refcounted reference that will remain valid until
308
+ // UnrefSynchEvent() is called. If a new SynchEvent is allocated,
309
+ // the string name is copied into it.
310
+ // When used with a mutex, the caller should also ensure that kMuEvent
311
+ // is set in the mutex word, and similarly for condition variables and kCVEvent.
312
+ static SynchEvent *EnsureSynchEvent(std::atomic<intptr_t> *addr,
313
+ const char *name, intptr_t bits,
314
+ intptr_t lockbit) {
315
+ uint32_t h = reinterpret_cast<intptr_t>(addr) % kNSynchEvent;
316
+ SynchEvent *e;
317
+ // first look for existing SynchEvent struct..
318
+ synch_event_mu.Lock();
319
+ for (e = synch_event[h];
320
+ e != nullptr && e->masked_addr != base_internal::HidePtr(addr);
321
+ e = e->next) {
322
+ }
323
+ if (e == nullptr) { // no SynchEvent struct found; make one.
324
+ if (name == nullptr) {
325
+ name = "";
326
+ }
327
+ size_t l = strlen(name);
328
+ e = reinterpret_cast<SynchEvent *>(
329
+ base_internal::LowLevelAlloc::Alloc(sizeof(*e) + l));
330
+ e->refcount = 2; // one for return value, one for linked list
331
+ e->masked_addr = base_internal::HidePtr(addr);
332
+ e->invariant = nullptr;
333
+ e->arg = nullptr;
334
+ e->log = false;
335
+ strcpy(e->name, name); // NOLINT(runtime/printf)
336
+ e->next = synch_event[h];
337
+ AtomicSetBits(addr, bits, lockbit);
338
+ synch_event[h] = e;
339
+ } else {
340
+ e->refcount++; // for return value
341
+ }
342
+ synch_event_mu.Unlock();
343
+ return e;
344
+ }
345
+
346
+ // Deallocate the SynchEvent *e, whose refcount has fallen to zero.
347
+ static void DeleteSynchEvent(SynchEvent *e) {
348
+ base_internal::LowLevelAlloc::Free(e);
349
+ }
350
+
351
+ // Decrement the reference count of *e, or do nothing if e==null.
352
+ static void UnrefSynchEvent(SynchEvent *e) {
353
+ if (e != nullptr) {
354
+ synch_event_mu.Lock();
355
+ bool del = (--(e->refcount) == 0);
356
+ synch_event_mu.Unlock();
357
+ if (del) {
358
+ DeleteSynchEvent(e);
359
+ }
360
+ }
361
+ }
362
+
363
+ // Forget the mapping from the object (Mutex or CondVar) at address addr
364
+ // to SynchEvent object, and clear "bits" in its word (waiting until lockbit
365
+ // is clear before doing so).
366
+ static void ForgetSynchEvent(std::atomic<intptr_t> *addr, intptr_t bits,
367
+ intptr_t lockbit) {
368
+ uint32_t h = reinterpret_cast<intptr_t>(addr) % kNSynchEvent;
369
+ SynchEvent **pe;
370
+ SynchEvent *e;
371
+ synch_event_mu.Lock();
372
+ for (pe = &synch_event[h];
373
+ (e = *pe) != nullptr && e->masked_addr != base_internal::HidePtr(addr);
374
+ pe = &e->next) {
375
+ }
376
+ bool del = false;
377
+ if (e != nullptr) {
378
+ *pe = e->next;
379
+ del = (--(e->refcount) == 0);
380
+ }
381
+ AtomicClearBits(addr, bits, lockbit);
382
+ synch_event_mu.Unlock();
383
+ if (del) {
384
+ DeleteSynchEvent(e);
385
+ }
386
+ }
387
+
388
+ // Return a refcounted reference to the SynchEvent of the object at address
389
+ // "addr", if any. The pointer returned is valid until the UnrefSynchEvent() is
390
+ // called.
391
+ static SynchEvent *GetSynchEvent(const void *addr) {
392
+ uint32_t h = reinterpret_cast<intptr_t>(addr) % kNSynchEvent;
393
+ SynchEvent *e;
394
+ synch_event_mu.Lock();
395
+ for (e = synch_event[h];
396
+ e != nullptr && e->masked_addr != base_internal::HidePtr(addr);
397
+ e = e->next) {
398
+ }
399
+ if (e != nullptr) {
400
+ e->refcount++;
401
+ }
402
+ synch_event_mu.Unlock();
403
+ return e;
404
+ }
405
+
406
+ // Called when an event "ev" occurs on a Mutex of CondVar "obj"
407
+ // if event recording is on
408
+ static void PostSynchEvent(void *obj, int ev) {
409
+ SynchEvent *e = GetSynchEvent(obj);
410
+ // logging is on if event recording is on and either there's no event struct,
411
+ // or it explicitly says to log
412
+ if (e == nullptr || e->log) {
413
+ void *pcs[40];
414
+ int n = absl::GetStackTrace(pcs, ABSL_ARRAYSIZE(pcs), 1);
415
+ // A buffer with enough space for the ASCII for all the PCs, even on a
416
+ // 64-bit machine.
417
+ char buffer[ABSL_ARRAYSIZE(pcs) * 24];
418
+ int pos = snprintf(buffer, sizeof (buffer), " @");
419
+ for (int i = 0; i != n; i++) {
420
+ pos += snprintf(&buffer[pos], sizeof (buffer) - pos, " %p", pcs[i]);
421
+ }
422
+ ABSL_RAW_LOG(INFO, "%s%p %s %s", event_properties[ev].msg, obj,
423
+ (e == nullptr ? "" : e->name), buffer);
424
+ }
425
+ const int flags = event_properties[ev].flags;
426
+ if ((flags & SYNCH_F_LCK) != 0 && e != nullptr && e->invariant != nullptr) {
427
+ // Calling the invariant as is causes problems under ThreadSanitizer.
428
+ // We are currently inside of Mutex Lock/Unlock and are ignoring all
429
+ // memory accesses and synchronization. If the invariant transitively
430
+ // synchronizes something else and we ignore the synchronization, we will
431
+ // get false positive race reports later.
432
+ // Reuse EvalConditionAnnotated to properly call into user code.
433
+ struct local {
434
+ static bool pred(SynchEvent *ev) {
435
+ (*ev->invariant)(ev->arg);
436
+ return false;
437
+ }
438
+ };
439
+ Condition cond(&local::pred, e);
440
+ Mutex *mu = static_cast<Mutex *>(obj);
441
+ const bool locking = (flags & SYNCH_F_UNLOCK) == 0;
442
+ const bool trylock = (flags & SYNCH_F_TRY) != 0;
443
+ const bool read_lock = (flags & SYNCH_F_R) != 0;
444
+ EvalConditionAnnotated(&cond, mu, locking, trylock, read_lock);
445
+ }
446
+ UnrefSynchEvent(e);
447
+ }
448
+
449
+ //------------------------------------------------------------------
450
+
451
+ // The SynchWaitParams struct encapsulates the way in which a thread is waiting:
452
+ // whether it has a timeout, the condition, exclusive/shared, and whether a
453
+ // condition variable wait has an associated Mutex (as opposed to another
454
+ // type of lock). It also points to the PerThreadSynch struct of its thread.
455
+ // cv_word tells Enqueue() to enqueue on a CondVar using CondVarEnqueue().
456
+ //
457
+ // This structure is held on the stack rather than directly in
458
+ // PerThreadSynch because a thread can be waiting on multiple Mutexes if,
459
+ // while waiting on one Mutex, the implementation calls a client callback
460
+ // (such as a Condition function) that acquires another Mutex. We don't
461
+ // strictly need to allow this, but programmers become confused if we do not
462
+ // allow them to use functions such a LOG() within Condition functions. The
463
+ // PerThreadSynch struct points at the most recent SynchWaitParams struct when
464
+ // the thread is on a Mutex's waiter queue.
465
+ struct SynchWaitParams {
466
+ SynchWaitParams(Mutex::MuHow how_arg, const Condition *cond_arg,
467
+ KernelTimeout timeout_arg, Mutex *cvmu_arg,
468
+ PerThreadSynch *thread_arg,
469
+ std::atomic<intptr_t> *cv_word_arg)
470
+ : how(how_arg),
471
+ cond(cond_arg),
472
+ timeout(timeout_arg),
473
+ cvmu(cvmu_arg),
474
+ thread(thread_arg),
475
+ cv_word(cv_word_arg),
476
+ contention_start_cycles(base_internal::CycleClock::Now()) {}
477
+
478
+ const Mutex::MuHow how; // How this thread needs to wait.
479
+ const Condition *cond; // The condition that this thread is waiting for.
480
+ // In Mutex, this field is set to zero if a timeout
481
+ // expires.
482
+ KernelTimeout timeout; // timeout expiry---absolute time
483
+ // In Mutex, this field is set to zero if a timeout
484
+ // expires.
485
+ Mutex *const cvmu; // used for transfer from cond var to mutex
486
+ PerThreadSynch *const thread; // thread that is waiting
487
+
488
+ // If not null, thread should be enqueued on the CondVar whose state
489
+ // word is cv_word instead of queueing normally on the Mutex.
490
+ std::atomic<intptr_t> *cv_word;
491
+
492
+ int64_t contention_start_cycles; // Time (in cycles) when this thread started
493
+ // to contend for the mutex.
494
+ };
495
+
496
+ struct SynchLocksHeld {
497
+ int n; // number of valid entries in locks[]
498
+ bool overflow; // true iff we overflowed the array at some point
499
+ struct {
500
+ Mutex *mu; // lock acquired
501
+ int32_t count; // times acquired
502
+ GraphId id; // deadlock_graph id of acquired lock
503
+ } locks[40];
504
+ // If a thread overfills the array during deadlock detection, we
505
+ // continue, discarding information as needed. If no overflow has
506
+ // taken place, we can provide more error checking, such as
507
+ // detecting when a thread releases a lock it does not hold.
508
+ };
509
+
510
+ // A sentinel value in lists that is not 0.
511
+ // A 0 value is used to mean "not on a list".
512
+ static PerThreadSynch *const kPerThreadSynchNull =
513
+ reinterpret_cast<PerThreadSynch *>(1);
514
+
515
+ static SynchLocksHeld *LocksHeldAlloc() {
516
+ SynchLocksHeld *ret = reinterpret_cast<SynchLocksHeld *>(
517
+ base_internal::LowLevelAlloc::Alloc(sizeof(SynchLocksHeld)));
518
+ ret->n = 0;
519
+ ret->overflow = false;
520
+ return ret;
521
+ }
522
+
523
+ // Return the PerThreadSynch-struct for this thread.
524
+ static PerThreadSynch *Synch_GetPerThread() {
525
+ ThreadIdentity *identity = GetOrCreateCurrentThreadIdentity();
526
+ return &identity->per_thread_synch;
527
+ }
528
+
529
+ static PerThreadSynch *Synch_GetPerThreadAnnotated(Mutex *mu) {
530
+ if (mu) {
531
+ ABSL_TSAN_MUTEX_PRE_DIVERT(mu, 0);
532
+ }
533
+ PerThreadSynch *w = Synch_GetPerThread();
534
+ if (mu) {
535
+ ABSL_TSAN_MUTEX_POST_DIVERT(mu, 0);
536
+ }
537
+ return w;
538
+ }
539
+
540
+ static SynchLocksHeld *Synch_GetAllLocks() {
541
+ PerThreadSynch *s = Synch_GetPerThread();
542
+ if (s->all_locks == nullptr) {
543
+ s->all_locks = LocksHeldAlloc(); // Freed by ReclaimThreadIdentity.
544
+ }
545
+ return s->all_locks;
546
+ }
547
+
548
+ // Post on "w"'s associated PerThreadSem.
549
+ inline void Mutex::IncrementSynchSem(Mutex *mu, PerThreadSynch *w) {
550
+ if (mu) {
551
+ ABSL_TSAN_MUTEX_PRE_DIVERT(mu, 0);
552
+ }
553
+ PerThreadSem::Post(w->thread_identity());
554
+ if (mu) {
555
+ ABSL_TSAN_MUTEX_POST_DIVERT(mu, 0);
556
+ }
557
+ }
558
+
559
+ // Wait on "w"'s associated PerThreadSem; returns false if timeout expired.
560
+ bool Mutex::DecrementSynchSem(Mutex *mu, PerThreadSynch *w, KernelTimeout t) {
561
+ if (mu) {
562
+ ABSL_TSAN_MUTEX_PRE_DIVERT(mu, 0);
563
+ }
564
+ assert(w == Synch_GetPerThread());
565
+ static_cast<void>(w);
566
+ bool res = PerThreadSem::Wait(t);
567
+ if (mu) {
568
+ ABSL_TSAN_MUTEX_POST_DIVERT(mu, 0);
569
+ }
570
+ return res;
571
+ }
572
+
573
+ // We're in a fatal signal handler that hopes to use Mutex and to get
574
+ // lucky by not deadlocking. We try to improve its chances of success
575
+ // by effectively disabling some of the consistency checks. This will
576
+ // prevent certain ABSL_RAW_CHECK() statements from being triggered when
577
+ // re-rentry is detected. The ABSL_RAW_CHECK() statements are those in the
578
+ // Mutex code checking that the "waitp" field has not been reused.
579
+ void Mutex::InternalAttemptToUseMutexInFatalSignalHandler() {
580
+ // Fix the per-thread state only if it exists.
581
+ ThreadIdentity *identity = CurrentThreadIdentityIfPresent();
582
+ if (identity != nullptr) {
583
+ identity->per_thread_synch.suppress_fatal_errors = true;
584
+ }
585
+ // Don't do deadlock detection when we are already failing.
586
+ synch_deadlock_detection.store(OnDeadlockCycle::kIgnore,
587
+ std::memory_order_release);
588
+ }
589
+
590
+ // --------------------------time support
591
+
592
+ // Return the current time plus the timeout. Use the same clock as
593
+ // PerThreadSem::Wait() for consistency. Unfortunately, we don't have
594
+ // such a choice when a deadline is given directly.
595
+ static absl::Time DeadlineFromTimeout(absl::Duration timeout) {
596
+ #ifndef _WIN32
597
+ struct timeval tv;
598
+ gettimeofday(&tv, nullptr);
599
+ return absl::TimeFromTimeval(tv) + timeout;
600
+ #else
601
+ return absl::Now() + timeout;
602
+ #endif
603
+ }
604
+
605
+ // --------------------------Mutexes
606
+
607
+ // In the layout below, the msb of the bottom byte is currently unused. Also,
608
+ // the following constraints were considered in choosing the layout:
609
+ // o Both the debug allocator's "uninitialized" and "freed" patterns (0xab and
610
+ // 0xcd) are illegal: reader and writer lock both held.
611
+ // o kMuWriter and kMuEvent should exceed kMuDesig and kMuWait, to enable the
612
+ // bit-twiddling trick in Mutex::Unlock().
613
+ // o kMuWriter / kMuReader == kMuWrWait / kMuWait,
614
+ // to enable the bit-twiddling trick in CheckForMutexCorruption().
615
+ static const intptr_t kMuReader = 0x0001L; // a reader holds the lock
616
+ static const intptr_t kMuDesig = 0x0002L; // there's a designated waker
617
+ static const intptr_t kMuWait = 0x0004L; // threads are waiting
618
+ static const intptr_t kMuWriter = 0x0008L; // a writer holds the lock
619
+ static const intptr_t kMuEvent = 0x0010L; // record this mutex's events
620
+ // INVARIANT1: there's a thread that was blocked on the mutex, is
621
+ // no longer, yet has not yet acquired the mutex. If there's a
622
+ // designated waker, all threads can avoid taking the slow path in
623
+ // unlock because the designated waker will subsequently acquire
624
+ // the lock and wake someone. To maintain INVARIANT1 the bit is
625
+ // set when a thread is unblocked(INV1a), and threads that were
626
+ // unblocked reset the bit when they either acquire or re-block
627
+ // (INV1b).
628
+ static const intptr_t kMuWrWait = 0x0020L; // runnable writer is waiting
629
+ // for a reader
630
+ static const intptr_t kMuSpin = 0x0040L; // spinlock protects wait list
631
+ static const intptr_t kMuLow = 0x00ffL; // mask all mutex bits
632
+ static const intptr_t kMuHigh = ~kMuLow; // mask pointer/reader count
633
+
634
+ // Hack to make constant values available to gdb pretty printer
635
+ enum {
636
+ kGdbMuSpin = kMuSpin,
637
+ kGdbMuEvent = kMuEvent,
638
+ kGdbMuWait = kMuWait,
639
+ kGdbMuWriter = kMuWriter,
640
+ kGdbMuDesig = kMuDesig,
641
+ kGdbMuWrWait = kMuWrWait,
642
+ kGdbMuReader = kMuReader,
643
+ kGdbMuLow = kMuLow,
644
+ };
645
+
646
+ // kMuWrWait implies kMuWait.
647
+ // kMuReader and kMuWriter are mutually exclusive.
648
+ // If kMuReader is zero, there are no readers.
649
+ // Otherwise, if kMuWait is zero, the high order bits contain a count of the
650
+ // number of readers. Otherwise, the reader count is held in
651
+ // PerThreadSynch::readers of the most recently queued waiter, again in the
652
+ // bits above kMuLow.
653
+ static const intptr_t kMuOne = 0x0100; // a count of one reader
654
+
655
+ // flags passed to Enqueue and LockSlow{,WithTimeout,Loop}
656
+ static const int kMuHasBlocked = 0x01; // already blocked (MUST == 1)
657
+ static const int kMuIsCond = 0x02; // conditional waiter (CV or Condition)
658
+
659
+ static_assert(PerThreadSynch::kAlignment > kMuLow,
660
+ "PerThreadSynch::kAlignment must be greater than kMuLow");
661
+
662
+ // This struct contains various bitmasks to be used in
663
+ // acquiring and releasing a mutex in a particular mode.
664
+ struct MuHowS {
665
+ // if all the bits in fast_need_zero are zero, the lock can be acquired by
666
+ // adding fast_add and oring fast_or. The bit kMuDesig should be reset iff
667
+ // this is the designated waker.
668
+ intptr_t fast_need_zero;
669
+ intptr_t fast_or;
670
+ intptr_t fast_add;
671
+
672
+ intptr_t slow_need_zero; // fast_need_zero with events (e.g. logging)
673
+
674
+ intptr_t slow_inc_need_zero; // if all the bits in slow_inc_need_zero are
675
+ // zero a reader can acquire a read share by
676
+ // setting the reader bit and incrementing
677
+ // the reader count (in last waiter since
678
+ // we're now slow-path). kMuWrWait be may
679
+ // be ignored if we already waited once.
680
+ };
681
+
682
+ static const MuHowS kSharedS = {
683
+ // shared or read lock
684
+ kMuWriter | kMuWait | kMuEvent, // fast_need_zero
685
+ kMuReader, // fast_or
686
+ kMuOne, // fast_add
687
+ kMuWriter | kMuWait, // slow_need_zero
688
+ kMuSpin | kMuWriter | kMuWrWait, // slow_inc_need_zero
689
+ };
690
+ static const MuHowS kExclusiveS = {
691
+ // exclusive or write lock
692
+ kMuWriter | kMuReader | kMuEvent, // fast_need_zero
693
+ kMuWriter, // fast_or
694
+ 0, // fast_add
695
+ kMuWriter | kMuReader, // slow_need_zero
696
+ ~static_cast<intptr_t>(0), // slow_inc_need_zero
697
+ };
698
+ static const Mutex::MuHow kShared = &kSharedS; // shared lock
699
+ static const Mutex::MuHow kExclusive = &kExclusiveS; // exclusive lock
700
+
701
+ #ifdef NDEBUG
702
+ static constexpr bool kDebugMode = false;
703
+ #else
704
+ static constexpr bool kDebugMode = true;
705
+ #endif
706
+
707
+ #ifdef THREAD_SANITIZER
708
+ static unsigned TsanFlags(Mutex::MuHow how) {
709
+ return how == kShared ? __tsan_mutex_read_lock : 0;
710
+ }
711
+ #endif
712
+
713
+ static bool DebugOnlyIsExiting() {
714
+ return false;
715
+ }
716
+
717
+ Mutex::~Mutex() {
718
+ intptr_t v = mu_.load(std::memory_order_relaxed);
719
+ if ((v & kMuEvent) != 0 && !DebugOnlyIsExiting()) {
720
+ ForgetSynchEvent(&this->mu_, kMuEvent, kMuSpin);
721
+ }
722
+ if (kDebugMode) {
723
+ this->ForgetDeadlockInfo();
724
+ }
725
+ ABSL_TSAN_MUTEX_DESTROY(this, __tsan_mutex_not_static);
726
+ }
727
+
728
+ void Mutex::EnableDebugLog(const char *name) {
729
+ SynchEvent *e = EnsureSynchEvent(&this->mu_, name, kMuEvent, kMuSpin);
730
+ e->log = true;
731
+ UnrefSynchEvent(e);
732
+ }
733
+
734
+ void EnableMutexInvariantDebugging(bool enabled) {
735
+ synch_check_invariants.store(enabled, std::memory_order_release);
736
+ }
737
+
738
+ void Mutex::EnableInvariantDebugging(void (*invariant)(void *),
739
+ void *arg) {
740
+ if (synch_check_invariants.load(std::memory_order_acquire) &&
741
+ invariant != nullptr) {
742
+ SynchEvent *e = EnsureSynchEvent(&this->mu_, nullptr, kMuEvent, kMuSpin);
743
+ e->invariant = invariant;
744
+ e->arg = arg;
745
+ UnrefSynchEvent(e);
746
+ }
747
+ }
748
+
749
+ void SetMutexDeadlockDetectionMode(OnDeadlockCycle mode) {
750
+ synch_deadlock_detection.store(mode, std::memory_order_release);
751
+ }
752
+
753
+ // Return true iff threads x and y are waiting on the same condition for the
754
+ // same type of lock. Requires that x and y be waiting on the same Mutex
755
+ // queue.
756
+ static bool MuSameCondition(PerThreadSynch *x, PerThreadSynch *y) {
757
+ return x->waitp->how == y->waitp->how &&
758
+ Condition::GuaranteedEqual(x->waitp->cond, y->waitp->cond);
759
+ }
760
+
761
+ // Given the contents of a mutex word containing a PerThreadSynch pointer,
762
+ // return the pointer.
763
+ static inline PerThreadSynch *GetPerThreadSynch(intptr_t v) {
764
+ return reinterpret_cast<PerThreadSynch *>(v & kMuHigh);
765
+ }
766
+
767
+ // The next several routines maintain the per-thread next and skip fields
768
+ // used in the Mutex waiter queue.
769
+ // The queue is a circular singly-linked list, of which the "head" is the
770
+ // last element, and head->next if the first element.
771
+ // The skip field has the invariant:
772
+ // For thread x, x->skip is one of:
773
+ // - invalid (iff x is not in a Mutex wait queue),
774
+ // - null, or
775
+ // - a pointer to a distinct thread waiting later in the same Mutex queue
776
+ // such that all threads in [x, x->skip] have the same condition and
777
+ // lock type (MuSameCondition() is true for all pairs in [x, x->skip]).
778
+ // In addition, if x->skip is valid, (x->may_skip || x->skip == null)
779
+ //
780
+ // By the spec of MuSameCondition(), it is not necessary when removing the
781
+ // first runnable thread y from the front a Mutex queue to adjust the skip
782
+ // field of another thread x because if x->skip==y, x->skip must (have) become
783
+ // invalid before y is removed. The function TryRemove can remove a specified
784
+ // thread from an arbitrary position in the queue whether runnable or not, so
785
+ // it fixes up skip fields that would otherwise be left dangling.
786
+ // The statement
787
+ // if (x->may_skip && MuSameCondition(x, x->next)) { x->skip = x->next; }
788
+ // maintains the invariant provided x is not the last waiter in a Mutex queue
789
+ // The statement
790
+ // if (x->skip != null) { x->skip = x->skip->skip; }
791
+ // maintains the invariant.
792
+
793
+ // Returns the last thread y in a mutex waiter queue such that all threads in
794
+ // [x, y] inclusive share the same condition. Sets skip fields of some threads
795
+ // in that range to optimize future evaluation of Skip() on x values in
796
+ // the range. Requires thread x is in a mutex waiter queue.
797
+ // The locking is unusual. Skip() is called under these conditions:
798
+ // - spinlock is held in call from Enqueue(), with maybe_unlocking == false
799
+ // - Mutex is held in call from UnlockSlow() by last unlocker, with
800
+ // maybe_unlocking == true
801
+ // - both Mutex and spinlock are held in call from DequeueAllWakeable() (from
802
+ // UnlockSlow()) and TryRemove()
803
+ // These cases are mutually exclusive, so Skip() never runs concurrently
804
+ // with itself on the same Mutex. The skip chain is used in these other places
805
+ // that cannot occur concurrently:
806
+ // - FixSkip() (from TryRemove()) - spinlock and Mutex are held)
807
+ // - Dequeue() (with spinlock and Mutex held)
808
+ // - UnlockSlow() (with spinlock and Mutex held)
809
+ // A more complex case is Enqueue()
810
+ // - Enqueue() (with spinlock held and maybe_unlocking == false)
811
+ // This is the first case in which Skip is called, above.
812
+ // - Enqueue() (without spinlock held; but queue is empty and being freshly
813
+ // formed)
814
+ // - Enqueue() (with spinlock held and maybe_unlocking == true)
815
+ // The first case has mutual exclusion, and the second isolation through
816
+ // working on an otherwise unreachable data structure.
817
+ // In the last case, Enqueue() is required to change no skip/next pointers
818
+ // except those in the added node and the former "head" node. This implies
819
+ // that the new node is added after head, and so must be the new head or the
820
+ // new front of the queue.
821
+ static PerThreadSynch *Skip(PerThreadSynch *x) {
822
+ PerThreadSynch *x0 = nullptr;
823
+ PerThreadSynch *x1 = x;
824
+ PerThreadSynch *x2 = x->skip;
825
+ if (x2 != nullptr) {
826
+ // Each iteration attempts to advance sequence (x0,x1,x2) to next sequence
827
+ // such that x1 == x0->skip && x2 == x1->skip
828
+ while ((x0 = x1, x1 = x2, x2 = x2->skip) != nullptr) {
829
+ x0->skip = x2; // short-circuit skip from x0 to x2
830
+ }
831
+ x->skip = x1; // short-circuit skip from x to result
832
+ }
833
+ return x1;
834
+ }
835
+
836
+ // "ancestor" appears before "to_be_removed" in the same Mutex waiter queue.
837
+ // The latter is going to be removed out of order, because of a timeout.
838
+ // Check whether "ancestor" has a skip field pointing to "to_be_removed",
839
+ // and fix it if it does.
840
+ static void FixSkip(PerThreadSynch *ancestor, PerThreadSynch *to_be_removed) {
841
+ if (ancestor->skip == to_be_removed) { // ancestor->skip left dangling
842
+ if (to_be_removed->skip != nullptr) {
843
+ ancestor->skip = to_be_removed->skip; // can skip past to_be_removed
844
+ } else if (ancestor->next != to_be_removed) { // they are not adjacent
845
+ ancestor->skip = ancestor->next; // can skip one past ancestor
846
+ } else {
847
+ ancestor->skip = nullptr; // can't skip at all
848
+ }
849
+ }
850
+ }
851
+
852
+ static void CondVarEnqueue(SynchWaitParams *waitp);
853
+
854
+ // Enqueue thread "waitp->thread" on a waiter queue.
855
+ // Called with mutex spinlock held if head != nullptr
856
+ // If head==nullptr and waitp->cv_word==nullptr, then Enqueue() is
857
+ // idempotent; it alters no state associated with the existing (empty)
858
+ // queue.
859
+ //
860
+ // If waitp->cv_word == nullptr, queue the thread at either the front or
861
+ // the end (according to its priority) of the circular mutex waiter queue whose
862
+ // head is "head", and return the new head. mu is the previous mutex state,
863
+ // which contains the reader count (perhaps adjusted for the operation in
864
+ // progress) if the list was empty and a read lock held, and the holder hint if
865
+ // the list was empty and a write lock held. (flags & kMuIsCond) indicates
866
+ // whether this thread was transferred from a CondVar or is waiting for a
867
+ // non-trivial condition. In this case, Enqueue() never returns nullptr
868
+ //
869
+ // If waitp->cv_word != nullptr, CondVarEnqueue() is called, and "head" is
870
+ // returned. This mechanism is used by CondVar to queue a thread on the
871
+ // condition variable queue instead of the mutex queue in implementing Wait().
872
+ // In this case, Enqueue() can return nullptr (if head==nullptr).
873
+ static PerThreadSynch *Enqueue(PerThreadSynch *head,
874
+ SynchWaitParams *waitp, intptr_t mu, int flags) {
875
+ // If we have been given a cv_word, call CondVarEnqueue() and return
876
+ // the previous head of the Mutex waiter queue.
877
+ if (waitp->cv_word != nullptr) {
878
+ CondVarEnqueue(waitp);
879
+ return head;
880
+ }
881
+
882
+ PerThreadSynch *s = waitp->thread;
883
+ ABSL_RAW_CHECK(
884
+ s->waitp == nullptr || // normal case
885
+ s->waitp == waitp || // Fer()---transfer from condition variable
886
+ s->suppress_fatal_errors,
887
+ "detected illegal recursion into Mutex code");
888
+ s->waitp = waitp;
889
+ s->skip = nullptr; // maintain skip invariant (see above)
890
+ s->may_skip = true; // always true on entering queue
891
+ s->wake = false; // not being woken
892
+ s->cond_waiter = ((flags & kMuIsCond) != 0);
893
+ if (head == nullptr) { // s is the only waiter
894
+ s->next = s; // it's the only entry in the cycle
895
+ s->readers = mu; // reader count is from mu word
896
+ s->maybe_unlocking = false; // no one is searching an empty list
897
+ head = s; // s is new head
898
+ } else {
899
+ PerThreadSynch *enqueue_after = nullptr; // we'll put s after this element
900
+ #ifdef ABSL_HAVE_PTHREAD_GETSCHEDPARAM
901
+ int64_t now_cycles = base_internal::CycleClock::Now();
902
+ if (s->next_priority_read_cycles < now_cycles) {
903
+ // Every so often, update our idea of the thread's priority.
904
+ // pthread_getschedparam() is 5% of the block/wakeup time;
905
+ // base_internal::CycleClock::Now() is 0.5%.
906
+ int policy;
907
+ struct sched_param param;
908
+ const int err = pthread_getschedparam(pthread_self(), &policy, &param);
909
+ if (err != 0) {
910
+ ABSL_RAW_LOG(ERROR, "pthread_getschedparam failed: %d", err);
911
+ } else {
912
+ s->priority = param.sched_priority;
913
+ s->next_priority_read_cycles =
914
+ now_cycles +
915
+ static_cast<int64_t>(base_internal::CycleClock::Frequency());
916
+ }
917
+ }
918
+ if (s->priority > head->priority) { // s's priority is above head's
919
+ // try to put s in priority-fifo order, or failing that at the front.
920
+ if (!head->maybe_unlocking) {
921
+ // No unlocker can be scanning the queue, so we can insert between
922
+ // skip-chains, and within a skip-chain if it has the same condition as
923
+ // s. We insert in priority-fifo order, examining the end of every
924
+ // skip-chain, plus every element with the same condition as s.
925
+ PerThreadSynch *advance_to = head; // next value of enqueue_after
926
+ PerThreadSynch *cur; // successor of enqueue_after
927
+ do {
928
+ enqueue_after = advance_to;
929
+ cur = enqueue_after->next; // this advance ensures progress
930
+ advance_to = Skip(cur); // normally, advance to end of skip chain
931
+ // (side-effect: optimizes skip chain)
932
+ if (advance_to != cur && s->priority > advance_to->priority &&
933
+ MuSameCondition(s, cur)) {
934
+ // but this skip chain is not a singleton, s has higher priority
935
+ // than its tail and has the same condition as the chain,
936
+ // so we can insert within the skip-chain
937
+ advance_to = cur; // advance by just one
938
+ }
939
+ } while (s->priority <= advance_to->priority);
940
+ // termination guaranteed because s->priority > head->priority
941
+ // and head is the end of a skip chain
942
+ } else if (waitp->how == kExclusive &&
943
+ Condition::GuaranteedEqual(waitp->cond, nullptr)) {
944
+ // An unlocker could be scanning the queue, but we know it will recheck
945
+ // the queue front for writers that have no condition, which is what s
946
+ // is, so an insert at front is safe.
947
+ enqueue_after = head; // add after head, at front
948
+ }
949
+ }
950
+ #endif
951
+ if (enqueue_after != nullptr) {
952
+ s->next = enqueue_after->next;
953
+ enqueue_after->next = s;
954
+
955
+ // enqueue_after can be: head, Skip(...), or cur.
956
+ // The first two imply enqueue_after->skip == nullptr, and
957
+ // the last is used only if MuSameCondition(s, cur).
958
+ // We require this because clearing enqueue_after->skip
959
+ // is impossible; enqueue_after's predecessors might also
960
+ // incorrectly skip over s if we were to allow other
961
+ // insertion points.
962
+ ABSL_RAW_CHECK(
963
+ enqueue_after->skip == nullptr || MuSameCondition(enqueue_after, s),
964
+ "Mutex Enqueue failure");
965
+
966
+ if (enqueue_after != head && enqueue_after->may_skip &&
967
+ MuSameCondition(enqueue_after, enqueue_after->next)) {
968
+ // enqueue_after can skip to its new successor, s
969
+ enqueue_after->skip = enqueue_after->next;
970
+ }
971
+ if (MuSameCondition(s, s->next)) { // s->may_skip is known to be true
972
+ s->skip = s->next; // s may skip to its successor
973
+ }
974
+ } else { // enqueue not done any other way, so
975
+ // we're inserting s at the back
976
+ // s will become new head; copy data from head into it
977
+ s->next = head->next; // add s after head
978
+ head->next = s;
979
+ s->readers = head->readers; // reader count is from previous head
980
+ s->maybe_unlocking = head->maybe_unlocking; // same for unlock hint
981
+ if (head->may_skip && MuSameCondition(head, s)) {
982
+ // head now has successor; may skip
983
+ head->skip = s;
984
+ }
985
+ head = s; // s is new head
986
+ }
987
+ }
988
+ s->state.store(PerThreadSynch::kQueued, std::memory_order_relaxed);
989
+ return head;
990
+ }
991
+
992
+ // Dequeue the successor pw->next of thread pw from the Mutex waiter queue
993
+ // whose last element is head. The new head element is returned, or null
994
+ // if the list is made empty.
995
+ // Dequeue is called with both spinlock and Mutex held.
996
+ static PerThreadSynch *Dequeue(PerThreadSynch *head, PerThreadSynch *pw) {
997
+ PerThreadSynch *w = pw->next;
998
+ pw->next = w->next; // snip w out of list
999
+ if (head == w) { // we removed the head
1000
+ head = (pw == w) ? nullptr : pw; // either emptied list, or pw is new head
1001
+ } else if (pw != head && MuSameCondition(pw, pw->next)) {
1002
+ // pw can skip to its new successor
1003
+ if (pw->next->skip !=
1004
+ nullptr) { // either skip to its successors skip target
1005
+ pw->skip = pw->next->skip;
1006
+ } else { // or to pw's successor
1007
+ pw->skip = pw->next;
1008
+ }
1009
+ }
1010
+ return head;
1011
+ }
1012
+
1013
+ // Traverse the elements [ pw->next, h] of the circular list whose last element
1014
+ // is head.
1015
+ // Remove all elements with wake==true and place them in the
1016
+ // singly-linked list wake_list in the order found. Assumes that
1017
+ // there is only one such element if the element has how == kExclusive.
1018
+ // Return the new head.
1019
+ static PerThreadSynch *DequeueAllWakeable(PerThreadSynch *head,
1020
+ PerThreadSynch *pw,
1021
+ PerThreadSynch **wake_tail) {
1022
+ PerThreadSynch *orig_h = head;
1023
+ PerThreadSynch *w = pw->next;
1024
+ bool skipped = false;
1025
+ do {
1026
+ if (w->wake) { // remove this element
1027
+ ABSL_RAW_CHECK(pw->skip == nullptr, "bad skip in DequeueAllWakeable");
1028
+ // we're removing pw's successor so either pw->skip is zero or we should
1029
+ // already have removed pw since if pw->skip!=null, pw has the same
1030
+ // condition as w.
1031
+ head = Dequeue(head, pw);
1032
+ w->next = *wake_tail; // keep list terminated
1033
+ *wake_tail = w; // add w to wake_list;
1034
+ wake_tail = &w->next; // next addition to end
1035
+ if (w->waitp->how == kExclusive) { // wake at most 1 writer
1036
+ break;
1037
+ }
1038
+ } else { // not waking this one; skip
1039
+ pw = Skip(w); // skip as much as possible
1040
+ skipped = true;
1041
+ }
1042
+ w = pw->next;
1043
+ // We want to stop processing after we've considered the original head,
1044
+ // orig_h. We can't test for w==orig_h in the loop because w may skip over
1045
+ // it; we are guaranteed only that w's predecessor will not skip over
1046
+ // orig_h. When we've considered orig_h, either we've processed it and
1047
+ // removed it (so orig_h != head), or we considered it and skipped it (so
1048
+ // skipped==true && pw == head because skipping from head always skips by
1049
+ // just one, leaving pw pointing at head). So we want to
1050
+ // continue the loop with the negation of that expression.
1051
+ } while (orig_h == head && (pw != head || !skipped));
1052
+ return head;
1053
+ }
1054
+
1055
+ // Try to remove thread s from the list of waiters on this mutex.
1056
+ // Does nothing if s is not on the waiter list.
1057
+ void Mutex::TryRemove(PerThreadSynch *s) {
1058
+ intptr_t v = mu_.load(std::memory_order_relaxed);
1059
+ // acquire spinlock & lock
1060
+ if ((v & (kMuWait | kMuSpin | kMuWriter | kMuReader)) == kMuWait &&
1061
+ mu_.compare_exchange_strong(v, v | kMuSpin | kMuWriter,
1062
+ std::memory_order_acquire,
1063
+ std::memory_order_relaxed)) {
1064
+ PerThreadSynch *h = GetPerThreadSynch(v);
1065
+ if (h != nullptr) {
1066
+ PerThreadSynch *pw = h; // pw is w's predecessor
1067
+ PerThreadSynch *w;
1068
+ if ((w = pw->next) != s) { // search for thread,
1069
+ do { // processing at least one element
1070
+ if (!MuSameCondition(s, w)) { // seeking different condition
1071
+ pw = Skip(w); // so skip all that won't match
1072
+ // we don't have to worry about dangling skip fields
1073
+ // in the threads we skipped; none can point to s
1074
+ // because their condition differs from s
1075
+ } else { // seeking same condition
1076
+ FixSkip(w, s); // fix up any skip pointer from w to s
1077
+ pw = w;
1078
+ }
1079
+ // don't search further if we found the thread, or we're about to
1080
+ // process the first thread again.
1081
+ } while ((w = pw->next) != s && pw != h);
1082
+ }
1083
+ if (w == s) { // found thread; remove it
1084
+ // pw->skip may be non-zero here; the loop above ensured that
1085
+ // no ancestor of s can skip to s, so removal is safe anyway.
1086
+ h = Dequeue(h, pw);
1087
+ s->next = nullptr;
1088
+ s->state.store(PerThreadSynch::kAvailable, std::memory_order_release);
1089
+ }
1090
+ }
1091
+ intptr_t nv;
1092
+ do { // release spinlock and lock
1093
+ v = mu_.load(std::memory_order_relaxed);
1094
+ nv = v & (kMuDesig | kMuEvent);
1095
+ if (h != nullptr) {
1096
+ nv |= kMuWait | reinterpret_cast<intptr_t>(h);
1097
+ h->readers = 0; // we hold writer lock
1098
+ h->maybe_unlocking = false; // finished unlocking
1099
+ }
1100
+ } while (!mu_.compare_exchange_weak(v, nv,
1101
+ std::memory_order_release,
1102
+ std::memory_order_relaxed));
1103
+ }
1104
+ }
1105
+
1106
+ // Wait until thread "s", which must be the current thread, is removed from the
1107
+ // this mutex's waiter queue. If "s->waitp->timeout" has a timeout, wake up
1108
+ // if the wait extends past the absolute time specified, even if "s" is still
1109
+ // on the mutex queue. In this case, remove "s" from the queue and return
1110
+ // true, otherwise return false.
1111
+ ABSL_XRAY_LOG_ARGS(1) void Mutex::Block(PerThreadSynch *s) {
1112
+ while (s->state.load(std::memory_order_acquire) == PerThreadSynch::kQueued) {
1113
+ if (!DecrementSynchSem(this, s, s->waitp->timeout)) {
1114
+ // After a timeout, we go into a spin loop until we remove ourselves
1115
+ // from the queue, or someone else removes us. We can't be sure to be
1116
+ // able to remove ourselves in a single lock acquisition because this
1117
+ // mutex may be held, and the holder has the right to read the centre
1118
+ // of the waiter queue without holding the spinlock.
1119
+ this->TryRemove(s);
1120
+ int c = 0;
1121
+ while (s->next != nullptr) {
1122
+ c = Delay(c, GENTLE);
1123
+ this->TryRemove(s);
1124
+ }
1125
+ if (kDebugMode) {
1126
+ // This ensures that we test the case that TryRemove() is called when s
1127
+ // is not on the queue.
1128
+ this->TryRemove(s);
1129
+ }
1130
+ s->waitp->timeout = KernelTimeout::Never(); // timeout is satisfied
1131
+ s->waitp->cond = nullptr; // condition no longer relevant for wakeups
1132
+ }
1133
+ }
1134
+ ABSL_RAW_CHECK(s->waitp != nullptr || s->suppress_fatal_errors,
1135
+ "detected illegal recursion in Mutex code");
1136
+ s->waitp = nullptr;
1137
+ }
1138
+
1139
+ // Wake thread w, and return the next thread in the list.
1140
+ PerThreadSynch *Mutex::Wakeup(PerThreadSynch *w) {
1141
+ PerThreadSynch *next = w->next;
1142
+ w->next = nullptr;
1143
+ w->state.store(PerThreadSynch::kAvailable, std::memory_order_release);
1144
+ IncrementSynchSem(this, w);
1145
+
1146
+ return next;
1147
+ }
1148
+
1149
+ static GraphId GetGraphIdLocked(Mutex *mu)
1150
+ ABSL_EXCLUSIVE_LOCKS_REQUIRED(deadlock_graph_mu) {
1151
+ if (!deadlock_graph) { // (re)create the deadlock graph.
1152
+ deadlock_graph =
1153
+ new (base_internal::LowLevelAlloc::Alloc(sizeof(*deadlock_graph)))
1154
+ GraphCycles;
1155
+ }
1156
+ return deadlock_graph->GetId(mu);
1157
+ }
1158
+
1159
+ static GraphId GetGraphId(Mutex *mu) ABSL_LOCKS_EXCLUDED(deadlock_graph_mu) {
1160
+ deadlock_graph_mu.Lock();
1161
+ GraphId id = GetGraphIdLocked(mu);
1162
+ deadlock_graph_mu.Unlock();
1163
+ return id;
1164
+ }
1165
+
1166
+ // Record a lock acquisition. This is used in debug mode for deadlock
1167
+ // detection. The held_locks pointer points to the relevant data
1168
+ // structure for each case.
1169
+ static void LockEnter(Mutex* mu, GraphId id, SynchLocksHeld *held_locks) {
1170
+ int n = held_locks->n;
1171
+ int i = 0;
1172
+ while (i != n && held_locks->locks[i].id != id) {
1173
+ i++;
1174
+ }
1175
+ if (i == n) {
1176
+ if (n == ABSL_ARRAYSIZE(held_locks->locks)) {
1177
+ held_locks->overflow = true; // lost some data
1178
+ } else { // we have room for lock
1179
+ held_locks->locks[i].mu = mu;
1180
+ held_locks->locks[i].count = 1;
1181
+ held_locks->locks[i].id = id;
1182
+ held_locks->n = n + 1;
1183
+ }
1184
+ } else {
1185
+ held_locks->locks[i].count++;
1186
+ }
1187
+ }
1188
+
1189
+ // Record a lock release. Each call to LockEnter(mu, id, x) should be
1190
+ // eventually followed by a call to LockLeave(mu, id, x) by the same thread.
1191
+ // It does not process the event if is not needed when deadlock detection is
1192
+ // disabled.
1193
+ static void LockLeave(Mutex* mu, GraphId id, SynchLocksHeld *held_locks) {
1194
+ int n = held_locks->n;
1195
+ int i = 0;
1196
+ while (i != n && held_locks->locks[i].id != id) {
1197
+ i++;
1198
+ }
1199
+ if (i == n) {
1200
+ if (!held_locks->overflow) {
1201
+ // The deadlock id may have been reassigned after ForgetDeadlockInfo,
1202
+ // but in that case mu should still be present.
1203
+ i = 0;
1204
+ while (i != n && held_locks->locks[i].mu != mu) {
1205
+ i++;
1206
+ }
1207
+ if (i == n) { // mu missing means releasing unheld lock
1208
+ SynchEvent *mu_events = GetSynchEvent(mu);
1209
+ ABSL_RAW_LOG(FATAL,
1210
+ "thread releasing lock it does not hold: %p %s; "
1211
+ ,
1212
+ static_cast<void *>(mu),
1213
+ mu_events == nullptr ? "" : mu_events->name);
1214
+ }
1215
+ }
1216
+ } else if (held_locks->locks[i].count == 1) {
1217
+ held_locks->n = n - 1;
1218
+ held_locks->locks[i] = held_locks->locks[n - 1];
1219
+ held_locks->locks[n - 1].id = InvalidGraphId();
1220
+ held_locks->locks[n - 1].mu =
1221
+ nullptr; // clear mu to please the leak detector.
1222
+ } else {
1223
+ assert(held_locks->locks[i].count > 0);
1224
+ held_locks->locks[i].count--;
1225
+ }
1226
+ }
1227
+
1228
+ // Call LockEnter() if in debug mode and deadlock detection is enabled.
1229
+ static inline void DebugOnlyLockEnter(Mutex *mu) {
1230
+ if (kDebugMode) {
1231
+ if (synch_deadlock_detection.load(std::memory_order_acquire) !=
1232
+ OnDeadlockCycle::kIgnore) {
1233
+ LockEnter(mu, GetGraphId(mu), Synch_GetAllLocks());
1234
+ }
1235
+ }
1236
+ }
1237
+
1238
+ // Call LockEnter() if in debug mode and deadlock detection is enabled.
1239
+ static inline void DebugOnlyLockEnter(Mutex *mu, GraphId id) {
1240
+ if (kDebugMode) {
1241
+ if (synch_deadlock_detection.load(std::memory_order_acquire) !=
1242
+ OnDeadlockCycle::kIgnore) {
1243
+ LockEnter(mu, id, Synch_GetAllLocks());
1244
+ }
1245
+ }
1246
+ }
1247
+
1248
+ // Call LockLeave() if in debug mode and deadlock detection is enabled.
1249
+ static inline void DebugOnlyLockLeave(Mutex *mu) {
1250
+ if (kDebugMode) {
1251
+ if (synch_deadlock_detection.load(std::memory_order_acquire) !=
1252
+ OnDeadlockCycle::kIgnore) {
1253
+ LockLeave(mu, GetGraphId(mu), Synch_GetAllLocks());
1254
+ }
1255
+ }
1256
+ }
1257
+
1258
+ static char *StackString(void **pcs, int n, char *buf, int maxlen,
1259
+ bool symbolize) {
1260
+ static const int kSymLen = 200;
1261
+ char sym[kSymLen];
1262
+ int len = 0;
1263
+ for (int i = 0; i != n; i++) {
1264
+ if (symbolize) {
1265
+ if (!symbolizer(pcs[i], sym, kSymLen)) {
1266
+ sym[0] = '\0';
1267
+ }
1268
+ snprintf(buf + len, maxlen - len, "%s\t@ %p %s\n",
1269
+ (i == 0 ? "\n" : ""),
1270
+ pcs[i], sym);
1271
+ } else {
1272
+ snprintf(buf + len, maxlen - len, " %p", pcs[i]);
1273
+ }
1274
+ len += strlen(&buf[len]);
1275
+ }
1276
+ return buf;
1277
+ }
1278
+
1279
+ static char *CurrentStackString(char *buf, int maxlen, bool symbolize) {
1280
+ void *pcs[40];
1281
+ return StackString(pcs, absl::GetStackTrace(pcs, ABSL_ARRAYSIZE(pcs), 2), buf,
1282
+ maxlen, symbolize);
1283
+ }
1284
+
1285
+ namespace {
1286
+ enum { kMaxDeadlockPathLen = 10 }; // maximum length of a deadlock cycle;
1287
+ // a path this long would be remarkable
1288
+ // Buffers required to report a deadlock.
1289
+ // We do not allocate them on stack to avoid large stack frame.
1290
+ struct DeadlockReportBuffers {
1291
+ char buf[6100];
1292
+ GraphId path[kMaxDeadlockPathLen];
1293
+ };
1294
+
1295
+ struct ScopedDeadlockReportBuffers {
1296
+ ScopedDeadlockReportBuffers() {
1297
+ b = reinterpret_cast<DeadlockReportBuffers *>(
1298
+ base_internal::LowLevelAlloc::Alloc(sizeof(*b)));
1299
+ }
1300
+ ~ScopedDeadlockReportBuffers() { base_internal::LowLevelAlloc::Free(b); }
1301
+ DeadlockReportBuffers *b;
1302
+ };
1303
+
1304
+ // Helper to pass to GraphCycles::UpdateStackTrace.
1305
+ int GetStack(void** stack, int max_depth) {
1306
+ return absl::GetStackTrace(stack, max_depth, 3);
1307
+ }
1308
+ } // anonymous namespace
1309
+
1310
+ // Called in debug mode when a thread is about to acquire a lock in a way that
1311
+ // may block.
1312
+ static GraphId DeadlockCheck(Mutex *mu) {
1313
+ if (synch_deadlock_detection.load(std::memory_order_acquire) ==
1314
+ OnDeadlockCycle::kIgnore) {
1315
+ return InvalidGraphId();
1316
+ }
1317
+
1318
+ SynchLocksHeld *all_locks = Synch_GetAllLocks();
1319
+
1320
+ absl::base_internal::SpinLockHolder lock(&deadlock_graph_mu);
1321
+ const GraphId mu_id = GetGraphIdLocked(mu);
1322
+
1323
+ if (all_locks->n == 0) {
1324
+ // There are no other locks held. Return now so that we don't need to
1325
+ // call GetSynchEvent(). This way we do not record the stack trace
1326
+ // for this Mutex. It's ok, since if this Mutex is involved in a deadlock,
1327
+ // it can't always be the first lock acquired by a thread.
1328
+ return mu_id;
1329
+ }
1330
+
1331
+ // We prefer to keep stack traces that show a thread holding and acquiring
1332
+ // as many locks as possible. This increases the chances that a given edge
1333
+ // in the acquires-before graph will be represented in the stack traces
1334
+ // recorded for the locks.
1335
+ deadlock_graph->UpdateStackTrace(mu_id, all_locks->n + 1, GetStack);
1336
+
1337
+ // For each other mutex already held by this thread:
1338
+ for (int i = 0; i != all_locks->n; i++) {
1339
+ const GraphId other_node_id = all_locks->locks[i].id;
1340
+ const Mutex *other =
1341
+ static_cast<const Mutex *>(deadlock_graph->Ptr(other_node_id));
1342
+ if (other == nullptr) {
1343
+ // Ignore stale lock
1344
+ continue;
1345
+ }
1346
+
1347
+ // Add the acquired-before edge to the graph.
1348
+ if (!deadlock_graph->InsertEdge(other_node_id, mu_id)) {
1349
+ ScopedDeadlockReportBuffers scoped_buffers;
1350
+ DeadlockReportBuffers *b = scoped_buffers.b;
1351
+ static int number_of_reported_deadlocks = 0;
1352
+ number_of_reported_deadlocks++;
1353
+ // Symbolize only 2 first deadlock report to avoid huge slowdowns.
1354
+ bool symbolize = number_of_reported_deadlocks <= 2;
1355
+ ABSL_RAW_LOG(ERROR, "Potential Mutex deadlock: %s",
1356
+ CurrentStackString(b->buf, sizeof (b->buf), symbolize));
1357
+ int len = 0;
1358
+ for (int j = 0; j != all_locks->n; j++) {
1359
+ void* pr = deadlock_graph->Ptr(all_locks->locks[j].id);
1360
+ if (pr != nullptr) {
1361
+ snprintf(b->buf + len, sizeof (b->buf) - len, " %p", pr);
1362
+ len += static_cast<int>(strlen(&b->buf[len]));
1363
+ }
1364
+ }
1365
+ ABSL_RAW_LOG(ERROR, "Acquiring %p Mutexes held: %s",
1366
+ static_cast<void *>(mu), b->buf);
1367
+ ABSL_RAW_LOG(ERROR, "Cycle: ");
1368
+ int path_len = deadlock_graph->FindPath(
1369
+ mu_id, other_node_id, ABSL_ARRAYSIZE(b->path), b->path);
1370
+ for (int j = 0; j != path_len; j++) {
1371
+ GraphId id = b->path[j];
1372
+ Mutex *path_mu = static_cast<Mutex *>(deadlock_graph->Ptr(id));
1373
+ if (path_mu == nullptr) continue;
1374
+ void** stack;
1375
+ int depth = deadlock_graph->GetStackTrace(id, &stack);
1376
+ snprintf(b->buf, sizeof(b->buf),
1377
+ "mutex@%p stack: ", static_cast<void *>(path_mu));
1378
+ StackString(stack, depth, b->buf + strlen(b->buf),
1379
+ static_cast<int>(sizeof(b->buf) - strlen(b->buf)),
1380
+ symbolize);
1381
+ ABSL_RAW_LOG(ERROR, "%s", b->buf);
1382
+ }
1383
+ if (synch_deadlock_detection.load(std::memory_order_acquire) ==
1384
+ OnDeadlockCycle::kAbort) {
1385
+ deadlock_graph_mu.Unlock(); // avoid deadlock in fatal sighandler
1386
+ ABSL_RAW_LOG(FATAL, "dying due to potential deadlock");
1387
+ return mu_id;
1388
+ }
1389
+ break; // report at most one potential deadlock per acquisition
1390
+ }
1391
+ }
1392
+
1393
+ return mu_id;
1394
+ }
1395
+
1396
+ // Invoke DeadlockCheck() iff we're in debug mode and
1397
+ // deadlock checking has been enabled.
1398
+ static inline GraphId DebugOnlyDeadlockCheck(Mutex *mu) {
1399
+ if (kDebugMode && synch_deadlock_detection.load(std::memory_order_acquire) !=
1400
+ OnDeadlockCycle::kIgnore) {
1401
+ return DeadlockCheck(mu);
1402
+ } else {
1403
+ return InvalidGraphId();
1404
+ }
1405
+ }
1406
+
1407
+ void Mutex::ForgetDeadlockInfo() {
1408
+ if (kDebugMode && synch_deadlock_detection.load(std::memory_order_acquire) !=
1409
+ OnDeadlockCycle::kIgnore) {
1410
+ deadlock_graph_mu.Lock();
1411
+ if (deadlock_graph != nullptr) {
1412
+ deadlock_graph->RemoveNode(this);
1413
+ }
1414
+ deadlock_graph_mu.Unlock();
1415
+ }
1416
+ }
1417
+
1418
+ void Mutex::AssertNotHeld() const {
1419
+ // We have the data to allow this check only if in debug mode and deadlock
1420
+ // detection is enabled.
1421
+ if (kDebugMode &&
1422
+ (mu_.load(std::memory_order_relaxed) & (kMuWriter | kMuReader)) != 0 &&
1423
+ synch_deadlock_detection.load(std::memory_order_acquire) !=
1424
+ OnDeadlockCycle::kIgnore) {
1425
+ GraphId id = GetGraphId(const_cast<Mutex *>(this));
1426
+ SynchLocksHeld *locks = Synch_GetAllLocks();
1427
+ for (int i = 0; i != locks->n; i++) {
1428
+ if (locks->locks[i].id == id) {
1429
+ SynchEvent *mu_events = GetSynchEvent(this);
1430
+ ABSL_RAW_LOG(FATAL, "thread should not hold mutex %p %s",
1431
+ static_cast<const void *>(this),
1432
+ (mu_events == nullptr ? "" : mu_events->name));
1433
+ }
1434
+ }
1435
+ }
1436
+ }
1437
+
1438
+ // Attempt to acquire *mu, and return whether successful. The implementation
1439
+ // may spin for a short while if the lock cannot be acquired immediately.
1440
+ static bool TryAcquireWithSpinning(std::atomic<intptr_t>* mu) {
1441
+ int c = mutex_globals.spinloop_iterations;
1442
+ int result = -1; // result of operation: 0=false, 1=true, -1=unknown
1443
+
1444
+ do { // do/while somewhat faster on AMD
1445
+ intptr_t v = mu->load(std::memory_order_relaxed);
1446
+ if ((v & (kMuReader|kMuEvent)) != 0) { // a reader or tracing -> give up
1447
+ result = 0;
1448
+ } else if (((v & kMuWriter) == 0) && // no holder -> try to acquire
1449
+ mu->compare_exchange_strong(v, kMuWriter | v,
1450
+ std::memory_order_acquire,
1451
+ std::memory_order_relaxed)) {
1452
+ result = 1;
1453
+ }
1454
+ } while (result == -1 && --c > 0);
1455
+ return result == 1;
1456
+ }
1457
+
1458
+ ABSL_XRAY_LOG_ARGS(1) void Mutex::Lock() {
1459
+ ABSL_TSAN_MUTEX_PRE_LOCK(this, 0);
1460
+ GraphId id = DebugOnlyDeadlockCheck(this);
1461
+ intptr_t v = mu_.load(std::memory_order_relaxed);
1462
+ // try fast acquire, then spin loop
1463
+ if ((v & (kMuWriter | kMuReader | kMuEvent)) != 0 ||
1464
+ !mu_.compare_exchange_strong(v, kMuWriter | v,
1465
+ std::memory_order_acquire,
1466
+ std::memory_order_relaxed)) {
1467
+ // try spin acquire, then slow loop
1468
+ if (!TryAcquireWithSpinning(&this->mu_)) {
1469
+ this->LockSlow(kExclusive, nullptr, 0);
1470
+ }
1471
+ }
1472
+ DebugOnlyLockEnter(this, id);
1473
+ ABSL_TSAN_MUTEX_POST_LOCK(this, 0, 0);
1474
+ }
1475
+
1476
+ ABSL_XRAY_LOG_ARGS(1) void Mutex::ReaderLock() {
1477
+ ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_read_lock);
1478
+ GraphId id = DebugOnlyDeadlockCheck(this);
1479
+ intptr_t v = mu_.load(std::memory_order_relaxed);
1480
+ // try fast acquire, then slow loop
1481
+ if ((v & (kMuWriter | kMuWait | kMuEvent)) != 0 ||
1482
+ !mu_.compare_exchange_strong(v, (kMuReader | v) + kMuOne,
1483
+ std::memory_order_acquire,
1484
+ std::memory_order_relaxed)) {
1485
+ this->LockSlow(kShared, nullptr, 0);
1486
+ }
1487
+ DebugOnlyLockEnter(this, id);
1488
+ ABSL_TSAN_MUTEX_POST_LOCK(this, __tsan_mutex_read_lock, 0);
1489
+ }
1490
+
1491
+ void Mutex::LockWhen(const Condition &cond) {
1492
+ ABSL_TSAN_MUTEX_PRE_LOCK(this, 0);
1493
+ GraphId id = DebugOnlyDeadlockCheck(this);
1494
+ this->LockSlow(kExclusive, &cond, 0);
1495
+ DebugOnlyLockEnter(this, id);
1496
+ ABSL_TSAN_MUTEX_POST_LOCK(this, 0, 0);
1497
+ }
1498
+
1499
+ bool Mutex::LockWhenWithTimeout(const Condition &cond, absl::Duration timeout) {
1500
+ return LockWhenWithDeadline(cond, DeadlineFromTimeout(timeout));
1501
+ }
1502
+
1503
+ bool Mutex::LockWhenWithDeadline(const Condition &cond, absl::Time deadline) {
1504
+ ABSL_TSAN_MUTEX_PRE_LOCK(this, 0);
1505
+ GraphId id = DebugOnlyDeadlockCheck(this);
1506
+ bool res = LockSlowWithDeadline(kExclusive, &cond,
1507
+ KernelTimeout(deadline), 0);
1508
+ DebugOnlyLockEnter(this, id);
1509
+ ABSL_TSAN_MUTEX_POST_LOCK(this, 0, 0);
1510
+ return res;
1511
+ }
1512
+
1513
+ void Mutex::ReaderLockWhen(const Condition &cond) {
1514
+ ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_read_lock);
1515
+ GraphId id = DebugOnlyDeadlockCheck(this);
1516
+ this->LockSlow(kShared, &cond, 0);
1517
+ DebugOnlyLockEnter(this, id);
1518
+ ABSL_TSAN_MUTEX_POST_LOCK(this, __tsan_mutex_read_lock, 0);
1519
+ }
1520
+
1521
+ bool Mutex::ReaderLockWhenWithTimeout(const Condition &cond,
1522
+ absl::Duration timeout) {
1523
+ return ReaderLockWhenWithDeadline(cond, DeadlineFromTimeout(timeout));
1524
+ }
1525
+
1526
+ bool Mutex::ReaderLockWhenWithDeadline(const Condition &cond,
1527
+ absl::Time deadline) {
1528
+ ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_read_lock);
1529
+ GraphId id = DebugOnlyDeadlockCheck(this);
1530
+ bool res = LockSlowWithDeadline(kShared, &cond, KernelTimeout(deadline), 0);
1531
+ DebugOnlyLockEnter(this, id);
1532
+ ABSL_TSAN_MUTEX_POST_LOCK(this, __tsan_mutex_read_lock, 0);
1533
+ return res;
1534
+ }
1535
+
1536
+ void Mutex::Await(const Condition &cond) {
1537
+ if (cond.Eval()) { // condition already true; nothing to do
1538
+ if (kDebugMode) {
1539
+ this->AssertReaderHeld();
1540
+ }
1541
+ } else { // normal case
1542
+ ABSL_RAW_CHECK(this->AwaitCommon(cond, KernelTimeout::Never()),
1543
+ "condition untrue on return from Await");
1544
+ }
1545
+ }
1546
+
1547
+ bool Mutex::AwaitWithTimeout(const Condition &cond, absl::Duration timeout) {
1548
+ return AwaitWithDeadline(cond, DeadlineFromTimeout(timeout));
1549
+ }
1550
+
1551
+ bool Mutex::AwaitWithDeadline(const Condition &cond, absl::Time deadline) {
1552
+ if (cond.Eval()) { // condition already true; nothing to do
1553
+ if (kDebugMode) {
1554
+ this->AssertReaderHeld();
1555
+ }
1556
+ return true;
1557
+ }
1558
+
1559
+ KernelTimeout t{deadline};
1560
+ bool res = this->AwaitCommon(cond, t);
1561
+ ABSL_RAW_CHECK(res || t.has_timeout(),
1562
+ "condition untrue on return from Await");
1563
+ return res;
1564
+ }
1565
+
1566
+ bool Mutex::AwaitCommon(const Condition &cond, KernelTimeout t) {
1567
+ this->AssertReaderHeld();
1568
+ MuHow how =
1569
+ (mu_.load(std::memory_order_relaxed) & kMuWriter) ? kExclusive : kShared;
1570
+ ABSL_TSAN_MUTEX_PRE_UNLOCK(this, TsanFlags(how));
1571
+ SynchWaitParams waitp(
1572
+ how, &cond, t, nullptr /*no cvmu*/, Synch_GetPerThreadAnnotated(this),
1573
+ nullptr /*no cv_word*/);
1574
+ int flags = kMuHasBlocked;
1575
+ if (!Condition::GuaranteedEqual(&cond, nullptr)) {
1576
+ flags |= kMuIsCond;
1577
+ }
1578
+ this->UnlockSlow(&waitp);
1579
+ this->Block(waitp.thread);
1580
+ ABSL_TSAN_MUTEX_POST_UNLOCK(this, TsanFlags(how));
1581
+ ABSL_TSAN_MUTEX_PRE_LOCK(this, TsanFlags(how));
1582
+ this->LockSlowLoop(&waitp, flags);
1583
+ bool res = waitp.cond != nullptr || // => cond known true from LockSlowLoop
1584
+ EvalConditionAnnotated(&cond, this, true, false, how == kShared);
1585
+ ABSL_TSAN_MUTEX_POST_LOCK(this, TsanFlags(how), 0);
1586
+ return res;
1587
+ }
1588
+
1589
+ ABSL_XRAY_LOG_ARGS(1) bool Mutex::TryLock() {
1590
+ ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_try_lock);
1591
+ intptr_t v = mu_.load(std::memory_order_relaxed);
1592
+ if ((v & (kMuWriter | kMuReader | kMuEvent)) == 0 && // try fast acquire
1593
+ mu_.compare_exchange_strong(v, kMuWriter | v,
1594
+ std::memory_order_acquire,
1595
+ std::memory_order_relaxed)) {
1596
+ DebugOnlyLockEnter(this);
1597
+ ABSL_TSAN_MUTEX_POST_LOCK(this, __tsan_mutex_try_lock, 0);
1598
+ return true;
1599
+ }
1600
+ if ((v & kMuEvent) != 0) { // we're recording events
1601
+ if ((v & kExclusive->slow_need_zero) == 0 && // try fast acquire
1602
+ mu_.compare_exchange_strong(
1603
+ v, (kExclusive->fast_or | v) + kExclusive->fast_add,
1604
+ std::memory_order_acquire, std::memory_order_relaxed)) {
1605
+ DebugOnlyLockEnter(this);
1606
+ PostSynchEvent(this, SYNCH_EV_TRYLOCK_SUCCESS);
1607
+ ABSL_TSAN_MUTEX_POST_LOCK(this, __tsan_mutex_try_lock, 0);
1608
+ return true;
1609
+ } else {
1610
+ PostSynchEvent(this, SYNCH_EV_TRYLOCK_FAILED);
1611
+ }
1612
+ }
1613
+ ABSL_TSAN_MUTEX_POST_LOCK(
1614
+ this, __tsan_mutex_try_lock | __tsan_mutex_try_lock_failed, 0);
1615
+ return false;
1616
+ }
1617
+
1618
+ ABSL_XRAY_LOG_ARGS(1) bool Mutex::ReaderTryLock() {
1619
+ ABSL_TSAN_MUTEX_PRE_LOCK(this,
1620
+ __tsan_mutex_read_lock | __tsan_mutex_try_lock);
1621
+ intptr_t v = mu_.load(std::memory_order_relaxed);
1622
+ // The while-loops (here and below) iterate only if the mutex word keeps
1623
+ // changing (typically because the reader count changes) under the CAS. We
1624
+ // limit the number of attempts to avoid having to think about livelock.
1625
+ int loop_limit = 5;
1626
+ while ((v & (kMuWriter|kMuWait|kMuEvent)) == 0 && loop_limit != 0) {
1627
+ if (mu_.compare_exchange_strong(v, (kMuReader | v) + kMuOne,
1628
+ std::memory_order_acquire,
1629
+ std::memory_order_relaxed)) {
1630
+ DebugOnlyLockEnter(this);
1631
+ ABSL_TSAN_MUTEX_POST_LOCK(
1632
+ this, __tsan_mutex_read_lock | __tsan_mutex_try_lock, 0);
1633
+ return true;
1634
+ }
1635
+ loop_limit--;
1636
+ v = mu_.load(std::memory_order_relaxed);
1637
+ }
1638
+ if ((v & kMuEvent) != 0) { // we're recording events
1639
+ loop_limit = 5;
1640
+ while ((v & kShared->slow_need_zero) == 0 && loop_limit != 0) {
1641
+ if (mu_.compare_exchange_strong(v, (kMuReader | v) + kMuOne,
1642
+ std::memory_order_acquire,
1643
+ std::memory_order_relaxed)) {
1644
+ DebugOnlyLockEnter(this);
1645
+ PostSynchEvent(this, SYNCH_EV_READERTRYLOCK_SUCCESS);
1646
+ ABSL_TSAN_MUTEX_POST_LOCK(
1647
+ this, __tsan_mutex_read_lock | __tsan_mutex_try_lock, 0);
1648
+ return true;
1649
+ }
1650
+ loop_limit--;
1651
+ v = mu_.load(std::memory_order_relaxed);
1652
+ }
1653
+ if ((v & kMuEvent) != 0) {
1654
+ PostSynchEvent(this, SYNCH_EV_READERTRYLOCK_FAILED);
1655
+ }
1656
+ }
1657
+ ABSL_TSAN_MUTEX_POST_LOCK(this,
1658
+ __tsan_mutex_read_lock | __tsan_mutex_try_lock |
1659
+ __tsan_mutex_try_lock_failed,
1660
+ 0);
1661
+ return false;
1662
+ }
1663
+
1664
+ ABSL_XRAY_LOG_ARGS(1) void Mutex::Unlock() {
1665
+ ABSL_TSAN_MUTEX_PRE_UNLOCK(this, 0);
1666
+ DebugOnlyLockLeave(this);
1667
+ intptr_t v = mu_.load(std::memory_order_relaxed);
1668
+
1669
+ if (kDebugMode && ((v & (kMuWriter | kMuReader)) != kMuWriter)) {
1670
+ ABSL_RAW_LOG(FATAL, "Mutex unlocked when destroyed or not locked: v=0x%x",
1671
+ static_cast<unsigned>(v));
1672
+ }
1673
+
1674
+ // should_try_cas is whether we'll try a compare-and-swap immediately.
1675
+ // NOTE: optimized out when kDebugMode is false.
1676
+ bool should_try_cas = ((v & (kMuEvent | kMuWriter)) == kMuWriter &&
1677
+ (v & (kMuWait | kMuDesig)) != kMuWait);
1678
+ // But, we can use an alternate computation of it, that compilers
1679
+ // currently don't find on their own. When that changes, this function
1680
+ // can be simplified.
1681
+ intptr_t x = (v ^ (kMuWriter | kMuWait)) & (kMuWriter | kMuEvent);
1682
+ intptr_t y = (v ^ (kMuWriter | kMuWait)) & (kMuWait | kMuDesig);
1683
+ // Claim: "x == 0 && y > 0" is equal to should_try_cas.
1684
+ // Also, because kMuWriter and kMuEvent exceed kMuDesig and kMuWait,
1685
+ // all possible non-zero values for x exceed all possible values for y.
1686
+ // Therefore, (x == 0 && y > 0) == (x < y).
1687
+ if (kDebugMode && should_try_cas != (x < y)) {
1688
+ // We would usually use PRIdPTR here, but is not correctly implemented
1689
+ // within the android toolchain.
1690
+ ABSL_RAW_LOG(FATAL, "internal logic error %llx %llx %llx\n",
1691
+ static_cast<long long>(v), static_cast<long long>(x),
1692
+ static_cast<long long>(y));
1693
+ }
1694
+ if (x < y &&
1695
+ mu_.compare_exchange_strong(v, v & ~(kMuWrWait | kMuWriter),
1696
+ std::memory_order_release,
1697
+ std::memory_order_relaxed)) {
1698
+ // fast writer release (writer with no waiters or with designated waker)
1699
+ } else {
1700
+ this->UnlockSlow(nullptr /*no waitp*/); // take slow path
1701
+ }
1702
+ ABSL_TSAN_MUTEX_POST_UNLOCK(this, 0);
1703
+ }
1704
+
1705
+ // Requires v to represent a reader-locked state.
1706
+ static bool ExactlyOneReader(intptr_t v) {
1707
+ assert((v & (kMuWriter|kMuReader)) == kMuReader);
1708
+ assert((v & kMuHigh) != 0);
1709
+ // The more straightforward "(v & kMuHigh) == kMuOne" also works, but
1710
+ // on some architectures the following generates slightly smaller code.
1711
+ // It may be faster too.
1712
+ constexpr intptr_t kMuMultipleWaitersMask = kMuHigh ^ kMuOne;
1713
+ return (v & kMuMultipleWaitersMask) == 0;
1714
+ }
1715
+
1716
+ ABSL_XRAY_LOG_ARGS(1) void Mutex::ReaderUnlock() {
1717
+ ABSL_TSAN_MUTEX_PRE_UNLOCK(this, __tsan_mutex_read_lock);
1718
+ DebugOnlyLockLeave(this);
1719
+ intptr_t v = mu_.load(std::memory_order_relaxed);
1720
+ assert((v & (kMuWriter|kMuReader)) == kMuReader);
1721
+ if ((v & (kMuReader|kMuWait|kMuEvent)) == kMuReader) {
1722
+ // fast reader release (reader with no waiters)
1723
+ intptr_t clear = ExactlyOneReader(v) ? kMuReader|kMuOne : kMuOne;
1724
+ if (mu_.compare_exchange_strong(v, v - clear,
1725
+ std::memory_order_release,
1726
+ std::memory_order_relaxed)) {
1727
+ ABSL_TSAN_MUTEX_POST_UNLOCK(this, __tsan_mutex_read_lock);
1728
+ return;
1729
+ }
1730
+ }
1731
+ this->UnlockSlow(nullptr /*no waitp*/); // take slow path
1732
+ ABSL_TSAN_MUTEX_POST_UNLOCK(this, __tsan_mutex_read_lock);
1733
+ }
1734
+
1735
+ // The zap_desig_waker bitmask is used to clear the designated waker flag in
1736
+ // the mutex if this thread has blocked, and therefore may be the designated
1737
+ // waker.
1738
+ static const intptr_t zap_desig_waker[] = {
1739
+ ~static_cast<intptr_t>(0), // not blocked
1740
+ ~static_cast<intptr_t>(
1741
+ kMuDesig) // blocked; turn off the designated waker bit
1742
+ };
1743
+
1744
+ // The ignore_waiting_writers bitmask is used to ignore the existence
1745
+ // of waiting writers if a reader that has already blocked once
1746
+ // wakes up.
1747
+ static const intptr_t ignore_waiting_writers[] = {
1748
+ ~static_cast<intptr_t>(0), // not blocked
1749
+ ~static_cast<intptr_t>(
1750
+ kMuWrWait) // blocked; pretend there are no waiting writers
1751
+ };
1752
+
1753
+ // Internal version of LockWhen(). See LockSlowWithDeadline()
1754
+ void Mutex::LockSlow(MuHow how, const Condition *cond, int flags) {
1755
+ ABSL_RAW_CHECK(
1756
+ this->LockSlowWithDeadline(how, cond, KernelTimeout::Never(), flags),
1757
+ "condition untrue on return from LockSlow");
1758
+ }
1759
+
1760
+ // Compute cond->Eval() and tell race detectors that we do it under mutex mu.
1761
+ static inline bool EvalConditionAnnotated(const Condition *cond, Mutex *mu,
1762
+ bool locking, bool trylock,
1763
+ bool read_lock) {
1764
+ // Delicate annotation dance.
1765
+ // We are currently inside of read/write lock/unlock operation.
1766
+ // All memory accesses are ignored inside of mutex operations + for unlock
1767
+ // operation tsan considers that we've already released the mutex.
1768
+ bool res = false;
1769
+ #ifdef THREAD_SANITIZER
1770
+ const int flags = read_lock ? __tsan_mutex_read_lock : 0;
1771
+ const int tryflags = flags | (trylock ? __tsan_mutex_try_lock : 0);
1772
+ #endif
1773
+ if (locking) {
1774
+ // For lock we pretend that we have finished the operation,
1775
+ // evaluate the predicate, then unlock the mutex and start locking it again
1776
+ // to match the annotation at the end of outer lock operation.
1777
+ // Note: we can't simply do POST_LOCK, Eval, PRE_LOCK, because then tsan
1778
+ // will think the lock acquisition is recursive which will trigger
1779
+ // deadlock detector.
1780
+ ABSL_TSAN_MUTEX_POST_LOCK(mu, tryflags, 0);
1781
+ res = cond->Eval();
1782
+ // There is no "try" version of Unlock, so use flags instead of tryflags.
1783
+ ABSL_TSAN_MUTEX_PRE_UNLOCK(mu, flags);
1784
+ ABSL_TSAN_MUTEX_POST_UNLOCK(mu, flags);
1785
+ ABSL_TSAN_MUTEX_PRE_LOCK(mu, tryflags);
1786
+ } else {
1787
+ // Similarly, for unlock we pretend that we have unlocked the mutex,
1788
+ // lock the mutex, evaluate the predicate, and start unlocking it again
1789
+ // to match the annotation at the end of outer unlock operation.
1790
+ ABSL_TSAN_MUTEX_POST_UNLOCK(mu, flags);
1791
+ ABSL_TSAN_MUTEX_PRE_LOCK(mu, flags);
1792
+ ABSL_TSAN_MUTEX_POST_LOCK(mu, flags, 0);
1793
+ res = cond->Eval();
1794
+ ABSL_TSAN_MUTEX_PRE_UNLOCK(mu, flags);
1795
+ }
1796
+ // Prevent unused param warnings in non-TSAN builds.
1797
+ static_cast<void>(mu);
1798
+ static_cast<void>(trylock);
1799
+ static_cast<void>(read_lock);
1800
+ return res;
1801
+ }
1802
+
1803
+ // Compute cond->Eval() hiding it from race detectors.
1804
+ // We are hiding it because inside of UnlockSlow we can evaluate a predicate
1805
+ // that was just added by a concurrent Lock operation; Lock adds the predicate
1806
+ // to the internal Mutex list without actually acquiring the Mutex
1807
+ // (it only acquires the internal spinlock, which is rightfully invisible for
1808
+ // tsan). As the result there is no tsan-visible synchronization between the
1809
+ // addition and this thread. So if we would enable race detection here,
1810
+ // it would race with the predicate initialization.
1811
+ static inline bool EvalConditionIgnored(Mutex *mu, const Condition *cond) {
1812
+ // Memory accesses are already ignored inside of lock/unlock operations,
1813
+ // but synchronization operations are also ignored. When we evaluate the
1814
+ // predicate we must ignore only memory accesses but not synchronization,
1815
+ // because missed synchronization can lead to false reports later.
1816
+ // So we "divert" (which un-ignores both memory accesses and synchronization)
1817
+ // and then separately turn on ignores of memory accesses.
1818
+ ABSL_TSAN_MUTEX_PRE_DIVERT(mu, 0);
1819
+ ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
1820
+ bool res = cond->Eval();
1821
+ ANNOTATE_IGNORE_READS_AND_WRITES_END();
1822
+ ABSL_TSAN_MUTEX_POST_DIVERT(mu, 0);
1823
+ static_cast<void>(mu); // Prevent unused param warning in non-TSAN builds.
1824
+ return res;
1825
+ }
1826
+
1827
+ // Internal equivalent of *LockWhenWithDeadline(), where
1828
+ // "t" represents the absolute timeout; !t.has_timeout() means "forever".
1829
+ // "how" is "kShared" (for ReaderLockWhen) or "kExclusive" (for LockWhen)
1830
+ // In flags, bits are ored together:
1831
+ // - kMuHasBlocked indicates that the client has already blocked on the call so
1832
+ // the designated waker bit must be cleared and waiting writers should not
1833
+ // obstruct this call
1834
+ // - kMuIsCond indicates that this is a conditional acquire (condition variable,
1835
+ // Await, LockWhen) so contention profiling should be suppressed.
1836
+ bool Mutex::LockSlowWithDeadline(MuHow how, const Condition *cond,
1837
+ KernelTimeout t, int flags) {
1838
+ intptr_t v = mu_.load(std::memory_order_relaxed);
1839
+ bool unlock = false;
1840
+ if ((v & how->fast_need_zero) == 0 && // try fast acquire
1841
+ mu_.compare_exchange_strong(
1842
+ v, (how->fast_or | (v & zap_desig_waker[flags & kMuHasBlocked])) +
1843
+ how->fast_add,
1844
+ std::memory_order_acquire, std::memory_order_relaxed)) {
1845
+ if (cond == nullptr ||
1846
+ EvalConditionAnnotated(cond, this, true, false, how == kShared)) {
1847
+ return true;
1848
+ }
1849
+ unlock = true;
1850
+ }
1851
+ SynchWaitParams waitp(
1852
+ how, cond, t, nullptr /*no cvmu*/, Synch_GetPerThreadAnnotated(this),
1853
+ nullptr /*no cv_word*/);
1854
+ if (!Condition::GuaranteedEqual(cond, nullptr)) {
1855
+ flags |= kMuIsCond;
1856
+ }
1857
+ if (unlock) {
1858
+ this->UnlockSlow(&waitp);
1859
+ this->Block(waitp.thread);
1860
+ flags |= kMuHasBlocked;
1861
+ }
1862
+ this->LockSlowLoop(&waitp, flags);
1863
+ return waitp.cond != nullptr || // => cond known true from LockSlowLoop
1864
+ cond == nullptr ||
1865
+ EvalConditionAnnotated(cond, this, true, false, how == kShared);
1866
+ }
1867
+
1868
+ // RAW_CHECK_FMT() takes a condition, a printf-style format string, and
1869
+ // the printf-style argument list. The format string must be a literal.
1870
+ // Arguments after the first are not evaluated unless the condition is true.
1871
+ #define RAW_CHECK_FMT(cond, ...) \
1872
+ do { \
1873
+ if (ABSL_PREDICT_FALSE(!(cond))) { \
1874
+ ABSL_RAW_LOG(FATAL, "Check " #cond " failed: " __VA_ARGS__); \
1875
+ } \
1876
+ } while (0)
1877
+
1878
+ static void CheckForMutexCorruption(intptr_t v, const char* label) {
1879
+ // Test for either of two situations that should not occur in v:
1880
+ // kMuWriter and kMuReader
1881
+ // kMuWrWait and !kMuWait
1882
+ const uintptr_t w = v ^ kMuWait;
1883
+ // By flipping that bit, we can now test for:
1884
+ // kMuWriter and kMuReader in w
1885
+ // kMuWrWait and kMuWait in w
1886
+ // We've chosen these two pairs of values to be so that they will overlap,
1887
+ // respectively, when the word is left shifted by three. This allows us to
1888
+ // save a branch in the common (correct) case of them not being coincident.
1889
+ static_assert(kMuReader << 3 == kMuWriter, "must match");
1890
+ static_assert(kMuWait << 3 == kMuWrWait, "must match");
1891
+ if (ABSL_PREDICT_TRUE((w & (w << 3) & (kMuWriter | kMuWrWait)) == 0)) return;
1892
+ RAW_CHECK_FMT((v & (kMuWriter | kMuReader)) != (kMuWriter | kMuReader),
1893
+ "%s: Mutex corrupt: both reader and writer lock held: %p",
1894
+ label, reinterpret_cast<void *>(v));
1895
+ RAW_CHECK_FMT((v & (kMuWait | kMuWrWait)) != kMuWrWait,
1896
+ "%s: Mutex corrupt: waiting writer with no waiters: %p",
1897
+ label, reinterpret_cast<void *>(v));
1898
+ assert(false);
1899
+ }
1900
+
1901
+ void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) {
1902
+ int c = 0;
1903
+ intptr_t v = mu_.load(std::memory_order_relaxed);
1904
+ if ((v & kMuEvent) != 0) {
1905
+ PostSynchEvent(this,
1906
+ waitp->how == kExclusive? SYNCH_EV_LOCK: SYNCH_EV_READERLOCK);
1907
+ }
1908
+ ABSL_RAW_CHECK(
1909
+ waitp->thread->waitp == nullptr || waitp->thread->suppress_fatal_errors,
1910
+ "detected illegal recursion into Mutex code");
1911
+ for (;;) {
1912
+ v = mu_.load(std::memory_order_relaxed);
1913
+ CheckForMutexCorruption(v, "Lock");
1914
+ if ((v & waitp->how->slow_need_zero) == 0) {
1915
+ if (mu_.compare_exchange_strong(
1916
+ v, (waitp->how->fast_or |
1917
+ (v & zap_desig_waker[flags & kMuHasBlocked])) +
1918
+ waitp->how->fast_add,
1919
+ std::memory_order_acquire, std::memory_order_relaxed)) {
1920
+ if (waitp->cond == nullptr ||
1921
+ EvalConditionAnnotated(waitp->cond, this, true, false,
1922
+ waitp->how == kShared)) {
1923
+ break; // we timed out, or condition true, so return
1924
+ }
1925
+ this->UnlockSlow(waitp); // got lock but condition false
1926
+ this->Block(waitp->thread);
1927
+ flags |= kMuHasBlocked;
1928
+ c = 0;
1929
+ }
1930
+ } else { // need to access waiter list
1931
+ bool dowait = false;
1932
+ if ((v & (kMuSpin|kMuWait)) == 0) { // no waiters
1933
+ // This thread tries to become the one and only waiter.
1934
+ PerThreadSynch *new_h = Enqueue(nullptr, waitp, v, flags);
1935
+ intptr_t nv = (v & zap_desig_waker[flags & kMuHasBlocked] & kMuLow) |
1936
+ kMuWait;
1937
+ ABSL_RAW_CHECK(new_h != nullptr, "Enqueue to empty list failed");
1938
+ if (waitp->how == kExclusive && (v & kMuReader) != 0) {
1939
+ nv |= kMuWrWait;
1940
+ }
1941
+ if (mu_.compare_exchange_strong(
1942
+ v, reinterpret_cast<intptr_t>(new_h) | nv,
1943
+ std::memory_order_release, std::memory_order_relaxed)) {
1944
+ dowait = true;
1945
+ } else { // attempted Enqueue() failed
1946
+ // zero out the waitp field set by Enqueue()
1947
+ waitp->thread->waitp = nullptr;
1948
+ }
1949
+ } else if ((v & waitp->how->slow_inc_need_zero &
1950
+ ignore_waiting_writers[flags & kMuHasBlocked]) == 0) {
1951
+ // This is a reader that needs to increment the reader count,
1952
+ // but the count is currently held in the last waiter.
1953
+ if (mu_.compare_exchange_strong(
1954
+ v, (v & zap_desig_waker[flags & kMuHasBlocked]) | kMuSpin |
1955
+ kMuReader,
1956
+ std::memory_order_acquire, std::memory_order_relaxed)) {
1957
+ PerThreadSynch *h = GetPerThreadSynch(v);
1958
+ h->readers += kMuOne; // inc reader count in waiter
1959
+ do { // release spinlock
1960
+ v = mu_.load(std::memory_order_relaxed);
1961
+ } while (!mu_.compare_exchange_weak(v, (v & ~kMuSpin) | kMuReader,
1962
+ std::memory_order_release,
1963
+ std::memory_order_relaxed));
1964
+ if (waitp->cond == nullptr ||
1965
+ EvalConditionAnnotated(waitp->cond, this, true, false,
1966
+ waitp->how == kShared)) {
1967
+ break; // we timed out, or condition true, so return
1968
+ }
1969
+ this->UnlockSlow(waitp); // got lock but condition false
1970
+ this->Block(waitp->thread);
1971
+ flags |= kMuHasBlocked;
1972
+ c = 0;
1973
+ }
1974
+ } else if ((v & kMuSpin) == 0 && // attempt to queue ourselves
1975
+ mu_.compare_exchange_strong(
1976
+ v, (v & zap_desig_waker[flags & kMuHasBlocked]) | kMuSpin |
1977
+ kMuWait,
1978
+ std::memory_order_acquire, std::memory_order_relaxed)) {
1979
+ PerThreadSynch *h = GetPerThreadSynch(v);
1980
+ PerThreadSynch *new_h = Enqueue(h, waitp, v, flags);
1981
+ intptr_t wr_wait = 0;
1982
+ ABSL_RAW_CHECK(new_h != nullptr, "Enqueue to list failed");
1983
+ if (waitp->how == kExclusive && (v & kMuReader) != 0) {
1984
+ wr_wait = kMuWrWait; // give priority to a waiting writer
1985
+ }
1986
+ do { // release spinlock
1987
+ v = mu_.load(std::memory_order_relaxed);
1988
+ } while (!mu_.compare_exchange_weak(
1989
+ v, (v & (kMuLow & ~kMuSpin)) | kMuWait | wr_wait |
1990
+ reinterpret_cast<intptr_t>(new_h),
1991
+ std::memory_order_release, std::memory_order_relaxed));
1992
+ dowait = true;
1993
+ }
1994
+ if (dowait) {
1995
+ this->Block(waitp->thread); // wait until removed from list or timeout
1996
+ flags |= kMuHasBlocked;
1997
+ c = 0;
1998
+ }
1999
+ }
2000
+ ABSL_RAW_CHECK(
2001
+ waitp->thread->waitp == nullptr || waitp->thread->suppress_fatal_errors,
2002
+ "detected illegal recursion into Mutex code");
2003
+ c = Delay(c, GENTLE); // delay, then try again
2004
+ }
2005
+ ABSL_RAW_CHECK(
2006
+ waitp->thread->waitp == nullptr || waitp->thread->suppress_fatal_errors,
2007
+ "detected illegal recursion into Mutex code");
2008
+ if ((v & kMuEvent) != 0) {
2009
+ PostSynchEvent(this,
2010
+ waitp->how == kExclusive? SYNCH_EV_LOCK_RETURNING :
2011
+ SYNCH_EV_READERLOCK_RETURNING);
2012
+ }
2013
+ }
2014
+
2015
+ // Unlock this mutex, which is held by the current thread.
2016
+ // If waitp is non-zero, it must be the wait parameters for the current thread
2017
+ // which holds the lock but is not runnable because its condition is false
2018
+ // or it is in the process of blocking on a condition variable; it must requeue
2019
+ // itself on the mutex/condvar to wait for its condition to become true.
2020
+ void Mutex::UnlockSlow(SynchWaitParams *waitp) {
2021
+ intptr_t v = mu_.load(std::memory_order_relaxed);
2022
+ this->AssertReaderHeld();
2023
+ CheckForMutexCorruption(v, "Unlock");
2024
+ if ((v & kMuEvent) != 0) {
2025
+ PostSynchEvent(this,
2026
+ (v & kMuWriter) != 0? SYNCH_EV_UNLOCK: SYNCH_EV_READERUNLOCK);
2027
+ }
2028
+ int c = 0;
2029
+ // the waiter under consideration to wake, or zero
2030
+ PerThreadSynch *w = nullptr;
2031
+ // the predecessor to w or zero
2032
+ PerThreadSynch *pw = nullptr;
2033
+ // head of the list searched previously, or zero
2034
+ PerThreadSynch *old_h = nullptr;
2035
+ // a condition that's known to be false.
2036
+ const Condition *known_false = nullptr;
2037
+ PerThreadSynch *wake_list = kPerThreadSynchNull; // list of threads to wake
2038
+ intptr_t wr_wait = 0; // set to kMuWrWait if we wake a reader and a
2039
+ // later writer could have acquired the lock
2040
+ // (starvation avoidance)
2041
+ ABSL_RAW_CHECK(waitp == nullptr || waitp->thread->waitp == nullptr ||
2042
+ waitp->thread->suppress_fatal_errors,
2043
+ "detected illegal recursion into Mutex code");
2044
+ // This loop finds threads wake_list to wakeup if any, and removes them from
2045
+ // the list of waiters. In addition, it places waitp.thread on the queue of
2046
+ // waiters if waitp is non-zero.
2047
+ for (;;) {
2048
+ v = mu_.load(std::memory_order_relaxed);
2049
+ if ((v & kMuWriter) != 0 && (v & (kMuWait | kMuDesig)) != kMuWait &&
2050
+ waitp == nullptr) {
2051
+ // fast writer release (writer with no waiters or with designated waker)
2052
+ if (mu_.compare_exchange_strong(v, v & ~(kMuWrWait | kMuWriter),
2053
+ std::memory_order_release,
2054
+ std::memory_order_relaxed)) {
2055
+ return;
2056
+ }
2057
+ } else if ((v & (kMuReader | kMuWait)) == kMuReader && waitp == nullptr) {
2058
+ // fast reader release (reader with no waiters)
2059
+ intptr_t clear = ExactlyOneReader(v) ? kMuReader | kMuOne : kMuOne;
2060
+ if (mu_.compare_exchange_strong(v, v - clear,
2061
+ std::memory_order_release,
2062
+ std::memory_order_relaxed)) {
2063
+ return;
2064
+ }
2065
+ } else if ((v & kMuSpin) == 0 && // attempt to get spinlock
2066
+ mu_.compare_exchange_strong(v, v | kMuSpin,
2067
+ std::memory_order_acquire,
2068
+ std::memory_order_relaxed)) {
2069
+ if ((v & kMuWait) == 0) { // no one to wake
2070
+ intptr_t nv;
2071
+ bool do_enqueue = true; // always Enqueue() the first time
2072
+ ABSL_RAW_CHECK(waitp != nullptr,
2073
+ "UnlockSlow is confused"); // about to sleep
2074
+ do { // must loop to release spinlock as reader count may change
2075
+ v = mu_.load(std::memory_order_relaxed);
2076
+ // decrement reader count if there are readers
2077
+ intptr_t new_readers = (v >= kMuOne)? v - kMuOne : v;
2078
+ PerThreadSynch *new_h = nullptr;
2079
+ if (do_enqueue) {
2080
+ // If we are enqueuing on a CondVar (waitp->cv_word != nullptr) then
2081
+ // we must not retry here. The initial attempt will always have
2082
+ // succeeded, further attempts would enqueue us against *this due to
2083
+ // Fer() handling.
2084
+ do_enqueue = (waitp->cv_word == nullptr);
2085
+ new_h = Enqueue(nullptr, waitp, new_readers, kMuIsCond);
2086
+ }
2087
+ intptr_t clear = kMuWrWait | kMuWriter; // by default clear write bit
2088
+ if ((v & kMuWriter) == 0 && ExactlyOneReader(v)) { // last reader
2089
+ clear = kMuWrWait | kMuReader; // clear read bit
2090
+ }
2091
+ nv = (v & kMuLow & ~clear & ~kMuSpin);
2092
+ if (new_h != nullptr) {
2093
+ nv |= kMuWait | reinterpret_cast<intptr_t>(new_h);
2094
+ } else { // new_h could be nullptr if we queued ourselves on a
2095
+ // CondVar
2096
+ // In that case, we must place the reader count back in the mutex
2097
+ // word, as Enqueue() did not store it in the new waiter.
2098
+ nv |= new_readers & kMuHigh;
2099
+ }
2100
+ // release spinlock & our lock; retry if reader-count changed
2101
+ // (writer count cannot change since we hold lock)
2102
+ } while (!mu_.compare_exchange_weak(v, nv,
2103
+ std::memory_order_release,
2104
+ std::memory_order_relaxed));
2105
+ break;
2106
+ }
2107
+
2108
+ // There are waiters.
2109
+ // Set h to the head of the circular waiter list.
2110
+ PerThreadSynch *h = GetPerThreadSynch(v);
2111
+ if ((v & kMuReader) != 0 && (h->readers & kMuHigh) > kMuOne) {
2112
+ // a reader but not the last
2113
+ h->readers -= kMuOne; // release our lock
2114
+ intptr_t nv = v; // normally just release spinlock
2115
+ if (waitp != nullptr) { // but waitp!=nullptr => must queue ourselves
2116
+ PerThreadSynch *new_h = Enqueue(h, waitp, v, kMuIsCond);
2117
+ ABSL_RAW_CHECK(new_h != nullptr,
2118
+ "waiters disappeared during Enqueue()!");
2119
+ nv &= kMuLow;
2120
+ nv |= kMuWait | reinterpret_cast<intptr_t>(new_h);
2121
+ }
2122
+ mu_.store(nv, std::memory_order_release); // release spinlock
2123
+ // can release with a store because there were waiters
2124
+ break;
2125
+ }
2126
+
2127
+ // Either we didn't search before, or we marked the queue
2128
+ // as "maybe_unlocking" and no one else should have changed it.
2129
+ ABSL_RAW_CHECK(old_h == nullptr || h->maybe_unlocking,
2130
+ "Mutex queue changed beneath us");
2131
+
2132
+ // The lock is becoming free, and there's a waiter
2133
+ if (old_h != nullptr &&
2134
+ !old_h->may_skip) { // we used old_h as a terminator
2135
+ old_h->may_skip = true; // allow old_h to skip once more
2136
+ ABSL_RAW_CHECK(old_h->skip == nullptr, "illegal skip from head");
2137
+ if (h != old_h && MuSameCondition(old_h, old_h->next)) {
2138
+ old_h->skip = old_h->next; // old_h not head & can skip to successor
2139
+ }
2140
+ }
2141
+ if (h->next->waitp->how == kExclusive &&
2142
+ Condition::GuaranteedEqual(h->next->waitp->cond, nullptr)) {
2143
+ // easy case: writer with no condition; no need to search
2144
+ pw = h; // wake w, the successor of h (=pw)
2145
+ w = h->next;
2146
+ w->wake = true;
2147
+ // We are waking up a writer. This writer may be racing against
2148
+ // an already awake reader for the lock. We want the
2149
+ // writer to usually win this race,
2150
+ // because if it doesn't, we can potentially keep taking a reader
2151
+ // perpetually and writers will starve. Worse than
2152
+ // that, this can also starve other readers if kMuWrWait gets set
2153
+ // later.
2154
+ wr_wait = kMuWrWait;
2155
+ } else if (w != nullptr && (w->waitp->how == kExclusive || h == old_h)) {
2156
+ // we found a waiter w to wake on a previous iteration and either it's
2157
+ // a writer, or we've searched the entire list so we have all the
2158
+ // readers.
2159
+ if (pw == nullptr) { // if w's predecessor is unknown, it must be h
2160
+ pw = h;
2161
+ }
2162
+ } else {
2163
+ // At this point we don't know all the waiters to wake, and the first
2164
+ // waiter has a condition or is a reader. We avoid searching over
2165
+ // waiters we've searched on previous iterations by starting at
2166
+ // old_h if it's set. If old_h==h, there's no one to wakeup at all.
2167
+ if (old_h == h) { // we've searched before, and nothing's new
2168
+ // so there's no one to wake.
2169
+ intptr_t nv = (v & ~(kMuReader|kMuWriter|kMuWrWait));
2170
+ h->readers = 0;
2171
+ h->maybe_unlocking = false; // finished unlocking
2172
+ if (waitp != nullptr) { // we must queue ourselves and sleep
2173
+ PerThreadSynch *new_h = Enqueue(h, waitp, v, kMuIsCond);
2174
+ nv &= kMuLow;
2175
+ if (new_h != nullptr) {
2176
+ nv |= kMuWait | reinterpret_cast<intptr_t>(new_h);
2177
+ } // else new_h could be nullptr if we queued ourselves on a
2178
+ // CondVar
2179
+ }
2180
+ // release spinlock & lock
2181
+ // can release with a store because there were waiters
2182
+ mu_.store(nv, std::memory_order_release);
2183
+ break;
2184
+ }
2185
+
2186
+ // set up to walk the list
2187
+ PerThreadSynch *w_walk; // current waiter during list walk
2188
+ PerThreadSynch *pw_walk; // previous waiter during list walk
2189
+ if (old_h != nullptr) { // we've searched up to old_h before
2190
+ pw_walk = old_h;
2191
+ w_walk = old_h->next;
2192
+ } else { // no prior search, start at beginning
2193
+ pw_walk =
2194
+ nullptr; // h->next's predecessor may change; don't record it
2195
+ w_walk = h->next;
2196
+ }
2197
+
2198
+ h->may_skip = false; // ensure we never skip past h in future searches
2199
+ // even if other waiters are queued after it.
2200
+ ABSL_RAW_CHECK(h->skip == nullptr, "illegal skip from head");
2201
+
2202
+ h->maybe_unlocking = true; // we're about to scan the waiter list
2203
+ // without the spinlock held.
2204
+ // Enqueue must be conservative about
2205
+ // priority queuing.
2206
+
2207
+ // We must release the spinlock to evaluate the conditions.
2208
+ mu_.store(v, std::memory_order_release); // release just spinlock
2209
+ // can release with a store because there were waiters
2210
+
2211
+ // h is the last waiter queued, and w_walk the first unsearched waiter.
2212
+ // Without the spinlock, the locations mu_ and h->next may now change
2213
+ // underneath us, but since we hold the lock itself, the only legal
2214
+ // change is to add waiters between h and w_walk. Therefore, it's safe
2215
+ // to walk the path from w_walk to h inclusive. (TryRemove() can remove
2216
+ // a waiter anywhere, but it acquires both the spinlock and the Mutex)
2217
+
2218
+ old_h = h; // remember we searched to here
2219
+
2220
+ // Walk the path upto and including h looking for waiters we can wake.
2221
+ while (pw_walk != h) {
2222
+ w_walk->wake = false;
2223
+ if (w_walk->waitp->cond ==
2224
+ nullptr || // no condition => vacuously true OR
2225
+ (w_walk->waitp->cond != known_false &&
2226
+ // this thread's condition is not known false, AND
2227
+ // is in fact true
2228
+ EvalConditionIgnored(this, w_walk->waitp->cond))) {
2229
+ if (w == nullptr) {
2230
+ w_walk->wake = true; // can wake this waiter
2231
+ w = w_walk;
2232
+ pw = pw_walk;
2233
+ if (w_walk->waitp->how == kExclusive) {
2234
+ wr_wait = kMuWrWait;
2235
+ break; // bail if waking this writer
2236
+ }
2237
+ } else if (w_walk->waitp->how == kShared) { // wake if a reader
2238
+ w_walk->wake = true;
2239
+ } else { // writer with true condition
2240
+ wr_wait = kMuWrWait;
2241
+ }
2242
+ } else { // can't wake; condition false
2243
+ known_false = w_walk->waitp->cond; // remember last false condition
2244
+ }
2245
+ if (w_walk->wake) { // we're waking reader w_walk
2246
+ pw_walk = w_walk; // don't skip similar waiters
2247
+ } else { // not waking; skip as much as possible
2248
+ pw_walk = Skip(w_walk);
2249
+ }
2250
+ // If pw_walk == h, then load of pw_walk->next can race with
2251
+ // concurrent write in Enqueue(). However, at the same time
2252
+ // we do not need to do the load, because we will bail out
2253
+ // from the loop anyway.
2254
+ if (pw_walk != h) {
2255
+ w_walk = pw_walk->next;
2256
+ }
2257
+ }
2258
+
2259
+ continue; // restart for(;;)-loop to wakeup w or to find more waiters
2260
+ }
2261
+ ABSL_RAW_CHECK(pw->next == w, "pw not w's predecessor");
2262
+ // The first (and perhaps only) waiter we've chosen to wake is w, whose
2263
+ // predecessor is pw. If w is a reader, we must wake all the other
2264
+ // waiters with wake==true as well. We may also need to queue
2265
+ // ourselves if waitp != null. The spinlock and the lock are still
2266
+ // held.
2267
+
2268
+ // This traverses the list in [ pw->next, h ], where h is the head,
2269
+ // removing all elements with wake==true and placing them in the
2270
+ // singly-linked list wake_list. Returns the new head.
2271
+ h = DequeueAllWakeable(h, pw, &wake_list);
2272
+
2273
+ intptr_t nv = (v & kMuEvent) | kMuDesig;
2274
+ // assume no waiters left,
2275
+ // set kMuDesig for INV1a
2276
+
2277
+ if (waitp != nullptr) { // we must queue ourselves and sleep
2278
+ h = Enqueue(h, waitp, v, kMuIsCond);
2279
+ // h is new last waiter; could be null if we queued ourselves on a
2280
+ // CondVar
2281
+ }
2282
+
2283
+ ABSL_RAW_CHECK(wake_list != kPerThreadSynchNull,
2284
+ "unexpected empty wake list");
2285
+
2286
+ if (h != nullptr) { // there are waiters left
2287
+ h->readers = 0;
2288
+ h->maybe_unlocking = false; // finished unlocking
2289
+ nv |= wr_wait | kMuWait | reinterpret_cast<intptr_t>(h);
2290
+ }
2291
+
2292
+ // release both spinlock & lock
2293
+ // can release with a store because there were waiters
2294
+ mu_.store(nv, std::memory_order_release);
2295
+ break; // out of for(;;)-loop
2296
+ }
2297
+ c = Delay(c, AGGRESSIVE); // aggressive here; no one can proceed till we do
2298
+ } // end of for(;;)-loop
2299
+
2300
+ if (wake_list != kPerThreadSynchNull) {
2301
+ int64_t enqueue_timestamp = wake_list->waitp->contention_start_cycles;
2302
+ bool cond_waiter = wake_list->cond_waiter;
2303
+ do {
2304
+ wake_list = Wakeup(wake_list); // wake waiters
2305
+ } while (wake_list != kPerThreadSynchNull);
2306
+ if (!cond_waiter) {
2307
+ // Sample lock contention events only if the (first) waiter was trying to
2308
+ // acquire the lock, not waiting on a condition variable or Condition.
2309
+ int64_t wait_cycles = base_internal::CycleClock::Now() - enqueue_timestamp;
2310
+ mutex_tracer("slow release", this, wait_cycles);
2311
+ ABSL_TSAN_MUTEX_PRE_DIVERT(this, 0);
2312
+ submit_profile_data(enqueue_timestamp);
2313
+ ABSL_TSAN_MUTEX_POST_DIVERT(this, 0);
2314
+ }
2315
+ }
2316
+ }
2317
+
2318
+ // Used by CondVar implementation to reacquire mutex after waking from
2319
+ // condition variable. This routine is used instead of Lock() because the
2320
+ // waiting thread may have been moved from the condition variable queue to the
2321
+ // mutex queue without a wakeup, by Trans(). In that case, when the thread is
2322
+ // finally woken, the woken thread will believe it has been woken from the
2323
+ // condition variable (i.e. its PC will be in when in the CondVar code), when
2324
+ // in fact it has just been woken from the mutex. Thus, it must enter the slow
2325
+ // path of the mutex in the same state as if it had just woken from the mutex.
2326
+ // That is, it must ensure to clear kMuDesig (INV1b).
2327
+ void Mutex::Trans(MuHow how) {
2328
+ this->LockSlow(how, nullptr, kMuHasBlocked | kMuIsCond);
2329
+ }
2330
+
2331
+ // Used by CondVar implementation to effectively wake thread w from the
2332
+ // condition variable. If this mutex is free, we simply wake the thread.
2333
+ // It will later acquire the mutex with high probability. Otherwise, we
2334
+ // enqueue thread w on this mutex.
2335
+ void Mutex::Fer(PerThreadSynch *w) {
2336
+ int c = 0;
2337
+ ABSL_RAW_CHECK(w->waitp->cond == nullptr,
2338
+ "Mutex::Fer while waiting on Condition");
2339
+ ABSL_RAW_CHECK(!w->waitp->timeout.has_timeout(),
2340
+ "Mutex::Fer while in timed wait");
2341
+ ABSL_RAW_CHECK(w->waitp->cv_word == nullptr,
2342
+ "Mutex::Fer with pending CondVar queueing");
2343
+ for (;;) {
2344
+ intptr_t v = mu_.load(std::memory_order_relaxed);
2345
+ // Note: must not queue if the mutex is unlocked (nobody will wake it).
2346
+ // For example, we can have only kMuWait (conditional) or maybe
2347
+ // kMuWait|kMuWrWait.
2348
+ // conflicting != 0 implies that the waking thread cannot currently take
2349
+ // the mutex, which in turn implies that someone else has it and can wake
2350
+ // us if we queue.
2351
+ const intptr_t conflicting =
2352
+ kMuWriter | (w->waitp->how == kShared ? 0 : kMuReader);
2353
+ if ((v & conflicting) == 0) {
2354
+ w->next = nullptr;
2355
+ w->state.store(PerThreadSynch::kAvailable, std::memory_order_release);
2356
+ IncrementSynchSem(this, w);
2357
+ return;
2358
+ } else {
2359
+ if ((v & (kMuSpin|kMuWait)) == 0) { // no waiters
2360
+ // This thread tries to become the one and only waiter.
2361
+ PerThreadSynch *new_h = Enqueue(nullptr, w->waitp, v, kMuIsCond);
2362
+ ABSL_RAW_CHECK(new_h != nullptr,
2363
+ "Enqueue failed"); // we must queue ourselves
2364
+ if (mu_.compare_exchange_strong(
2365
+ v, reinterpret_cast<intptr_t>(new_h) | (v & kMuLow) | kMuWait,
2366
+ std::memory_order_release, std::memory_order_relaxed)) {
2367
+ return;
2368
+ }
2369
+ } else if ((v & kMuSpin) == 0 &&
2370
+ mu_.compare_exchange_strong(v, v | kMuSpin | kMuWait)) {
2371
+ PerThreadSynch *h = GetPerThreadSynch(v);
2372
+ PerThreadSynch *new_h = Enqueue(h, w->waitp, v, kMuIsCond);
2373
+ ABSL_RAW_CHECK(new_h != nullptr,
2374
+ "Enqueue failed"); // we must queue ourselves
2375
+ do {
2376
+ v = mu_.load(std::memory_order_relaxed);
2377
+ } while (!mu_.compare_exchange_weak(
2378
+ v,
2379
+ (v & kMuLow & ~kMuSpin) | kMuWait |
2380
+ reinterpret_cast<intptr_t>(new_h),
2381
+ std::memory_order_release, std::memory_order_relaxed));
2382
+ return;
2383
+ }
2384
+ }
2385
+ c = Delay(c, GENTLE);
2386
+ }
2387
+ }
2388
+
2389
+ void Mutex::AssertHeld() const {
2390
+ if ((mu_.load(std::memory_order_relaxed) & kMuWriter) == 0) {
2391
+ SynchEvent *e = GetSynchEvent(this);
2392
+ ABSL_RAW_LOG(FATAL, "thread should hold write lock on Mutex %p %s",
2393
+ static_cast<const void *>(this),
2394
+ (e == nullptr ? "" : e->name));
2395
+ }
2396
+ }
2397
+
2398
+ void Mutex::AssertReaderHeld() const {
2399
+ if ((mu_.load(std::memory_order_relaxed) & (kMuReader | kMuWriter)) == 0) {
2400
+ SynchEvent *e = GetSynchEvent(this);
2401
+ ABSL_RAW_LOG(
2402
+ FATAL, "thread should hold at least a read lock on Mutex %p %s",
2403
+ static_cast<const void *>(this), (e == nullptr ? "" : e->name));
2404
+ }
2405
+ }
2406
+
2407
+ // -------------------------------- condition variables
2408
+ static const intptr_t kCvSpin = 0x0001L; // spinlock protects waiter list
2409
+ static const intptr_t kCvEvent = 0x0002L; // record events
2410
+
2411
+ static const intptr_t kCvLow = 0x0003L; // low order bits of CV
2412
+
2413
+ // Hack to make constant values available to gdb pretty printer
2414
+ enum { kGdbCvSpin = kCvSpin, kGdbCvEvent = kCvEvent, kGdbCvLow = kCvLow, };
2415
+
2416
+ static_assert(PerThreadSynch::kAlignment > kCvLow,
2417
+ "PerThreadSynch::kAlignment must be greater than kCvLow");
2418
+
2419
+ void CondVar::EnableDebugLog(const char *name) {
2420
+ SynchEvent *e = EnsureSynchEvent(&this->cv_, name, kCvEvent, kCvSpin);
2421
+ e->log = true;
2422
+ UnrefSynchEvent(e);
2423
+ }
2424
+
2425
+ CondVar::~CondVar() {
2426
+ if ((cv_.load(std::memory_order_relaxed) & kCvEvent) != 0) {
2427
+ ForgetSynchEvent(&this->cv_, kCvEvent, kCvSpin);
2428
+ }
2429
+ }
2430
+
2431
+
2432
+ // Remove thread s from the list of waiters on this condition variable.
2433
+ void CondVar::Remove(PerThreadSynch *s) {
2434
+ intptr_t v;
2435
+ int c = 0;
2436
+ for (v = cv_.load(std::memory_order_relaxed);;
2437
+ v = cv_.load(std::memory_order_relaxed)) {
2438
+ if ((v & kCvSpin) == 0 && // attempt to acquire spinlock
2439
+ cv_.compare_exchange_strong(v, v | kCvSpin,
2440
+ std::memory_order_acquire,
2441
+ std::memory_order_relaxed)) {
2442
+ PerThreadSynch *h = reinterpret_cast<PerThreadSynch *>(v & ~kCvLow);
2443
+ if (h != nullptr) {
2444
+ PerThreadSynch *w = h;
2445
+ while (w->next != s && w->next != h) { // search for thread
2446
+ w = w->next;
2447
+ }
2448
+ if (w->next == s) { // found thread; remove it
2449
+ w->next = s->next;
2450
+ if (h == s) {
2451
+ h = (w == s) ? nullptr : w;
2452
+ }
2453
+ s->next = nullptr;
2454
+ s->state.store(PerThreadSynch::kAvailable, std::memory_order_release);
2455
+ }
2456
+ }
2457
+ // release spinlock
2458
+ cv_.store((v & kCvEvent) | reinterpret_cast<intptr_t>(h),
2459
+ std::memory_order_release);
2460
+ return;
2461
+ } else {
2462
+ c = Delay(c, GENTLE); // try again after a delay
2463
+ }
2464
+ }
2465
+ }
2466
+
2467
+ // Queue thread waitp->thread on condition variable word cv_word using
2468
+ // wait parameters waitp.
2469
+ // We split this into a separate routine, rather than simply doing it as part
2470
+ // of WaitCommon(). If we were to queue ourselves on the condition variable
2471
+ // before calling Mutex::UnlockSlow(), the Mutex code might be re-entered (via
2472
+ // the logging code, or via a Condition function) and might potentially attempt
2473
+ // to block this thread. That would be a problem if the thread were already on
2474
+ // a the condition variable waiter queue. Thus, we use the waitp->cv_word
2475
+ // to tell the unlock code to call CondVarEnqueue() to queue the thread on the
2476
+ // condition variable queue just before the mutex is to be unlocked, and (most
2477
+ // importantly) after any call to an external routine that might re-enter the
2478
+ // mutex code.
2479
+ static void CondVarEnqueue(SynchWaitParams *waitp) {
2480
+ // This thread might be transferred to the Mutex queue by Fer() when
2481
+ // we are woken. To make sure that is what happens, Enqueue() doesn't
2482
+ // call CondVarEnqueue() again but instead uses its normal code. We
2483
+ // must do this before we queue ourselves so that cv_word will be null
2484
+ // when seen by the dequeuer, who may wish immediately to requeue
2485
+ // this thread on another queue.
2486
+ std::atomic<intptr_t> *cv_word = waitp->cv_word;
2487
+ waitp->cv_word = nullptr;
2488
+
2489
+ intptr_t v = cv_word->load(std::memory_order_relaxed);
2490
+ int c = 0;
2491
+ while ((v & kCvSpin) != 0 || // acquire spinlock
2492
+ !cv_word->compare_exchange_weak(v, v | kCvSpin,
2493
+ std::memory_order_acquire,
2494
+ std::memory_order_relaxed)) {
2495
+ c = Delay(c, GENTLE);
2496
+ v = cv_word->load(std::memory_order_relaxed);
2497
+ }
2498
+ ABSL_RAW_CHECK(waitp->thread->waitp == nullptr, "waiting when shouldn't be");
2499
+ waitp->thread->waitp = waitp; // prepare ourselves for waiting
2500
+ PerThreadSynch *h = reinterpret_cast<PerThreadSynch *>(v & ~kCvLow);
2501
+ if (h == nullptr) { // add this thread to waiter list
2502
+ waitp->thread->next = waitp->thread;
2503
+ } else {
2504
+ waitp->thread->next = h->next;
2505
+ h->next = waitp->thread;
2506
+ }
2507
+ waitp->thread->state.store(PerThreadSynch::kQueued,
2508
+ std::memory_order_relaxed);
2509
+ cv_word->store((v & kCvEvent) | reinterpret_cast<intptr_t>(waitp->thread),
2510
+ std::memory_order_release);
2511
+ }
2512
+
2513
+ bool CondVar::WaitCommon(Mutex *mutex, KernelTimeout t) {
2514
+ bool rc = false; // return value; true iff we timed-out
2515
+
2516
+ intptr_t mutex_v = mutex->mu_.load(std::memory_order_relaxed);
2517
+ Mutex::MuHow mutex_how = ((mutex_v & kMuWriter) != 0) ? kExclusive : kShared;
2518
+ ABSL_TSAN_MUTEX_PRE_UNLOCK(mutex, TsanFlags(mutex_how));
2519
+
2520
+ // maybe trace this call
2521
+ intptr_t v = cv_.load(std::memory_order_relaxed);
2522
+ cond_var_tracer("Wait", this);
2523
+ if ((v & kCvEvent) != 0) {
2524
+ PostSynchEvent(this, SYNCH_EV_WAIT);
2525
+ }
2526
+
2527
+ // Release mu and wait on condition variable.
2528
+ SynchWaitParams waitp(mutex_how, nullptr, t, mutex,
2529
+ Synch_GetPerThreadAnnotated(mutex), &cv_);
2530
+ // UnlockSlow() will call CondVarEnqueue() just before releasing the
2531
+ // Mutex, thus queuing this thread on the condition variable. See
2532
+ // CondVarEnqueue() for the reasons.
2533
+ mutex->UnlockSlow(&waitp);
2534
+
2535
+ // wait for signal
2536
+ while (waitp.thread->state.load(std::memory_order_acquire) ==
2537
+ PerThreadSynch::kQueued) {
2538
+ if (!Mutex::DecrementSynchSem(mutex, waitp.thread, t)) {
2539
+ this->Remove(waitp.thread);
2540
+ rc = true;
2541
+ }
2542
+ }
2543
+
2544
+ ABSL_RAW_CHECK(waitp.thread->waitp != nullptr, "not waiting when should be");
2545
+ waitp.thread->waitp = nullptr; // cleanup
2546
+
2547
+ // maybe trace this call
2548
+ cond_var_tracer("Unwait", this);
2549
+ if ((v & kCvEvent) != 0) {
2550
+ PostSynchEvent(this, SYNCH_EV_WAIT_RETURNING);
2551
+ }
2552
+
2553
+ // From synchronization point of view Wait is unlock of the mutex followed
2554
+ // by lock of the mutex. We've annotated start of unlock in the beginning
2555
+ // of the function. Now, finish unlock and annotate lock of the mutex.
2556
+ // (Trans is effectively lock).
2557
+ ABSL_TSAN_MUTEX_POST_UNLOCK(mutex, TsanFlags(mutex_how));
2558
+ ABSL_TSAN_MUTEX_PRE_LOCK(mutex, TsanFlags(mutex_how));
2559
+ mutex->Trans(mutex_how); // Reacquire mutex
2560
+ ABSL_TSAN_MUTEX_POST_LOCK(mutex, TsanFlags(mutex_how), 0);
2561
+ return rc;
2562
+ }
2563
+
2564
+ bool CondVar::WaitWithTimeout(Mutex *mu, absl::Duration timeout) {
2565
+ return WaitWithDeadline(mu, DeadlineFromTimeout(timeout));
2566
+ }
2567
+
2568
+ bool CondVar::WaitWithDeadline(Mutex *mu, absl::Time deadline) {
2569
+ return WaitCommon(mu, KernelTimeout(deadline));
2570
+ }
2571
+
2572
+ void CondVar::Wait(Mutex *mu) {
2573
+ WaitCommon(mu, KernelTimeout::Never());
2574
+ }
2575
+
2576
+ // Wake thread w
2577
+ // If it was a timed wait, w will be waiting on w->cv
2578
+ // Otherwise, if it was not a Mutex mutex, w will be waiting on w->sem
2579
+ // Otherwise, w is transferred to the Mutex mutex via Mutex::Fer().
2580
+ void CondVar::Wakeup(PerThreadSynch *w) {
2581
+ if (w->waitp->timeout.has_timeout() || w->waitp->cvmu == nullptr) {
2582
+ // The waiting thread only needs to observe "w->state == kAvailable" to be
2583
+ // released, we must cache "cvmu" before clearing "next".
2584
+ Mutex *mu = w->waitp->cvmu;
2585
+ w->next = nullptr;
2586
+ w->state.store(PerThreadSynch::kAvailable, std::memory_order_release);
2587
+ Mutex::IncrementSynchSem(mu, w);
2588
+ } else {
2589
+ w->waitp->cvmu->Fer(w);
2590
+ }
2591
+ }
2592
+
2593
+ void CondVar::Signal() {
2594
+ ABSL_TSAN_MUTEX_PRE_SIGNAL(nullptr, 0);
2595
+ intptr_t v;
2596
+ int c = 0;
2597
+ for (v = cv_.load(std::memory_order_relaxed); v != 0;
2598
+ v = cv_.load(std::memory_order_relaxed)) {
2599
+ if ((v & kCvSpin) == 0 && // attempt to acquire spinlock
2600
+ cv_.compare_exchange_strong(v, v | kCvSpin,
2601
+ std::memory_order_acquire,
2602
+ std::memory_order_relaxed)) {
2603
+ PerThreadSynch *h = reinterpret_cast<PerThreadSynch *>(v & ~kCvLow);
2604
+ PerThreadSynch *w = nullptr;
2605
+ if (h != nullptr) { // remove first waiter
2606
+ w = h->next;
2607
+ if (w == h) {
2608
+ h = nullptr;
2609
+ } else {
2610
+ h->next = w->next;
2611
+ }
2612
+ }
2613
+ // release spinlock
2614
+ cv_.store((v & kCvEvent) | reinterpret_cast<intptr_t>(h),
2615
+ std::memory_order_release);
2616
+ if (w != nullptr) {
2617
+ CondVar::Wakeup(w); // wake waiter, if there was one
2618
+ cond_var_tracer("Signal wakeup", this);
2619
+ }
2620
+ if ((v & kCvEvent) != 0) {
2621
+ PostSynchEvent(this, SYNCH_EV_SIGNAL);
2622
+ }
2623
+ ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0);
2624
+ return;
2625
+ } else {
2626
+ c = Delay(c, GENTLE);
2627
+ }
2628
+ }
2629
+ ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0);
2630
+ }
2631
+
2632
+ void CondVar::SignalAll () {
2633
+ ABSL_TSAN_MUTEX_PRE_SIGNAL(nullptr, 0);
2634
+ intptr_t v;
2635
+ int c = 0;
2636
+ for (v = cv_.load(std::memory_order_relaxed); v != 0;
2637
+ v = cv_.load(std::memory_order_relaxed)) {
2638
+ // empty the list if spinlock free
2639
+ // We do this by simply setting the list to empty using
2640
+ // compare and swap. We then have the entire list in our hands,
2641
+ // which cannot be changing since we grabbed it while no one
2642
+ // held the lock.
2643
+ if ((v & kCvSpin) == 0 &&
2644
+ cv_.compare_exchange_strong(v, v & kCvEvent, std::memory_order_acquire,
2645
+ std::memory_order_relaxed)) {
2646
+ PerThreadSynch *h = reinterpret_cast<PerThreadSynch *>(v & ~kCvLow);
2647
+ if (h != nullptr) {
2648
+ PerThreadSynch *w;
2649
+ PerThreadSynch *n = h->next;
2650
+ do { // for every thread, wake it up
2651
+ w = n;
2652
+ n = n->next;
2653
+ CondVar::Wakeup(w);
2654
+ } while (w != h);
2655
+ cond_var_tracer("SignalAll wakeup", this);
2656
+ }
2657
+ if ((v & kCvEvent) != 0) {
2658
+ PostSynchEvent(this, SYNCH_EV_SIGNALALL);
2659
+ }
2660
+ ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0);
2661
+ return;
2662
+ } else {
2663
+ c = Delay(c, GENTLE); // try again after a delay
2664
+ }
2665
+ }
2666
+ ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0);
2667
+ }
2668
+
2669
+ void ReleasableMutexLock::Release() {
2670
+ ABSL_RAW_CHECK(this->mu_ != nullptr,
2671
+ "ReleasableMutexLock::Release may only be called once");
2672
+ this->mu_->Unlock();
2673
+ this->mu_ = nullptr;
2674
+ }
2675
+
2676
+ #ifdef THREAD_SANITIZER
2677
+ extern "C" void __tsan_read1(void *addr);
2678
+ #else
2679
+ #define __tsan_read1(addr) // do nothing if TSan not enabled
2680
+ #endif
2681
+
2682
+ // A function that just returns its argument, dereferenced
2683
+ static bool Dereference(void *arg) {
2684
+ // ThreadSanitizer does not instrument this file for memory accesses.
2685
+ // This function dereferences a user variable that can participate
2686
+ // in a data race, so we need to manually tell TSan about this memory access.
2687
+ __tsan_read1(arg);
2688
+ return *(static_cast<bool *>(arg));
2689
+ }
2690
+
2691
+ Condition::Condition() {} // null constructor, used for kTrue only
2692
+ const Condition Condition::kTrue;
2693
+
2694
+ Condition::Condition(bool (*func)(void *), void *arg)
2695
+ : eval_(&CallVoidPtrFunction),
2696
+ function_(func),
2697
+ method_(nullptr),
2698
+ arg_(arg) {}
2699
+
2700
+ bool Condition::CallVoidPtrFunction(const Condition *c) {
2701
+ return (*c->function_)(c->arg_);
2702
+ }
2703
+
2704
+ Condition::Condition(const bool *cond)
2705
+ : eval_(CallVoidPtrFunction),
2706
+ function_(Dereference),
2707
+ method_(nullptr),
2708
+ // const_cast is safe since Dereference does not modify arg
2709
+ arg_(const_cast<bool *>(cond)) {}
2710
+
2711
+ bool Condition::Eval() const {
2712
+ // eval_ == null for kTrue
2713
+ return (this->eval_ == nullptr) || (*this->eval_)(this);
2714
+ }
2715
+
2716
+ bool Condition::GuaranteedEqual(const Condition *a, const Condition *b) {
2717
+ if (a == nullptr) {
2718
+ return b == nullptr || b->eval_ == nullptr;
2719
+ }
2720
+ if (b == nullptr || b->eval_ == nullptr) {
2721
+ return a->eval_ == nullptr;
2722
+ }
2723
+ return a->eval_ == b->eval_ && a->function_ == b->function_ &&
2724
+ a->arg_ == b->arg_ && a->method_ == b->method_;
2725
+ }
2726
+
2727
+ ABSL_NAMESPACE_END
2728
+ } // namespace absl