tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

vlog_config.h (6268B)


      1 // Copyright 2022 The Abseil Authors
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     https://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 //
     15 // -----------------------------------------------------------------------------
     16 // vlog_config.h
     17 // -----------------------------------------------------------------------------
     18 //
     19 // This header file defines `VLogSite`, a public primitive that represents
     20 // a callsite for the `VLOG` family of macros and related libraries.
     21 // It also declares and defines multiple internal utilities used to implement
     22 // `VLOG`, such as `VLogSiteManager`.
     23 
     24 #ifndef ABSL_LOG_INTERNAL_VLOG_CONFIG_H_
     25 #define ABSL_LOG_INTERNAL_VLOG_CONFIG_H_
     26 
     27 // IWYU pragma: private, include "absl/log/log.h"
     28 
     29 #include <atomic>
     30 #include <cstdint>
     31 #include <functional>
     32 #include <limits>
     33 #include <type_traits>
     34 
     35 #include "absl/base/attributes.h"
     36 #include "absl/base/config.h"
     37 #include "absl/base/nullability.h"
     38 #include "absl/base/optimization.h"
     39 #include "absl/base/thread_annotations.h"
     40 #include "absl/strings/string_view.h"
     41 
     42 namespace absl {
     43 ABSL_NAMESPACE_BEGIN
     44 namespace log_internal {
     45 
     46 class SyntheticBinary;
     47 class VLogSite;
     48 
     49 int RegisterAndInitialize(VLogSite* absl_nonnull v);
     50 void UpdateVLogSites();
     51 constexpr int kUseFlag = (std::numeric_limits<int16_t>::min)();
     52 
     53 // Represents a unique callsite for a `VLOG()` or `VLOG_IS_ON()` call.
     54 //
     55 // Libraries that provide `VLOG`-like functionality should use this to
     56 // efficiently handle --vmodule.
     57 //
     58 // VLogSite objects must not be destroyed until the program exits. Doing so will
     59 // probably yield nasty segfaults in VLogSiteManager::UpdateLogSites(). The
     60 // recommendation is to make all such objects function-local statics.
     61 class VLogSite final {
     62 public:
     63  // `f` must not be destroyed until the program exits.
     64  explicit constexpr VLogSite(const char* absl_nonnull f)
     65      : file_(f), v_(kUninitialized), next_(nullptr) {}
     66  VLogSite(const VLogSite&) = delete;
     67  VLogSite& operator=(const VLogSite&) = delete;
     68 
     69  // Inlining the function yields a ~3x performance improvement at the cost of a
     70  // 1.5x code size increase at the call site.
     71  // Takes locks but does not allocate memory.
     72  ABSL_ATTRIBUTE_ALWAYS_INLINE
     73  bool IsEnabled(int level) {
     74    int stale_v = v_.load(std::memory_order_relaxed);
     75    if (ABSL_PREDICT_TRUE(level > stale_v)) {
     76      return false;
     77    }
     78 
     79    // We put everything other than the fast path, i.e. vlogging is initialized
     80    // but not on, behind an out-of-line function to reduce code size.
     81    // "level" is almost always a call-site constant, so we can save a bit
     82    // of code space by special-casing for a few common levels.
     83 #if ABSL_HAVE_BUILTIN(__builtin_constant_p) || defined(__GNUC__)
     84    if (__builtin_constant_p(level)) {
     85      if (level == 0) return SlowIsEnabled0(stale_v);
     86      if (level == 1) return SlowIsEnabled1(stale_v);
     87      if (level == 2) return SlowIsEnabled2(stale_v);
     88      if (level == 3) return SlowIsEnabled3(stale_v);
     89      if (level == 4) return SlowIsEnabled4(stale_v);
     90      if (level == 5) return SlowIsEnabled5(stale_v);
     91    }
     92 #endif
     93    return SlowIsEnabled(stale_v, level);
     94  }
     95 
     96 private:
     97  friend int log_internal::RegisterAndInitialize(VLogSite* absl_nonnull v);
     98  friend void log_internal::UpdateVLogSites();
     99  friend class log_internal::SyntheticBinary;
    100  static constexpr int kUninitialized = (std::numeric_limits<int>::max)();
    101 
    102  // SlowIsEnabled performs slower checks to determine whether a log site is
    103  // enabled. Because it is expected to be called somewhat rarely
    104  // (comparatively), it is not inlined to save on code size.
    105  //
    106  // Prerequisites to calling SlowIsEnabled:
    107  //   1) stale_v is uninitialized OR
    108  //   2) stale_v is initialized and >= level (meaning we must log).
    109  // Takes locks but does not allocate memory.
    110  ABSL_ATTRIBUTE_NOINLINE
    111  bool SlowIsEnabled(int stale_v, int level);
    112  ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled0(int stale_v);
    113  ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled1(int stale_v);
    114  ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled2(int stale_v);
    115  ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled3(int stale_v);
    116  ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled4(int stale_v);
    117  ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled5(int stale_v);
    118 
    119  // This object is too size-sensitive to use absl::string_view.
    120  const char* absl_nonnull const file_;
    121  std::atomic<int> v_;
    122  std::atomic<VLogSite*> next_;
    123 };
    124 static_assert(std::is_trivially_destructible<VLogSite>::value,
    125              "VLogSite must be trivially destructible");
    126 
    127 // Returns the current verbose log level of `file`.
    128 // Does not allocate memory.
    129 int VLogLevel(absl::string_view file);
    130 
    131 // Registers a site `v` to get updated as `vmodule` and `v` change.  Also
    132 // initializes the site based on their current values, and returns that result.
    133 // Does not allocate memory.
    134 int RegisterAndInitialize(VLogSite* absl_nonnull v);
    135 
    136 // Allocates memory.
    137 void UpdateVLogSites();
    138 
    139 // Completely overwrites the saved value of `vmodule`.
    140 // Allocates memory.
    141 void UpdateVModule(absl::string_view vmodule);
    142 
    143 // Updates the global verbosity level to `v` and returns the prior value.
    144 // Allocates memory.
    145 int UpdateGlobalVLogLevel(int v);
    146 
    147 // Atomically prepends `module_pattern=log_level` to the start of vmodule.
    148 // Returns the prior value for `module_pattern` if there was an exact match and
    149 // `global_v` otherwise.
    150 // Allocates memory.
    151 int PrependVModule(absl::string_view module_pattern, int log_level);
    152 
    153 // Registers `on_update` to be called whenever `v` or `vmodule` change.
    154 // Allocates memory.
    155 void OnVLogVerbosityUpdate(std::function<void()> cb);
    156 
    157 // Does not allocate memory.
    158 VLogSite* absl_nullable SetVModuleListHeadForTestOnly(
    159    VLogSite* absl_nullable v);
    160 
    161 }  // namespace log_internal
    162 ABSL_NAMESPACE_END
    163 }  // namespace absl
    164 
    165 #endif  // ABSL_LOG_INTERNAL_VLOG_CONFIG_H_