tor-browser

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

AutoProfilerLabel.cpp (3739B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "mozilla/AutoProfilerLabel.h"
      8 
      9 #include "mozilla/Assertions.h"
     10 #include "mozilla/PlatformMutex.h"
     11 
     12 namespace mozilla {
     13 
     14 // RAII class that encapsulates all shared static data, and enforces locking
     15 // when accessing this data.
     16 class MOZ_RAII AutoProfilerLabelData {
     17 public:
     18  AutoProfilerLabelData() { sAPLMutex.Lock(); }
     19 
     20  ~AutoProfilerLabelData() { sAPLMutex.Unlock(); }
     21 
     22  AutoProfilerLabelData(const AutoProfilerLabelData&) = delete;
     23  void operator=(const AutoProfilerLabelData&) = delete;
     24 
     25  const ProfilerLabelEnter& EnterCRef() const { return sEnter; }
     26  ProfilerLabelEnter& EnterRef() { return sEnter; }
     27 
     28  const ProfilerLabelExit& ExitCRef() const { return sExit; }
     29  ProfilerLabelExit& ExitRef() { return sExit; }
     30 
     31  const uint32_t& GenerationCRef() const { return sGeneration; }
     32  uint32_t& GenerationRef() { return sGeneration; }
     33 
     34  static bool RacyIsProfilerPresent() { return !!sGeneration; }
     35 
     36 private:
     37  // Thin shell around mozglue PlatformMutex, for local internal use.
     38  // Does not preserve behavior in JS record/replay.
     39  class Mutex : private mozilla::detail::MutexImpl {
     40   public:
     41    Mutex() = default;
     42    void Lock() { mozilla::detail::MutexImpl::lock(); }
     43    void Unlock() { mozilla::detail::MutexImpl::unlock(); }
     44  };
     45 
     46  // Mutex protecting access to the following static members.
     47  static Mutex sAPLMutex MOZ_UNANNOTATED;
     48 
     49  static ProfilerLabelEnter sEnter;
     50  static ProfilerLabelExit sExit;
     51 
     52  // Current "generation" of RegisterProfilerLabelEnterExit calls.
     53  static uint32_t sGeneration;
     54 };
     55 
     56 MOZ_RUNINIT /* static */ AutoProfilerLabelData::Mutex
     57    AutoProfilerLabelData::sAPLMutex;
     58 /* static */ ProfilerLabelEnter AutoProfilerLabelData::sEnter = nullptr;
     59 /* static */ ProfilerLabelExit AutoProfilerLabelData::sExit = nullptr;
     60 /* static */ uint32_t AutoProfilerLabelData::sGeneration = 0;
     61 
     62 void RegisterProfilerLabelEnterExit(ProfilerLabelEnter aEnter,
     63                                    ProfilerLabelExit aExit) {
     64  MOZ_ASSERT(!aEnter == !aExit, "Must provide both null or both non-null");
     65 
     66  AutoProfilerLabelData data;
     67  MOZ_ASSERT(!aEnter != !data.EnterRef(),
     68             "Must go from null to non-null, or from non-null to null");
     69  data.EnterRef() = aEnter;
     70  data.ExitRef() = aExit;
     71  ++data.GenerationRef();
     72 }
     73 
     74 bool IsProfilerPresent() {
     75  return AutoProfilerLabelData::RacyIsProfilerPresent();
     76 }
     77 
     78 ProfilerLabel ProfilerLabelBegin(const char* aLabelName,
     79                                 const char* aDynamicString, void* aSp) {
     80  const AutoProfilerLabelData data;
     81  void* entryContext = (data.EnterCRef())
     82                           ? data.EnterCRef()(aLabelName, aDynamicString, aSp)
     83                           : nullptr;
     84  uint32_t generation = data.GenerationCRef();
     85 
     86  return std::make_tuple(entryContext, generation);
     87 }
     88 
     89 void ProfilerLabelEnd(const ProfilerLabel& aLabel) {
     90  if (!IsValidProfilerLabel(aLabel)) {
     91    return;
     92  }
     93 
     94  const AutoProfilerLabelData data;
     95  if (data.ExitCRef() && (std::get<1>(aLabel) == data.GenerationCRef())) {
     96    data.ExitCRef()(std::get<0>(aLabel));
     97  }
     98 }
     99 
    100 AutoProfilerLabel::AutoProfilerLabel(const char* aLabel,
    101                                     const char* aDynamicString) {
    102  std::tie(mEntryContext, mGeneration) =
    103      ProfilerLabelBegin(aLabel, aDynamicString, this);
    104 }
    105 
    106 AutoProfilerLabel::~AutoProfilerLabel() {
    107  ProfilerLabelEnd(std::make_tuple(mEntryContext, mGeneration));
    108 }
    109 
    110 }  // namespace mozilla