LCOV - code coverage report
Current view: top level - xpcom/threads - HangAnnotations.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 17 110 15.5 %
Date: 2017-07-14 16:53:18 Functions: 3 23 13.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; 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/HangAnnotations.h"
       8             : 
       9             : #include <vector>
      10             : 
      11             : #include "MainThreadUtils.h"
      12             : #include "mozilla/DebugOnly.h"
      13             : #include "nsXULAppAPI.h"
      14             : 
      15             : namespace mozilla {
      16             : namespace HangMonitor {
      17             : 
      18             : // Chrome hang annotators. This can go away once BHR has completely replaced
      19             : // ChromeHangs.
      20           3 : static StaticAutoPtr<Observer::Annotators> gChromehangAnnotators;
      21             : 
      22             : class BrowserHangAnnotations : public HangAnnotations
      23             : {
      24             : public:
      25             :   BrowserHangAnnotations();
      26             :   ~BrowserHangAnnotations();
      27             : 
      28             :   void AddAnnotation(const nsAString& aName, const int32_t aData) override;
      29             :   void AddAnnotation(const nsAString& aName, const double aData) override;
      30             :   void AddAnnotation(const nsAString& aName, const nsAString& aData) override;
      31             :   void AddAnnotation(const nsAString& aName, const nsACString& aData) override;
      32             :   void AddAnnotation(const nsAString& aName, const bool aData) override;
      33             : 
      34             :   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
      35             :   bool IsEmpty() const override;
      36             :   UniquePtr<Enumerator> GetEnumerator() override;
      37             : 
      38             :   typedef std::pair<nsString, nsString> AnnotationType;
      39             :   typedef std::vector<AnnotationType> VectorType;
      40             :   typedef VectorType::const_iterator IteratorType;
      41             : 
      42             : private:
      43             :   VectorType  mAnnotations;
      44             : };
      45             : 
      46           0 : BrowserHangAnnotations::BrowserHangAnnotations()
      47             : {
      48           0 :   MOZ_COUNT_CTOR(BrowserHangAnnotations);
      49           0 : }
      50             : 
      51           0 : BrowserHangAnnotations::~BrowserHangAnnotations()
      52             : {
      53           0 :   MOZ_COUNT_DTOR(BrowserHangAnnotations);
      54           0 : }
      55             : 
      56             : void
      57           0 : BrowserHangAnnotations::AddAnnotation(const nsAString& aName, const int32_t aData)
      58             : {
      59           0 :   nsString dataString;
      60           0 :   dataString.AppendInt(aData);
      61           0 :   AnnotationType annotation = std::make_pair(nsString(aName), dataString);
      62           0 :   mAnnotations.push_back(annotation);
      63           0 : }
      64             : 
      65             : void
      66           0 : BrowserHangAnnotations::AddAnnotation(const nsAString& aName, const double aData)
      67             : {
      68           0 :   nsString dataString;
      69           0 :   dataString.AppendFloat(aData);
      70           0 :   AnnotationType annotation = std::make_pair(nsString(aName), dataString);
      71           0 :   mAnnotations.push_back(annotation);
      72           0 : }
      73             : 
      74             : void
      75           0 : BrowserHangAnnotations::AddAnnotation(const nsAString& aName, const nsAString& aData)
      76             : {
      77           0 :   AnnotationType annotation = std::make_pair(nsString(aName), nsString(aData));
      78           0 :   mAnnotations.push_back(annotation);
      79           0 : }
      80             : 
      81             : void
      82           0 : BrowserHangAnnotations::AddAnnotation(const nsAString& aName, const nsACString& aData)
      83             : {
      84           0 :   nsString dataString;
      85           0 :   AppendUTF8toUTF16(aData, dataString);
      86           0 :   AnnotationType annotation = std::make_pair(nsString(aName), dataString);
      87           0 :   mAnnotations.push_back(annotation);
      88           0 : }
      89             : 
      90             : void
      91           0 : BrowserHangAnnotations::AddAnnotation(const nsAString& aName, const bool aData)
      92             : {
      93           0 :   nsString dataString;
      94           0 :   dataString += aData ? NS_LITERAL_STRING("true") : NS_LITERAL_STRING("false");
      95           0 :   AnnotationType annotation = std::make_pair(nsString(aName), dataString);
      96           0 :   mAnnotations.push_back(annotation);
      97           0 : }
      98             : 
      99             : /**
     100             :  * This class itself does not use synchronization but it (and its parent object)
     101             :  * should be protected by mutual exclusion in some way. In Telemetry the chrome
     102             :  * hang data is protected via TelemetryImpl::mHangReportsMutex.
     103             :  */
     104             : class ChromeHangAnnotationEnumerator : public HangAnnotations::Enumerator
     105             : {
     106             : public:
     107             :   explicit ChromeHangAnnotationEnumerator(const BrowserHangAnnotations::VectorType& aAnnotations);
     108             :   ~ChromeHangAnnotationEnumerator();
     109             : 
     110             :   virtual bool Next(nsAString& aOutName, nsAString& aOutValue);
     111             : 
     112             : private:
     113             :   BrowserHangAnnotations::IteratorType mIterator;
     114             :   BrowserHangAnnotations::IteratorType mEnd;
     115             : };
     116             : 
     117           0 : ChromeHangAnnotationEnumerator::ChromeHangAnnotationEnumerator(
     118           0 :                           const BrowserHangAnnotations::VectorType& aAnnotations)
     119             :   : mIterator(aAnnotations.begin())
     120           0 :   , mEnd(aAnnotations.end())
     121             : {
     122           0 :   MOZ_COUNT_CTOR(ChromeHangAnnotationEnumerator);
     123           0 : }
     124             : 
     125           0 : ChromeHangAnnotationEnumerator::~ChromeHangAnnotationEnumerator()
     126             : {
     127           0 :   MOZ_COUNT_DTOR(ChromeHangAnnotationEnumerator);
     128           0 : }
     129             : 
     130             : bool
     131           0 : ChromeHangAnnotationEnumerator::Next(nsAString& aOutName, nsAString& aOutValue)
     132             : {
     133           0 :   aOutName.Truncate();
     134           0 :   aOutValue.Truncate();
     135           0 :   if (mIterator == mEnd) {
     136           0 :     return false;
     137             :   }
     138           0 :   aOutName = mIterator->first;
     139           0 :   aOutValue = mIterator->second;
     140           0 :   ++mIterator;
     141           0 :   return true;
     142             : }
     143             : 
     144             : bool
     145           0 : BrowserHangAnnotations::IsEmpty() const
     146             : {
     147           0 :   return mAnnotations.empty();
     148             : }
     149             : 
     150             : size_t
     151           0 : BrowserHangAnnotations::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
     152             : {
     153             :   size_t result = sizeof(mAnnotations) +
     154           0 :                   mAnnotations.capacity() * sizeof(AnnotationType);
     155           0 :   for (IteratorType i = mAnnotations.begin(), e = mAnnotations.end(); i != e;
     156             :        ++i) {
     157           0 :     result += i->first.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
     158           0 :     result += i->second.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
     159             :   }
     160             : 
     161           0 :   return result;
     162             : }
     163             : 
     164             : UniquePtr<HangAnnotations::Enumerator>
     165           0 : BrowserHangAnnotations::GetEnumerator()
     166             : {
     167           0 :   if (mAnnotations.empty()) {
     168           0 :     return nullptr;
     169             :   }
     170           0 :   return MakeUnique<ChromeHangAnnotationEnumerator>(mAnnotations);
     171             : }
     172             : 
     173             : namespace Observer {
     174             : 
     175           1 : Annotators::Annotators()
     176           1 :   : mMutex("HangMonitor::Annotators::mMutex")
     177             : {
     178           1 :   MOZ_COUNT_CTOR(Annotators);
     179           1 : }
     180             : 
     181           0 : Annotators::~Annotators()
     182             : {
     183           0 :   MOZ_ASSERT(mAnnotators.empty());
     184           0 :   MOZ_COUNT_DTOR(Annotators);
     185           0 : }
     186             : 
     187             : bool
     188           1 : Annotators::Register(Annotator& aAnnotator)
     189             : {
     190           2 :   MutexAutoLock lock(mMutex);
     191           1 :   auto result = mAnnotators.insert(&aAnnotator);
     192           2 :   return result.second;
     193             : }
     194             : 
     195             : bool
     196           0 : Annotators::Unregister(Annotator& aAnnotator)
     197             : {
     198           0 :   MutexAutoLock lock(mMutex);
     199           0 :   DebugOnly<std::set<Annotator*>::size_type> numErased;
     200           0 :   numErased = mAnnotators.erase(&aAnnotator);
     201           0 :   MOZ_ASSERT(numErased == 1);
     202           0 :   return mAnnotators.empty();
     203             : }
     204             : 
     205             : UniquePtr<HangAnnotations>
     206           0 : Annotators::GatherAnnotations()
     207             : {
     208           0 :   auto annotations = MakeUnique<BrowserHangAnnotations>();
     209             :   { // Scope for lock
     210           0 :     MutexAutoLock lock(mMutex);
     211           0 :     for (std::set<Annotator*>::iterator i = mAnnotators.begin(),
     212           0 :                                         e = mAnnotators.end();
     213             :          i != e; ++i) {
     214           0 :       (*i)->AnnotateHang(*annotations);
     215             :     }
     216             :   }
     217           0 :   if (annotations->IsEmpty()) {
     218           0 :     return nullptr;
     219             :   }
     220           0 :   return Move(annotations);
     221             : }
     222             : 
     223             : } // namespace Observer
     224             : 
     225             : void
     226           3 : RegisterAnnotator(Annotator& aAnnotator)
     227             : {
     228           3 :   BackgroundHangMonitor::RegisterAnnotator(aAnnotator);
     229             :   // We still register annotators for ChromeHangs
     230           6 :   if (NS_IsMainThread() &&
     231           3 :       GeckoProcessType_Default == XRE_GetProcessType()) {
     232           1 :     if (!gChromehangAnnotators) {
     233           1 :       gChromehangAnnotators = new Observer::Annotators();
     234             :     }
     235           1 :     gChromehangAnnotators->Register(aAnnotator);
     236             :   }
     237           3 : }
     238             : 
     239             : void
     240           0 : UnregisterAnnotator(Annotator& aAnnotator)
     241             : {
     242           0 :   BackgroundHangMonitor::UnregisterAnnotator(aAnnotator);
     243             :   // We still register annotators for ChromeHangs
     244           0 :   if (NS_IsMainThread() &&
     245           0 :       GeckoProcessType_Default == XRE_GetProcessType()) {
     246           0 :     if (gChromehangAnnotators->Unregister(aAnnotator)) {
     247           0 :       gChromehangAnnotators = nullptr;
     248             :     }
     249             :   }
     250           0 : }
     251             : 
     252             : UniquePtr<HangAnnotations>
     253           0 : ChromeHangAnnotatorCallout()
     254             : {
     255           0 :   if (!gChromehangAnnotators) {
     256           0 :     return nullptr;
     257             :   }
     258           0 :   return gChromehangAnnotators->GatherAnnotations();
     259             : }
     260             : 
     261             : } // namespace HangMonitor
     262             : } // namespace mozilla

Generated by: LCOV version 1.13