Commit a8b03d90 by Abseil Team Committed by Gennadiy Rozental

Export of internal Abseil changes

--
5b9d5ce21074c0541432555d383d1b9c5898b553 by Gennadiy Rozental <rogeeff@google.com>:

Convert FlagSaver into public API

PiperOrigin-RevId: 314799739

--
5f796c9862b1177f161f4b10fe1a84698ebbb5cf by Abseil Team <absl-team@google.com>:

Google-internal changes only.

PiperOrigin-RevId: 314786474

--
67f2ae0ac5ae73bcd9d57a058ac4fea8fc1243ba by Gennadiy Rozental <rogeeff@google.com>:

Makes sure stacktrace_generic is only used with glibc.

Fixes #701

PiperOrigin-RevId: 314726944

--
efb1ef3636b0698b79d3ee3590f12c4dff32a3cb by Samuel Benzaquen <sbenza@google.com>:

Take the bits into account when reserving the space for the operation, not just
the exponent.

PiperOrigin-RevId: 314622744
GitOrigin-RevId: 5b9d5ce21074c0541432555d383d1b9c5898b553
Change-Id: I080a5e333e2dc1545b5aa0417882f7ac7116a20c
parent 1d31b5c3
...@@ -29,6 +29,9 @@ extern "C" void __google_enable_rescheduling(bool disable_result); ...@@ -29,6 +29,9 @@ extern "C" void __google_enable_rescheduling(bool disable_result);
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN ABSL_NAMESPACE_BEGIN
class CondVar;
class Mutex;
namespace base_internal { namespace base_internal {
class SchedulingHelper; // To allow use of SchedulingGuard. class SchedulingHelper; // To allow use of SchedulingGuard.
...@@ -77,6 +80,8 @@ class SchedulingGuard { ...@@ -77,6 +80,8 @@ class SchedulingGuard {
}; };
// Access to SchedulingGuard is explicitly white-listed. // Access to SchedulingGuard is explicitly white-listed.
friend class absl::CondVar;
friend class absl::Mutex;
friend class SchedulingHelper; friend class SchedulingHelper;
friend class SpinLock; friend class SpinLock;
......
...@@ -61,7 +61,7 @@ ...@@ -61,7 +61,7 @@
# elif defined(__aarch64__) # elif defined(__aarch64__)
#define ABSL_STACKTRACE_INL_HEADER \ #define ABSL_STACKTRACE_INL_HEADER \
"absl/debugging/internal/stacktrace_aarch64-inl.inc" "absl/debugging/internal/stacktrace_aarch64-inl.inc"
# elif defined(__arm__) #elif defined(__arm__) && defined(__GLIBC__)
// Note: When using glibc this may require -funwind-tables to function properly. // Note: When using glibc this may require -funwind-tables to function properly.
#define ABSL_STACKTRACE_INL_HEADER \ #define ABSL_STACKTRACE_INL_HEADER \
"absl/debugging/internal/stacktrace_generic-inl.inc" "absl/debugging/internal/stacktrace_generic-inl.inc"
......
...@@ -47,7 +47,7 @@ class CommandLineFlagTest : public testing::Test { ...@@ -47,7 +47,7 @@ class CommandLineFlagTest : public testing::Test {
absl::SetFlagsUsageConfig(default_config); absl::SetFlagsUsageConfig(default_config);
} }
void SetUp() override { flag_saver_ = absl::make_unique<flags::FlagSaver>(); } void SetUp() override { flag_saver_ = absl::make_unique<absl::FlagSaver>(); }
void TearDown() override { flag_saver_.reset(); } void TearDown() override { flag_saver_.reset(); }
private: private:
...@@ -60,7 +60,7 @@ class CommandLineFlagTest : public testing::Test { ...@@ -60,7 +60,7 @@ class CommandLineFlagTest : public testing::Test {
return std::string(fname); return std::string(fname);
} }
std::unique_ptr<flags::FlagSaver> flag_saver_; std::unique_ptr<absl::FlagSaver> flag_saver_;
}; };
TEST_F(CommandLineFlagTest, TestAttributesAccessMethods) { TEST_F(CommandLineFlagTest, TestAttributesAccessMethods) {
......
...@@ -81,7 +81,7 @@ class FlagTest : public testing::Test { ...@@ -81,7 +81,7 @@ class FlagTest : public testing::Test {
#endif #endif
return std::string(fname); return std::string(fname);
} }
flags::FlagSaver flag_saver_; absl::FlagSaver flag_saver_;
}; };
struct S1 { struct S1 {
......
...@@ -89,31 +89,6 @@ inline bool RetiredFlag(const char* flag_name) { ...@@ -89,31 +89,6 @@ inline bool RetiredFlag(const char* flag_name) {
return flags_internal::Retire(flag_name, base_internal::FastTypeId<T>()); return flags_internal::Retire(flag_name, base_internal::FastTypeId<T>());
} }
//-----------------------------------------------------------------------------
// Saves the states (value, default value, whether the user has set
// the flag, registered validators, etc) of all flags, and restores
// them when the FlagSaver is destroyed.
//
// This class is thread-safe. However, its destructor writes to
// exactly the set of flags that have changed value during its
// lifetime, so concurrent _direct_ access to those flags
// (i.e. FLAGS_foo instead of {Get,Set}CommandLineOption()) is unsafe.
class FlagSaver {
public:
FlagSaver();
~FlagSaver();
FlagSaver(const FlagSaver&) = delete;
void operator=(const FlagSaver&) = delete;
// Prevents saver from restoring the saved state of flags.
void Ignore();
private:
class FlagSaverImpl* impl_; // we use pimpl here to keep API steady
};
} // namespace flags_internal } // namespace flags_internal
ABSL_NAMESPACE_END ABSL_NAMESPACE_END
} // namespace absl } // namespace absl
......
...@@ -89,7 +89,7 @@ class UsageReportingTest : public testing::Test { ...@@ -89,7 +89,7 @@ class UsageReportingTest : public testing::Test {
} }
private: private:
flags::FlagSaver flag_saver_; absl::FlagSaver flag_saver_;
}; };
// -------------------------------------------------------------------- // --------------------------------------------------------------------
......
...@@ -208,7 +208,7 @@ using testing::ElementsAreArray; ...@@ -208,7 +208,7 @@ using testing::ElementsAreArray;
class ParseTest : public testing::Test { class ParseTest : public testing::Test {
private: private:
flags::FlagSaver flag_saver_; absl::FlagSaver flag_saver_;
}; };
// -------------------------------------------------------------------- // --------------------------------------------------------------------
......
...@@ -65,7 +65,8 @@ class FlagRegistry { ...@@ -65,7 +65,8 @@ class FlagRegistry {
static FlagRegistry& GlobalRegistry(); // returns a singleton registry static FlagRegistry& GlobalRegistry(); // returns a singleton registry
private: private:
friend class FlagSaverImpl; // reads all the flags in order to copy them friend class flags_internal::FlagSaverImpl; // reads all the flags in order
// to copy them
friend void ForEachFlagUnlocked( friend void ForEachFlagUnlocked(
std::function<void(CommandLineFlag&)> visitor); std::function<void(CommandLineFlag&)> visitor);
...@@ -249,15 +250,6 @@ bool Retire(const char* name, FlagFastTypeId type_id) { ...@@ -249,15 +250,6 @@ bool Retire(const char* name, FlagFastTypeId type_id) {
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// FlagSaver
// FlagSaverImpl
// This class stores the states of all flags at construct time,
// and restores all flags to that state at destruct time.
// Its major implementation challenge is that it never modifies
// pointers in the 'main' registry, so global FLAG_* vars always
// point to the right place.
// --------------------------------------------------------------------
class FlagSaverImpl { class FlagSaverImpl {
public: public:
FlagSaverImpl() = default; FlagSaverImpl() = default;
...@@ -288,11 +280,10 @@ class FlagSaverImpl { ...@@ -288,11 +280,10 @@ class FlagSaverImpl {
backup_registry_; backup_registry_;
}; };
FlagSaver::FlagSaver() : impl_(new FlagSaverImpl) { impl_->SaveFromRegistry(); } } // namespace flags_internal
void FlagSaver::Ignore() { FlagSaver::FlagSaver() : impl_(new flags_internal::FlagSaverImpl) {
delete impl_; impl_->SaveFromRegistry();
impl_ = nullptr;
} }
FlagSaver::~FlagSaver() { FlagSaver::~FlagSaver() {
...@@ -304,8 +295,6 @@ FlagSaver::~FlagSaver() { ...@@ -304,8 +295,6 @@ FlagSaver::~FlagSaver() {
// -------------------------------------------------------------------- // --------------------------------------------------------------------
} // namespace flags_internal
CommandLineFlag* FindCommandLineFlag(absl::string_view name) { CommandLineFlag* FindCommandLineFlag(absl::string_view name) {
if (name.empty()) return nullptr; if (name.empty()) return nullptr;
flags_internal::FlagRegistry& registry = flags_internal::FlagRegistry& registry =
......
...@@ -31,6 +31,9 @@ ...@@ -31,6 +31,9 @@
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN ABSL_NAMESPACE_BEGIN
namespace flags_internal {
class FlagSaverImpl;
} // namespace flags_internal
// FindCommandLineFlag() // FindCommandLineFlag()
// //
...@@ -39,6 +42,41 @@ ABSL_NAMESPACE_BEGIN ...@@ -39,6 +42,41 @@ ABSL_NAMESPACE_BEGIN
// 'retired' flag is specified. // 'retired' flag is specified.
CommandLineFlag* FindCommandLineFlag(absl::string_view name); CommandLineFlag* FindCommandLineFlag(absl::string_view name);
//------------------------------------------------------------------------------
// FlagSaver
//------------------------------------------------------------------------------
//
// A FlagSaver object stores the state of flags in the scope where the FlagSaver
// is defined, allowing modification of those flags within that scope and
// automatic restoration of the flags to their previous state upon leaving the
// scope.
//
// A FlagSaver can be used within tests to temporarily change the test
// environment and restore the test case to its previous state.
//
// Example:
//
// void MyFunc() {
// absl::FlagSaver fs;
// ...
// absl::SetFlag(FLAGS_myFlag, otherValue);
// ...
// } // scope of FlagSaver left, flags return to previous state
//
// This class is thread-safe.
class FlagSaver {
public:
FlagSaver();
~FlagSaver();
FlagSaver(const FlagSaver&) = delete;
void operator=(const FlagSaver&) = delete;
private:
flags_internal::FlagSaverImpl* impl_;
};
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
ABSL_NAMESPACE_END ABSL_NAMESPACE_END
......
...@@ -34,11 +34,11 @@ namespace flags = absl::flags_internal; ...@@ -34,11 +34,11 @@ namespace flags = absl::flags_internal;
class ReflectionTest : public testing::Test { class ReflectionTest : public testing::Test {
protected: protected:
void SetUp() override { flag_saver_ = absl::make_unique<flags::FlagSaver>(); } void SetUp() override { flag_saver_ = absl::make_unique<absl::FlagSaver>(); }
void TearDown() override { flag_saver_.reset(); } void TearDown() override { flag_saver_.reset(); }
private: private:
std::unique_ptr<flags::FlagSaver> flag_saver_; std::unique_ptr<absl::FlagSaver> flag_saver_;
}; };
// -------------------------------------------------------------------- // --------------------------------------------------------------------
......
...@@ -764,6 +764,12 @@ TEST_F(FormatConvertTest, LongDouble) { ...@@ -764,6 +764,12 @@ TEST_F(FormatConvertTest, LongDouble) {
} }
} }
// Regression tests
//
// Using a string literal because not all platforms support hex literals or it
// might be out of range.
doubles.push_back(std::strtold("-0xf.ffffffb5feafffbp-16324L", nullptr));
for (const char *fmt : kFormats) { for (const char *fmt : kFormats) {
for (char f : {'f', 'F', // for (char f : {'f', 'F', //
'g', 'G', // 'g', 'G', //
......
...@@ -224,13 +224,13 @@ class FractionalDigitGenerator { ...@@ -224,13 +224,13 @@ class FractionalDigitGenerator {
// This function will allocate enough stack space to perform the conversion. // This function will allocate enough stack space to perform the conversion.
static void RunConversion( static void RunConversion(
uint128 v, int exp, absl::FunctionRef<void(FractionalDigitGenerator)> f) { uint128 v, int exp, absl::FunctionRef<void(FractionalDigitGenerator)> f) {
using Limits = std::numeric_limits<long double>;
assert(-exp < 0); assert(-exp < 0);
assert(-exp >= std::numeric_limits<long double>::min_exponent - 128); assert(-exp >= Limits::min_exponent - 128);
static_assert( static_assert(StackArray::kMaxCapacity >=
StackArray::kMaxCapacity >= (Limits::digits + 128 - Limits::min_exponent + 31) / 32,
(128 - std::numeric_limits<long double>::min_exponent + 31) / 32,
""); "");
StackArray::RunWithCapacity((exp + 31) / 32, StackArray::RunWithCapacity((Limits::digits + exp + 31) / 32,
[=](absl::Span<uint32_t> input) { [=](absl::Span<uint32_t> input) {
f(FractionalDigitGenerator(input, v, exp)); f(FractionalDigitGenerator(input, v, exp));
}); });
......
...@@ -58,6 +58,7 @@ ...@@ -58,6 +58,7 @@
using absl::base_internal::CurrentThreadIdentityIfPresent; using absl::base_internal::CurrentThreadIdentityIfPresent;
using absl::base_internal::PerThreadSynch; using absl::base_internal::PerThreadSynch;
using absl::base_internal::SchedulingGuard;
using absl::base_internal::ThreadIdentity; using absl::base_internal::ThreadIdentity;
using absl::synchronization_internal::GetOrCreateCurrentThreadIdentity; using absl::synchronization_internal::GetOrCreateCurrentThreadIdentity;
using absl::synchronization_internal::GraphCycles; using absl::synchronization_internal::GraphCycles;
...@@ -1108,6 +1109,7 @@ void Mutex::TryRemove(PerThreadSynch *s) { ...@@ -1108,6 +1109,7 @@ void Mutex::TryRemove(PerThreadSynch *s) {
// on the mutex queue. In this case, remove "s" from the queue and return // on the mutex queue. In this case, remove "s" from the queue and return
// true, otherwise return false. // true, otherwise return false.
ABSL_XRAY_LOG_ARGS(1) void Mutex::Block(PerThreadSynch *s) { ABSL_XRAY_LOG_ARGS(1) void Mutex::Block(PerThreadSynch *s) {
SchedulingGuard::ScopedDisable disable_rescheduling;
while (s->state.load(std::memory_order_acquire) == PerThreadSynch::kQueued) { while (s->state.load(std::memory_order_acquire) == PerThreadSynch::kQueued) {
if (!DecrementSynchSem(this, s, s->waitp->timeout)) { if (!DecrementSynchSem(this, s, s->waitp->timeout)) {
// After a timeout, we go into a spin loop until we remove ourselves // After a timeout, we go into a spin loop until we remove ourselves
...@@ -1897,6 +1899,7 @@ static void CheckForMutexCorruption(intptr_t v, const char* label) { ...@@ -1897,6 +1899,7 @@ static void CheckForMutexCorruption(intptr_t v, const char* label) {
} }
void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) { void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) {
SchedulingGuard::ScopedDisable disable_rescheduling;
int c = 0; int c = 0;
intptr_t v = mu_.load(std::memory_order_relaxed); intptr_t v = mu_.load(std::memory_order_relaxed);
if ((v & kMuEvent) != 0) { if ((v & kMuEvent) != 0) {
...@@ -2016,6 +2019,7 @@ void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) { ...@@ -2016,6 +2019,7 @@ void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) {
// or it is in the process of blocking on a condition variable; it must requeue // or it is in the process of blocking on a condition variable; it must requeue
// itself on the mutex/condvar to wait for its condition to become true. // itself on the mutex/condvar to wait for its condition to become true.
ABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams *waitp) { ABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams *waitp) {
SchedulingGuard::ScopedDisable disable_rescheduling;
intptr_t v = mu_.load(std::memory_order_relaxed); intptr_t v = mu_.load(std::memory_order_relaxed);
this->AssertReaderHeld(); this->AssertReaderHeld();
CheckForMutexCorruption(v, "Unlock"); CheckForMutexCorruption(v, "Unlock");
...@@ -2331,6 +2335,7 @@ void Mutex::Trans(MuHow how) { ...@@ -2331,6 +2335,7 @@ void Mutex::Trans(MuHow how) {
// It will later acquire the mutex with high probability. Otherwise, we // It will later acquire the mutex with high probability. Otherwise, we
// enqueue thread w on this mutex. // enqueue thread w on this mutex.
void Mutex::Fer(PerThreadSynch *w) { void Mutex::Fer(PerThreadSynch *w) {
SchedulingGuard::ScopedDisable disable_rescheduling;
int c = 0; int c = 0;
ABSL_RAW_CHECK(w->waitp->cond == nullptr, ABSL_RAW_CHECK(w->waitp->cond == nullptr,
"Mutex::Fer while waiting on Condition"); "Mutex::Fer while waiting on Condition");
...@@ -2429,6 +2434,7 @@ CondVar::~CondVar() { ...@@ -2429,6 +2434,7 @@ CondVar::~CondVar() {
// Remove thread s from the list of waiters on this condition variable. // Remove thread s from the list of waiters on this condition variable.
void CondVar::Remove(PerThreadSynch *s) { void CondVar::Remove(PerThreadSynch *s) {
SchedulingGuard::ScopedDisable disable_rescheduling;
intptr_t v; intptr_t v;
int c = 0; int c = 0;
for (v = cv_.load(std::memory_order_relaxed);; for (v = cv_.load(std::memory_order_relaxed);;
...@@ -2589,6 +2595,7 @@ void CondVar::Wakeup(PerThreadSynch *w) { ...@@ -2589,6 +2595,7 @@ void CondVar::Wakeup(PerThreadSynch *w) {
} }
void CondVar::Signal() { void CondVar::Signal() {
SchedulingGuard::ScopedDisable disable_rescheduling;
ABSL_TSAN_MUTEX_PRE_SIGNAL(nullptr, 0); ABSL_TSAN_MUTEX_PRE_SIGNAL(nullptr, 0);
intptr_t v; intptr_t v;
int c = 0; int c = 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment