about summary refs log tree commit diff
path: root/absl
diff options
context:
space:
mode:
Diffstat (limited to 'absl')
-rwxr-xr-xabsl/abseil.podspec.gen.py247
-rw-r--r--absl/base/BUILD.bazel4
-rw-r--r--absl/base/CMakeLists.txt8
-rw-r--r--absl/base/attributes.h6
-rw-r--r--absl/base/call_once.h13
-rw-r--r--absl/base/policy_checks.h10
-rw-r--r--absl/container/internal/hashtablez_sampler.cc21
-rw-r--r--absl/container/internal/hashtablez_sampler.h10
-rw-r--r--absl/container/internal/hashtablez_sampler_test.cc2
-rw-r--r--absl/container/internal/raw_hash_set.h4
-rw-r--r--absl/container/internal/raw_hash_set_test.cc2
-rw-r--r--absl/debugging/BUILD.bazel5
-rw-r--r--absl/debugging/CMakeLists.txt1
-rw-r--r--absl/functional/BUILD.bazel16
-rw-r--r--absl/hash/hash_test.cc27
-rw-r--r--absl/hash/internal/hash.h13
-rw-r--r--absl/numeric/int128.h4
-rw-r--r--absl/random/CMakeLists.txt1
-rw-r--r--absl/random/internal/BUILD.bazel5
-rw-r--r--absl/random/internal/randen_hwaes.cc48
-rw-r--r--absl/strings/internal/numbers_test_common.h5
-rw-r--r--absl/strings/numbers.cc66
-rw-r--r--absl/strings/numbers.h21
-rw-r--r--absl/strings/numbers_test.cc63
-rw-r--r--absl/synchronization/internal/waiter.cc7
-rw-r--r--absl/synchronization/internal/waiter.h11
26 files changed, 503 insertions, 117 deletions
diff --git a/absl/abseil.podspec.gen.py b/absl/abseil.podspec.gen.py
new file mode 100755
index 000000000000..2bf153c002ab
--- /dev/null
+++ b/absl/abseil.podspec.gen.py
@@ -0,0 +1,247 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""This script generates abseil.podspec from all BUILD.bazel files.
+
+This is expected to run on abseil git repository with Bazel 1.0 on Linux.
+It recursively analyzes BUILD.bazel files using query command of Bazel to
+dump its build rules in XML format. From these rules, it constructs podspec
+structure.
+"""
+
+import argparse
+import collections
+import os
+import re
+import subprocess
+import xml.etree.ElementTree
+
+# Template of root podspec.
+SPEC_TEMPLATE = """
+# This file has been automatically generated from a script.
+# Please make modifications to `abseil.podspec.gen.py` instead.
+Pod::Spec.new do |s|
+  s.name     = 'abseil'
+  s.version  = '${version}'
+  s.summary  = 'Abseil Common Libraries (C++) from Google'
+  s.homepage = 'https://abseil.io'
+  s.license  = 'Apache License, Version 2.0'
+  s.authors  = { 'Abseil Team' => 'abseil-io@googlegroups.com' }
+  s.source = {
+    :git => 'https://github.com/abseil/abseil-cpp.git',
+    :tag => '${tag}',
+  }
+  s.module_name = 'absl'
+  s.header_mappings_dir = 'absl'
+  s.header_dir = 'absl'
+  s.libraries = 'c++'
+  s.compiler_flags = '-Wno-everything'
+  s.pod_target_xcconfig = {
+    'USER_HEADER_SEARCH_PATHS' => '$(inherited) "$(PODS_TARGET_SRCROOT)"',
+    'USE_HEADERMAP' => 'NO',
+    'ALWAYS_SEARCH_USER_PATHS' => 'NO',
+  }
+  s.ios.deployment_target = '7.0'
+  s.osx.deployment_target = '10.9'
+  s.tvos.deployment_target = '9.0'
+  s.watchos.deployment_target = '2.0'
+"""
+
+# Limited platforms that abseil supports.
+# This is mainly because of sigaltstack unavailable on watchOS.
+LIMITED_SUPPORT_PLATFORMS = [
+    "ios.deployment_target = '7.0'",
+    "osx.deployment_target = '10.9'",
+]
+
+# Custom specification per rule.
+CUSTOM_SPEC_MAP = {
+    "//absl/debugging:failure_signal_handler": LIMITED_SUPPORT_PLATFORMS,
+}
+
+# Rule object representing the rule of Bazel BUILD.
+Rule = collections.namedtuple(
+    "Rule", "type name package srcs hdrs textual_hdrs deps visibility testonly")
+
+
+def get_elem_value(elem, name):
+  """Returns the value of XML element with the given name."""
+  for child in elem:
+    if child.attrib.get("name") != name:
+      continue
+    if child.tag == "string":
+      return child.attrib.get("value")
+    if child.tag == "boolean":
+      return child.attrib.get("value") == "true"
+    if child.tag == "list":
+      return [nested_child.attrib.get("value") for nested_child in child]
+    raise "Cannot recognize tag: " + child.tag
+  return None
+
+
+def normalize_paths(paths):
+  """Returns the list of normalized path."""
+  # e.g. ["//absl/strings:dir/header.h"] -> ["absl/strings/dir/header.h"]
+  return [path.lstrip("/").replace(":", "/") for path in paths]
+
+
+def parse_rule(elem, package):
+  """Returns a rule from bazel XML rule."""
+  return Rule(
+      type=elem.attrib["class"],
+      name=get_elem_value(elem, "name"),
+      package=package,
+      srcs=normalize_paths(get_elem_value(elem, "srcs") or []),
+      hdrs=normalize_paths(get_elem_value(elem, "hdrs") or []),
+      textual_hdrs=normalize_paths(get_elem_value(elem, "textual_hdrs") or []),
+      deps=get_elem_value(elem, "deps") or [],
+      visibility=get_elem_value(elem, "visibility") or [],
+      testonly=get_elem_value(elem, "testonly") or False)
+
+
+def read_build(package):
+  """Runs bazel query on given package file and returns all cc rules."""
+  result = subprocess.check_output(
+      ["bazel", "query", package + ":all", "--output", "xml"])
+  root = xml.etree.ElementTree.fromstring(result)
+  return [
+      parse_rule(elem, package)
+      for elem in root
+      if elem.tag == "rule" and elem.attrib["class"].startswith("cc_")
+  ]
+
+
+def collect_rules(root_path):
+  """Collects and returns all rules from root path recursively."""
+  rules = []
+  for cur, _, _ in os.walk(root_path):
+    build_path = os.path.join(cur, "BUILD.bazel")
+    if os.path.exists(build_path):
+      rules.extend(read_build("//" + cur))
+  return rules
+
+
+def relevant_rule(rule):
+  """Returns true if a given rule is relevant when generating a podspec."""
+  return (
+      # cc_library only (ignore cc_test, cc_binary)
+      rule.type == "cc_library" and
+      # ignore empty rule
+      (rule.hdrs + rule.textual_hdrs + rule.srcs) and
+      # ignore test-only rule
+      not rule.testonly)
+
+
+def get_spec_var(depth):
+  """Returns the name of variable for spec with given depth."""
+  return "s" if depth == 0 else "s{}".format(depth)
+
+
+def get_spec_name(label):
+  """Converts the label of bazel rule to the name of podspec."""
+  assert label.startswith("//absl/"), "{} doesn't start with //absl/".format(
+      label)
+  # e.g. //absl/apple/banana -> abseil/apple/banana
+  return "abseil/" + label[7:]
+
+
+def write_podspec(f, rules, args):
+  """Writes a podspec from given rules and args."""
+  rule_dir = build_rule_directory(rules)["abseil"]
+  # Write root part with given arguments
+  spec = re.sub(r"\$\{(\w+)\}", lambda x: args[x.group(1)],
+                SPEC_TEMPLATE).lstrip()
+  f.write(spec)
+  # Write all target rules
+  write_podspec_map(f, rule_dir, 0)
+  f.write("end\n")
+
+
+def build_rule_directory(rules):
+  """Builds a tree-style rule directory from given rules."""
+  rule_dir = {}
+  for rule in rules:
+    cur = rule_dir
+    for frag in get_spec_name(rule.package).split("/"):
+      cur = cur.setdefault(frag, {})
+    cur[rule.name] = rule
+  return rule_dir
+
+
+def write_podspec_map(f, cur_map, depth):
+  """Writes podspec from rule map recursively."""
+  for key, value in sorted(cur_map.items()):
+    indent = "  " * (depth + 1)
+    f.write("{indent}{var0}.subspec '{key}' do |{var1}|\n".format(
+        indent=indent,
+        key=key,
+        var0=get_spec_var(depth),
+        var1=get_spec_var(depth + 1)))
+    if isinstance(value, dict):
+      write_podspec_map(f, value, depth + 1)
+    else:
+      write_podspec_rule(f, value, depth + 1)
+    f.write("{indent}end\n".format(indent=indent))
+
+
+def write_podspec_rule(f, rule, depth):
+  """Writes podspec from given rule."""
+  indent = "  " * (depth + 1)
+  spec_var = get_spec_var(depth)
+  # Puts all files in hdrs, textual_hdrs, and srcs into source_files.
+  # Since CocoaPods treats header_files a bit differently from bazel,
+  # this won't generate a header_files field so that all source_files
+  # are considered as header files.
+  srcs = sorted(set(rule.hdrs + rule.textual_hdrs + rule.srcs))
+  write_indented_list(
+      f, "{indent}{var}.source_files = ".format(indent=indent, var=spec_var),
+      srcs)
+  # Writes dependencies of this rule.
+  for dep in sorted(rule.deps):
+    name = get_spec_name(dep.replace(":", "/"))
+    f.write("{indent}{var}.dependency '{dep}'\n".format(
+        indent=indent, var=spec_var, dep=name))
+  # Writes custom specification.
+  custom_spec = CUSTOM_SPEC_MAP.get(rule.package + ":" + rule.name)
+  if custom_spec:
+    for spec in custom_spec:
+      f.write("{indent}{var}.{spec}\n".format(
+          indent=indent, var=spec_var, spec=spec))
+
+
+def write_indented_list(f, leading, values):
+  """Writes leading values in an indented style."""
+  f.write(leading)
+  f.write((",\n" + " " * len(leading)).join("'{}'".format(v) for v in values))
+  f.write("\n")
+
+
+def generate(args):
+  """Generates a podspec file from all BUILD files under absl directory."""
+  rules = filter(relevant_rule, collect_rules("absl"))
+  with open(args.output, "wt") as f:
+    write_podspec(f, rules, vars(args))
+
+
+def main():
+  parser = argparse.ArgumentParser(
+      description="Generates abseil.podspec from BUILD.bazel")
+  parser.add_argument(
+      "-v", "--version", help="The version of podspec", required=True)
+  parser.add_argument(
+      "-t",
+      "--tag",
+      default=None,
+      help="The name of git tag (default: version)")
+  parser.add_argument(
+      "-o",
+      "--output",
+      default="abseil.podspec",
+      help="The name of output file (default: abseil.podspec)")
+  args = parser.parse_args()
+  if args.tag is None:
+    args.tag = args.version
+  generate(args)
+
+
+if __name__ == "__main__":
+  main()
diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel
index 6fc712d968f3..7e234bc66779 100644
--- a/absl/base/BUILD.bazel
+++ b/absl/base/BUILD.bazel
@@ -192,7 +192,9 @@ cc_library(
     ],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = select({
-        "//absl:windows": [],
+        "//absl:windows": [
+            "-DEFAULTLIB:shlwapi.lib",
+        ],
         "//conditions:default": ["-pthread"],
     }) + ABSL_DEFAULT_LINKOPTS,
     deps = [
diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt
index 9550cdb2db49..7ab6955e2176 100644
--- a/absl/base/CMakeLists.txt
+++ b/absl/base/CMakeLists.txt
@@ -14,6 +14,8 @@
 # limitations under the License.
 #
 
+find_library(LIBRT rt)
+
 absl_cc_library(
   NAME
     atomic_hook
@@ -163,16 +165,18 @@ absl_cc_library(
     "internal/thread_identity.h"
     "internal/tsan_mutex_interface.h"
     "internal/unscaledcycleclock.h"
-    "log_severity.h"
   SRCS
     "internal/cycleclock.cc"
     "internal/spinlock.cc"
     "internal/sysinfo.cc"
     "internal/thread_identity.cc"
     "internal/unscaledcycleclock.cc"
-    "log_severity.cc"
   COPTS
     ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+    $<$<BOOL:${LIBRT}>:${LIBRT}>
+    $<$<BOOL:${MINGW}>:"shlwapi">
   DEPS
     absl::atomic_hook
     absl::base_internal
diff --git a/absl/base/attributes.h b/absl/base/attributes.h
index 7b7656a859b8..acd1c5269829 100644
--- a/absl/base/attributes.h
+++ b/absl/base/attributes.h
@@ -158,9 +158,11 @@
 // Weak attributes currently do not work properly in LLVM's Windows backend,
 // so disable them there. See https://bugs.llvm.org/show_bug.cgi?id=37598
 // for further information.
-#if (ABSL_HAVE_ATTRIBUTE(weak) || \
+// The MinGW compiler doesn't complain about the weak attribute until the link
+// step, presumably because Windows doesn't use ELF binaries.
+#if (ABSL_HAVE_ATTRIBUTE(weak) ||                   \
      (defined(__GNUC__) && !defined(__clang__))) && \
-    !(defined(__llvm__) && defined(_WIN32))
+    !(defined(__llvm__) && defined(_WIN32)) && !defined(__MINGW32__)
 #undef ABSL_ATTRIBUTE_WEAK
 #define ABSL_ATTRIBUTE_WEAK __attribute__((weak))
 #define ABSL_HAVE_ATTRIBUTE_WEAK 1
diff --git a/absl/base/call_once.h b/absl/base/call_once.h
index 4aa6360cffc5..e1614e517a8d 100644
--- a/absl/base/call_once.h
+++ b/absl/base/call_once.h
@@ -148,7 +148,7 @@ void CallOnceImpl(std::atomic<uint32_t>* control,
                   Args&&... args) {
 #ifndef NDEBUG
   {
-    uint32_t old_control = control->load(std::memory_order_acquire);
+    uint32_t old_control = control->load(std::memory_order_relaxed);
     if (old_control != kOnceInit &&
         old_control != kOnceRunning &&
         old_control != kOnceWaiter &&
@@ -166,14 +166,23 @@ void CallOnceImpl(std::atomic<uint32_t>* control,
   // Must do this before potentially modifying control word's state.
   base_internal::SchedulingHelper maybe_disable_scheduling(scheduling_mode);
   // Short circuit the simplest case to avoid procedure call overhead.
+  // The base_internal::SpinLockWait() call returns either kOnceInit or
+  // kOnceDone. If it returns kOnceDone, it must have loaded the control word
+  // with std::memory_order_acquire and seen a value of kOnceDone.
   uint32_t old_control = kOnceInit;
   if (control->compare_exchange_strong(old_control, kOnceRunning,
-                                       std::memory_order_acquire,
                                        std::memory_order_relaxed) ||
       base_internal::SpinLockWait(control, ABSL_ARRAYSIZE(trans), trans,
                                   scheduling_mode) == kOnceInit) {
     base_internal::Invoke(std::forward<Callable>(fn),
                           std::forward<Args>(args)...);
+    // The call to SpinLockWake below is an optimization, because the waiter
+    // in SpinLockWait is waiting with a short timeout. The atomic load/store
+    // sequence is slightly faster than an atomic exchange:
+    //   old_control = control->exchange(base_internal::kOnceDone,
+    //                                   std::memory_order_release);
+    // We opt for a slightly faster case when there are no waiters, in spite
+    // of longer tail latency when there are waiters.
     old_control = control->load(std::memory_order_relaxed);
     control->store(base_internal::kOnceDone, std::memory_order_release);
     if (old_control == base_internal::kOnceWaiter) {
diff --git a/absl/base/policy_checks.h b/absl/base/policy_checks.h
index 699fb1a2e0fc..4dfa49e54ac2 100644
--- a/absl/base/policy_checks.h
+++ b/absl/base/policy_checks.h
@@ -82,16 +82,6 @@
 // Standard Library Check
 // -----------------------------------------------------------------------------
 
-// We have chosen glibc 2.12 as the minimum as it was tagged for release
-// in May, 2010 and includes some functionality used in Google software
-// (for instance pthread_setname_np):
-// https://sourceware.org/ml/libc-alpha/2010-05/msg00000.html
-#if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
-#if !__GLIBC_PREREQ(2, 12)
-#error "Minimum required version of glibc is 2.12."
-#endif
-#endif
-
 #if defined(_STLPORT_VERSION)
 #error "STLPort is not supported."
 #endif
diff --git a/absl/container/internal/hashtablez_sampler.cc b/absl/container/internal/hashtablez_sampler.cc
index 0a7ef61c8fe5..4aec0a07ffb3 100644
--- a/absl/container/internal/hashtablez_sampler.cc
+++ b/absl/container/internal/hashtablez_sampler.cc
@@ -38,16 +38,18 @@ ABSL_CONST_INIT std::atomic<bool> g_hashtablez_enabled{
 ABSL_CONST_INIT std::atomic<int32_t> g_hashtablez_sample_parameter{1 << 10};
 ABSL_CONST_INIT std::atomic<int32_t> g_hashtablez_max_samples{1 << 20};
 
-#if ABSL_HAVE_THREAD_LOCAL
-thread_local absl::base_internal::ExponentialBiased
-    g_exponential_biased_generator;
-#else
-ABSL_CONST_INIT static absl::base_internal::ExponentialBiased
+#if ABSL_PER_THREAD_TLS == 1
+ABSL_PER_THREAD_TLS_KEYWORD absl::base_internal::ExponentialBiased
     g_exponential_biased_generator;
 #endif
 
 }  // namespace
 
+#if ABSL_PER_THREAD_TLS == 1
+ABSL_PER_THREAD_TLS_KEYWORD int64_t global_next_sample = 0;
+#endif  // ABSL_PER_THREAD_TLS == 1
+
+
 HashtablezSampler& HashtablezSampler::Global() {
   static auto* sampler = new HashtablezSampler();
   return *sampler;
@@ -189,6 +191,10 @@ HashtablezInfo* SampleSlow(int64_t* next_sample) {
     return HashtablezSampler::Global().Register();
   }
 
+#if ABSL_PER_THREAD_TLS == 0
+  *next_sample = std::numeric_limits<int64_t>::max();
+  return nullptr;
+#else
   bool first = *next_sample < 0;
   *next_sample = g_exponential_biased_generator.Get(
       g_hashtablez_sample_parameter.load(std::memory_order_relaxed));
@@ -210,12 +216,9 @@ HashtablezInfo* SampleSlow(int64_t* next_sample) {
   }
 
   return HashtablezSampler::Global().Register();
+#endif
 }
 
-#if ABSL_PER_THREAD_TLS == 1
-ABSL_PER_THREAD_TLS_KEYWORD int64_t global_next_sample = 0;
-#endif  // ABSL_PER_THREAD_TLS == 1
-
 void UnsampleSlow(HashtablezInfo* info) {
   HashtablezSampler::Global().Unregister(info);
 }
diff --git a/absl/container/internal/hashtablez_sampler.h b/absl/container/internal/hashtablez_sampler.h
index 53996bb9fa4c..c694df057d8e 100644
--- a/absl/container/internal/hashtablez_sampler.h
+++ b/absl/container/internal/hashtablez_sampler.h
@@ -186,16 +186,14 @@ extern ABSL_PER_THREAD_TLS_KEYWORD int64_t global_next_sample;
 // Returns an RAII sampling handle that manages registration and unregistation
 // with the global sampler.
 inline HashtablezInfoHandle Sample() {
-#if ABSL_PER_THREAD_TLS == 0
-  static auto* mu = new absl::Mutex;
-  static int64_t global_next_sample = 0;
-  absl::MutexLock l(mu);
-#endif  // !ABSL_HAVE_THREAD_LOCAL
-
+#if ABSL_PER_THREAD_TLS == 1
   if (ABSL_PREDICT_TRUE(--global_next_sample > 0)) {
     return HashtablezInfoHandle(nullptr);
   }
   return HashtablezInfoHandle(SampleSlow(&global_next_sample));
+#else
+  return HashtablezInfoHandle(nullptr);
+#endif  // !ABSL_PER_THREAD_TLS
 }
 
 // Holds samples and their associated stack traces with a soft limit of
diff --git a/absl/container/internal/hashtablez_sampler_test.cc b/absl/container/internal/hashtablez_sampler_test.cc
index 7f9e8dd21ffc..af4b5ee108ac 100644
--- a/absl/container/internal/hashtablez_sampler_test.cc
+++ b/absl/container/internal/hashtablez_sampler_test.cc
@@ -168,6 +168,7 @@ TEST(HashtablezInfoTest, RecordRehash) {
   EXPECT_EQ(info.num_erases.load(), 0);
 }
 
+#if ABSL_PER_THREAD_TLS == 1
 TEST(HashtablezSamplerTest, SmallSampleParameter) {
   SetHashtablezEnabled(true);
   SetHashtablezSampleParameter(100);
@@ -211,6 +212,7 @@ TEST(HashtablezSamplerTest, Sample) {
   }
   EXPECT_NEAR(sample_rate, 0.01, 0.005);
 }
+#endif
 
 TEST(HashtablezSamplerTest, Handle) {
   auto& sampler = HashtablezSampler::Global();
diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h
index bf0c03c44f2e..469226fedd86 100644
--- a/absl/container/internal/raw_hash_set.h
+++ b/absl/container/internal/raw_hash_set.h
@@ -638,8 +638,8 @@ class raw_hash_set {
     }
 
     friend bool operator==(const iterator& a, const iterator& b) {
-      /* To be enabled: a.assert_is_valid(); */
-      /* To be enabled: b.assert_is_valid(); */
+      a.assert_is_valid();
+      b.assert_is_valid();
       return a.ctrl_ == b.ctrl_;
     }
     friend bool operator!=(const iterator& a, const iterator& b) {
diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc
index 33cfa72ce7ab..ec8f92313bac 100644
--- a/absl/container/internal/raw_hash_set_test.cc
+++ b/absl/container/internal/raw_hash_set_test.cc
@@ -1841,6 +1841,7 @@ TEST(TableDeathTest, EraseOfEndAsserts) {
   EXPECT_DEATH_IF_SUPPORTED(t.erase(t.end()), kDeathMsg);
 }
 
+#if ABSL_PER_THREAD_TLS == 1
 TEST(RawHashSamplerTest, Sample) {
   // Enable the feature even if the prod default is off.
   SetHashtablezEnabled(true);
@@ -1861,6 +1862,7 @@ TEST(RawHashSamplerTest, Sample) {
   EXPECT_NEAR((end_size - start_size) / static_cast<double>(tables.size()),
               0.01, 0.005);
 }
+#endif
 
 TEST(RawHashSamplerTest, DoNotSampleCustomAllocators) {
   // Enable the feature even if the prod default is off.
diff --git a/absl/debugging/BUILD.bazel b/absl/debugging/BUILD.bazel
index beec279ff8e2..2601090bc60b 100644
--- a/absl/debugging/BUILD.bazel
+++ b/absl/debugging/BUILD.bazel
@@ -55,7 +55,10 @@ cc_library(
         "symbolize.h",
     ],
     copts = ABSL_DEFAULT_COPTS,
-    linkopts = ABSL_DEFAULT_LINKOPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS + select({
+        "//absl:windows": ["-DEFAULTLIB:dbghelp.lib"],
+        "//conditions:default": [],
+    }),
     deps = [
         ":debugging_internal",
         ":demangle_internal",
diff --git a/absl/debugging/CMakeLists.txt b/absl/debugging/CMakeLists.txt
index b3e35b6d744e..eff504b48832 100644
--- a/absl/debugging/CMakeLists.txt
+++ b/absl/debugging/CMakeLists.txt
@@ -44,6 +44,7 @@ absl_cc_library(
     ${ABSL_DEFAULT_COPTS}
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
+    $<$<BOOL:${MINGW}>:"dbghelp">
   DEPS
     absl::debugging_internal
     absl::demangle_internal
diff --git a/absl/functional/BUILD.bazel b/absl/functional/BUILD.bazel
index e861b8a56010..0a7b588e70e0 100644
--- a/absl/functional/BUILD.bazel
+++ b/absl/functional/BUILD.bazel
@@ -1,3 +1,19 @@
+#
+# Copyright 2019 The Abseil Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
 load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
 load(
     "//absl:copts/configure_copts.bzl",
diff --git a/absl/hash/hash_test.cc b/absl/hash/hash_test.cc
index 61f7661f5912..42c0c3d8bf7e 100644
--- a/absl/hash/hash_test.cc
+++ b/absl/hash/hash_test.cc
@@ -300,6 +300,33 @@ TEST(HashValueTest, Strings) {
             SpyHash(absl::string_view("ABC")));
 }
 
+TEST(HashValueTest, WString) {
+  EXPECT_TRUE((is_hashable<std::wstring>::value));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      std::wstring(), std::wstring(L"ABC"), std::wstring(L"ABC"),
+      std::wstring(L"Some other different string"),
+      std::wstring(L"Iñtërnâtiônàlizætiøn"))));
+}
+
+TEST(HashValueTest, U16String) {
+  EXPECT_TRUE((is_hashable<std::u16string>::value));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      std::u16string(), std::u16string(u"ABC"), std::u16string(u"ABC"),
+      std::u16string(u"Some other different string"),
+      std::u16string(u"Iñtërnâtiônàlizætiøn"))));
+}
+
+TEST(HashValueTest, U32String) {
+  EXPECT_TRUE((is_hashable<std::u32string>::value));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      std::u32string(), std::u32string(U"ABC"), std::u32string(U"ABC"),
+      std::u32string(U"Some other different string"),
+      std::u32string(U"Iñtërnâtiônàlizætiøn"))));
+}
+
 TEST(HashValueTest, StdArray) {
   EXPECT_TRUE((is_hashable<std::array<int, 3>>::value));
 
diff --git a/absl/hash/internal/hash.h b/absl/hash/internal/hash.h
index e99f8e75bd9e..7d44f57dc90d 100644
--- a/absl/hash/internal/hash.h
+++ b/absl/hash/internal/hash.h
@@ -427,6 +427,19 @@ H AbslHashValue(H hash_state, absl::string_view str) {
       str.size());
 }
 
+// Support std::wstring, std::u16string and std::u32string.
+template <typename Char, typename Alloc, typename H,
+          typename = absl::enable_if_t<std::is_same<Char, wchar_t>::value ||
+                                       std::is_same<Char, char16_t>::value ||
+                                       std::is_same<Char, char32_t>::value>>
+H AbslHashValue(
+    H hash_state,
+    const std::basic_string<Char, std::char_traits<Char>, Alloc>& str) {
+  return H::combine(
+      H::combine_contiguous(std::move(hash_state), str.data(), str.size()),
+      str.size());
+}
+
 // -----------------------------------------------------------------------------
 // AbslHashValue for Sequence Containers
 // -----------------------------------------------------------------------------
diff --git a/absl/numeric/int128.h b/absl/numeric/int128.h
index 10be8eca42e7..4f965686c393 100644
--- a/absl/numeric/int128.h
+++ b/absl/numeric/int128.h
@@ -720,9 +720,9 @@ inline uint128& uint128::operator--() {
 }
 
 #if defined(ABSL_HAVE_INTRINSIC_INT128)
-#include "absl/numeric/int128_have_intrinsic.inc"
+#include "absl/numeric/int128_have_intrinsic.inc"  // IWYU pragma: export
 #else  // ABSL_HAVE_INTRINSIC_INT128
-#include "absl/numeric/int128_no_intrinsic.inc"
+#include "absl/numeric/int128_no_intrinsic.inc"  // IWYU pragma: export
 #endif  // ABSL_HAVE_INTRINSIC_INT128
 
 }  // namespace absl
diff --git a/absl/random/CMakeLists.txt b/absl/random/CMakeLists.txt
index 289854ffd40d..264a6f3c6abc 100644
--- a/absl/random/CMakeLists.txt
+++ b/absl/random/CMakeLists.txt
@@ -447,6 +447,7 @@ absl_cc_library(
     ${ABSL_DEFAULT_COPTS}
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
+    $<$<BOOL:${MINGW}>:"bcrypt">
   DEPS
     absl::core_headers
     absl::optional
diff --git a/absl/random/internal/BUILD.bazel b/absl/random/internal/BUILD.bazel
index 91388d19f3c5..cc9bc013bc90 100644
--- a/absl/random/internal/BUILD.bazel
+++ b/absl/random/internal/BUILD.bazel
@@ -89,7 +89,10 @@ cc_library(
         "seed_material.h",
     ],
     copts = ABSL_DEFAULT_COPTS,
-    linkopts = ABSL_DEFAULT_LINKOPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS + select({
+        "//absl:windows": ["-DEFAULTLIB:bcrypt.lib"],
+        "//conditions:default": [],
+    }),
     deps = [
         ":fast_uniform_bits",
         "//absl/base:core_headers",
diff --git a/absl/random/internal/randen_hwaes.cc b/absl/random/internal/randen_hwaes.cc
index 7d5b2b74128b..6cc36fd39b5e 100644
--- a/absl/random/internal/randen_hwaes.cc
+++ b/absl/random/internal/randen_hwaes.cc
@@ -159,13 +159,11 @@ inline ABSL_TARGET_CRYPTO Vector128 ReverseBytes(const Vector128& v) {
 // WARNING: these load/store in native byte order. It is OK to load and then
 // store an unchanged vector, but interpreting the bits as a number or input
 // to AES will have undefined results.
-inline ABSL_TARGET_CRYPTO Vector128
-Vector128Load(const void* ABSL_RANDOM_INTERNAL_RESTRICT from) {
+inline ABSL_TARGET_CRYPTO Vector128 Vector128Load(const void* from) {
   return vec_vsx_ld(0, reinterpret_cast<const Vector128*>(from));
 }
 
-inline ABSL_TARGET_CRYPTO void Vector128Store(
-    const Vector128& v, void* ABSL_RANDOM_INTERNAL_RESTRICT to) {
+inline ABSL_TARGET_CRYPTO void Vector128Store(const Vector128& v, void* to) {
   vec_vsx_st(v, 0, reinterpret_cast<Vector128*>(to));
 }
 
@@ -177,8 +175,7 @@ inline ABSL_TARGET_CRYPTO Vector128 AesRound(const Vector128& state,
 }
 
 // Enables native loads in the round loop by pre-swapping.
-inline ABSL_TARGET_CRYPTO void SwapEndian(
-    uint64_t* ABSL_RANDOM_INTERNAL_RESTRICT state) {
+inline ABSL_TARGET_CRYPTO void SwapEndian(uint64_t* state) {
   using absl::random_internal::RandenTraits;
   constexpr size_t kLanes = 2;
   constexpr size_t kFeistelBlocks = RandenTraits::kFeistelBlocks;
@@ -230,13 +227,11 @@ using Vector128 = uint8x16_t;
 
 namespace {
 
-inline ABSL_TARGET_CRYPTO Vector128
-Vector128Load(const void* ABSL_RANDOM_INTERNAL_RESTRICT from) {
+inline ABSL_TARGET_CRYPTO Vector128 Vector128Load(const void* from) {
   return vld1q_u8(reinterpret_cast<const uint8_t*>(from));
 }
 
-inline ABSL_TARGET_CRYPTO void Vector128Store(
-    const Vector128& v, void* ABSL_RANDOM_INTERNAL_RESTRICT to) {
+inline ABSL_TARGET_CRYPTO void Vector128Store(const Vector128& v, void* to) {
   vst1q_u8(reinterpret_cast<uint8_t*>(to), v);
 }
 
@@ -254,8 +249,7 @@ inline ABSL_TARGET_CRYPTO Vector128 AesRound(const Vector128& state,
   return vaesmcq_u8(vaeseq_u8(state, uint8x16_t{})) ^ round_key;
 }
 
-inline ABSL_TARGET_CRYPTO void SwapEndian(
-    uint64_t* ABSL_RANDOM_INTERNAL_RESTRICT) {}
+inline ABSL_TARGET_CRYPTO void SwapEndian(uint64_t*) {}
 
 }  // namespace
 
@@ -283,15 +277,12 @@ class Vector128 {
   __m128i data_;
 };
 
-inline ABSL_TARGET_CRYPTO Vector128
-Vector128Load(const void* ABSL_RANDOM_INTERNAL_RESTRICT from) {
+inline ABSL_TARGET_CRYPTO Vector128 Vector128Load(const void* from) {
   return Vector128(_mm_load_si128(reinterpret_cast<const __m128i*>(from)));
 }
 
-inline ABSL_TARGET_CRYPTO void Vector128Store(
-    const Vector128& v, void* ABSL_RANDOM_INTERNAL_RESTRICT to) {
-  _mm_store_si128(reinterpret_cast<__m128i * ABSL_RANDOM_INTERNAL_RESTRICT>(to),
-                  v.data());
+inline ABSL_TARGET_CRYPTO void Vector128Store(const Vector128& v, void* to) {
+  _mm_store_si128(reinterpret_cast<__m128i*>(to), v.data());
 }
 
 // One round of AES. "round_key" is a public constant for breaking the
@@ -304,8 +295,7 @@ inline ABSL_TARGET_CRYPTO Vector128 AesRound(const Vector128& state,
   return Vector128(_mm_aesenc_si128(state.data(), round_key.data()));
 }
 
-inline ABSL_TARGET_CRYPTO void SwapEndian(
-    uint64_t* ABSL_RANDOM_INTERNAL_RESTRICT) {}
+inline ABSL_TARGET_CRYPTO void SwapEndian(uint64_t*) {}
 
 }  // namespace
 
@@ -402,8 +392,7 @@ constexpr size_t kLanes = 2;
 
 // Block shuffles applies a shuffle to the entire state between AES rounds.
 // Improved odd-even shuffle from "New criterion for diffusion property".
-inline ABSL_TARGET_CRYPTO void BlockShuffle(
-    uint64_t* ABSL_RANDOM_INTERNAL_RESTRICT state) {
+inline ABSL_TARGET_CRYPTO void BlockShuffle(uint64_t* state) {
   static_assert(kFeistelBlocks == 16, "Expecting 16 FeistelBlocks.");
 
   constexpr size_t shuffle[kFeistelBlocks] = {7,  2, 13, 4,  11, 8,  3, 6,
@@ -452,8 +441,7 @@ inline ABSL_TARGET_CRYPTO void BlockShuffle(
 // parallel hides the 7-cycle AESNI latency on HSW. Note that the Feistel
 // XORs are 'free' (included in the second AES instruction).
 inline ABSL_TARGET_CRYPTO const u64x2* FeistelRound(
-    uint64_t* ABSL_RANDOM_INTERNAL_RESTRICT state,
-    const u64x2* ABSL_RANDOM_INTERNAL_RESTRICT keys) {
+    uint64_t* state, const u64x2* ABSL_RANDOM_INTERNAL_RESTRICT keys) {
   static_assert(kFeistelBlocks == 16, "Expecting 16 FeistelBlocks.");
 
   // MSVC does a horrible job at unrolling loops.
@@ -513,8 +501,7 @@ inline ABSL_TARGET_CRYPTO const u64x2* FeistelRound(
 // 2^64 queries if the round function is a PRF. This is similar to the b=8 case
 // of Simpira v2, but more efficient than its generic construction for b=16.
 inline ABSL_TARGET_CRYPTO void Permute(
-    const void* ABSL_RANDOM_INTERNAL_RESTRICT keys,
-    uint64_t* ABSL_RANDOM_INTERNAL_RESTRICT state) {
+    const void* ABSL_RANDOM_INTERNAL_RESTRICT keys, uint64_t* state) {
   const u64x2* ABSL_RANDOM_INTERNAL_RESTRICT keys128 =
       static_cast<const u64x2*>(keys);
 
@@ -544,10 +531,8 @@ const void* ABSL_TARGET_CRYPTO RandenHwAes::GetKeys() {
 // NOLINTNEXTLINE
 void ABSL_TARGET_CRYPTO RandenHwAes::Absorb(const void* seed_void,
                                             void* state_void) {
-  uint64_t* ABSL_RANDOM_INTERNAL_RESTRICT state =
-      reinterpret_cast<uint64_t*>(state_void);
-  const uint64_t* ABSL_RANDOM_INTERNAL_RESTRICT seed =
-      reinterpret_cast<const uint64_t*>(seed_void);
+  auto* state = static_cast<uint64_t*>(state_void);
+  const auto* seed = static_cast<const uint64_t*>(seed_void);
 
   constexpr size_t kCapacityBlocks = kCapacityBytes / sizeof(Vector128);
   constexpr size_t kStateBlocks = kStateBytes / sizeof(Vector128);
@@ -623,8 +608,7 @@ void ABSL_TARGET_CRYPTO RandenHwAes::Generate(const void* keys,
                                               void* state_void) {
   static_assert(kCapacityBytes == sizeof(Vector128), "Capacity mismatch");
 
-  uint64_t* ABSL_RANDOM_INTERNAL_RESTRICT state =
-      reinterpret_cast<uint64_t*>(state_void);
+  auto* state = static_cast<uint64_t*>(state_void);
 
   const Vector128 prev_inner = Vector128Load(state);
 
diff --git a/absl/strings/internal/numbers_test_common.h b/absl/strings/internal/numbers_test_common.h
index 28247205af48..a263219e27b4 100644
--- a/absl/strings/internal/numbers_test_common.h
+++ b/absl/strings/internal/numbers_test_common.h
@@ -42,8 +42,9 @@ inline bool Itoa(IntType value, int base, std::string* destination) {
   while (value != 0) {
     const IntType next_value = value / base;
     // Can't use std::abs here because of problems when IntType is unsigned.
-    int remainder = value > next_value * base ? value - next_value * base
-                                              : next_value * base - value;
+    int remainder =
+        static_cast<int>(value > next_value * base ? value - next_value * base
+                                                   : next_value * base - value);
     char c = remainder < 10 ? '0' + remainder : 'A' + remainder - 10;
     destination->insert(0, 1, c);
     value = next_value;
diff --git a/absl/strings/numbers.cc b/absl/strings/numbers.cc
index d7b94fc1301e..4890bd54a549 100644
--- a/absl/strings/numbers.cc
+++ b/absl/strings/numbers.cc
@@ -93,43 +93,6 @@ bool SimpleAtod(absl::string_view str, double* out) {
   return true;
 }
 
-namespace {
-
-// Writes a two-character representation of 'i' to 'buf'. 'i' must be in the
-// range 0 <= i < 100, and buf must have space for two characters. Example:
-//   char buf[2];
-//   PutTwoDigits(42, buf);
-//   // buf[0] == '4'
-//   // buf[1] == '2'
-inline void PutTwoDigits(size_t i, char* buf) {
-  static const char two_ASCII_digits[100][2] = {
-    {'0', '0'}, {'0', '1'}, {'0', '2'}, {'0', '3'}, {'0', '4'},
-    {'0', '5'}, {'0', '6'}, {'0', '7'}, {'0', '8'}, {'0', '9'},
-    {'1', '0'}, {'1', '1'}, {'1', '2'}, {'1', '3'}, {'1', '4'},
-    {'1', '5'}, {'1', '6'}, {'1', '7'}, {'1', '8'}, {'1', '9'},
-    {'2', '0'}, {'2', '1'}, {'2', '2'}, {'2', '3'}, {'2', '4'},
-    {'2', '5'}, {'2', '6'}, {'2', '7'}, {'2', '8'}, {'2', '9'},
-    {'3', '0'}, {'3', '1'}, {'3', '2'}, {'3', '3'}, {'3', '4'},
-    {'3', '5'}, {'3', '6'}, {'3', '7'}, {'3', '8'}, {'3', '9'},
-    {'4', '0'}, {'4', '1'}, {'4', '2'}, {'4', '3'}, {'4', '4'},
-    {'4', '5'}, {'4', '6'}, {'4', '7'}, {'4', '8'}, {'4', '9'},
-    {'5', '0'}, {'5', '1'}, {'5', '2'}, {'5', '3'}, {'5', '4'},
-    {'5', '5'}, {'5', '6'}, {'5', '7'}, {'5', '8'}, {'5', '9'},
-    {'6', '0'}, {'6', '1'}, {'6', '2'}, {'6', '3'}, {'6', '4'},
-    {'6', '5'}, {'6', '6'}, {'6', '7'}, {'6', '8'}, {'6', '9'},
-    {'7', '0'}, {'7', '1'}, {'7', '2'}, {'7', '3'}, {'7', '4'},
-    {'7', '5'}, {'7', '6'}, {'7', '7'}, {'7', '8'}, {'7', '9'},
-    {'8', '0'}, {'8', '1'}, {'8', '2'}, {'8', '3'}, {'8', '4'},
-    {'8', '5'}, {'8', '6'}, {'8', '7'}, {'8', '8'}, {'8', '9'},
-    {'9', '0'}, {'9', '1'}, {'9', '2'}, {'9', '3'}, {'9', '4'},
-    {'9', '5'}, {'9', '6'}, {'9', '7'}, {'9', '8'}, {'9', '9'}
-  };
-  assert(i < 100);
-  memcpy(buf, two_ASCII_digits[i], 2);
-}
-
-}  // namespace
-
 bool SimpleAtob(absl::string_view str, bool* out) {
   ABSL_RAW_CHECK(out != nullptr, "Output pointer must not be nullptr.");
   if (EqualsIgnoreCase(str, "true") || EqualsIgnoreCase(str, "t") ||
@@ -496,13 +459,13 @@ static ExpDigits SplitToSix(const double value) {
 
   int two_digits = dddddd / 10000;
   dddddd -= two_digits * 10000;
-  PutTwoDigits(two_digits, &exp_dig.digits[0]);
+  numbers_internal::PutTwoDigits(two_digits, &exp_dig.digits[0]);
 
   two_digits = dddddd / 100;
   dddddd -= two_digits * 100;
-  PutTwoDigits(two_digits, &exp_dig.digits[2]);
+  numbers_internal::PutTwoDigits(two_digits, &exp_dig.digits[2]);
 
-  PutTwoDigits(dddddd, &exp_dig.digits[4]);
+  numbers_internal::PutTwoDigits(dddddd, &exp_dig.digits[4]);
   return exp_dig;
 }
 
@@ -908,6 +871,25 @@ ABSL_CONST_INIT const char kHexTable[513] =
     "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
     "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
 
+ABSL_CONST_INIT const char two_ASCII_digits[100][2] = {
+    {'0', '0'}, {'0', '1'}, {'0', '2'}, {'0', '3'}, {'0', '4'}, {'0', '5'},
+    {'0', '6'}, {'0', '7'}, {'0', '8'}, {'0', '9'}, {'1', '0'}, {'1', '1'},
+    {'1', '2'}, {'1', '3'}, {'1', '4'}, {'1', '5'}, {'1', '6'}, {'1', '7'},
+    {'1', '8'}, {'1', '9'}, {'2', '0'}, {'2', '1'}, {'2', '2'}, {'2', '3'},
+    {'2', '4'}, {'2', '5'}, {'2', '6'}, {'2', '7'}, {'2', '8'}, {'2', '9'},
+    {'3', '0'}, {'3', '1'}, {'3', '2'}, {'3', '3'}, {'3', '4'}, {'3', '5'},
+    {'3', '6'}, {'3', '7'}, {'3', '8'}, {'3', '9'}, {'4', '0'}, {'4', '1'},
+    {'4', '2'}, {'4', '3'}, {'4', '4'}, {'4', '5'}, {'4', '6'}, {'4', '7'},
+    {'4', '8'}, {'4', '9'}, {'5', '0'}, {'5', '1'}, {'5', '2'}, {'5', '3'},
+    {'5', '4'}, {'5', '5'}, {'5', '6'}, {'5', '7'}, {'5', '8'}, {'5', '9'},
+    {'6', '0'}, {'6', '1'}, {'6', '2'}, {'6', '3'}, {'6', '4'}, {'6', '5'},
+    {'6', '6'}, {'6', '7'}, {'6', '8'}, {'6', '9'}, {'7', '0'}, {'7', '1'},
+    {'7', '2'}, {'7', '3'}, {'7', '4'}, {'7', '5'}, {'7', '6'}, {'7', '7'},
+    {'7', '8'}, {'7', '9'}, {'8', '0'}, {'8', '1'}, {'8', '2'}, {'8', '3'},
+    {'8', '4'}, {'8', '5'}, {'8', '6'}, {'8', '7'}, {'8', '8'}, {'8', '9'},
+    {'9', '0'}, {'9', '1'}, {'9', '2'}, {'9', '3'}, {'9', '4'}, {'9', '5'},
+    {'9', '6'}, {'9', '7'}, {'9', '8'}, {'9', '9'}};
+
 bool safe_strto32_base(absl::string_view text, int32_t* value, int base) {
   return safe_int_internal<int32_t>(text, value, base);
 }
@@ -924,5 +906,9 @@ bool safe_strtou64_base(absl::string_view text, uint64_t* value, int base) {
   return safe_uint_internal<uint64_t>(text, value, base);
 }
 
+bool safe_strtou128_base(absl::string_view text, uint128* value, int base) {
+  return safe_uint_internal<absl::uint128>(text, value, base);
+}
+
 }  // namespace numbers_internal
 }  // namespace absl
diff --git a/absl/strings/numbers.h b/absl/strings/numbers.h
index 9b8ec89a8941..5e15ca40b736 100644
--- a/absl/strings/numbers.h
+++ b/absl/strings/numbers.h
@@ -67,7 +67,7 @@ ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view str, int_type* out);
 // Converts the given string (optionally followed or preceded by ASCII
 // whitespace) into a float, which may be rounded on overflow or underflow.
 // See https://en.cppreference.com/w/c/string/byte/strtof for details about the
-// allowed formats for `str`, except SimpleAtof() is locale-indepdent and will
+// allowed formats for `str`, except SimpleAtof() is locale-independent and will
 // always use the "C" locale. If any errors are encountered, this function
 // returns `false`, leaving `out` in an unspecified state.
 ABSL_MUST_USE_RESULT bool SimpleAtof(absl::string_view str, float* out);
@@ -102,12 +102,26 @@ namespace numbers_internal {
 // Digit conversion.
 extern const char kHexChar[17];    // 0123456789abcdef
 extern const char kHexTable[513];  // 000102030405060708090a0b0c0d0e0f1011...
+extern const char two_ASCII_digits[100][2];  // 00, 01, 02, 03...
+
+// Writes a two-character representation of 'i' to 'buf'. 'i' must be in the
+// range 0 <= i < 100, and buf must have space for two characters. Example:
+//   char buf[2];
+//   PutTwoDigits(42, buf);
+//   // buf[0] == '4'
+//   // buf[1] == '2'
+inline void PutTwoDigits(size_t i, char* buf) {
+  assert(i < 100);
+  memcpy(buf, two_ASCII_digits[i], 2);
+}
 
 // safe_strto?() functions for implementing SimpleAtoi()
 bool safe_strto32_base(absl::string_view text, int32_t* value, int base);
 bool safe_strto64_base(absl::string_view text, int64_t* value, int base);
 bool safe_strtou32_base(absl::string_view text, uint32_t* value, int base);
 bool safe_strtou64_base(absl::string_view text, uint64_t* value, int base);
+bool safe_strtou128_base(absl::string_view text, absl::uint128* value,
+                         int base);
 
 static const int kFastToBufferSize = 32;
 static const int kSixDigitsToBufferSize = 16;
@@ -232,6 +246,11 @@ ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view str, int_type* out) {
   return numbers_internal::safe_strtoi_base(str, out, 10);
 }
 
+ABSL_MUST_USE_RESULT inline bool SimpleAtoi(absl::string_view str,
+                                            absl::uint128* out) {
+  return numbers_internal::safe_strtou128_base(str, out, 10);
+}
+
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_NUMBERS_H_
diff --git a/absl/strings/numbers_test.cc b/absl/strings/numbers_test.cc
index b92b9a8cb2a8..68229b15a4e2 100644
--- a/absl/strings/numbers_test.cc
+++ b/absl/strings/numbers_test.cc
@@ -249,7 +249,9 @@ TEST(Numbers, TestFastPrints) {
 
 template <typename int_type, typename in_val_type>
 void VerifySimpleAtoiGood(in_val_type in_value, int_type exp_value) {
-  std::string s = absl::StrCat(in_value);
+  std::string s;
+  // uint128 can be streamed but not StrCat'd
+  absl::strings_internal::OStringStream(&s) << in_value;
   int_type x = static_cast<int_type>(~exp_value);
   EXPECT_TRUE(SimpleAtoi(s, &x))
       << "in_value=" << in_value << " s=" << s << " x=" << x;
@@ -325,6 +327,25 @@ TEST(NumbersTest, Atoi) {
   VerifySimpleAtoiGood<uint64_t>(std::numeric_limits<uint64_t>::max(),
                                  std::numeric_limits<uint64_t>::max());
 
+  // SimpleAtoi(absl::string_view, absl::uint128)
+  VerifySimpleAtoiGood<absl::uint128>(0, 0);
+  VerifySimpleAtoiGood<absl::uint128>(42, 42);
+  VerifySimpleAtoiBad<absl::uint128>(-42);
+
+  VerifySimpleAtoiBad<absl::uint128>(std::numeric_limits<int32_t>::min());
+  VerifySimpleAtoiGood<absl::uint128>(std::numeric_limits<int32_t>::max(),
+                                      std::numeric_limits<int32_t>::max());
+  VerifySimpleAtoiGood<absl::uint128>(std::numeric_limits<uint32_t>::max(),
+                                      std::numeric_limits<uint32_t>::max());
+  VerifySimpleAtoiBad<absl::uint128>(std::numeric_limits<int64_t>::min());
+  VerifySimpleAtoiGood<absl::uint128>(std::numeric_limits<int64_t>::max(),
+                                      std::numeric_limits<int64_t>::max());
+  VerifySimpleAtoiGood<absl::uint128>(std::numeric_limits<uint64_t>::max(),
+                                      std::numeric_limits<uint64_t>::max());
+  VerifySimpleAtoiGood<absl::uint128>(
+      std::numeric_limits<absl::uint128>::max(),
+      std::numeric_limits<absl::uint128>::max());
+
   // Some other types
   VerifySimpleAtoiGood<int>(-42, -42);
   VerifySimpleAtoiGood<int32_t>(-42, -42);
@@ -657,6 +678,46 @@ TEST(stringtest, safe_strtou32_random) {
 TEST(stringtest, safe_strtou64_random) {
   test_random_integer_parse_base<uint64_t>(&safe_strtou64_base);
 }
+TEST(stringtest, safe_strtou128_random) {
+  // random number generators don't work for uint128, and
+  // uint128 can be streamed but not StrCat'd, so this code must be custom
+  // implemented for uint128, but is generally the same as what's above.
+  // test_random_integer_parse_base<absl::uint128>(
+  //     &absl::numbers_internal::safe_strtou128_base);
+  using RandomEngine = std::minstd_rand0;
+  using IntType = absl::uint128;
+  constexpr auto parse_func = &absl::numbers_internal::safe_strtou128_base;
+
+  std::random_device rd;
+  RandomEngine rng(rd());
+  std::uniform_int_distribution<uint64_t> random_uint64(
+      std::numeric_limits<uint64_t>::min());
+  std::uniform_int_distribution<int> random_base(2, 35);
+
+  for (size_t i = 0; i < kNumRandomTests; i++) {
+    IntType value = random_uint64(rng);
+    value = (value << 64) + random_uint64(rng);
+    int base = random_base(rng);
+    std::string str_value;
+    EXPECT_TRUE(Itoa<IntType>(value, base, &str_value));
+    IntType parsed_value;
+
+    // Test successful parse
+    EXPECT_TRUE(parse_func(str_value, &parsed_value, base));
+    EXPECT_EQ(parsed_value, value);
+
+    // Test overflow
+    std::string s;
+    absl::strings_internal::OStringStream(&s)
+        << std::numeric_limits<IntType>::max() << value;
+    EXPECT_FALSE(parse_func(s, &parsed_value, base));
+
+    // Test underflow
+    s.clear();
+    absl::strings_internal::OStringStream(&s) << "-" << value;
+    EXPECT_FALSE(parse_func(s, &parsed_value, base));
+  }
+}
 
 TEST(stringtest, safe_strtou32_base) {
   for (int i = 0; strtouint32_test_cases()[i].str != nullptr; ++i) {
diff --git a/absl/synchronization/internal/waiter.cc b/absl/synchronization/internal/waiter.cc
index 8e7137705325..f1425872e5b6 100644
--- a/absl/synchronization/internal/waiter.cc
+++ b/absl/synchronization/internal/waiter.cc
@@ -342,8 +342,11 @@ bool Waiter::Wait(KernelTimeout t) {
 }
 
 void Waiter::Post() {
-  wakeups_.fetch_add(1, std::memory_order_release);  // Post a wakeup.
-  Poke();
+  // Post a wakeup.
+  if (wakeups_.fetch_add(1, std::memory_order_release) == 0) {
+    // We incremented from 0, need to wake a potential waiter.
+    Poke();
+  }
 }
 
 void Waiter::Poke() {
diff --git a/absl/synchronization/internal/waiter.h b/absl/synchronization/internal/waiter.h
index cac81d5fd226..9540598be5d3 100644
--- a/absl/synchronization/internal/waiter.h
+++ b/absl/synchronization/internal/waiter.h
@@ -24,6 +24,10 @@
 #include <pthread.h>
 #endif
 
+#ifdef __linux__
+#include <linux/futex.h>
+#endif
+
 #ifdef ABSL_HAVE_SEMAPHORE_H
 #include <semaphore.h>
 #endif
@@ -44,7 +48,12 @@
 #define ABSL_WAITER_MODE ABSL_FORCE_WAITER_MODE
 #elif defined(_WIN32) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
 #define ABSL_WAITER_MODE ABSL_WAITER_MODE_WIN32
-#elif defined(__linux__)
+#elif defined(__BIONIC__)
+// Bionic supports all the futex operations we need even when some of the futex
+// definitions are missing.
+#define ABSL_WAITER_MODE ABSL_WAITER_MODE_FUTEX
+#elif defined(__linux__) && defined(FUTEX_CLOCK_REALTIME)
+// FUTEX_CLOCK_REALTIME requires Linux >= 2.6.28.
 #define ABSL_WAITER_MODE ABSL_WAITER_MODE_FUTEX
 #elif defined(ABSL_HAVE_SEMAPHORE_H)
 #define ABSL_WAITER_MODE ABSL_WAITER_MODE_SEM