mirror of
https://github.com/m5stack/StackFlow.git
synced 2026-05-20 11:32:11 -07:00
[update] move public include into static_lib, update llm & vlm
This commit is contained in:
@@ -5,7 +5,7 @@ import shutil
|
||||
os.environ['SDK_PATH'] = os.path.normpath(str(Path(os.getcwd())/'..'/'..'/'SDK'))
|
||||
os.environ['EXT_COMPONENTS_PATH'] = os.path.normpath(str(Path(os.getcwd())/'..'/'..'/'ext_components'))
|
||||
|
||||
version = 'v0.0.9'
|
||||
version = 'v0.1.0'
|
||||
static_lib = 'static_lib'
|
||||
update = False
|
||||
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
// Copyright 2017 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.
|
||||
//
|
||||
// -----------------------------------------------------------------------------
|
||||
// File: algorithm.h
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// This header file contains Google extensions to the standard <algorithm> C++
|
||||
// header.
|
||||
|
||||
#ifndef ABSL_ALGORITHM_ALGORITHM_H_
|
||||
#define ABSL_ALGORITHM_ALGORITHM_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
||||
#include "absl/base/config.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
|
||||
// equal()
|
||||
// rotate()
|
||||
//
|
||||
// Historical note: Abseil once provided implementations of these algorithms
|
||||
// prior to their adoption in C++14. New code should prefer to use the std
|
||||
// variants.
|
||||
//
|
||||
// See the documentation for the STL <algorithm> header for more information:
|
||||
// https://en.cppreference.com/w/cpp/header/algorithm
|
||||
using std::equal;
|
||||
using std::rotate;
|
||||
|
||||
// linear_search()
|
||||
//
|
||||
// Performs a linear search for `value` using the iterator `first` up to
|
||||
// but not including `last`, returning true if [`first`, `last`) contains an
|
||||
// element equal to `value`.
|
||||
//
|
||||
// A linear search is of O(n) complexity which is guaranteed to make at most
|
||||
// n = (`last` - `first`) comparisons. A linear search over short containers
|
||||
// may be faster than a binary search, even when the container is sorted.
|
||||
template <typename InputIterator, typename EqualityComparable>
|
||||
bool linear_search(InputIterator first, InputIterator last,
|
||||
const EqualityComparable& value) {
|
||||
return std::find(first, last, value) != last;
|
||||
}
|
||||
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_ALGORITHM_ALGORITHM_H_
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,225 +0,0 @@
|
||||
// Copyright 2017 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.
|
||||
//
|
||||
// -----------------------------------------------------------------------------
|
||||
// File: call_once.h
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// This header file provides an Abseil version of `std::call_once` for invoking
|
||||
// a given function at most once, across all threads. This Abseil version is
|
||||
// faster than the C++11 version and incorporates the C++17 argument-passing
|
||||
// fix, so that (for example) non-const references may be passed to the invoked
|
||||
// function.
|
||||
|
||||
#ifndef ABSL_BASE_CALL_ONCE_H_
|
||||
#define ABSL_BASE_CALL_ONCE_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/base/internal/invoke.h"
|
||||
#include "absl/base/internal/low_level_scheduling.h"
|
||||
#include "absl/base/internal/raw_logging.h"
|
||||
#include "absl/base/internal/scheduling_mode.h"
|
||||
#include "absl/base/internal/spinlock_wait.h"
|
||||
#include "absl/base/macros.h"
|
||||
#include "absl/base/nullability.h"
|
||||
#include "absl/base/optimization.h"
|
||||
#include "absl/base/port.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
|
||||
class once_flag;
|
||||
|
||||
namespace base_internal {
|
||||
absl::Nonnull<std::atomic<uint32_t>*> ControlWord(
|
||||
absl::Nonnull<absl::once_flag*> flag);
|
||||
} // namespace base_internal
|
||||
|
||||
// call_once()
|
||||
//
|
||||
// For all invocations using a given `once_flag`, invokes a given `fn` exactly
|
||||
// once across all threads. The first call to `call_once()` with a particular
|
||||
// `once_flag` argument (that does not throw an exception) will run the
|
||||
// specified function with the provided `args`; other calls with the same
|
||||
// `once_flag` argument will not run the function, but will wait
|
||||
// for the provided function to finish running (if it is still running).
|
||||
//
|
||||
// This mechanism provides a safe, simple, and fast mechanism for one-time
|
||||
// initialization in a multi-threaded process.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// class MyInitClass {
|
||||
// public:
|
||||
// ...
|
||||
// mutable absl::once_flag once_;
|
||||
//
|
||||
// MyInitClass* init() const {
|
||||
// absl::call_once(once_, &MyInitClass::Init, this);
|
||||
// return ptr_;
|
||||
// }
|
||||
//
|
||||
template <typename Callable, typename... Args>
|
||||
void call_once(absl::once_flag& flag, Callable&& fn, Args&&... args);
|
||||
|
||||
// once_flag
|
||||
//
|
||||
// Objects of this type are used to distinguish calls to `call_once()` and
|
||||
// ensure the provided function is only invoked once across all threads. This
|
||||
// type is not copyable or movable. However, it has a `constexpr`
|
||||
// constructor, and is safe to use as a namespace-scoped global variable.
|
||||
class once_flag {
|
||||
public:
|
||||
constexpr once_flag() : control_(0) {}
|
||||
once_flag(const once_flag&) = delete;
|
||||
once_flag& operator=(const once_flag&) = delete;
|
||||
|
||||
private:
|
||||
friend absl::Nonnull<std::atomic<uint32_t>*> base_internal::ControlWord(
|
||||
absl::Nonnull<once_flag*> flag);
|
||||
std::atomic<uint32_t> control_;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// End of public interfaces.
|
||||
// Implementation details follow.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace base_internal {
|
||||
|
||||
// Like call_once, but uses KERNEL_ONLY scheduling. Intended to be used to
|
||||
// initialize entities used by the scheduler implementation.
|
||||
template <typename Callable, typename... Args>
|
||||
void LowLevelCallOnce(absl::Nonnull<absl::once_flag*> flag, Callable&& fn,
|
||||
Args&&... args);
|
||||
|
||||
// Disables scheduling while on stack when scheduling mode is non-cooperative.
|
||||
// No effect for cooperative scheduling modes.
|
||||
class SchedulingHelper {
|
||||
public:
|
||||
explicit SchedulingHelper(base_internal::SchedulingMode mode) : mode_(mode) {
|
||||
if (mode_ == base_internal::SCHEDULE_KERNEL_ONLY) {
|
||||
guard_result_ = base_internal::SchedulingGuard::DisableRescheduling();
|
||||
}
|
||||
}
|
||||
|
||||
~SchedulingHelper() {
|
||||
if (mode_ == base_internal::SCHEDULE_KERNEL_ONLY) {
|
||||
base_internal::SchedulingGuard::EnableRescheduling(guard_result_);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
base_internal::SchedulingMode mode_;
|
||||
bool guard_result_ = false;
|
||||
};
|
||||
|
||||
// Bit patterns for call_once state machine values. Internal implementation
|
||||
// detail, not for use by clients.
|
||||
//
|
||||
// The bit patterns are arbitrarily chosen from unlikely values, to aid in
|
||||
// debugging. However, kOnceInit must be 0, so that a zero-initialized
|
||||
// once_flag will be valid for immediate use.
|
||||
enum {
|
||||
kOnceInit = 0,
|
||||
kOnceRunning = 0x65C2937B,
|
||||
kOnceWaiter = 0x05A308D2,
|
||||
// A very small constant is chosen for kOnceDone so that it fit in a single
|
||||
// compare with immediate instruction for most common ISAs. This is verified
|
||||
// for x86, POWER and ARM.
|
||||
kOnceDone = 221, // Random Number
|
||||
};
|
||||
|
||||
template <typename Callable, typename... Args>
|
||||
ABSL_ATTRIBUTE_NOINLINE void CallOnceImpl(
|
||||
absl::Nonnull<std::atomic<uint32_t>*> control,
|
||||
base_internal::SchedulingMode scheduling_mode, Callable&& fn,
|
||||
Args&&... args) {
|
||||
#ifndef NDEBUG
|
||||
{
|
||||
uint32_t old_control = control->load(std::memory_order_relaxed);
|
||||
if (old_control != kOnceInit &&
|
||||
old_control != kOnceRunning &&
|
||||
old_control != kOnceWaiter &&
|
||||
old_control != kOnceDone) {
|
||||
ABSL_RAW_LOG(FATAL, "Unexpected value for control word: 0x%lx",
|
||||
static_cast<unsigned long>(old_control)); // NOLINT
|
||||
}
|
||||
}
|
||||
#endif // NDEBUG
|
||||
static const base_internal::SpinLockWaitTransition trans[] = {
|
||||
{kOnceInit, kOnceRunning, true},
|
||||
{kOnceRunning, kOnceWaiter, false},
|
||||
{kOnceDone, kOnceDone, true}};
|
||||
|
||||
// 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_relaxed) ||
|
||||
base_internal::SpinLockWait(control, ABSL_ARRAYSIZE(trans), trans,
|
||||
scheduling_mode) == kOnceInit) {
|
||||
base_internal::invoke(std::forward<Callable>(fn),
|
||||
std::forward<Args>(args)...);
|
||||
old_control =
|
||||
control->exchange(base_internal::kOnceDone, std::memory_order_release);
|
||||
if (old_control == base_internal::kOnceWaiter) {
|
||||
base_internal::SpinLockWake(control, true);
|
||||
}
|
||||
} // else *control is already kOnceDone
|
||||
}
|
||||
|
||||
inline absl::Nonnull<std::atomic<uint32_t>*> ControlWord(
|
||||
absl::Nonnull<once_flag*> flag) {
|
||||
return &flag->control_;
|
||||
}
|
||||
|
||||
template <typename Callable, typename... Args>
|
||||
void LowLevelCallOnce(absl::Nonnull<absl::once_flag*> flag, Callable&& fn,
|
||||
Args&&... args) {
|
||||
std::atomic<uint32_t>* once = base_internal::ControlWord(flag);
|
||||
uint32_t s = once->load(std::memory_order_acquire);
|
||||
if (ABSL_PREDICT_FALSE(s != base_internal::kOnceDone)) {
|
||||
base_internal::CallOnceImpl(once, base_internal::SCHEDULE_KERNEL_ONLY,
|
||||
std::forward<Callable>(fn),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace base_internal
|
||||
|
||||
template <typename Callable, typename... Args>
|
||||
void call_once(absl::once_flag& flag, Callable&& fn, Args&&... args) {
|
||||
std::atomic<uint32_t>* once = base_internal::ControlWord(&flag);
|
||||
uint32_t s = once->load(std::memory_order_acquire);
|
||||
if (ABSL_PREDICT_FALSE(s != base_internal::kOnceDone)) {
|
||||
base_internal::CallOnceImpl(
|
||||
once, base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL,
|
||||
std::forward<Callable>(fn), std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_BASE_CALL_ONCE_H_
|
||||
@@ -1,180 +0,0 @@
|
||||
//
|
||||
// Copyright 2017 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.
|
||||
//
|
||||
// -----------------------------------------------------------------------------
|
||||
// File: casts.h
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// This header file defines casting templates to fit use cases not covered by
|
||||
// the standard casts provided in the C++ standard. As with all cast operations,
|
||||
// use these with caution and only if alternatives do not exist.
|
||||
|
||||
#ifndef ABSL_BASE_CASTS_H_
|
||||
#define ABSL_BASE_CASTS_H_
|
||||
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#if defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L
|
||||
#include <bit> // For std::bit_cast.
|
||||
#endif // defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L
|
||||
|
||||
#include "absl/base/internal/identity.h"
|
||||
#include "absl/base/macros.h"
|
||||
#include "absl/meta/type_traits.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
|
||||
// implicit_cast()
|
||||
//
|
||||
// Performs an implicit conversion between types following the language
|
||||
// rules for implicit conversion; if an implicit conversion is otherwise
|
||||
// allowed by the language in the given context, this function performs such an
|
||||
// implicit conversion.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// // If the context allows implicit conversion:
|
||||
// From from;
|
||||
// To to = from;
|
||||
//
|
||||
// // Such code can be replaced by:
|
||||
// implicit_cast<To>(from);
|
||||
//
|
||||
// An `implicit_cast()` may also be used to annotate numeric type conversions
|
||||
// that, although safe, may produce compiler warnings (such as `long` to `int`).
|
||||
// Additionally, an `implicit_cast()` is also useful within return statements to
|
||||
// indicate a specific implicit conversion is being undertaken.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// return implicit_cast<double>(size_in_bytes) / capacity_;
|
||||
//
|
||||
// Annotating code with `implicit_cast()` allows you to explicitly select
|
||||
// particular overloads and template instantiations, while providing a safer
|
||||
// cast than `reinterpret_cast()` or `static_cast()`.
|
||||
//
|
||||
// Additionally, an `implicit_cast()` can be used to allow upcasting within a
|
||||
// type hierarchy where incorrect use of `static_cast()` could accidentally
|
||||
// allow downcasting.
|
||||
//
|
||||
// Finally, an `implicit_cast()` can be used to perform implicit conversions
|
||||
// from unrelated types that otherwise couldn't be implicitly cast directly;
|
||||
// C++ will normally only implicitly cast "one step" in such conversions.
|
||||
//
|
||||
// That is, if C is a type which can be implicitly converted to B, with B being
|
||||
// a type that can be implicitly converted to A, an `implicit_cast()` can be
|
||||
// used to convert C to B (which the compiler can then implicitly convert to A
|
||||
// using language rules).
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// // Assume an object C is convertible to B, which is implicitly convertible
|
||||
// // to A
|
||||
// A a = implicit_cast<B>(C);
|
||||
//
|
||||
// Such implicit cast chaining may be useful within template logic.
|
||||
template <typename To>
|
||||
constexpr To implicit_cast(typename absl::internal::type_identity_t<To> to) {
|
||||
return to;
|
||||
}
|
||||
|
||||
// bit_cast()
|
||||
//
|
||||
// Creates a value of the new type `Dest` whose representation is the same as
|
||||
// that of the argument, which is of (deduced) type `Source` (a "bitwise cast";
|
||||
// every bit in the value representation of the result is equal to the
|
||||
// corresponding bit in the object representation of the source). Source and
|
||||
// destination types must be of the same size, and both types must be trivially
|
||||
// copyable.
|
||||
//
|
||||
// As with most casts, use with caution. A `bit_cast()` might be needed when you
|
||||
// need to treat a value as the value of some other type, for example, to access
|
||||
// the individual bits of an object which are not normally accessible through
|
||||
// the object's type, such as for working with the binary representation of a
|
||||
// floating point value:
|
||||
//
|
||||
// float f = 3.14159265358979;
|
||||
// int i = bit_cast<int>(f);
|
||||
// // i = 0x40490fdb
|
||||
//
|
||||
// Reinterpreting and accessing a value directly as a different type (as shown
|
||||
// below) usually results in undefined behavior.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// // WRONG
|
||||
// float f = 3.14159265358979;
|
||||
// int i = reinterpret_cast<int&>(f); // Wrong
|
||||
// int j = *reinterpret_cast<int*>(&f); // Equally wrong
|
||||
// int k = *bit_cast<int*>(&f); // Equally wrong
|
||||
//
|
||||
// Reinterpret-casting results in undefined behavior according to the ISO C++
|
||||
// specification, section [basic.lval]. Roughly, this section says: if an object
|
||||
// in memory has one type, and a program accesses it with a different type, the
|
||||
// result is undefined behavior for most "different type".
|
||||
//
|
||||
// Using bit_cast on a pointer and then dereferencing it is no better than using
|
||||
// reinterpret_cast. You should only use bit_cast on the value itself.
|
||||
//
|
||||
// Such casting results in type punning: holding an object in memory of one type
|
||||
// and reading its bits back using a different type. A `bit_cast()` avoids this
|
||||
// issue by copying the object representation to a new value, which avoids
|
||||
// introducing this undefined behavior (since the original value is never
|
||||
// accessed in the wrong way).
|
||||
//
|
||||
// The requirements of `absl::bit_cast` are more strict than that of
|
||||
// `std::bit_cast` unless compiler support is available. Specifically, without
|
||||
// compiler support, this implementation also requires `Dest` to be
|
||||
// default-constructible. In C++20, `absl::bit_cast` is replaced by
|
||||
// `std::bit_cast`.
|
||||
#if defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L
|
||||
|
||||
using std::bit_cast;
|
||||
|
||||
#else // defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L
|
||||
|
||||
template <
|
||||
typename Dest, typename Source,
|
||||
typename std::enable_if<sizeof(Dest) == sizeof(Source) &&
|
||||
std::is_trivially_copyable<Source>::value &&
|
||||
std::is_trivially_copyable<Dest>::value
|
||||
#if !ABSL_HAVE_BUILTIN(__builtin_bit_cast)
|
||||
&& std::is_default_constructible<Dest>::value
|
||||
#endif // !ABSL_HAVE_BUILTIN(__builtin_bit_cast)
|
||||
,
|
||||
int>::type = 0>
|
||||
#if ABSL_HAVE_BUILTIN(__builtin_bit_cast)
|
||||
inline constexpr Dest bit_cast(const Source& source) {
|
||||
return __builtin_bit_cast(Dest, source);
|
||||
}
|
||||
#else // ABSL_HAVE_BUILTIN(__builtin_bit_cast)
|
||||
inline Dest bit_cast(const Source& source) {
|
||||
Dest dest;
|
||||
memcpy(static_cast<void*>(std::addressof(dest)),
|
||||
static_cast<const void*>(std::addressof(source)), sizeof(dest));
|
||||
return dest;
|
||||
}
|
||||
#endif // ABSL_HAVE_BUILTIN(__builtin_bit_cast)
|
||||
|
||||
#endif // defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L
|
||||
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_BASE_CASTS_H_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,76 +0,0 @@
|
||||
// Copyright 2017 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.
|
||||
//
|
||||
// -----------------------------------------------------------------------------
|
||||
// kConstInit
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// A constructor tag used to mark an object as safe for use as a global
|
||||
// variable, avoiding the usual lifetime issues that can affect globals.
|
||||
|
||||
#ifndef ABSL_BASE_CONST_INIT_H_
|
||||
#define ABSL_BASE_CONST_INIT_H_
|
||||
|
||||
#include "absl/base/config.h"
|
||||
|
||||
// In general, objects with static storage duration (such as global variables)
|
||||
// can trigger tricky object lifetime situations. Attempting to access them
|
||||
// from the constructors or destructors of other global objects can result in
|
||||
// undefined behavior, unless their constructors and destructors are designed
|
||||
// with this issue in mind.
|
||||
//
|
||||
// The normal way to deal with this issue in C++11 is to use constant
|
||||
// initialization and trivial destructors.
|
||||
//
|
||||
// Constant initialization is guaranteed to occur before any other code
|
||||
// executes. Constructors that are declared 'constexpr' are eligible for
|
||||
// constant initialization. You can annotate a variable declaration with the
|
||||
// ABSL_CONST_INIT macro to express this intent. For compilers that support
|
||||
// it, this annotation will cause a compilation error for declarations that
|
||||
// aren't subject to constant initialization (perhaps because a runtime value
|
||||
// was passed as a constructor argument).
|
||||
//
|
||||
// On program shutdown, lifetime issues can be avoided on global objects by
|
||||
// ensuring that they contain trivial destructors. A class has a trivial
|
||||
// destructor unless it has a user-defined destructor, a virtual method or base
|
||||
// class, or a data member or base class with a non-trivial destructor of its
|
||||
// own. Objects with static storage duration and a trivial destructor are not
|
||||
// cleaned up on program shutdown, and are thus safe to access from other code
|
||||
// running during shutdown.
|
||||
//
|
||||
// For a few core Abseil classes, we make a best effort to allow for safe global
|
||||
// instances, even though these classes have non-trivial destructors. These
|
||||
// objects can be created with the absl::kConstInit tag. For example:
|
||||
// ABSL_CONST_INIT absl::Mutex global_mutex(absl::kConstInit);
|
||||
//
|
||||
// The line above declares a global variable of type absl::Mutex which can be
|
||||
// accessed at any point during startup or shutdown. global_mutex's destructor
|
||||
// will still run, but will not invalidate the object. Note that C++ specifies
|
||||
// that accessing an object after its destructor has run results in undefined
|
||||
// behavior, but this pattern works on the toolchains we support.
|
||||
//
|
||||
// The absl::kConstInit tag should only be used to define objects with static
|
||||
// or thread_local storage duration.
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
|
||||
enum ConstInitType {
|
||||
kConstInit,
|
||||
};
|
||||
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_BASE_CONST_INIT_H_
|
||||
@@ -1,496 +0,0 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
// This file defines dynamic annotations for use with dynamic analysis tool
|
||||
// such as valgrind, PIN, etc.
|
||||
//
|
||||
// Dynamic annotation is a source code annotation that affects the generated
|
||||
// code (that is, the annotation is not a comment). Each such annotation is
|
||||
// attached to a particular instruction and/or to a particular object (address)
|
||||
// in the program.
|
||||
//
|
||||
// The annotations that should be used by users are macros in all upper-case
|
||||
// (e.g., ABSL_ANNOTATE_THREAD_NAME).
|
||||
//
|
||||
// Actual implementation of these macros may differ depending on the dynamic
|
||||
// analysis tool being used.
|
||||
//
|
||||
// This file supports the following configurations:
|
||||
// - Dynamic Annotations enabled (with static thread-safety warnings disabled).
|
||||
// In this case, macros expand to functions implemented by Thread Sanitizer,
|
||||
// when building with TSan. When not provided an external implementation,
|
||||
// dynamic_annotations.cc provides no-op implementations.
|
||||
//
|
||||
// - Static Clang thread-safety warnings enabled.
|
||||
// When building with a Clang compiler that supports thread-safety warnings,
|
||||
// a subset of annotations can be statically-checked at compile-time. We
|
||||
// expand these macros to static-inline functions that can be analyzed for
|
||||
// thread-safety, but afterwards elided when building the final binary.
|
||||
//
|
||||
// - All annotations are disabled.
|
||||
// If neither Dynamic Annotations nor Clang thread-safety warnings are
|
||||
// enabled, then all annotation-macros expand to empty.
|
||||
|
||||
#ifndef ABSL_BASE_DYNAMIC_ANNOTATIONS_H_
|
||||
#define ABSL_BASE_DYNAMIC_ANNOTATIONS_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/base/config.h"
|
||||
#ifdef __cplusplus
|
||||
#include "absl/base/macros.h"
|
||||
#endif
|
||||
|
||||
#ifdef ABSL_HAVE_HWADDRESS_SANITIZER
|
||||
#include <sanitizer/hwasan_interface.h>
|
||||
#endif
|
||||
|
||||
// TODO(rogeeff): Remove after the backward compatibility period.
|
||||
#include "absl/base/internal/dynamic_annotations.h" // IWYU pragma: export
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Decide which features are enabled.
|
||||
|
||||
#ifdef ABSL_HAVE_THREAD_SANITIZER
|
||||
|
||||
#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 1
|
||||
#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 1
|
||||
#define ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED 1
|
||||
#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 0
|
||||
#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED 1
|
||||
|
||||
#else
|
||||
|
||||
#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 0
|
||||
#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 0
|
||||
#define ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED 0
|
||||
|
||||
// Clang provides limited support for static thread-safety analysis through a
|
||||
// feature called Annotalysis. We configure macro-definitions according to
|
||||
// whether Annotalysis support is available. When running in opt-mode, GCC
|
||||
// will issue a warning, if these attributes are compiled. Only include them
|
||||
// when compiling using Clang.
|
||||
|
||||
#if defined(__clang__)
|
||||
#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 1
|
||||
#if !defined(SWIG)
|
||||
#define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 1
|
||||
#endif
|
||||
#else
|
||||
#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 0
|
||||
#endif
|
||||
|
||||
// Read/write annotations are enabled in Annotalysis mode; disabled otherwise.
|
||||
#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED \
|
||||
ABSL_INTERNAL_ANNOTALYSIS_ENABLED
|
||||
|
||||
#endif // ABSL_HAVE_THREAD_SANITIZER
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define ABSL_INTERNAL_BEGIN_EXTERN_C extern "C" {
|
||||
#define ABSL_INTERNAL_END_EXTERN_C } // extern "C"
|
||||
#define ABSL_INTERNAL_GLOBAL_SCOPED(F) ::F
|
||||
#define ABSL_INTERNAL_STATIC_INLINE inline
|
||||
#else
|
||||
#define ABSL_INTERNAL_BEGIN_EXTERN_C // empty
|
||||
#define ABSL_INTERNAL_END_EXTERN_C // empty
|
||||
#define ABSL_INTERNAL_GLOBAL_SCOPED(F) F
|
||||
#define ABSL_INTERNAL_STATIC_INLINE static inline
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Define race annotations.
|
||||
|
||||
#if ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 1
|
||||
// Some of the symbols used in this section (e.g. AnnotateBenignRaceSized) are
|
||||
// defined by the compiler-based sanitizer implementation, not by the Abseil
|
||||
// library. Therefore they do not use ABSL_INTERNAL_C_SYMBOL.
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Annotations that suppress errors. It is usually better to express the
|
||||
// program's synchronization using the other annotations, but these can be used
|
||||
// when all else fails.
|
||||
|
||||
// Report that we may have a benign race at `pointer`, with size
|
||||
// "sizeof(*(pointer))". `pointer` must be a non-void* pointer. Insert at the
|
||||
// point where `pointer` has been allocated, preferably close to the point
|
||||
// where the race happens. See also ABSL_ANNOTATE_BENIGN_RACE_STATIC.
|
||||
#define ABSL_ANNOTATE_BENIGN_RACE(pointer, description) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateBenignRaceSized) \
|
||||
(__FILE__, __LINE__, pointer, sizeof(*(pointer)), description)
|
||||
|
||||
// Same as ABSL_ANNOTATE_BENIGN_RACE(`address`, `description`), but applies to
|
||||
// the memory range [`address`, `address`+`size`).
|
||||
#define ABSL_ANNOTATE_BENIGN_RACE_SIZED(address, size, description) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateBenignRaceSized) \
|
||||
(__FILE__, __LINE__, address, size, description)
|
||||
|
||||
// Enable (`enable`!=0) or disable (`enable`==0) race detection for all threads.
|
||||
// This annotation could be useful if you want to skip expensive race analysis
|
||||
// during some period of program execution, e.g. during initialization.
|
||||
#define ABSL_ANNOTATE_ENABLE_RACE_DETECTION(enable) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateEnableRaceDetection) \
|
||||
(__FILE__, __LINE__, enable)
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Annotations useful for debugging.
|
||||
|
||||
// Report the current thread `name` to a race detector.
|
||||
#define ABSL_ANNOTATE_THREAD_NAME(name) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateThreadName)(__FILE__, __LINE__, name)
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Annotations useful when implementing locks. They are not normally needed by
|
||||
// modules that merely use locks. The `lock` argument is a pointer to the lock
|
||||
// object.
|
||||
|
||||
// Report that a lock has been created at address `lock`.
|
||||
#define ABSL_ANNOTATE_RWLOCK_CREATE(lock) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreate)(__FILE__, __LINE__, lock)
|
||||
|
||||
// Report that a linker initialized lock has been created at address `lock`.
|
||||
#ifdef ABSL_HAVE_THREAD_SANITIZER
|
||||
#define ABSL_ANNOTATE_RWLOCK_CREATE_STATIC(lock) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreateStatic) \
|
||||
(__FILE__, __LINE__, lock)
|
||||
#else
|
||||
#define ABSL_ANNOTATE_RWLOCK_CREATE_STATIC(lock) \
|
||||
ABSL_ANNOTATE_RWLOCK_CREATE(lock)
|
||||
#endif
|
||||
|
||||
// Report that the lock at address `lock` is about to be destroyed.
|
||||
#define ABSL_ANNOTATE_RWLOCK_DESTROY(lock) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockDestroy)(__FILE__, __LINE__, lock)
|
||||
|
||||
// Report that the lock at address `lock` has been acquired.
|
||||
// `is_w`=1 for writer lock, `is_w`=0 for reader lock.
|
||||
#define ABSL_ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockAcquired) \
|
||||
(__FILE__, __LINE__, lock, is_w)
|
||||
|
||||
// Report that the lock at address `lock` is about to be released.
|
||||
// `is_w`=1 for writer lock, `is_w`=0 for reader lock.
|
||||
#define ABSL_ANNOTATE_RWLOCK_RELEASED(lock, is_w) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockReleased) \
|
||||
(__FILE__, __LINE__, lock, is_w)
|
||||
|
||||
// Apply ABSL_ANNOTATE_BENIGN_RACE_SIZED to a static variable `static_var`.
|
||||
#define ABSL_ANNOTATE_BENIGN_RACE_STATIC(static_var, description) \
|
||||
namespace { \
|
||||
class static_var##_annotator { \
|
||||
public: \
|
||||
static_var##_annotator() { \
|
||||
ABSL_ANNOTATE_BENIGN_RACE_SIZED(&static_var, sizeof(static_var), \
|
||||
#static_var ": " description); \
|
||||
} \
|
||||
}; \
|
||||
static static_var##_annotator the##static_var##_annotator; \
|
||||
} // namespace
|
||||
|
||||
// Function prototypes of annotations provided by the compiler-based sanitizer
|
||||
// implementation.
|
||||
ABSL_INTERNAL_BEGIN_EXTERN_C
|
||||
void AnnotateRWLockCreate(const char* file, int line,
|
||||
const volatile void* lock);
|
||||
void AnnotateRWLockCreateStatic(const char* file, int line,
|
||||
const volatile void* lock);
|
||||
void AnnotateRWLockDestroy(const char* file, int line,
|
||||
const volatile void* lock);
|
||||
void AnnotateRWLockAcquired(const char* file, int line,
|
||||
const volatile void* lock, long is_w); // NOLINT
|
||||
void AnnotateRWLockReleased(const char* file, int line,
|
||||
const volatile void* lock, long is_w); // NOLINT
|
||||
void AnnotateBenignRace(const char* file, int line,
|
||||
const volatile void* address, const char* description);
|
||||
void AnnotateBenignRaceSized(const char* file, int line,
|
||||
const volatile void* address, size_t size,
|
||||
const char* description);
|
||||
void AnnotateThreadName(const char* file, int line, const char* name);
|
||||
void AnnotateEnableRaceDetection(const char* file, int line, int enable);
|
||||
ABSL_INTERNAL_END_EXTERN_C
|
||||
|
||||
#else // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 0
|
||||
|
||||
#define ABSL_ANNOTATE_RWLOCK_CREATE(lock) // empty
|
||||
#define ABSL_ANNOTATE_RWLOCK_CREATE_STATIC(lock) // empty
|
||||
#define ABSL_ANNOTATE_RWLOCK_DESTROY(lock) // empty
|
||||
#define ABSL_ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) // empty
|
||||
#define ABSL_ANNOTATE_RWLOCK_RELEASED(lock, is_w) // empty
|
||||
#define ABSL_ANNOTATE_BENIGN_RACE(address, description) // empty
|
||||
#define ABSL_ANNOTATE_BENIGN_RACE_SIZED(address, size, description) // empty
|
||||
#define ABSL_ANNOTATE_THREAD_NAME(name) // empty
|
||||
#define ABSL_ANNOTATE_ENABLE_RACE_DETECTION(enable) // empty
|
||||
#define ABSL_ANNOTATE_BENIGN_RACE_STATIC(static_var, description) // empty
|
||||
|
||||
#endif // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Define memory annotations.
|
||||
|
||||
#ifdef ABSL_HAVE_MEMORY_SANITIZER
|
||||
|
||||
#include <sanitizer/msan_interface.h>
|
||||
|
||||
#define ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
|
||||
__msan_unpoison(address, size)
|
||||
|
||||
#define ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
|
||||
__msan_allocated_memory(address, size)
|
||||
|
||||
#else // !defined(ABSL_HAVE_MEMORY_SANITIZER)
|
||||
|
||||
// TODO(rogeeff): remove this branch
|
||||
#ifdef ABSL_HAVE_THREAD_SANITIZER
|
||||
#define ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
|
||||
do { \
|
||||
(void)(address); \
|
||||
(void)(size); \
|
||||
} while (0)
|
||||
#define ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
|
||||
do { \
|
||||
(void)(address); \
|
||||
(void)(size); \
|
||||
} while (0)
|
||||
#else
|
||||
|
||||
#define ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(address, size) // empty
|
||||
#define ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) // empty
|
||||
|
||||
#endif
|
||||
|
||||
#endif // ABSL_HAVE_MEMORY_SANITIZER
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Define IGNORE_READS_BEGIN/_END attributes.
|
||||
|
||||
#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 // !defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
|
||||
|
||||
#define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE // empty
|
||||
#define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE // empty
|
||||
|
||||
#endif // defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Define IGNORE_READS_BEGIN/_END annotations.
|
||||
|
||||
#if ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED == 1
|
||||
// Some of the symbols used in this section (e.g. AnnotateIgnoreReadsBegin) are
|
||||
// defined by the compiler-based implementation, not by the Abseil
|
||||
// library. Therefore they do not use ABSL_INTERNAL_C_SYMBOL.
|
||||
|
||||
// Request the analysis tool to ignore all reads in the current thread until
|
||||
// ABSL_ANNOTATE_IGNORE_READS_END is called. Useful to ignore intentional racey
|
||||
// reads, while still checking other reads and all writes.
|
||||
// See also ABSL_ANNOTATE_UNPROTECTED_READ.
|
||||
#define ABSL_ANNOTATE_IGNORE_READS_BEGIN() \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsBegin) \
|
||||
(__FILE__, __LINE__)
|
||||
|
||||
// Stop ignoring reads.
|
||||
#define ABSL_ANNOTATE_IGNORE_READS_END() \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsEnd) \
|
||||
(__FILE__, __LINE__)
|
||||
|
||||
// Function prototypes of annotations provided by the compiler-based sanitizer
|
||||
// implementation.
|
||||
ABSL_INTERNAL_BEGIN_EXTERN_C
|
||||
void AnnotateIgnoreReadsBegin(const char* file, int line)
|
||||
ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE;
|
||||
void AnnotateIgnoreReadsEnd(const char* file,
|
||||
int line) ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE;
|
||||
ABSL_INTERNAL_END_EXTERN_C
|
||||
|
||||
#elif defined(ABSL_INTERNAL_ANNOTALYSIS_ENABLED)
|
||||
|
||||
// When Annotalysis is enabled without Dynamic Annotations, the use of
|
||||
// static-inline functions allows the annotations to be read at compile-time,
|
||||
// while still letting the compiler elide the functions from the final build.
|
||||
//
|
||||
// TODO(delesley) -- The exclusive lock here ignores writes as well, but
|
||||
// allows IGNORE_READS_AND_WRITES to work properly.
|
||||
|
||||
#define ABSL_ANNOTATE_IGNORE_READS_BEGIN() \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED( \
|
||||
ABSL_INTERNAL_C_SYMBOL(AbslInternalAnnotateIgnoreReadsBegin)) \
|
||||
()
|
||||
|
||||
#define ABSL_ANNOTATE_IGNORE_READS_END() \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED( \
|
||||
ABSL_INTERNAL_C_SYMBOL(AbslInternalAnnotateIgnoreReadsEnd)) \
|
||||
()
|
||||
|
||||
ABSL_INTERNAL_STATIC_INLINE void ABSL_INTERNAL_C_SYMBOL(
|
||||
AbslInternalAnnotateIgnoreReadsBegin)()
|
||||
ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE {}
|
||||
|
||||
ABSL_INTERNAL_STATIC_INLINE void ABSL_INTERNAL_C_SYMBOL(
|
||||
AbslInternalAnnotateIgnoreReadsEnd)()
|
||||
ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE {}
|
||||
|
||||
#else
|
||||
|
||||
#define ABSL_ANNOTATE_IGNORE_READS_BEGIN() // empty
|
||||
#define ABSL_ANNOTATE_IGNORE_READS_END() // empty
|
||||
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Define IGNORE_WRITES_BEGIN/_END annotations.
|
||||
|
||||
#if ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED == 1
|
||||
|
||||
// Similar to ABSL_ANNOTATE_IGNORE_READS_BEGIN, but ignore writes instead.
|
||||
#define ABSL_ANNOTATE_IGNORE_WRITES_BEGIN() \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreWritesBegin)(__FILE__, __LINE__)
|
||||
|
||||
// Stop ignoring writes.
|
||||
#define ABSL_ANNOTATE_IGNORE_WRITES_END() \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreWritesEnd)(__FILE__, __LINE__)
|
||||
|
||||
// Function prototypes of annotations provided by the compiler-based sanitizer
|
||||
// implementation.
|
||||
ABSL_INTERNAL_BEGIN_EXTERN_C
|
||||
void AnnotateIgnoreWritesBegin(const char* file, int line);
|
||||
void AnnotateIgnoreWritesEnd(const char* file, int line);
|
||||
ABSL_INTERNAL_END_EXTERN_C
|
||||
|
||||
#else
|
||||
|
||||
#define ABSL_ANNOTATE_IGNORE_WRITES_BEGIN() // empty
|
||||
#define ABSL_ANNOTATE_IGNORE_WRITES_END() // empty
|
||||
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Define the ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_* annotations using the more
|
||||
// primitive annotations defined above.
|
||||
//
|
||||
// Instead of doing
|
||||
// ABSL_ANNOTATE_IGNORE_READS_BEGIN();
|
||||
// ... = x;
|
||||
// ABSL_ANNOTATE_IGNORE_READS_END();
|
||||
// one can use
|
||||
// ... = ABSL_ANNOTATE_UNPROTECTED_READ(x);
|
||||
|
||||
#if defined(ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED)
|
||||
|
||||
// Start ignoring all memory accesses (both reads and writes).
|
||||
#define ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
|
||||
do { \
|
||||
ABSL_ANNOTATE_IGNORE_READS_BEGIN(); \
|
||||
ABSL_ANNOTATE_IGNORE_WRITES_BEGIN(); \
|
||||
} while (0)
|
||||
|
||||
// Stop ignoring both reads and writes.
|
||||
#define ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END() \
|
||||
do { \
|
||||
ABSL_ANNOTATE_IGNORE_WRITES_END(); \
|
||||
ABSL_ANNOTATE_IGNORE_READS_END(); \
|
||||
} while (0)
|
||||
|
||||
#ifdef __cplusplus
|
||||
// ABSL_ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads.
|
||||
#define ABSL_ANNOTATE_UNPROTECTED_READ(x) \
|
||||
absl::base_internal::AnnotateUnprotectedRead(x)
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
|
||||
template <typename T>
|
||||
inline T AnnotateUnprotectedRead(const volatile T& x) { // NOLINT
|
||||
ABSL_ANNOTATE_IGNORE_READS_BEGIN();
|
||||
T res = x;
|
||||
ABSL_ANNOTATE_IGNORE_READS_END();
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() // empty
|
||||
#define ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END() // empty
|
||||
#define ABSL_ANNOTATE_UNPROTECTED_READ(x) (x)
|
||||
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Address sanitizer annotations
|
||||
|
||||
#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.
|
||||
#include <sanitizer/common_interface_defs.h>
|
||||
|
||||
#define ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid) \
|
||||
__sanitizer_annotate_contiguous_container(beg, end, old_mid, new_mid)
|
||||
#define ABSL_ADDRESS_SANITIZER_REDZONE(name) \
|
||||
struct { \
|
||||
alignas(8) char x[8]; \
|
||||
} name
|
||||
|
||||
#else
|
||||
|
||||
#define ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid) // empty
|
||||
#define ABSL_ADDRESS_SANITIZER_REDZONE(name) static_assert(true, "")
|
||||
|
||||
#endif // ABSL_HAVE_ADDRESS_SANITIZER
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// HWAddress sanitizer annotations
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace absl {
|
||||
#ifdef ABSL_HAVE_HWADDRESS_SANITIZER
|
||||
// Under HWASAN changes the tag of the pointer.
|
||||
template <typename T>
|
||||
T* HwasanTagPointer(T* ptr, uintptr_t tag) {
|
||||
return reinterpret_cast<T*>(__hwasan_tag_pointer(ptr, tag));
|
||||
}
|
||||
#else
|
||||
template <typename T>
|
||||
T* HwasanTagPointer(T* ptr, uintptr_t) {
|
||||
return ptr;
|
||||
}
|
||||
#endif
|
||||
} // namespace absl
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Undefine the macros intended only for this file.
|
||||
|
||||
#undef ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED
|
||||
#undef ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED
|
||||
#undef ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED
|
||||
#undef ABSL_INTERNAL_ANNOTALYSIS_ENABLED
|
||||
#undef ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED
|
||||
#undef ABSL_INTERNAL_BEGIN_EXTERN_C
|
||||
#undef ABSL_INTERNAL_END_EXTERN_C
|
||||
#undef ABSL_INTERNAL_STATIC_INLINE
|
||||
|
||||
#endif // ABSL_BASE_DYNAMIC_ANNOTATIONS_H_
|
||||
@@ -1,200 +0,0 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
#ifndef ABSL_BASE_INTERNAL_ATOMIC_HOOK_H_
|
||||
#define ABSL_BASE_INTERNAL_ATOMIC_HOOK_H_
|
||||
|
||||
#include <atomic>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/base/config.h"
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
#define ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT 0
|
||||
#else
|
||||
#define ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT 1
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define ABSL_HAVE_WORKING_ATOMIC_POINTER 0
|
||||
#else
|
||||
#define ABSL_HAVE_WORKING_ATOMIC_POINTER 1
|
||||
#endif
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
|
||||
template <typename T>
|
||||
class AtomicHook;
|
||||
|
||||
// To workaround AtomicHook not being constant-initializable on some platforms,
|
||||
// prefer to annotate instances with `ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES`
|
||||
// instead of `ABSL_CONST_INIT`.
|
||||
#if ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT
|
||||
#define ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_CONST_INIT
|
||||
#else
|
||||
#define ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
|
||||
#endif
|
||||
|
||||
// `AtomicHook` is a helper class, templatized on a raw function pointer type,
|
||||
// for implementing Abseil customization hooks. It is a callable object that
|
||||
// dispatches to the registered hook. Objects of type `AtomicHook` must have
|
||||
// static or thread storage duration.
|
||||
//
|
||||
// A default constructed object performs a no-op (and returns a default
|
||||
// constructed object) if no hook has been registered.
|
||||
//
|
||||
// Hooks can be pre-registered via constant initialization, for example:
|
||||
//
|
||||
// ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static AtomicHook<void(*)()>
|
||||
// my_hook(DefaultAction);
|
||||
//
|
||||
// and then changed at runtime via a call to `Store()`.
|
||||
//
|
||||
// Reads and writes guarantee memory_order_acquire/memory_order_release
|
||||
// semantics.
|
||||
template <typename ReturnType, typename... Args>
|
||||
class AtomicHook<ReturnType (*)(Args...)> {
|
||||
public:
|
||||
using FnPtr = ReturnType (*)(Args...);
|
||||
|
||||
// Constructs an object that by default performs a no-op (and
|
||||
// returns a default constructed object) when no hook as been registered.
|
||||
constexpr AtomicHook() : AtomicHook(DummyFunction) {}
|
||||
|
||||
// Constructs an object that by default dispatches to/returns the
|
||||
// pre-registered default_fn when no hook has been registered at runtime.
|
||||
#if ABSL_HAVE_WORKING_ATOMIC_POINTER && ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT
|
||||
explicit constexpr AtomicHook(FnPtr default_fn)
|
||||
: hook_(default_fn), default_fn_(default_fn) {}
|
||||
#elif ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT
|
||||
explicit constexpr AtomicHook(FnPtr default_fn)
|
||||
: hook_(kUninitialized), default_fn_(default_fn) {}
|
||||
#else
|
||||
// As of January 2020, on all known versions of MSVC this constructor runs in
|
||||
// the global constructor sequence. If `Store()` is called by a dynamic
|
||||
// initializer, we want to preserve the value, even if this constructor runs
|
||||
// after the call to `Store()`. If not, `hook_` will be
|
||||
// zero-initialized by the linker and we have no need to set it.
|
||||
// https://developercommunity.visualstudio.com/content/problem/336946/class-with-constexpr-constructor-not-using-static.html
|
||||
explicit constexpr AtomicHook(FnPtr default_fn)
|
||||
: /* hook_(deliberately omitted), */ default_fn_(default_fn) {
|
||||
static_assert(kUninitialized == 0, "here we rely on zero-initialization");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Stores the provided function pointer as the value for this hook.
|
||||
//
|
||||
// This is intended to be called once. Multiple calls are legal only if the
|
||||
// same function pointer is provided for each call. The store is implemented
|
||||
// as a memory_order_release operation, and read accesses are implemented as
|
||||
// memory_order_acquire.
|
||||
void Store(FnPtr fn) {
|
||||
bool success = DoStore(fn);
|
||||
static_cast<void>(success);
|
||||
assert(success);
|
||||
}
|
||||
|
||||
// Invokes the registered callback. If no callback has yet been registered, a
|
||||
// default-constructed object of the appropriate type is returned instead.
|
||||
template <typename... CallArgs>
|
||||
ReturnType operator()(CallArgs&&... args) const {
|
||||
return DoLoad()(std::forward<CallArgs>(args)...);
|
||||
}
|
||||
|
||||
// Returns the registered callback, or nullptr if none has been registered.
|
||||
// Useful if client code needs to conditionalize behavior based on whether a
|
||||
// callback was registered.
|
||||
//
|
||||
// Note that atomic_hook.Load()() and atomic_hook() have different semantics:
|
||||
// operator()() will perform a no-op if no callback was registered, while
|
||||
// Load()() will dereference a null function pointer. Prefer operator()() to
|
||||
// Load()() unless you must conditionalize behavior on whether a hook was
|
||||
// registered.
|
||||
FnPtr Load() const {
|
||||
FnPtr ptr = DoLoad();
|
||||
return (ptr == DummyFunction) ? nullptr : ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
static ReturnType DummyFunction(Args...) {
|
||||
return ReturnType();
|
||||
}
|
||||
|
||||
// Current versions of MSVC (as of September 2017) have a broken
|
||||
// implementation of std::atomic<T*>: Its constructor attempts to do the
|
||||
// equivalent of a reinterpret_cast in a constexpr context, which is not
|
||||
// allowed.
|
||||
//
|
||||
// This causes an issue when building with LLVM under Windows. To avoid this,
|
||||
// we use a less-efficient, intptr_t-based implementation on Windows.
|
||||
#if ABSL_HAVE_WORKING_ATOMIC_POINTER
|
||||
// Return the stored value, or DummyFunction if no value has been stored.
|
||||
FnPtr DoLoad() const { return hook_.load(std::memory_order_acquire); }
|
||||
|
||||
// Store the given value. Returns false if a different value was already
|
||||
// stored to this object.
|
||||
bool DoStore(FnPtr fn) {
|
||||
assert(fn);
|
||||
FnPtr expected = default_fn_;
|
||||
const bool store_succeeded = hook_.compare_exchange_strong(
|
||||
expected, fn, std::memory_order_acq_rel, std::memory_order_acquire);
|
||||
const bool same_value_already_stored = (expected == fn);
|
||||
return store_succeeded || same_value_already_stored;
|
||||
}
|
||||
|
||||
std::atomic<FnPtr> hook_;
|
||||
#else // !ABSL_HAVE_WORKING_ATOMIC_POINTER
|
||||
// Use a sentinel value unlikely to be the address of an actual function.
|
||||
static constexpr intptr_t kUninitialized = 0;
|
||||
|
||||
static_assert(sizeof(intptr_t) >= sizeof(FnPtr),
|
||||
"intptr_t can't contain a function pointer");
|
||||
|
||||
FnPtr DoLoad() const {
|
||||
const intptr_t value = hook_.load(std::memory_order_acquire);
|
||||
if (value == kUninitialized) {
|
||||
return default_fn_;
|
||||
}
|
||||
return reinterpret_cast<FnPtr>(value);
|
||||
}
|
||||
|
||||
bool DoStore(FnPtr fn) {
|
||||
assert(fn);
|
||||
const auto value = reinterpret_cast<intptr_t>(fn);
|
||||
intptr_t expected = kUninitialized;
|
||||
const bool store_succeeded = hook_.compare_exchange_strong(
|
||||
expected, value, std::memory_order_acq_rel, std::memory_order_acquire);
|
||||
const bool same_value_already_stored = (expected == value);
|
||||
return store_succeeded || same_value_already_stored;
|
||||
}
|
||||
|
||||
std::atomic<intptr_t> hook_;
|
||||
#endif
|
||||
|
||||
const FnPtr default_fn_;
|
||||
};
|
||||
|
||||
#undef ABSL_HAVE_WORKING_ATOMIC_POINTER
|
||||
#undef ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_BASE_INTERNAL_ATOMIC_HOOK_H_
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
#ifndef ABSL_BASE_INTERNAL_ATOMIC_HOOK_TEST_HELPER_H_
|
||||
#define ABSL_BASE_INTERNAL_ATOMIC_HOOK_TEST_HELPER_H_
|
||||
|
||||
#include "absl/base/internal/atomic_hook.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace atomic_hook_internal {
|
||||
|
||||
using VoidF = void (*)();
|
||||
extern absl::base_internal::AtomicHook<VoidF> func;
|
||||
extern int default_func_calls;
|
||||
void DefaultFunc();
|
||||
void RegisterFunc(VoidF func);
|
||||
|
||||
} // namespace atomic_hook_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_BASE_INTERNAL_ATOMIC_HOOK_TEST_HELPER_H_
|
||||
@@ -1,144 +0,0 @@
|
||||
//
|
||||
// Copyright 2017 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.
|
||||
//
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// File: cycleclock.h
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// This header file defines a `CycleClock`, which yields the value and frequency
|
||||
// of a cycle counter that increments at a rate that is approximately constant.
|
||||
//
|
||||
// NOTE:
|
||||
//
|
||||
// The cycle counter frequency is not necessarily related to the core clock
|
||||
// frequency and should not be treated as such. That is, `CycleClock` cycles are
|
||||
// not necessarily "CPU cycles" and code should not rely on that behavior, even
|
||||
// if experimentally observed.
|
||||
//
|
||||
// An arbitrary offset may have been added to the counter at power on.
|
||||
//
|
||||
// On some platforms, the rate and offset of the counter may differ
|
||||
// slightly when read from different CPUs of a multiprocessor. Usually,
|
||||
// we try to ensure that the operating system adjusts values periodically
|
||||
// so that values agree approximately. If you need stronger guarantees,
|
||||
// consider using alternate interfaces.
|
||||
//
|
||||
// The CPU is not required to maintain the ordering of a cycle counter read
|
||||
// with respect to surrounding instructions.
|
||||
|
||||
#ifndef ABSL_BASE_INTERNAL_CYCLECLOCK_H_
|
||||
#define ABSL_BASE_INTERNAL_CYCLECLOCK_H_
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/internal/cycleclock_config.h"
|
||||
#include "absl/base/internal/unscaledcycleclock.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
|
||||
using CycleClockSourceFunc = int64_t (*)();
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// CycleClock
|
||||
// -----------------------------------------------------------------------------
|
||||
class CycleClock {
|
||||
public:
|
||||
// CycleClock::Now()
|
||||
//
|
||||
// Returns the value of a cycle counter that counts at a rate that is
|
||||
// approximately constant.
|
||||
static int64_t Now();
|
||||
|
||||
// CycleClock::Frequency()
|
||||
//
|
||||
// Returns the amount by which `CycleClock::Now()` increases per second. Note
|
||||
// that this value may not necessarily match the core CPU clock frequency.
|
||||
static double Frequency();
|
||||
|
||||
private:
|
||||
#if ABSL_USE_UNSCALED_CYCLECLOCK
|
||||
static CycleClockSourceFunc LoadCycleClockSource();
|
||||
|
||||
static constexpr int32_t kShift = kCycleClockShift;
|
||||
static constexpr double kFrequencyScale = kCycleClockFrequencyScale;
|
||||
|
||||
ABSL_CONST_INIT static std::atomic<CycleClockSourceFunc> cycle_clock_source_;
|
||||
#endif // ABSL_USE_UNSCALED_CYCLECLOC
|
||||
|
||||
CycleClock() = delete; // no instances
|
||||
CycleClock(const CycleClock&) = delete;
|
||||
CycleClock& operator=(const CycleClock&) = delete;
|
||||
|
||||
friend class CycleClockSource;
|
||||
};
|
||||
|
||||
class CycleClockSource {
|
||||
private:
|
||||
// CycleClockSource::Register()
|
||||
//
|
||||
// Register a function that provides an alternate source for the unscaled CPU
|
||||
// cycle count value. The source function must be async signal safe, must not
|
||||
// call CycleClock::Now(), and must have a frequency that matches that of the
|
||||
// unscaled clock used by CycleClock. A nullptr value resets CycleClock to use
|
||||
// the default source.
|
||||
static void Register(CycleClockSourceFunc source);
|
||||
};
|
||||
|
||||
#if ABSL_USE_UNSCALED_CYCLECLOCK
|
||||
|
||||
inline CycleClockSourceFunc CycleClock::LoadCycleClockSource() {
|
||||
#if !defined(__x86_64__)
|
||||
// Optimize for the common case (no callback) by first doing a relaxed load;
|
||||
// this is significantly faster on non-x86 platforms.
|
||||
if (cycle_clock_source_.load(std::memory_order_relaxed) == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
#endif // !defined(__x86_64__)
|
||||
|
||||
// This corresponds to the store(std::memory_order_release) in
|
||||
// CycleClockSource::Register, and makes sure that any updates made prior to
|
||||
// registering the callback are visible to this thread before the callback
|
||||
// is invoked.
|
||||
return cycle_clock_source_.load(std::memory_order_acquire);
|
||||
}
|
||||
|
||||
// Accessing globals in inlined code in Window DLLs is problematic.
|
||||
#ifndef _WIN32
|
||||
inline int64_t CycleClock::Now() {
|
||||
auto fn = LoadCycleClockSource();
|
||||
if (fn == nullptr) {
|
||||
return base_internal::UnscaledCycleClock::Now() >> kShift;
|
||||
}
|
||||
return fn() >> kShift;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline double CycleClock::Frequency() {
|
||||
return kFrequencyScale * base_internal::UnscaledCycleClock::Frequency();
|
||||
}
|
||||
|
||||
#endif // ABSL_USE_UNSCALED_CYCLECLOCK
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_BASE_INTERNAL_CYCLECLOCK_H_
|
||||
@@ -1,55 +0,0 @@
|
||||
// Copyright 2022 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.
|
||||
|
||||
#ifndef ABSL_BASE_INTERNAL_CYCLECLOCK_CONFIG_H_
|
||||
#define ABSL_BASE_INTERNAL_CYCLECLOCK_CONFIG_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/internal/inline_variable.h"
|
||||
#include "absl/base/internal/unscaledcycleclock_config.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
|
||||
#if ABSL_USE_UNSCALED_CYCLECLOCK
|
||||
#ifdef NDEBUG
|
||||
#ifdef ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY
|
||||
// Not debug mode and the UnscaledCycleClock frequency is the CPU
|
||||
// frequency. Scale the CycleClock to prevent overflow if someone
|
||||
// tries to represent the time as cycles since the Unix epoch.
|
||||
ABSL_INTERNAL_INLINE_CONSTEXPR(int32_t, kCycleClockShift, 1);
|
||||
#else
|
||||
// Not debug mode and the UnscaledCycleClock isn't operating at the
|
||||
// raw CPU frequency. There is no need to do any scaling, so don't
|
||||
// needlessly sacrifice precision.
|
||||
ABSL_INTERNAL_INLINE_CONSTEXPR(int32_t, kCycleClockShift, 0);
|
||||
#endif
|
||||
#else // NDEBUG
|
||||
// In debug mode use a different shift to discourage depending on a
|
||||
// particular shift value.
|
||||
ABSL_INTERNAL_INLINE_CONSTEXPR(int32_t, kCycleClockShift, 2);
|
||||
#endif // NDEBUG
|
||||
|
||||
ABSL_INTERNAL_INLINE_CONSTEXPR(double, kCycleClockFrequencyScale,
|
||||
1.0 / (1 << kCycleClockShift));
|
||||
#endif // ABSL_USE_UNSCALED_CYCLECLOC
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_BASE_INTERNAL_CYCLECLOCK_CONFIG_H_
|
||||
@@ -1,170 +0,0 @@
|
||||
// Copyright 2017 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.
|
||||
//
|
||||
// Functions for directly invoking mmap() via syscall, avoiding the case where
|
||||
// mmap() has been locally overridden.
|
||||
|
||||
#ifndef ABSL_BASE_INTERNAL_DIRECT_MMAP_H_
|
||||
#define ABSL_BASE_INTERNAL_DIRECT_MMAP_H_
|
||||
|
||||
#include "absl/base/config.h"
|
||||
|
||||
#ifdef ABSL_HAVE_MMAP
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef __BIONIC__
|
||||
#include <sys/syscall.h>
|
||||
#else
|
||||
#include <syscall.h>
|
||||
#endif
|
||||
|
||||
#include <linux/unistd.h>
|
||||
#include <unistd.h>
|
||||
#include <cerrno>
|
||||
#include <cstdarg>
|
||||
#include <cstdint>
|
||||
|
||||
#ifdef __mips__
|
||||
// Include definitions of the ABI currently in use.
|
||||
#if defined(__BIONIC__) || !defined(__GLIBC__)
|
||||
// Android doesn't have sgidefs.h, but does have asm/sgidefs.h, which has the
|
||||
// definitions we need.
|
||||
#include <asm/sgidefs.h>
|
||||
#else
|
||||
#include <sgidefs.h>
|
||||
#endif // __BIONIC__ || !__GLIBC__
|
||||
#endif // __mips__
|
||||
|
||||
// SYS_mmap and SYS_munmap are not defined in Android.
|
||||
#ifdef __BIONIC__
|
||||
extern "C" void* __mmap2(void*, size_t, int, int, int, size_t);
|
||||
#if defined(__NR_mmap) && !defined(SYS_mmap)
|
||||
#define SYS_mmap __NR_mmap
|
||||
#endif
|
||||
#ifndef SYS_munmap
|
||||
#define SYS_munmap __NR_munmap
|
||||
#endif
|
||||
#endif // __BIONIC__
|
||||
|
||||
#if defined(__NR_mmap2) && !defined(SYS_mmap2)
|
||||
#define SYS_mmap2 __NR_mmap2
|
||||
#endif
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
|
||||
// Platform specific logic extracted from
|
||||
// https://chromium.googlesource.com/linux-syscall-support/+/master/linux_syscall_support.h
|
||||
inline void* DirectMmap(void* start, size_t length, int prot, int flags, int fd,
|
||||
off_t offset) noexcept {
|
||||
#if defined(__i386__) || defined(__ARM_ARCH_3__) || defined(__ARM_EABI__) || \
|
||||
defined(__m68k__) || defined(__sh__) || \
|
||||
(defined(__hppa__) && !defined(__LP64__)) || \
|
||||
(defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) || \
|
||||
(defined(__PPC__) && !defined(__PPC64__)) || \
|
||||
(defined(__riscv) && __riscv_xlen == 32) || \
|
||||
(defined(__s390__) && !defined(__s390x__)) || \
|
||||
(defined(__sparc__) && !defined(__arch64__))
|
||||
// On these architectures, implement mmap with mmap2.
|
||||
static int pagesize = 0;
|
||||
if (pagesize == 0) {
|
||||
#if defined(__wasm__) || defined(__asmjs__)
|
||||
pagesize = getpagesize();
|
||||
#else
|
||||
pagesize = sysconf(_SC_PAGESIZE);
|
||||
#endif
|
||||
}
|
||||
if (offset < 0 || offset % pagesize != 0) {
|
||||
errno = EINVAL;
|
||||
return MAP_FAILED;
|
||||
}
|
||||
#ifdef __BIONIC__
|
||||
// SYS_mmap2 has problems on Android API level <= 16.
|
||||
// Workaround by invoking __mmap2() instead.
|
||||
return __mmap2(start, length, prot, flags, fd,
|
||||
static_cast<size_t>(offset / pagesize));
|
||||
#else
|
||||
return reinterpret_cast<void*>(
|
||||
syscall(SYS_mmap2, start, length, prot, flags, fd,
|
||||
static_cast<unsigned long>(offset / pagesize))); // NOLINT
|
||||
#endif
|
||||
#elif defined(__s390x__)
|
||||
// On s390x, mmap() arguments are passed in memory.
|
||||
unsigned long buf[6] = {reinterpret_cast<unsigned long>(start), // NOLINT
|
||||
static_cast<unsigned long>(length), // NOLINT
|
||||
static_cast<unsigned long>(prot), // NOLINT
|
||||
static_cast<unsigned long>(flags), // NOLINT
|
||||
static_cast<unsigned long>(fd), // NOLINT
|
||||
static_cast<unsigned long>(offset)}; // NOLINT
|
||||
return reinterpret_cast<void*>(syscall(SYS_mmap, buf));
|
||||
#elif defined(__x86_64__)
|
||||
// The x32 ABI has 32 bit longs, but the syscall interface is 64 bit.
|
||||
// We need to explicitly cast to an unsigned 64 bit type to avoid implicit
|
||||
// sign extension. We can't cast pointers directly because those are
|
||||
// 32 bits, and gcc will dump ugly warnings about casting from a pointer
|
||||
// to an integer of a different size. We also need to make sure __off64_t
|
||||
// isn't truncated to 32-bits under x32.
|
||||
#define MMAP_SYSCALL_ARG(x) ((uint64_t)(uintptr_t)(x))
|
||||
return reinterpret_cast<void*>(
|
||||
syscall(SYS_mmap, MMAP_SYSCALL_ARG(start), MMAP_SYSCALL_ARG(length),
|
||||
MMAP_SYSCALL_ARG(prot), MMAP_SYSCALL_ARG(flags),
|
||||
MMAP_SYSCALL_ARG(fd), static_cast<uint64_t>(offset)));
|
||||
#undef MMAP_SYSCALL_ARG
|
||||
#else // Remaining 64-bit aritectures.
|
||||
static_assert(sizeof(unsigned long) == 8, "Platform is not 64-bit");
|
||||
return reinterpret_cast<void*>(
|
||||
syscall(SYS_mmap, start, length, prot, flags, fd, offset));
|
||||
#endif
|
||||
}
|
||||
|
||||
inline int DirectMunmap(void* start, size_t length) {
|
||||
return static_cast<int>(syscall(SYS_munmap, start, length));
|
||||
}
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#else // !__linux__
|
||||
|
||||
// For non-linux platforms where we have mmap, just dispatch directly to the
|
||||
// actual mmap()/munmap() methods.
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
|
||||
inline void* DirectMmap(void* start, size_t length, int prot, int flags, int fd,
|
||||
off_t offset) {
|
||||
return mmap(start, length, prot, flags, fd, offset);
|
||||
}
|
||||
|
||||
inline int DirectMunmap(void* start, size_t length) {
|
||||
return munmap(start, length);
|
||||
}
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // __linux__
|
||||
|
||||
#endif // ABSL_HAVE_MMAP
|
||||
|
||||
#endif // ABSL_BASE_INTERNAL_DIRECT_MMAP_H_
|
||||
@@ -1,398 +0,0 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
// This file defines dynamic annotations for use with dynamic analysis tool
|
||||
// such as valgrind, PIN, etc.
|
||||
//
|
||||
// Dynamic annotation is a source code annotation that affects the generated
|
||||
// code (that is, the annotation is not a comment). Each such annotation is
|
||||
// attached to a particular instruction and/or to a particular object (address)
|
||||
// in the program.
|
||||
//
|
||||
// The annotations that should be used by users are macros in all upper-case
|
||||
// (e.g., ANNOTATE_THREAD_NAME).
|
||||
//
|
||||
// Actual implementation of these macros may differ depending on the dynamic
|
||||
// analysis tool being used.
|
||||
//
|
||||
// This file supports the following configurations:
|
||||
// - Dynamic Annotations enabled (with static thread-safety warnings disabled).
|
||||
// In this case, macros expand to functions implemented by Thread Sanitizer,
|
||||
// when building with TSan. When not provided an external implementation,
|
||||
// dynamic_annotations.cc provides no-op implementations.
|
||||
//
|
||||
// - Static Clang thread-safety warnings enabled.
|
||||
// When building with a Clang compiler that supports thread-safety warnings,
|
||||
// a subset of annotations can be statically-checked at compile-time. We
|
||||
// expand these macros to static-inline functions that can be analyzed for
|
||||
// thread-safety, but afterwards elided when building the final binary.
|
||||
//
|
||||
// - All annotations are disabled.
|
||||
// If neither Dynamic Annotations nor Clang thread-safety warnings are
|
||||
// enabled, then all annotation-macros expand to empty.
|
||||
|
||||
#ifndef ABSL_BASE_INTERNAL_DYNAMIC_ANNOTATIONS_H_
|
||||
#define ABSL_BASE_INTERNAL_DYNAMIC_ANNOTATIONS_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "absl/base/config.h"
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Decide which features are enabled
|
||||
|
||||
#ifndef DYNAMIC_ANNOTATIONS_ENABLED
|
||||
#define DYNAMIC_ANNOTATIONS_ENABLED 0
|
||||
#endif
|
||||
|
||||
#if defined(__clang__) && !defined(SWIG)
|
||||
#define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 1
|
||||
#endif
|
||||
|
||||
#if DYNAMIC_ANNOTATIONS_ENABLED != 0
|
||||
|
||||
#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 1
|
||||
#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 1
|
||||
#define ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED 1
|
||||
#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 0
|
||||
#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED 1
|
||||
|
||||
#else
|
||||
|
||||
#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 0
|
||||
#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 0
|
||||
#define ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED 0
|
||||
|
||||
// Clang provides limited support for static thread-safety analysis through a
|
||||
// feature called Annotalysis. We configure macro-definitions according to
|
||||
// whether Annotalysis support is available. When running in opt-mode, GCC
|
||||
// will issue a warning, if these attributes are compiled. Only include them
|
||||
// when compiling using Clang.
|
||||
|
||||
// ANNOTALYSIS_ENABLED == 1 when IGNORE_READ_ATTRIBUTE_ENABLED == 1
|
||||
#define ABSL_INTERNAL_ANNOTALYSIS_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(ABSL_HAVE_MEMORY_SANITIZER) && !defined(__native_client__)
|
||||
#define ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED 1
|
||||
#endif
|
||||
|
||||
#ifndef ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED
|
||||
#define ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED 0
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define ABSL_INTERNAL_BEGIN_EXTERN_C extern "C" {
|
||||
#define ABSL_INTERNAL_END_EXTERN_C } // extern "C"
|
||||
#define ABSL_INTERNAL_GLOBAL_SCOPED(F) ::F
|
||||
#define ABSL_INTERNAL_STATIC_INLINE inline
|
||||
#else
|
||||
#define ABSL_INTERNAL_BEGIN_EXTERN_C // empty
|
||||
#define ABSL_INTERNAL_END_EXTERN_C // empty
|
||||
#define ABSL_INTERNAL_GLOBAL_SCOPED(F) F
|
||||
#define ABSL_INTERNAL_STATIC_INLINE static inline
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Define race annotations.
|
||||
|
||||
#if ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 1
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Annotations that suppress errors. It is usually better to express the
|
||||
// program's synchronization using the other annotations, but these can be used
|
||||
// when all else fails.
|
||||
|
||||
// Report that we may have a benign race at `pointer`, with size
|
||||
// "sizeof(*(pointer))". `pointer` must be a non-void* pointer. Insert at the
|
||||
// point where `pointer` has been allocated, preferably close to the point
|
||||
// where the race happens. See also ANNOTATE_BENIGN_RACE_STATIC.
|
||||
#define ANNOTATE_BENIGN_RACE(pointer, description) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateBenignRaceSized) \
|
||||
(__FILE__, __LINE__, pointer, sizeof(*(pointer)), description)
|
||||
|
||||
// Same as ANNOTATE_BENIGN_RACE(`address`, `description`), but applies to
|
||||
// the memory range [`address`, `address`+`size`).
|
||||
#define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateBenignRaceSized) \
|
||||
(__FILE__, __LINE__, address, size, description)
|
||||
|
||||
// Enable (`enable`!=0) or disable (`enable`==0) race detection for all threads.
|
||||
// This annotation could be useful if you want to skip expensive race analysis
|
||||
// during some period of program execution, e.g. during initialization.
|
||||
#define ANNOTATE_ENABLE_RACE_DETECTION(enable) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateEnableRaceDetection) \
|
||||
(__FILE__, __LINE__, enable)
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Annotations useful for debugging.
|
||||
|
||||
// Report the current thread `name` to a race detector.
|
||||
#define ANNOTATE_THREAD_NAME(name) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateThreadName)(__FILE__, __LINE__, name)
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Annotations useful when implementing locks. They are not normally needed by
|
||||
// modules that merely use locks. The `lock` argument is a pointer to the lock
|
||||
// object.
|
||||
|
||||
// Report that a lock has been created at address `lock`.
|
||||
#define ANNOTATE_RWLOCK_CREATE(lock) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreate)(__FILE__, __LINE__, lock)
|
||||
|
||||
// Report that a linker initialized lock has been created at address `lock`.
|
||||
#ifdef ABSL_HAVE_THREAD_SANITIZER
|
||||
#define ANNOTATE_RWLOCK_CREATE_STATIC(lock) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreateStatic) \
|
||||
(__FILE__, __LINE__, lock)
|
||||
#else
|
||||
#define ANNOTATE_RWLOCK_CREATE_STATIC(lock) ANNOTATE_RWLOCK_CREATE(lock)
|
||||
#endif
|
||||
|
||||
// Report that the lock at address `lock` is about to be destroyed.
|
||||
#define ANNOTATE_RWLOCK_DESTROY(lock) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockDestroy)(__FILE__, __LINE__, lock)
|
||||
|
||||
// Report that the lock at address `lock` has been acquired.
|
||||
// `is_w`=1 for writer lock, `is_w`=0 for reader lock.
|
||||
#define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockAcquired) \
|
||||
(__FILE__, __LINE__, lock, is_w)
|
||||
|
||||
// Report that the lock at address `lock` is about to be released.
|
||||
// `is_w`=1 for writer lock, `is_w`=0 for reader lock.
|
||||
#define ANNOTATE_RWLOCK_RELEASED(lock, is_w) \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockReleased) \
|
||||
(__FILE__, __LINE__, lock, is_w)
|
||||
|
||||
// Apply ANNOTATE_BENIGN_RACE_SIZED to a static variable `static_var`.
|
||||
#define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) \
|
||||
namespace { \
|
||||
class static_var##_annotator { \
|
||||
public: \
|
||||
static_var##_annotator() { \
|
||||
ANNOTATE_BENIGN_RACE_SIZED(&static_var, sizeof(static_var), \
|
||||
#static_var ": " description); \
|
||||
} \
|
||||
}; \
|
||||
static static_var##_annotator the##static_var##_annotator; \
|
||||
} // namespace
|
||||
|
||||
#else // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 0
|
||||
|
||||
#define ANNOTATE_RWLOCK_CREATE(lock) // empty
|
||||
#define ANNOTATE_RWLOCK_CREATE_STATIC(lock) // empty
|
||||
#define ANNOTATE_RWLOCK_DESTROY(lock) // empty
|
||||
#define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) // empty
|
||||
#define ANNOTATE_RWLOCK_RELEASED(lock, is_w) // empty
|
||||
#define ANNOTATE_BENIGN_RACE(address, description) // empty
|
||||
#define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) // empty
|
||||
#define ANNOTATE_THREAD_NAME(name) // empty
|
||||
#define ANNOTATE_ENABLE_RACE_DETECTION(enable) // empty
|
||||
#define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) // empty
|
||||
|
||||
#endif // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Define memory annotations.
|
||||
|
||||
#if ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED == 1
|
||||
|
||||
#include <sanitizer/msan_interface.h>
|
||||
|
||||
#define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
|
||||
__msan_unpoison(address, size)
|
||||
|
||||
#define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
|
||||
__msan_allocated_memory(address, size)
|
||||
|
||||
#else // ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED == 0
|
||||
|
||||
#if DYNAMIC_ANNOTATIONS_ENABLED == 1
|
||||
#define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
|
||||
do { \
|
||||
(void)(address); \
|
||||
(void)(size); \
|
||||
} while (0)
|
||||
#define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
|
||||
do { \
|
||||
(void)(address); \
|
||||
(void)(size); \
|
||||
} while (0)
|
||||
#else
|
||||
#define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) // empty
|
||||
#define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) // empty
|
||||
#endif
|
||||
|
||||
#endif // ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Define IGNORE_READS_BEGIN/_END attributes.
|
||||
|
||||
#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 // !defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
|
||||
|
||||
#define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE // empty
|
||||
#define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE // empty
|
||||
|
||||
#endif // defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Define IGNORE_READS_BEGIN/_END annotations.
|
||||
|
||||
#if ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED == 1
|
||||
|
||||
// Request the analysis tool to ignore all reads in the current thread until
|
||||
// ANNOTATE_IGNORE_READS_END is called. Useful to ignore intentional racey
|
||||
// reads, while still checking other reads and all writes.
|
||||
// See also ANNOTATE_UNPROTECTED_READ.
|
||||
#define ANNOTATE_IGNORE_READS_BEGIN() \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsBegin)(__FILE__, __LINE__)
|
||||
|
||||
// Stop ignoring reads.
|
||||
#define ANNOTATE_IGNORE_READS_END() \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsEnd)(__FILE__, __LINE__)
|
||||
|
||||
#elif defined(ABSL_INTERNAL_ANNOTALYSIS_ENABLED)
|
||||
|
||||
// When Annotalysis is enabled without Dynamic Annotations, the use of
|
||||
// static-inline functions allows the annotations to be read at compile-time,
|
||||
// while still letting the compiler elide the functions from the final build.
|
||||
//
|
||||
// TODO(delesley) -- The exclusive lock here ignores writes as well, but
|
||||
// allows IGNORE_READS_AND_WRITES to work properly.
|
||||
|
||||
#define ANNOTATE_IGNORE_READS_BEGIN() \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AbslInternalAnnotateIgnoreReadsBegin)()
|
||||
|
||||
#define ANNOTATE_IGNORE_READS_END() \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AbslInternalAnnotateIgnoreReadsEnd)()
|
||||
|
||||
#else
|
||||
|
||||
#define ANNOTATE_IGNORE_READS_BEGIN() // empty
|
||||
#define ANNOTATE_IGNORE_READS_END() // empty
|
||||
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Define IGNORE_WRITES_BEGIN/_END annotations.
|
||||
|
||||
#if ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED == 1
|
||||
|
||||
// Similar to ANNOTATE_IGNORE_READS_BEGIN, but ignore writes instead.
|
||||
#define ANNOTATE_IGNORE_WRITES_BEGIN() \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreWritesBegin)(__FILE__, __LINE__)
|
||||
|
||||
// Stop ignoring writes.
|
||||
#define ANNOTATE_IGNORE_WRITES_END() \
|
||||
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreWritesEnd)(__FILE__, __LINE__)
|
||||
|
||||
#else
|
||||
|
||||
#define ANNOTATE_IGNORE_WRITES_BEGIN() // empty
|
||||
#define ANNOTATE_IGNORE_WRITES_END() // empty
|
||||
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Define the ANNOTATE_IGNORE_READS_AND_WRITES_* annotations using the more
|
||||
// primitive annotations defined above.
|
||||
//
|
||||
// Instead of doing
|
||||
// ANNOTATE_IGNORE_READS_BEGIN();
|
||||
// ... = x;
|
||||
// ANNOTATE_IGNORE_READS_END();
|
||||
// one can use
|
||||
// ... = ANNOTATE_UNPROTECTED_READ(x);
|
||||
|
||||
#if defined(ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED)
|
||||
|
||||
// Start ignoring all memory accesses (both reads and writes).
|
||||
#define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
|
||||
do { \
|
||||
ANNOTATE_IGNORE_READS_BEGIN(); \
|
||||
ANNOTATE_IGNORE_WRITES_BEGIN(); \
|
||||
} while (0)
|
||||
|
||||
// Stop ignoring both reads and writes.
|
||||
#define ANNOTATE_IGNORE_READS_AND_WRITES_END() \
|
||||
do { \
|
||||
ANNOTATE_IGNORE_WRITES_END(); \
|
||||
ANNOTATE_IGNORE_READS_END(); \
|
||||
} while (0)
|
||||
|
||||
#ifdef __cplusplus
|
||||
// ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads.
|
||||
#define ANNOTATE_UNPROTECTED_READ(x) \
|
||||
absl::base_internal::AnnotateUnprotectedRead(x)
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() // empty
|
||||
#define ANNOTATE_IGNORE_READS_AND_WRITES_END() // empty
|
||||
#define ANNOTATE_UNPROTECTED_READ(x) (x)
|
||||
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Address sanitizer annotations
|
||||
|
||||
#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.
|
||||
#include <sanitizer/common_interface_defs.h>
|
||||
|
||||
#define ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid) \
|
||||
__sanitizer_annotate_contiguous_container(beg, end, old_mid, new_mid)
|
||||
#define ADDRESS_SANITIZER_REDZONE(name) \
|
||||
struct { \
|
||||
char x[8] __attribute__((aligned(8))); \
|
||||
} name
|
||||
|
||||
#else
|
||||
|
||||
#define ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid)
|
||||
#define ADDRESS_SANITIZER_REDZONE(name) static_assert(true, "")
|
||||
|
||||
#endif // ABSL_HAVE_ADDRESS_SANITIZER
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Undefine the macros intended only for this file.
|
||||
|
||||
#undef ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED
|
||||
#undef ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED
|
||||
#undef ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED
|
||||
#undef ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED
|
||||
#undef ABSL_INTERNAL_ANNOTALYSIS_ENABLED
|
||||
#undef ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED
|
||||
#undef ABSL_INTERNAL_BEGIN_EXTERN_C
|
||||
#undef ABSL_INTERNAL_END_EXTERN_C
|
||||
#undef ABSL_INTERNAL_STATIC_INLINE
|
||||
|
||||
#endif // ABSL_BASE_INTERNAL_DYNAMIC_ANNOTATIONS_H_
|
||||
@@ -1,283 +0,0 @@
|
||||
// Copyright 2017 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.
|
||||
//
|
||||
|
||||
#ifndef ABSL_BASE_INTERNAL_ENDIAN_H_
|
||||
#define ABSL_BASE_INTERNAL_ENDIAN_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "absl/base/casts.h"
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/internal/unaligned_access.h"
|
||||
#include "absl/base/nullability.h"
|
||||
#include "absl/base/port.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
|
||||
inline uint64_t gbswap_64(uint64_t host_int) {
|
||||
#if ABSL_HAVE_BUILTIN(__builtin_bswap64) || defined(__GNUC__)
|
||||
return __builtin_bswap64(host_int);
|
||||
#elif defined(_MSC_VER)
|
||||
return _byteswap_uint64(host_int);
|
||||
#else
|
||||
return (((host_int & uint64_t{0xFF}) << 56) |
|
||||
((host_int & uint64_t{0xFF00}) << 40) |
|
||||
((host_int & uint64_t{0xFF0000}) << 24) |
|
||||
((host_int & uint64_t{0xFF000000}) << 8) |
|
||||
((host_int & uint64_t{0xFF00000000}) >> 8) |
|
||||
((host_int & uint64_t{0xFF0000000000}) >> 24) |
|
||||
((host_int & uint64_t{0xFF000000000000}) >> 40) |
|
||||
((host_int & uint64_t{0xFF00000000000000}) >> 56));
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint32_t gbswap_32(uint32_t host_int) {
|
||||
#if ABSL_HAVE_BUILTIN(__builtin_bswap32) || defined(__GNUC__)
|
||||
return __builtin_bswap32(host_int);
|
||||
#elif defined(_MSC_VER)
|
||||
return _byteswap_ulong(host_int);
|
||||
#else
|
||||
return (((host_int & uint32_t{0xFF}) << 24) |
|
||||
((host_int & uint32_t{0xFF00}) << 8) |
|
||||
((host_int & uint32_t{0xFF0000}) >> 8) |
|
||||
((host_int & uint32_t{0xFF000000}) >> 24));
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint16_t gbswap_16(uint16_t host_int) {
|
||||
#if ABSL_HAVE_BUILTIN(__builtin_bswap16) || defined(__GNUC__)
|
||||
return __builtin_bswap16(host_int);
|
||||
#elif defined(_MSC_VER)
|
||||
return _byteswap_ushort(host_int);
|
||||
#else
|
||||
return (((host_int & uint16_t{0xFF}) << 8) |
|
||||
((host_int & uint16_t{0xFF00}) >> 8));
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef ABSL_IS_LITTLE_ENDIAN
|
||||
|
||||
// Portable definitions for htonl (host-to-network) and friends on little-endian
|
||||
// architectures.
|
||||
inline uint16_t ghtons(uint16_t x) { return gbswap_16(x); }
|
||||
inline uint32_t ghtonl(uint32_t x) { return gbswap_32(x); }
|
||||
inline uint64_t ghtonll(uint64_t x) { return gbswap_64(x); }
|
||||
|
||||
#elif defined ABSL_IS_BIG_ENDIAN
|
||||
|
||||
// Portable definitions for htonl (host-to-network) etc on big-endian
|
||||
// architectures. These definitions are simpler since the host byte order is the
|
||||
// same as network byte order.
|
||||
inline uint16_t ghtons(uint16_t x) { return x; }
|
||||
inline uint32_t ghtonl(uint32_t x) { return x; }
|
||||
inline uint64_t ghtonll(uint64_t x) { return x; }
|
||||
|
||||
#else
|
||||
#error \
|
||||
"Unsupported byte order: Either ABSL_IS_BIG_ENDIAN or " \
|
||||
"ABSL_IS_LITTLE_ENDIAN must be defined"
|
||||
#endif // byte order
|
||||
|
||||
inline uint16_t gntohs(uint16_t x) { return ghtons(x); }
|
||||
inline uint32_t gntohl(uint32_t x) { return ghtonl(x); }
|
||||
inline uint64_t gntohll(uint64_t x) { return ghtonll(x); }
|
||||
|
||||
// Utilities to convert numbers between the current hosts's native byte
|
||||
// order and little-endian byte order
|
||||
//
|
||||
// Load/Store methods are alignment safe
|
||||
namespace little_endian {
|
||||
// Conversion functions.
|
||||
#ifdef ABSL_IS_LITTLE_ENDIAN
|
||||
|
||||
inline uint16_t FromHost16(uint16_t x) { return x; }
|
||||
inline uint16_t ToHost16(uint16_t x) { return x; }
|
||||
|
||||
inline uint32_t FromHost32(uint32_t x) { return x; }
|
||||
inline uint32_t ToHost32(uint32_t x) { return x; }
|
||||
|
||||
inline uint64_t FromHost64(uint64_t x) { return x; }
|
||||
inline uint64_t ToHost64(uint64_t x) { return x; }
|
||||
|
||||
inline constexpr bool IsLittleEndian() { return true; }
|
||||
|
||||
#elif defined ABSL_IS_BIG_ENDIAN
|
||||
|
||||
inline uint16_t FromHost16(uint16_t x) { return gbswap_16(x); }
|
||||
inline uint16_t ToHost16(uint16_t x) { return gbswap_16(x); }
|
||||
|
||||
inline uint32_t FromHost32(uint32_t x) { return gbswap_32(x); }
|
||||
inline uint32_t ToHost32(uint32_t x) { return gbswap_32(x); }
|
||||
|
||||
inline uint64_t FromHost64(uint64_t x) { return gbswap_64(x); }
|
||||
inline uint64_t ToHost64(uint64_t x) { return gbswap_64(x); }
|
||||
|
||||
inline constexpr bool IsLittleEndian() { return false; }
|
||||
|
||||
#endif /* ENDIAN */
|
||||
|
||||
inline uint8_t FromHost(uint8_t x) { return x; }
|
||||
inline uint16_t FromHost(uint16_t x) { return FromHost16(x); }
|
||||
inline uint32_t FromHost(uint32_t x) { return FromHost32(x); }
|
||||
inline uint64_t FromHost(uint64_t x) { return FromHost64(x); }
|
||||
inline uint8_t ToHost(uint8_t x) { return x; }
|
||||
inline uint16_t ToHost(uint16_t x) { return ToHost16(x); }
|
||||
inline uint32_t ToHost(uint32_t x) { return ToHost32(x); }
|
||||
inline uint64_t ToHost(uint64_t x) { return ToHost64(x); }
|
||||
|
||||
inline int8_t FromHost(int8_t x) { return x; }
|
||||
inline int16_t FromHost(int16_t x) {
|
||||
return bit_cast<int16_t>(FromHost16(bit_cast<uint16_t>(x)));
|
||||
}
|
||||
inline int32_t FromHost(int32_t x) {
|
||||
return bit_cast<int32_t>(FromHost32(bit_cast<uint32_t>(x)));
|
||||
}
|
||||
inline int64_t FromHost(int64_t x) {
|
||||
return bit_cast<int64_t>(FromHost64(bit_cast<uint64_t>(x)));
|
||||
}
|
||||
inline int8_t ToHost(int8_t x) { return x; }
|
||||
inline int16_t ToHost(int16_t x) {
|
||||
return bit_cast<int16_t>(ToHost16(bit_cast<uint16_t>(x)));
|
||||
}
|
||||
inline int32_t ToHost(int32_t x) {
|
||||
return bit_cast<int32_t>(ToHost32(bit_cast<uint32_t>(x)));
|
||||
}
|
||||
inline int64_t ToHost(int64_t x) {
|
||||
return bit_cast<int64_t>(ToHost64(bit_cast<uint64_t>(x)));
|
||||
}
|
||||
|
||||
// Functions to do unaligned loads and stores in little-endian order.
|
||||
inline uint16_t Load16(absl::Nonnull<const void *> p) {
|
||||
return ToHost16(ABSL_INTERNAL_UNALIGNED_LOAD16(p));
|
||||
}
|
||||
|
||||
inline void Store16(absl::Nonnull<void *> p, uint16_t v) {
|
||||
ABSL_INTERNAL_UNALIGNED_STORE16(p, FromHost16(v));
|
||||
}
|
||||
|
||||
inline uint32_t Load32(absl::Nonnull<const void *> p) {
|
||||
return ToHost32(ABSL_INTERNAL_UNALIGNED_LOAD32(p));
|
||||
}
|
||||
|
||||
inline void Store32(absl::Nonnull<void *> p, uint32_t v) {
|
||||
ABSL_INTERNAL_UNALIGNED_STORE32(p, FromHost32(v));
|
||||
}
|
||||
|
||||
inline uint64_t Load64(absl::Nonnull<const void *> p) {
|
||||
return ToHost64(ABSL_INTERNAL_UNALIGNED_LOAD64(p));
|
||||
}
|
||||
|
||||
inline void Store64(absl::Nonnull<void *> p, uint64_t v) {
|
||||
ABSL_INTERNAL_UNALIGNED_STORE64(p, FromHost64(v));
|
||||
}
|
||||
|
||||
} // namespace little_endian
|
||||
|
||||
// Utilities to convert numbers between the current hosts's native byte
|
||||
// order and big-endian byte order (same as network byte order)
|
||||
//
|
||||
// Load/Store methods are alignment safe
|
||||
namespace big_endian {
|
||||
#ifdef ABSL_IS_LITTLE_ENDIAN
|
||||
|
||||
inline uint16_t FromHost16(uint16_t x) { return gbswap_16(x); }
|
||||
inline uint16_t ToHost16(uint16_t x) { return gbswap_16(x); }
|
||||
|
||||
inline uint32_t FromHost32(uint32_t x) { return gbswap_32(x); }
|
||||
inline uint32_t ToHost32(uint32_t x) { return gbswap_32(x); }
|
||||
|
||||
inline uint64_t FromHost64(uint64_t x) { return gbswap_64(x); }
|
||||
inline uint64_t ToHost64(uint64_t x) { return gbswap_64(x); }
|
||||
|
||||
inline constexpr bool IsLittleEndian() { return true; }
|
||||
|
||||
#elif defined ABSL_IS_BIG_ENDIAN
|
||||
|
||||
inline uint16_t FromHost16(uint16_t x) { return x; }
|
||||
inline uint16_t ToHost16(uint16_t x) { return x; }
|
||||
|
||||
inline uint32_t FromHost32(uint32_t x) { return x; }
|
||||
inline uint32_t ToHost32(uint32_t x) { return x; }
|
||||
|
||||
inline uint64_t FromHost64(uint64_t x) { return x; }
|
||||
inline uint64_t ToHost64(uint64_t x) { return x; }
|
||||
|
||||
inline constexpr bool IsLittleEndian() { return false; }
|
||||
|
||||
#endif /* ENDIAN */
|
||||
|
||||
inline uint8_t FromHost(uint8_t x) { return x; }
|
||||
inline uint16_t FromHost(uint16_t x) { return FromHost16(x); }
|
||||
inline uint32_t FromHost(uint32_t x) { return FromHost32(x); }
|
||||
inline uint64_t FromHost(uint64_t x) { return FromHost64(x); }
|
||||
inline uint8_t ToHost(uint8_t x) { return x; }
|
||||
inline uint16_t ToHost(uint16_t x) { return ToHost16(x); }
|
||||
inline uint32_t ToHost(uint32_t x) { return ToHost32(x); }
|
||||
inline uint64_t ToHost(uint64_t x) { return ToHost64(x); }
|
||||
|
||||
inline int8_t FromHost(int8_t x) { return x; }
|
||||
inline int16_t FromHost(int16_t x) {
|
||||
return bit_cast<int16_t>(FromHost16(bit_cast<uint16_t>(x)));
|
||||
}
|
||||
inline int32_t FromHost(int32_t x) {
|
||||
return bit_cast<int32_t>(FromHost32(bit_cast<uint32_t>(x)));
|
||||
}
|
||||
inline int64_t FromHost(int64_t x) {
|
||||
return bit_cast<int64_t>(FromHost64(bit_cast<uint64_t>(x)));
|
||||
}
|
||||
inline int8_t ToHost(int8_t x) { return x; }
|
||||
inline int16_t ToHost(int16_t x) {
|
||||
return bit_cast<int16_t>(ToHost16(bit_cast<uint16_t>(x)));
|
||||
}
|
||||
inline int32_t ToHost(int32_t x) {
|
||||
return bit_cast<int32_t>(ToHost32(bit_cast<uint32_t>(x)));
|
||||
}
|
||||
inline int64_t ToHost(int64_t x) {
|
||||
return bit_cast<int64_t>(ToHost64(bit_cast<uint64_t>(x)));
|
||||
}
|
||||
|
||||
// Functions to do unaligned loads and stores in big-endian order.
|
||||
inline uint16_t Load16(absl::Nonnull<const void *> p) {
|
||||
return ToHost16(ABSL_INTERNAL_UNALIGNED_LOAD16(p));
|
||||
}
|
||||
|
||||
inline void Store16(absl::Nonnull<void *> p, uint16_t v) {
|
||||
ABSL_INTERNAL_UNALIGNED_STORE16(p, FromHost16(v));
|
||||
}
|
||||
|
||||
inline uint32_t Load32(absl::Nonnull<const void *> p) {
|
||||
return ToHost32(ABSL_INTERNAL_UNALIGNED_LOAD32(p));
|
||||
}
|
||||
|
||||
inline void Store32(absl::Nonnull<void *>p, uint32_t v) {
|
||||
ABSL_INTERNAL_UNALIGNED_STORE32(p, FromHost32(v));
|
||||
}
|
||||
|
||||
inline uint64_t Load64(absl::Nonnull<const void *> p) {
|
||||
return ToHost64(ABSL_INTERNAL_UNALIGNED_LOAD64(p));
|
||||
}
|
||||
|
||||
inline void Store64(absl::Nonnull<void *> p, uint64_t v) {
|
||||
ABSL_INTERNAL_UNALIGNED_STORE64(p, FromHost64(v));
|
||||
}
|
||||
|
||||
} // namespace big_endian
|
||||
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_BASE_INTERNAL_ENDIAN_H_
|
||||
@@ -1,43 +0,0 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
#ifndef ABSL_BASE_INTERNAL_ERRNO_SAVER_H_
|
||||
#define ABSL_BASE_INTERNAL_ERRNO_SAVER_H_
|
||||
|
||||
#include <cerrno>
|
||||
|
||||
#include "absl/base/config.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
|
||||
// `ErrnoSaver` captures the value of `errno` upon construction and restores it
|
||||
// upon deletion. It is used in low-level code and must be super fast. Do not
|
||||
// add instrumentation, even in debug modes.
|
||||
class ErrnoSaver {
|
||||
public:
|
||||
ErrnoSaver() : saved_errno_(errno) {}
|
||||
~ErrnoSaver() { errno = saved_errno_; }
|
||||
int operator()() const { return saved_errno_; }
|
||||
|
||||
private:
|
||||
const int saved_errno_;
|
||||
};
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_BASE_INTERNAL_ERRNO_SAVER_H_
|
||||
-1109
File diff suppressed because it is too large
Load Diff
@@ -1,42 +0,0 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
// Testing utilities for ABSL types which throw exceptions.
|
||||
|
||||
#ifndef ABSL_BASE_INTERNAL_EXCEPTION_TESTING_H_
|
||||
#define ABSL_BASE_INTERNAL_EXCEPTION_TESTING_H_
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/base/config.h"
|
||||
|
||||
// ABSL_BASE_INTERNAL_EXPECT_FAIL tests either for a specified thrown exception
|
||||
// if exceptions are enabled, or for death with a specified text in the error
|
||||
// message
|
||||
#ifdef ABSL_HAVE_EXCEPTIONS
|
||||
|
||||
#define ABSL_BASE_INTERNAL_EXPECT_FAIL(expr, exception_t, text) \
|
||||
EXPECT_THROW(expr, exception_t)
|
||||
|
||||
#elif defined(__ANDROID__)
|
||||
// Android asserts do not log anywhere that gtest can currently inspect.
|
||||
// So we expect exit, but cannot match the message.
|
||||
#define ABSL_BASE_INTERNAL_EXPECT_FAIL(expr, exception_t, text) \
|
||||
EXPECT_DEATH(expr, ".*")
|
||||
#else
|
||||
#define ABSL_BASE_INTERNAL_EXPECT_FAIL(expr, exception_t, text) \
|
||||
EXPECT_DEATH_IF_SUPPORTED(expr, text)
|
||||
|
||||
#endif
|
||||
|
||||
#endif // ABSL_BASE_INTERNAL_EXCEPTION_TESTING_H_
|
||||
@@ -1,50 +0,0 @@
|
||||
//
|
||||
// Copyright 2020 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.
|
||||
//
|
||||
|
||||
#ifndef ABSL_BASE_INTERNAL_FAST_TYPE_ID_H_
|
||||
#define ABSL_BASE_INTERNAL_FAST_TYPE_ID_H_
|
||||
|
||||
#include "absl/base/config.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
namespace base_internal {
|
||||
|
||||
template <typename Type>
|
||||
struct FastTypeTag {
|
||||
constexpr static char dummy_var = 0;
|
||||
};
|
||||
|
||||
#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
|
||||
template <typename Type>
|
||||
constexpr char FastTypeTag<Type>::dummy_var;
|
||||
#endif
|
||||
|
||||
// FastTypeId<Type>() evaluates at compile/link-time to a unique pointer for the
|
||||
// passed-in type. These are meant to be good match for keys into maps or
|
||||
// straight up comparisons.
|
||||
using FastTypeIdType = const void*;
|
||||
|
||||
template <typename Type>
|
||||
constexpr inline FastTypeIdType FastTypeId() {
|
||||
return &FastTypeTag<Type>::dummy_var;
|
||||
}
|
||||
|
||||
} // namespace base_internal
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_BASE_INTERNAL_FAST_TYPE_ID_H_
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user