LCOV - code coverage report
Current view: top level - xpcom/threads - BlockingResourceBase.h (source / functions) Hit Total Coverage
Test: output.info Lines: 22 22 100.0 %
Date: 2017-07-14 16:53:18 Functions: 8 8 100.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             : 
       8             : #ifndef mozilla_BlockingResourceBase_h
       9             : #define mozilla_BlockingResourceBase_h
      10             : 
      11             : #include "mozilla/Logging.h"
      12             : 
      13             : #include "nscore.h"
      14             : #include "nsDebug.h"
      15             : #include "nsError.h"
      16             : #include "nsISupportsImpl.h"
      17             : 
      18             : #ifdef DEBUG
      19             : 
      20             : // NB: Comment this out to enable callstack tracking.
      21             : #define MOZ_CALLSTACK_DISABLED
      22             : 
      23             : #include "prinit.h"
      24             : 
      25             : #include "nsStringGlue.h"
      26             : 
      27             : #ifndef MOZ_CALLSTACK_DISABLED
      28             : #include "nsTArray.h"
      29             : #endif
      30             : 
      31             : #include "nsXPCOM.h"
      32             : #endif
      33             : 
      34             : //
      35             : // This header is not meant to be included by client code.
      36             : //
      37             : 
      38             : namespace mozilla {
      39             : 
      40             : #ifdef DEBUG
      41             : template <class T> class DeadlockDetector;
      42             : #endif
      43             : 
      44             : /**
      45             :  * BlockingResourceBase
      46             :  * Base class of resources that might block clients trying to acquire them.
      47             :  * Does debugging and deadlock detection in DEBUG builds.
      48             :  **/
      49             : class BlockingResourceBase
      50             : {
      51             : public:
      52             :   // Needs to be kept in sync with kResourceTypeNames.
      53             :   enum BlockingResourceType { eMutex, eReentrantMonitor, eCondVar };
      54             : 
      55             :   /**
      56             :    * kResourceTypeName
      57             :    * Human-readable version of BlockingResourceType enum.
      58             :    */
      59             :   static const char* const kResourceTypeName[];
      60             : 
      61             : 
      62             : #ifdef DEBUG
      63             : 
      64             :   static size_t
      65             :   SizeOfDeadlockDetector(MallocSizeOf aMallocSizeOf);
      66             : 
      67             :   /**
      68             :    * Print
      69             :    * Write a description of this blocking resource to |aOut|.  If
      70             :    * the resource appears to be currently acquired, the current
      71             :    * acquisition context is printed and true is returned.
      72             :    * Otherwise, we print the context from |aFirstSeen|, the
      73             :    * first acquisition from which the code calling |Print()|
      74             :    * became interested in us, and return false.
      75             :    *
      76             :    * *NOT* thread safe.  Reads |mAcquisitionContext| without
      77             :    * synchronization, but this will not cause correctness
      78             :    * problems.
      79             :    *
      80             :    * FIXME bug 456272: hack alert: because we can't write call
      81             :    * contexts into strings, all info is written to stderr, but
      82             :    * only some info is written into |aOut|
      83             :    */
      84             :   bool Print(nsACString& aOut) const;
      85             : 
      86             :   size_t
      87             :   SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
      88             :   {
      89             :     // NB: |mName| is not reported as it's expected to be a static string.
      90             :     //     If we switch to a nsString it should be added to the tally.
      91             :     //     |mChainPrev| is not reported because its memory is not owned.
      92             :     size_t n = aMallocSizeOf(this);
      93             :     return n;
      94             :   }
      95             : 
      96             :   // ``DDT'' = ``Deadlock Detector Type''
      97             :   typedef DeadlockDetector<BlockingResourceBase> DDT;
      98             : 
      99             : protected:
     100             : #ifdef MOZ_CALLSTACK_DISABLED
     101             :   typedef bool AcquisitionState;
     102             : #else
     103             :   typedef AutoTArray<void*, 24> AcquisitionState;
     104             : #endif
     105             : 
     106             :   /**
     107             :    * BlockingResourceBase
     108             :    * Initialize this blocking resource.  Also hooks the resource into
     109             :    * instrumentation code.
     110             :    *
     111             :    * Thread safe.
     112             :    *
     113             :    * @param aName A meaningful, unique name that can be used in
     114             :    *              error messages, et al.
     115             :    * @param aType The specific type of |this|, if any.
     116             :    **/
     117             :   BlockingResourceBase(const char* aName, BlockingResourceType aType);
     118             : 
     119             :   ~BlockingResourceBase();
     120             : 
     121             :   /**
     122             :    * CheckAcquire
     123             :    *
     124             :    * Thread safe.
     125             :    **/
     126             :   void CheckAcquire();
     127             : 
     128             :   /**
     129             :    * Acquire
     130             :    *
     131             :    * *NOT* thread safe.  Requires ownership of underlying resource.
     132             :    **/
     133             :   void Acquire(); //NS_NEEDS_RESOURCE(this)
     134             : 
     135             :   /**
     136             :    * Release
     137             :    * Remove this resource from the current thread's acquisition chain.
     138             :    * The resource does not have to be at the front of the chain, although
     139             :    * it is confusing to release resources in a different order than they
     140             :    * are acquired.  This generates a warning.
     141             :    *
     142             :    * *NOT* thread safe.  Requires ownership of underlying resource.
     143             :    **/
     144             :   void Release();             //NS_NEEDS_RESOURCE(this)
     145             : 
     146             :   /**
     147             :    * ResourceChainFront
     148             :    *
     149             :    * Thread safe.
     150             :    *
     151             :    * @return the front of the resource acquisition chain, i.e., the last
     152             :    *         resource acquired.
     153             :    */
     154      382899 :   static BlockingResourceBase* ResourceChainFront()
     155             :   {
     156             :     return
     157      382899 :       (BlockingResourceBase*)PR_GetThreadPrivate(sResourceAcqnChainFrontTPI);
     158             :   }
     159             : 
     160             :   /**
     161             :    * ResourceChainPrev
     162             :    *
     163             :    * *NOT* thread safe.  Requires ownership of underlying resource.
     164             :    */
     165         814 :   static BlockingResourceBase* ResourceChainPrev(
     166             :       const BlockingResourceBase* aResource)
     167             :   {
     168         814 :     return aResource->mChainPrev;
     169             :   } //NS_NEEDS_RESOURCE(this)
     170             : 
     171             :   /**
     172             :    * ResourceChainAppend
     173             :    * Set |this| to the front of the resource acquisition chain, and link
     174             :    * |this| to |aPrev|.
     175             :    *
     176             :    * *NOT* thread safe.  Requires ownership of underlying resource.
     177             :    */
     178       93730 :   void ResourceChainAppend(BlockingResourceBase* aPrev)
     179             :   {
     180       93730 :     mChainPrev = aPrev;
     181       93730 :     PR_SetThreadPrivate(sResourceAcqnChainFrontTPI, this);
     182       93718 :   } //NS_NEEDS_RESOURCE(this)
     183             : 
     184             :   /**
     185             :    * ResourceChainRemove
     186             :    * Remove |this| from the front of the resource acquisition chain.
     187             :    *
     188             :    * *NOT* thread safe.  Requires ownership of underlying resource.
     189             :    */
     190       93660 :   void ResourceChainRemove()
     191             :   {
     192       93660 :     NS_ASSERTION(this == ResourceChainFront(), "not at chain front");
     193       93648 :     PR_SetThreadPrivate(sResourceAcqnChainFrontTPI, mChainPrev);
     194       93651 :   } //NS_NEEDS_RESOURCE(this)
     195             : 
     196             :   /**
     197             :    * GetAcquisitionState
     198             :    * Return whether or not this resource was acquired.
     199             :    *
     200             :    * *NOT* thread safe.  Requires ownership of underlying resource.
     201             :    */
     202         752 :   AcquisitionState GetAcquisitionState()
     203             :   {
     204         752 :     return mAcquired;
     205             :   }
     206             : 
     207             :   /**
     208             :    * SetAcquisitionState
     209             :    * Set whether or not this resource was acquired.
     210             :    *
     211             :    * *NOT* thread safe.  Requires ownership of underlying resource.
     212             :    */
     213         694 :   void SetAcquisitionState(const AcquisitionState& aAcquisitionState)
     214             :   {
     215         694 :     mAcquired = aAcquisitionState;
     216         694 :   }
     217             : 
     218             :   /**
     219             :    * ClearAcquisitionState
     220             :    * Indicate this resource is not acquired.
     221             :    *
     222             :    * *NOT* thread safe.  Requires ownership of underlying resource.
     223             :    */
     224       94402 :   void ClearAcquisitionState()
     225             :   {
     226             : #ifdef MOZ_CALLSTACK_DISABLED
     227       94402 :     mAcquired = false;
     228             : #else
     229             :     mAcquired.Clear();
     230             : #endif
     231       94402 :   }
     232             : 
     233             :   /**
     234             :    * IsAcquired
     235             :    * Indicates if this resource is acquired.
     236             :    *
     237             :    * *NOT* thread safe.  Requires ownership of underlying resource.
     238             :    */
     239      239523 :   bool IsAcquired() const
     240             :   {
     241             : #ifdef MOZ_CALLSTACK_DISABLED
     242      239523 :     return mAcquired;
     243             : #else
     244             :     return !mAcquired.IsEmpty();
     245             : #endif
     246             :   }
     247             : 
     248             :   /**
     249             :    * mChainPrev
     250             :    * A series of resource acquisitions creates a chain of orders.  This
     251             :    * chain is implemented as a linked list; |mChainPrev| points to the
     252             :    * resource most recently Acquire()'d before this one.
     253             :    **/
     254             :   BlockingResourceBase* mChainPrev;
     255             : 
     256             : private:
     257             :   /**
     258             :    * mName
     259             :    * A descriptive name for this resource.  Used in error
     260             :    * messages etc.
     261             :    */
     262             :   const char* mName;
     263             : 
     264             :   /**
     265             :    * mType
     266             :    * The more specific type of this resource.  Used to implement
     267             :    * special semantics (e.g., reentrancy of monitors).
     268             :    **/
     269             :   BlockingResourceType mType;
     270             : 
     271             :   /**
     272             :    * mAcquired
     273             :    * Indicates if this resource is currently acquired.
     274             :    */
     275             :   AcquisitionState mAcquired;
     276             : 
     277             : #ifndef MOZ_CALLSTACK_DISABLED
     278             :   /**
     279             :    * mFirstSeen
     280             :    * Inidicates where this resource was first acquired.
     281             :    */
     282             :   AcquisitionState mFirstSeen;
     283             : #endif
     284             : 
     285             :   /**
     286             :    * sCallOnce
     287             :    * Ensures static members are initialized only once, and in a
     288             :    * thread-safe way.
     289             :    */
     290             :   static PRCallOnceType sCallOnce;
     291             : 
     292             :   /**
     293             :    * sResourceAcqnChainFrontTPI
     294             :    * Thread-private index to the front of each thread's resource
     295             :    * acquisition chain.
     296             :    */
     297             :   static unsigned sResourceAcqnChainFrontTPI;
     298             : 
     299             :   /**
     300             :    * sDeadlockDetector
     301             :    * Does as named.
     302             :    */
     303             :   static DDT* sDeadlockDetector;
     304             : 
     305             :   /**
     306             :    * InitStatics
     307             :    * Inititialize static members of BlockingResourceBase that can't
     308             :    * be statically initialized.
     309             :    *
     310             :    * *NOT* thread safe.
     311             :    */
     312             :   static PRStatus InitStatics();
     313             : 
     314             :   /**
     315             :    * Shutdown
     316             :    * Free static members.
     317             :    *
     318             :    * *NOT* thread safe.
     319             :    */
     320             :   static void Shutdown();
     321             : 
     322             :   static void StackWalkCallback(uint32_t aFrameNumber, void* aPc,
     323             :                                 void* aSp, void* aClosure);
     324             :   static void GetStackTrace(AcquisitionState& aState);
     325             : 
     326             : #  ifdef MOZILLA_INTERNAL_API
     327             :   // so it can call BlockingResourceBase::Shutdown()
     328             :   friend void LogTerm();
     329             : #  endif  // ifdef MOZILLA_INTERNAL_API
     330             : 
     331             : #else  // non-DEBUG implementation
     332             : 
     333             :   BlockingResourceBase(const char* aName, BlockingResourceType aType) {}
     334             : 
     335             :   ~BlockingResourceBase() {}
     336             : 
     337             : #endif
     338             : };
     339             : 
     340             : 
     341             : } // namespace mozilla
     342             : 
     343             : 
     344             : #endif // mozilla_BlockingResourceBase_h

Generated by: LCOV version 1.13