merge(3p/absl): subtree merge of Abseil up to e19260f
... notably, this includes Abseil's own StatusOr type, which conflicted with our implementation (that was taken from TensorFlow). Change-Id: Ie7d6764b64055caaeb8dc7b6b9d066291e6b538f
This commit is contained in:
parent
cc27324d02
commit
082c006c04
854 changed files with 11260 additions and 5296 deletions
|
|
@ -83,10 +83,11 @@ ABSL_BASE_INTERNAL_FORCEINLINE int CountLeadingZeros64(uint64_t n) {
|
|||
#elif defined(_MSC_VER) && !defined(__clang__)
|
||||
// MSVC does not have __buitin_clzll. Compose two calls to _BitScanReverse
|
||||
unsigned long result = 0; // NOLINT(runtime/int)
|
||||
if ((n >> 32) && _BitScanReverse(&result, n >> 32)) {
|
||||
if ((n >> 32) &&
|
||||
_BitScanReverse(&result, static_cast<unsigned long>(n >> 32))) {
|
||||
return 31 - result;
|
||||
}
|
||||
if (_BitScanReverse(&result, n)) {
|
||||
if (_BitScanReverse(&result, static_cast<unsigned long>(n))) {
|
||||
return 63 - result;
|
||||
}
|
||||
return 64;
|
||||
|
|
@ -170,10 +171,10 @@ ABSL_BASE_INTERNAL_FORCEINLINE int CountTrailingZerosNonZero64(uint64_t n) {
|
|||
#elif defined(_MSC_VER) && !defined(__clang__)
|
||||
unsigned long result = 0; // NOLINT(runtime/int)
|
||||
if (static_cast<uint32_t>(n) == 0) {
|
||||
_BitScanForward(&result, n >> 32);
|
||||
_BitScanForward(&result, static_cast<unsigned long>(n >> 32));
|
||||
return result + 32;
|
||||
}
|
||||
_BitScanForward(&result, n);
|
||||
_BitScanForward(&result, static_cast<unsigned long>(n));
|
||||
return result;
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
static_assert(sizeof(unsigned long long) == sizeof(n), // NOLINT(runtime/int)
|
||||
|
|
|
|||
|
|
@ -58,8 +58,6 @@
|
|||
|
||||
#if defined(__clang__) && !defined(SWIG)
|
||||
#define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 1
|
||||
#else
|
||||
#define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 0
|
||||
#endif
|
||||
|
||||
#if DYNAMIC_ANNOTATIONS_ENABLED != 0
|
||||
|
|
@ -84,19 +82,16 @@
|
|||
|
||||
// ANNOTALYSIS_ENABLED == 1 when IGNORE_READ_ATTRIBUTE_ENABLED == 1
|
||||
#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED \
|
||||
ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED
|
||||
defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
|
||||
// Read/write annotations are enabled in Annotalysis mode; disabled otherwise.
|
||||
#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED \
|
||||
ABSL_INTERNAL_ANNOTALYSIS_ENABLED
|
||||
#endif
|
||||
|
||||
// Memory annotations are also made available to LLVM's Memory Sanitizer
|
||||
#if defined(MEMORY_SANITIZER) && defined(__has_feature) && \
|
||||
!defined(__native_client__)
|
||||
#if __has_feature(memory_sanitizer)
|
||||
#if defined(ABSL_HAVE_MEMORY_SANITIZER) && !defined(__native_client__)
|
||||
#define ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED
|
||||
#define ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED 0
|
||||
|
|
@ -162,7 +157,7 @@
|
|||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreate)(__FILE__, __LINE__, lock)
|
||||
|
||||
// Report that a linker initialized lock has been created at address `lock`.
|
||||
#ifdef THREAD_SANITIZER
|
||||
#ifdef ABSL_HAVE_THREAD_SANITIZER
|
||||
#define ANNOTATE_RWLOCK_CREATE_STATIC(lock) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreateStatic) \
|
||||
(__FILE__, __LINE__, lock)
|
||||
|
|
@ -250,19 +245,19 @@
|
|||
// -------------------------------------------------------------------------
|
||||
// Define IGNORE_READS_BEGIN/_END attributes.
|
||||
|
||||
#if ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED == 1
|
||||
#if defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
|
||||
|
||||
#define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE \
|
||||
__attribute((exclusive_lock_function("*")))
|
||||
#define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE \
|
||||
__attribute((unlock_function("*")))
|
||||
|
||||
#else // ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED == 0
|
||||
#else // !defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
|
||||
|
||||
#define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE // empty
|
||||
#define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE // empty
|
||||
|
||||
#endif // ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED
|
||||
#endif // defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Define IGNORE_READS_BEGIN/_END annotations.
|
||||
|
|
@ -367,7 +362,7 @@
|
|||
// -------------------------------------------------------------------------
|
||||
// Address sanitizer annotations
|
||||
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#ifdef ABSL_HAVE_ADDRESS_SANITIZER
|
||||
// Describe the current state of a contiguous container such as e.g.
|
||||
// std::vector or std::string. For more details see
|
||||
// sanitizer/common_interface_defs.h, which is provided by the compiler.
|
||||
|
|
@ -385,7 +380,7 @@
|
|||
#define ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid)
|
||||
#define ADDRESS_SANITIZER_REDZONE(name) static_assert(true, "")
|
||||
|
||||
#endif // ADDRESS_SANITIZER
|
||||
#endif // ABSL_HAVE_ADDRESS_SANITIZER
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Undefine the macros intended only for this file.
|
||||
|
|
|
|||
|
|
@ -185,7 +185,7 @@ TEST(ExponentialBiasedTest, InitializationModes) {
|
|||
ABSL_CONST_INIT static ExponentialBiased eb_static;
|
||||
EXPECT_THAT(eb_static.GetSkipCount(2), Ge(0));
|
||||
|
||||
#if ABSL_HAVE_THREAD_LOCAL
|
||||
#ifdef ABSL_HAVE_THREAD_LOCAL
|
||||
thread_local ExponentialBiased eb_thread;
|
||||
EXPECT_THAT(eb_thread.GetSkipCount(2), Ge(0));
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// absl::base_internal::Invoke(f, args...) is an implementation of
|
||||
// absl::base_internal::invoke(f, args...) is an implementation of
|
||||
// INVOKE(f, args...) from section [func.require] of the C++ standard.
|
||||
//
|
||||
// [func.require]
|
||||
|
|
@ -29,7 +29,7 @@
|
|||
// is not one of the types described in the previous item;
|
||||
// 5. f(t1, t2, ..., tN) in all other cases.
|
||||
//
|
||||
// The implementation is SFINAE-friendly: substitution failure within Invoke()
|
||||
// The implementation is SFINAE-friendly: substitution failure within invoke()
|
||||
// isn't an error.
|
||||
|
||||
#ifndef ABSL_BASE_INTERNAL_INVOKE_H_
|
||||
|
|
@ -170,13 +170,13 @@ struct Invoker {
|
|||
|
||||
// The result type of Invoke<F, Args...>.
|
||||
template <typename F, typename... Args>
|
||||
using InvokeT = decltype(Invoker<F, Args...>::type::Invoke(
|
||||
using invoke_result_t = decltype(Invoker<F, Args...>::type::Invoke(
|
||||
std::declval<F>(), std::declval<Args>()...));
|
||||
|
||||
// Invoke(f, args...) is an implementation of INVOKE(f, args...) from section
|
||||
// [func.require] of the C++ standard.
|
||||
template <typename F, typename... Args>
|
||||
InvokeT<F, Args...> Invoke(F&& f, Args&&... args) {
|
||||
invoke_result_t<F, Args...> invoke(F&& f, Args&&... args) {
|
||||
return Invoker<F, Args...>::type::Invoke(std::forward<F>(f),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -598,7 +598,7 @@ static void *DoAllocWithArena(size_t request, LowLevelAlloc::Arena *arena) {
|
|||
section.Leave();
|
||||
result = &s->levels;
|
||||
}
|
||||
ANNOTATE_MEMORY_IS_UNINITIALIZED(result, request);
|
||||
ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(result, request);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#ifndef ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_
|
||||
#define ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_
|
||||
|
||||
#include "absl/base/internal/raw_logging.h"
|
||||
#include "absl/base/internal/scheduling_mode.h"
|
||||
#include "absl/base/macros.h"
|
||||
|
||||
|
|
@ -29,6 +30,13 @@ extern "C" void __google_enable_rescheduling(bool disable_result);
|
|||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
class CondVar;
|
||||
class Mutex;
|
||||
|
||||
namespace synchronization_internal {
|
||||
int MutexDelay(int32_t c, int mode);
|
||||
} // namespace synchronization_internal
|
||||
|
||||
namespace base_internal {
|
||||
|
||||
class SchedulingHelper; // To allow use of SchedulingGuard.
|
||||
|
|
@ -53,6 +61,8 @@ class SchedulingGuard {
|
|||
public:
|
||||
// Returns true iff the calling thread may be cooperatively rescheduled.
|
||||
static bool ReschedulingIsAllowed();
|
||||
SchedulingGuard(const SchedulingGuard&) = delete;
|
||||
SchedulingGuard& operator=(const SchedulingGuard&) = delete;
|
||||
|
||||
private:
|
||||
// Disable cooperative rescheduling of the calling thread. It may still
|
||||
|
|
@ -76,12 +86,23 @@ class SchedulingGuard {
|
|||
bool disabled;
|
||||
};
|
||||
|
||||
// Access to SchedulingGuard is explicitly white-listed.
|
||||
// A scoped helper to enable rescheduling temporarily.
|
||||
// REQUIRES: destructor must run in same thread as constructor.
|
||||
class ScopedEnable {
|
||||
public:
|
||||
ScopedEnable();
|
||||
~ScopedEnable();
|
||||
|
||||
private:
|
||||
int scheduling_disabled_depth_;
|
||||
};
|
||||
|
||||
// Access to SchedulingGuard is explicitly permitted.
|
||||
friend class absl::CondVar;
|
||||
friend class absl::Mutex;
|
||||
friend class SchedulingHelper;
|
||||
friend class SpinLock;
|
||||
|
||||
SchedulingGuard(const SchedulingGuard&) = delete;
|
||||
SchedulingGuard& operator=(const SchedulingGuard&) = delete;
|
||||
friend int absl::synchronization_internal::MutexDelay(int32_t c, int mode);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -100,6 +121,12 @@ inline void SchedulingGuard::EnableRescheduling(bool /* disable_result */) {
|
|||
return;
|
||||
}
|
||||
|
||||
inline SchedulingGuard::ScopedEnable::ScopedEnable()
|
||||
: scheduling_disabled_depth_(0) {}
|
||||
inline SchedulingGuard::ScopedEnable::~ScopedEnable() {
|
||||
ABSL_RAW_CHECK(scheduling_disabled_depth_ == 0, "disable unused warning");
|
||||
}
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@
|
|||
|
||||
// TODO(gfalcon): We want raw-logging to work on as many platforms as possible.
|
||||
// Explicitly #error out when not ABSL_LOW_LEVEL_WRITE_SUPPORTED, except for a
|
||||
// whitelisted set of platforms for which we expect not to be able to raw log.
|
||||
// selected set of platforms for which we expect not to be able to raw log.
|
||||
|
||||
ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static absl::base_internal::AtomicHook<
|
||||
absl::raw_logging_internal::LogPrefixHook>
|
||||
|
|
@ -227,7 +227,7 @@ bool RawLoggingFullySupported() {
|
|||
#endif // !ABSL_LOW_LEVEL_WRITE_SUPPORTED
|
||||
}
|
||||
|
||||
ABSL_DLL ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
|
||||
ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_DLL
|
||||
absl::base_internal::AtomicHook<InternalLogFunction>
|
||||
internal_log_function(DefaultInternalLog);
|
||||
|
||||
|
|
|
|||
|
|
@ -72,10 +72,14 @@
|
|||
//
|
||||
// The API is a subset of the above: each macro only takes two arguments. Use
|
||||
// StrCat if you need to build a richer message.
|
||||
#define ABSL_INTERNAL_LOG(severity, message) \
|
||||
do { \
|
||||
::absl::raw_logging_internal::internal_log_function( \
|
||||
ABSL_RAW_LOGGING_INTERNAL_##severity, __FILE__, __LINE__, message); \
|
||||
#define ABSL_INTERNAL_LOG(severity, message) \
|
||||
do { \
|
||||
constexpr const char* absl_raw_logging_internal_filename = __FILE__; \
|
||||
::absl::raw_logging_internal::internal_log_function( \
|
||||
ABSL_RAW_LOGGING_INTERNAL_##severity, \
|
||||
absl_raw_logging_internal_filename, __LINE__, message); \
|
||||
if (ABSL_RAW_LOGGING_INTERNAL_##severity == ::absl::LogSeverity::kFatal) \
|
||||
ABSL_INTERNAL_UNREACHABLE; \
|
||||
} while (0)
|
||||
|
||||
#define ABSL_INTERNAL_CHECK(condition, message) \
|
||||
|
|
@ -170,7 +174,7 @@ using InternalLogFunction = void (*)(absl::LogSeverity severity,
|
|||
const char* file, int line,
|
||||
const std::string& message);
|
||||
|
||||
ABSL_DLL ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES extern base_internal::AtomicHook<
|
||||
ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_DLL extern base_internal::AtomicHook<
|
||||
InternalLogFunction>
|
||||
internal_log_function;
|
||||
|
||||
|
|
|
|||
|
|
@ -64,7 +64,14 @@ class ABSL_LOCKABLE SpinLock {
|
|||
constexpr SpinLock(absl::ConstInitType, base_internal::SchedulingMode mode)
|
||||
: lockword_(IsCooperative(mode) ? kSpinLockCooperative : 0) {}
|
||||
|
||||
// For global SpinLock instances prefer trivial destructor when possible.
|
||||
// Default but non-trivial destructor in some build configurations causes an
|
||||
// extra static initializer.
|
||||
#ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE
|
||||
~SpinLock() { ABSL_TSAN_MUTEX_DESTROY(this, __tsan_mutex_not_static); }
|
||||
#else
|
||||
~SpinLock() = default;
|
||||
#endif
|
||||
|
||||
// Acquire this SpinLock.
|
||||
inline void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION() {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include "absl/base/internal/strerror.h"
|
||||
|
||||
#include <array>
|
||||
#include <cerrno>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
|
|
@ -21,13 +22,13 @@
|
|||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/base/internal/errno_saver.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
namespace {
|
||||
|
||||
const char* StrErrorAdaptor(int errnum, char* buf, size_t buflen) {
|
||||
#if defined(_WIN32)
|
||||
int rc = strerror_s(buf, buflen, errnum);
|
||||
|
|
@ -35,15 +36,6 @@ const char* StrErrorAdaptor(int errnum, char* buf, size_t buflen) {
|
|||
if (rc == 0 && strncmp(buf, "Unknown error", buflen) == 0) *buf = '\0';
|
||||
return buf;
|
||||
#else
|
||||
#if defined(__GLIBC__) || defined(__APPLE__)
|
||||
// Use the BSD sys_errlist API provided by GNU glibc and others to
|
||||
// avoid any need to copy the message into the local buffer first.
|
||||
if (0 <= errnum && errnum < sys_nerr) {
|
||||
if (const char* p = sys_errlist[errnum]) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// The type of `ret` is platform-specific; both of these branches must compile
|
||||
// either way but only one will execute on any given platform:
|
||||
auto ret = strerror_r(errnum, buf, buflen);
|
||||
|
|
@ -57,9 +49,8 @@ const char* StrErrorAdaptor(int errnum, char* buf, size_t buflen) {
|
|||
}
|
||||
#endif
|
||||
}
|
||||
} // namespace
|
||||
|
||||
std::string StrError(int errnum) {
|
||||
std::string StrErrorInternal(int errnum) {
|
||||
absl::base_internal::ErrnoSaver errno_saver;
|
||||
char buf[100];
|
||||
const char* str = StrErrorAdaptor(errnum, buf, sizeof buf);
|
||||
|
|
@ -70,6 +61,28 @@ std::string StrError(int errnum) {
|
|||
return str;
|
||||
}
|
||||
|
||||
// kSysNerr is the number of errors from a recent glibc. `StrError()` falls back
|
||||
// to `StrErrorAdaptor()` if the value is larger than this.
|
||||
constexpr int kSysNerr = 135;
|
||||
|
||||
std::array<std::string, kSysNerr>* NewStrErrorTable() {
|
||||
auto* table = new std::array<std::string, kSysNerr>;
|
||||
for (int i = 0; i < static_cast<int>(table->size()); ++i) {
|
||||
(*table)[i] = StrErrorInternal(i);
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::string StrError(int errnum) {
|
||||
static const auto* table = NewStrErrorTable();
|
||||
if (errnum >= 0 && errnum < static_cast<int>(table->size())) {
|
||||
return (*table)[errnum];
|
||||
}
|
||||
return StrErrorInternal(errnum);
|
||||
}
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
|
|
|||
|
|
@ -20,15 +20,6 @@
|
|||
#include "benchmark/benchmark.h"
|
||||
|
||||
namespace {
|
||||
#if defined(__GLIBC__) || defined(__APPLE__)
|
||||
void BM_SysErrList(benchmark::State& state) {
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(std::string(sys_errlist[ERANGE]));
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_SysErrList);
|
||||
#endif
|
||||
|
||||
void BM_AbslStrError(benchmark::State& state) {
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(absl::base_internal::StrError(ERANGE));
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
|
|
@ -50,6 +51,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include "absl/base/call_once.h"
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/internal/raw_logging.h"
|
||||
#include "absl/base/internal/spinlock.h"
|
||||
#include "absl/base/internal/unscaledcycleclock.h"
|
||||
|
|
@ -420,6 +422,18 @@ pid_t GetTID() {
|
|||
|
||||
#endif
|
||||
|
||||
// GetCachedTID() caches the thread ID in thread-local storage (which is a
|
||||
// userspace construct) to avoid unnecessary system calls. Without this caching,
|
||||
// it can take roughly 98ns, while it takes roughly 1ns with this caching.
|
||||
pid_t GetCachedTID() {
|
||||
#ifdef ABSL_HAVE_THREAD_LOCAL
|
||||
static thread_local pid_t thread_id = GetTID();
|
||||
return thread_id;
|
||||
#else
|
||||
return GetTID();
|
||||
#endif // ABSL_HAVE_THREAD_LOCAL
|
||||
}
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include <cstdint>
|
||||
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/port.h"
|
||||
|
||||
namespace absl {
|
||||
|
|
@ -59,6 +60,13 @@ using pid_t = uint32_t;
|
|||
#endif
|
||||
pid_t GetTID();
|
||||
|
||||
// Like GetTID(), but caches the result in thread-local storage in order
|
||||
// to avoid unnecessary system calls. Note that there are some cases where
|
||||
// one must call through to GetTID directly, which is why this exists as a
|
||||
// separate function. For example, GetCachedTID() is not safe to call in
|
||||
// an asynchronous signal-handling context nor right after a call to fork().
|
||||
pid_t GetCachedTID();
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include <cassert>
|
||||
#include <memory>
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/base/call_once.h"
|
||||
#include "absl/base/internal/raw_logging.h"
|
||||
#include "absl/base/internal/spinlock.h"
|
||||
|
|
@ -53,9 +54,11 @@ void AllocateThreadIdentityKey(ThreadIdentityReclaimerFunction reclaimer) {
|
|||
// exist within a process (via dlopen() or similar), references to
|
||||
// thread_identity_ptr from each instance of the code will refer to
|
||||
// *different* instances of this ptr.
|
||||
#ifdef __GNUC__
|
||||
// Apple platforms have the visibility attribute, but issue a compile warning
|
||||
// that protected visibility is unsupported.
|
||||
#if ABSL_HAVE_ATTRIBUTE(visibility) && !defined(__APPLE__)
|
||||
__attribute__((visibility("protected")))
|
||||
#endif // __GNUC__
|
||||
#endif // ABSL_HAVE_ATTRIBUTE(visibility) && !defined(__APPLE__)
|
||||
#if ABSL_PER_THREAD_TLS
|
||||
// Prefer __thread to thread_local as benchmarks indicate it is a bit faster.
|
||||
ABSL_PER_THREAD_TLS_KEYWORD ThreadIdentity* thread_identity_ptr = nullptr;
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/internal/per_thread_tls.h"
|
||||
#include "absl/base/optimization.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
|
|
@ -69,30 +70,28 @@ struct PerThreadSynch {
|
|||
// is using this PerThreadSynch as a terminator. Its
|
||||
// skip field must not be filled in because the loop
|
||||
// might then skip over the terminator.
|
||||
|
||||
// The wait parameters of the current wait. waitp is null if the
|
||||
// thread is not waiting. Transitions from null to non-null must
|
||||
// occur before the enqueue commit point (state = kQueued in
|
||||
// Enqueue() and CondVarEnqueue()). Transitions from non-null to
|
||||
// null must occur after the wait is finished (state = kAvailable in
|
||||
// Mutex::Block() and CondVar::WaitCommon()). This field may be
|
||||
// changed only by the thread that describes this PerThreadSynch. A
|
||||
// special case is Fer(), which calls Enqueue() on another thread,
|
||||
// but with an identical SynchWaitParams pointer, thus leaving the
|
||||
// pointer unchanged.
|
||||
SynchWaitParams *waitp;
|
||||
|
||||
bool suppress_fatal_errors; // If true, try to proceed even in the face of
|
||||
// broken invariants. This is used within fatal
|
||||
// signal handlers to improve the chances of
|
||||
// debug logging information being output
|
||||
// successfully.
|
||||
|
||||
intptr_t readers; // Number of readers in mutex.
|
||||
int priority; // Priority of thread (updated every so often).
|
||||
|
||||
// When priority will next be read (cycles).
|
||||
int64_t next_priority_read_cycles;
|
||||
bool wake; // This thread is to be woken from a Mutex.
|
||||
// If "x" is on a waiter list for a mutex, "x->cond_waiter" is true iff the
|
||||
// waiter is waiting on the mutex as part of a CV Wait or Mutex Await.
|
||||
//
|
||||
// The value of "x->cond_waiter" is meaningless if "x" is not on a
|
||||
// Mutex waiter list.
|
||||
bool cond_waiter;
|
||||
bool maybe_unlocking; // Valid at head of Mutex waiter queue;
|
||||
// true if UnlockSlow could be searching
|
||||
// for a waiter to wake. Used for an optimization
|
||||
// in Enqueue(). true is always a valid value.
|
||||
// Can be reset to false when the unlocker or any
|
||||
// writer releases the lock, or a reader fully
|
||||
// releases the lock. It may not be set to false
|
||||
// by a reader that decrements the count to
|
||||
// non-zero. protected by mutex spinlock
|
||||
bool suppress_fatal_errors; // If true, try to proceed even in the face
|
||||
// of broken invariants. This is used within
|
||||
// fatal signal handlers to improve the
|
||||
// chances of debug logging information being
|
||||
// output successfully.
|
||||
int priority; // Priority of thread (updated every so often).
|
||||
|
||||
// State values:
|
||||
// kAvailable: This PerThreadSynch is available.
|
||||
|
|
@ -111,30 +110,30 @@ struct PerThreadSynch {
|
|||
};
|
||||
std::atomic<State> state;
|
||||
|
||||
bool maybe_unlocking; // Valid at head of Mutex waiter queue;
|
||||
// true if UnlockSlow could be searching
|
||||
// for a waiter to wake. Used for an optimization
|
||||
// in Enqueue(). true is always a valid value.
|
||||
// Can be reset to false when the unlocker or any
|
||||
// writer releases the lock, or a reader fully releases
|
||||
// the lock. It may not be set to false by a reader
|
||||
// that decrements the count to non-zero.
|
||||
// protected by mutex spinlock
|
||||
// The wait parameters of the current wait. waitp is null if the
|
||||
// thread is not waiting. Transitions from null to non-null must
|
||||
// occur before the enqueue commit point (state = kQueued in
|
||||
// Enqueue() and CondVarEnqueue()). Transitions from non-null to
|
||||
// null must occur after the wait is finished (state = kAvailable in
|
||||
// Mutex::Block() and CondVar::WaitCommon()). This field may be
|
||||
// changed only by the thread that describes this PerThreadSynch. A
|
||||
// special case is Fer(), which calls Enqueue() on another thread,
|
||||
// but with an identical SynchWaitParams pointer, thus leaving the
|
||||
// pointer unchanged.
|
||||
SynchWaitParams* waitp;
|
||||
|
||||
bool wake; // This thread is to be woken from a Mutex.
|
||||
intptr_t readers; // Number of readers in mutex.
|
||||
|
||||
// If "x" is on a waiter list for a mutex, "x->cond_waiter" is true iff the
|
||||
// waiter is waiting on the mutex as part of a CV Wait or Mutex Await.
|
||||
//
|
||||
// The value of "x->cond_waiter" is meaningless if "x" is not on a
|
||||
// Mutex waiter list.
|
||||
bool cond_waiter;
|
||||
// When priority will next be read (cycles).
|
||||
int64_t next_priority_read_cycles;
|
||||
|
||||
// Locks held; used during deadlock detection.
|
||||
// Allocated in Synch_GetAllLocks() and freed in ReclaimThreadIdentity().
|
||||
SynchLocksHeld *all_locks;
|
||||
};
|
||||
|
||||
// The instances of this class are allocated in NewThreadIdentity() with an
|
||||
// alignment of PerThreadSynch::kAlignment.
|
||||
struct ThreadIdentity {
|
||||
// Must be the first member. The Mutex implementation requires that
|
||||
// the PerThreadSynch object associated with each thread is
|
||||
|
|
@ -212,7 +211,9 @@ void ClearCurrentThreadIdentity();
|
|||
#define ABSL_THREAD_IDENTITY_MODE ABSL_FORCE_THREAD_IDENTITY_MODE
|
||||
#elif defined(_WIN32) && !defined(__MINGW32__)
|
||||
#define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_CPP11
|
||||
#elif ABSL_PER_THREAD_TLS && defined(__GOOGLE_GRTE_VERSION__) && \
|
||||
#elif defined(__APPLE__) && defined(ABSL_HAVE_THREAD_LOCAL)
|
||||
#define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_CPP11
|
||||
#elif ABSL_PER_THREAD_TLS && defined(__GOOGLE_GRTE_VERSION__) && \
|
||||
(__GOOGLE_GRTE_VERSION__ >= 20140228L)
|
||||
// Support for async-safe TLS was specifically added in GRTEv4. It's not
|
||||
// present in the upstream eglibc.
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ TEST(ThreadIdentityTest, BasicIdentityWorksThreaded) {
|
|||
// - If a thread implementation chooses to recycle threads, that
|
||||
// correct re-initialization occurs.
|
||||
static const int kNumLoops = 3;
|
||||
static const int kNumThreads = 400;
|
||||
static const int kNumThreads = 32;
|
||||
for (int iter = 0; iter < kNumLoops; iter++) {
|
||||
std::vector<std::thread> threads;
|
||||
for (int i = 0; i < kNumThreads; ++i) {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include <functional>
|
||||
#include <new>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/internal/raw_logging.h"
|
||||
|
||||
|
|
@ -25,83 +26,186 @@ namespace absl {
|
|||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
|
||||
// NOTE: The various STL exception throwing functions are placed within the
|
||||
// #ifdef blocks so the symbols aren't exposed on platforms that don't support
|
||||
// them, such as the Android NDK. For example, ANGLE fails to link when building
|
||||
// within AOSP without them, since the STL functions don't exist.
|
||||
namespace {
|
||||
#ifdef ABSL_HAVE_EXCEPTIONS
|
||||
template <typename T>
|
||||
[[noreturn]] void Throw(const T& error) {
|
||||
#ifdef ABSL_HAVE_EXCEPTIONS
|
||||
throw error;
|
||||
#else
|
||||
ABSL_RAW_LOG(FATAL, "%s", error.what());
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
} // namespace
|
||||
|
||||
void ThrowStdLogicError(const std::string& what_arg) {
|
||||
#ifdef ABSL_HAVE_EXCEPTIONS
|
||||
Throw(std::logic_error(what_arg));
|
||||
#else
|
||||
ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
void ThrowStdLogicError(const char* what_arg) {
|
||||
#ifdef ABSL_HAVE_EXCEPTIONS
|
||||
Throw(std::logic_error(what_arg));
|
||||
#else
|
||||
ABSL_RAW_LOG(FATAL, "%s", what_arg);
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
void ThrowStdInvalidArgument(const std::string& what_arg) {
|
||||
#ifdef ABSL_HAVE_EXCEPTIONS
|
||||
Throw(std::invalid_argument(what_arg));
|
||||
#else
|
||||
ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
void ThrowStdInvalidArgument(const char* what_arg) {
|
||||
#ifdef ABSL_HAVE_EXCEPTIONS
|
||||
Throw(std::invalid_argument(what_arg));
|
||||
#else
|
||||
ABSL_RAW_LOG(FATAL, "%s", what_arg);
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
void ThrowStdDomainError(const std::string& what_arg) {
|
||||
#ifdef ABSL_HAVE_EXCEPTIONS
|
||||
Throw(std::domain_error(what_arg));
|
||||
#else
|
||||
ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
void ThrowStdDomainError(const char* what_arg) {
|
||||
#ifdef ABSL_HAVE_EXCEPTIONS
|
||||
Throw(std::domain_error(what_arg));
|
||||
#else
|
||||
ABSL_RAW_LOG(FATAL, "%s", what_arg);
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
void ThrowStdLengthError(const std::string& what_arg) {
|
||||
#ifdef ABSL_HAVE_EXCEPTIONS
|
||||
Throw(std::length_error(what_arg));
|
||||
#else
|
||||
ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
void ThrowStdLengthError(const char* what_arg) {
|
||||
#ifdef ABSL_HAVE_EXCEPTIONS
|
||||
Throw(std::length_error(what_arg));
|
||||
#else
|
||||
ABSL_RAW_LOG(FATAL, "%s", what_arg);
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
void ThrowStdOutOfRange(const std::string& what_arg) {
|
||||
#ifdef ABSL_HAVE_EXCEPTIONS
|
||||
Throw(std::out_of_range(what_arg));
|
||||
#else
|
||||
ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
void ThrowStdOutOfRange(const char* what_arg) {
|
||||
#ifdef ABSL_HAVE_EXCEPTIONS
|
||||
Throw(std::out_of_range(what_arg));
|
||||
#else
|
||||
ABSL_RAW_LOG(FATAL, "%s", what_arg);
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
void ThrowStdRuntimeError(const std::string& what_arg) {
|
||||
#ifdef ABSL_HAVE_EXCEPTIONS
|
||||
Throw(std::runtime_error(what_arg));
|
||||
#else
|
||||
ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
void ThrowStdRuntimeError(const char* what_arg) {
|
||||
#ifdef ABSL_HAVE_EXCEPTIONS
|
||||
Throw(std::runtime_error(what_arg));
|
||||
#else
|
||||
ABSL_RAW_LOG(FATAL, "%s", what_arg);
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
void ThrowStdRangeError(const std::string& what_arg) {
|
||||
#ifdef ABSL_HAVE_EXCEPTIONS
|
||||
Throw(std::range_error(what_arg));
|
||||
#else
|
||||
ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
void ThrowStdRangeError(const char* what_arg) {
|
||||
#ifdef ABSL_HAVE_EXCEPTIONS
|
||||
Throw(std::range_error(what_arg));
|
||||
#else
|
||||
ABSL_RAW_LOG(FATAL, "%s", what_arg);
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
void ThrowStdOverflowError(const std::string& what_arg) {
|
||||
#ifdef ABSL_HAVE_EXCEPTIONS
|
||||
Throw(std::overflow_error(what_arg));
|
||||
#else
|
||||
ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
void ThrowStdOverflowError(const char* what_arg) {
|
||||
#ifdef ABSL_HAVE_EXCEPTIONS
|
||||
Throw(std::overflow_error(what_arg));
|
||||
#else
|
||||
ABSL_RAW_LOG(FATAL, "%s", what_arg);
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
void ThrowStdUnderflowError(const std::string& what_arg) {
|
||||
#ifdef ABSL_HAVE_EXCEPTIONS
|
||||
Throw(std::underflow_error(what_arg));
|
||||
#else
|
||||
ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
void ThrowStdUnderflowError(const char* what_arg) {
|
||||
#ifdef ABSL_HAVE_EXCEPTIONS
|
||||
Throw(std::underflow_error(what_arg));
|
||||
#else
|
||||
ABSL_RAW_LOG(FATAL, "%s", what_arg);
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
void ThrowStdBadFunctionCall() { Throw(std::bad_function_call()); }
|
||||
void ThrowStdBadFunctionCall() {
|
||||
#ifdef ABSL_HAVE_EXCEPTIONS
|
||||
Throw(std::bad_function_call());
|
||||
#else
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
void ThrowStdBadAlloc() { Throw(std::bad_alloc()); }
|
||||
void ThrowStdBadAlloc() {
|
||||
#ifdef ABSL_HAVE_EXCEPTIONS
|
||||
Throw(std::bad_alloc());
|
||||
#else
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
#ifndef ABSL_BASE_INTERNAL_TSAN_MUTEX_INTERFACE_H_
|
||||
#define ABSL_BASE_INTERNAL_TSAN_MUTEX_INTERFACE_H_
|
||||
|
||||
#include "absl/base/config.h"
|
||||
|
||||
// ABSL_INTERNAL_HAVE_TSAN_INTERFACE
|
||||
// Macro intended only for internal use.
|
||||
//
|
||||
|
|
@ -28,7 +30,7 @@
|
|||
#error "ABSL_INTERNAL_HAVE_TSAN_INTERFACE cannot be directly set."
|
||||
#endif
|
||||
|
||||
#if defined(THREAD_SANITIZER) && defined(__has_include)
|
||||
#if defined(ABSL_HAVE_THREAD_SANITIZER) && defined(__has_include)
|
||||
#if __has_include(<sanitizer/tsan_interface.h>)
|
||||
#define ABSL_INTERNAL_HAVE_TSAN_INTERFACE 1
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -31,80 +31,6 @@
|
|||
// The unaligned API is C++ only. The declarations use C++ features
|
||||
// (namespaces, inline) which are absent or incompatible in C.
|
||||
#if defined(__cplusplus)
|
||||
|
||||
#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) ||\
|
||||
defined(MEMORY_SANITIZER)
|
||||
// Consider we have an unaligned load/store of 4 bytes from address 0x...05.
|
||||
// AddressSanitizer will treat it as a 3-byte access to the range 05:07 and
|
||||
// will miss a bug if 08 is the first unaddressable byte.
|
||||
// ThreadSanitizer will also treat this as a 3-byte access to 05:07 and will
|
||||
// miss a race between this access and some other accesses to 08.
|
||||
// MemorySanitizer will correctly propagate the shadow on unaligned stores
|
||||
// and correctly report bugs on unaligned loads, but it may not properly
|
||||
// update and report the origin of the uninitialized memory.
|
||||
// For all three tools, replacing an unaligned access with a tool-specific
|
||||
// callback solves the problem.
|
||||
|
||||
// Make sure uint16_t/uint32_t/uint64_t are defined.
|
||||
#include <stdint.h>
|
||||
|
||||
extern "C" {
|
||||
uint16_t __sanitizer_unaligned_load16(const void *p);
|
||||
uint32_t __sanitizer_unaligned_load32(const void *p);
|
||||
uint64_t __sanitizer_unaligned_load64(const void *p);
|
||||
void __sanitizer_unaligned_store16(void *p, uint16_t v);
|
||||
void __sanitizer_unaligned_store32(void *p, uint32_t v);
|
||||
void __sanitizer_unaligned_store64(void *p, uint64_t v);
|
||||
} // extern "C"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
|
||||
inline uint16_t UnalignedLoad16(const void *p) {
|
||||
return __sanitizer_unaligned_load16(p);
|
||||
}
|
||||
|
||||
inline uint32_t UnalignedLoad32(const void *p) {
|
||||
return __sanitizer_unaligned_load32(p);
|
||||
}
|
||||
|
||||
inline uint64_t UnalignedLoad64(const void *p) {
|
||||
return __sanitizer_unaligned_load64(p);
|
||||
}
|
||||
|
||||
inline void UnalignedStore16(void *p, uint16_t v) {
|
||||
__sanitizer_unaligned_store16(p, v);
|
||||
}
|
||||
|
||||
inline void UnalignedStore32(void *p, uint32_t v) {
|
||||
__sanitizer_unaligned_store32(p, v);
|
||||
}
|
||||
|
||||
inline void UnalignedStore64(void *p, uint64_t v) {
|
||||
__sanitizer_unaligned_store64(p, v);
|
||||
}
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#define ABSL_INTERNAL_UNALIGNED_LOAD16(_p) \
|
||||
(absl::base_internal::UnalignedLoad16(_p))
|
||||
#define ABSL_INTERNAL_UNALIGNED_LOAD32(_p) \
|
||||
(absl::base_internal::UnalignedLoad32(_p))
|
||||
#define ABSL_INTERNAL_UNALIGNED_LOAD64(_p) \
|
||||
(absl::base_internal::UnalignedLoad64(_p))
|
||||
|
||||
#define ABSL_INTERNAL_UNALIGNED_STORE16(_p, _val) \
|
||||
(absl::base_internal::UnalignedStore16(_p, _val))
|
||||
#define ABSL_INTERNAL_UNALIGNED_STORE32(_p, _val) \
|
||||
(absl::base_internal::UnalignedStore32(_p, _val))
|
||||
#define ABSL_INTERNAL_UNALIGNED_STORE64(_p, _val) \
|
||||
(absl::base_internal::UnalignedStore64(_p, _val))
|
||||
|
||||
#else
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
|
|
@ -151,8 +77,6 @@ ABSL_NAMESPACE_END
|
|||
#define ABSL_INTERNAL_UNALIGNED_STORE64(_p, _val) \
|
||||
(absl::base_internal::UnalignedStore64(_p, _val))
|
||||
|
||||
#endif
|
||||
|
||||
#endif // defined(__cplusplus), end of unaligned API
|
||||
|
||||
#endif // ABSL_BASE_INTERNAL_UNALIGNED_ACCESS_H_
|
||||
|
|
|
|||
|
|
@ -123,9 +123,7 @@ double UnscaledCycleClock::Frequency() {
|
|||
|
||||
#pragma intrinsic(__rdtsc)
|
||||
|
||||
int64_t UnscaledCycleClock::Now() {
|
||||
return __rdtsc();
|
||||
}
|
||||
int64_t UnscaledCycleClock::Now() { return __rdtsc(); }
|
||||
|
||||
double UnscaledCycleClock::Frequency() {
|
||||
return base_internal::NominalCPUFrequency();
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@
|
|||
// UnscaledCycleClock
|
||||
// An UnscaledCycleClock yields the value and frequency of a cycle counter
|
||||
// that increments at a rate that is approximately constant.
|
||||
// This class is for internal / whitelisted use only, you should consider
|
||||
// using CycleClock instead.
|
||||
// This class is for internal use only, you should consider using CycleClock
|
||||
// instead.
|
||||
//
|
||||
// Notes:
|
||||
// The cycle counter frequency is not necessarily the core clock frequency.
|
||||
|
|
@ -109,7 +109,7 @@ class UnscaledCycleClock {
|
|||
// value.
|
||||
static double Frequency();
|
||||
|
||||
// Whitelisted friends.
|
||||
// Allowed users
|
||||
friend class base_internal::CycleClock;
|
||||
friend class time_internal::UnscaledCycleClockWrapperForGetCurrentTime;
|
||||
friend class base_internal::UnscaledCycleClockWrapperForInitializeFrequency;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue