LCOV - code coverage report
Current view: directory - objdir/dist/include/mozilla - BlockingResourceBase.h (source / functions) Found Hit Coverage
Test: app.info Lines: 31 30 96.8 %
Date: 2012-06-02 Functions: 9 9 100.0 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2                 :  * vim: sw=4 ts=4 et :
       3                 :  * ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is mozilla.org code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Netscape Communications Corporation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Chris Jones <jones.chris.g@gmail.com>
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      28                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : 
      41                 : #ifndef mozilla_BlockingResourceBase_h
      42                 : #define mozilla_BlockingResourceBase_h
      43                 : 
      44                 : #include "prlock.h"
      45                 : #include "prlog.h"
      46                 : 
      47                 : #include "nscore.h"
      48                 : #include "nsDebug.h"
      49                 : #include "nsError.h"
      50                 : #include "nsTraceRefcnt.h"
      51                 : 
      52                 : #ifdef DEBUG
      53                 : #include "prinit.h"
      54                 : #include "prthread.h"
      55                 : 
      56                 : #include "nsStringGlue.h"
      57                 : 
      58                 : #include "mozilla/DeadlockDetector.h"
      59                 : #include "nsXPCOM.h"
      60                 : #endif
      61                 : 
      62                 : //
      63                 : // This header is not meant to be included by client code.
      64                 : //
      65                 : 
      66                 : namespace mozilla {
      67                 : 
      68                 : 
      69                 : /**
      70                 :  * BlockingResourceBase
      71                 :  * Base class of resources that might block clients trying to acquire them.  
      72                 :  * Does debugging and deadlock detection in DEBUG builds.
      73                 :  **/
      74                 : class NS_COM_GLUE BlockingResourceBase
      75                 : {
      76                 : public:
      77                 :     // Needs to be kept in sync with kResourceTypeNames.
      78                 :     enum BlockingResourceType { eMutex, eReentrantMonitor, eCondVar };
      79                 : 
      80                 :     /**
      81                 :      * kResourceTypeName
      82                 :      * Human-readable version of BlockingResourceType enum.
      83                 :      */
      84                 :     static const char* const kResourceTypeName[];
      85                 : 
      86                 : 
      87                 : #ifdef DEBUG
      88                 : 
      89                 : private:
      90                 :     // forward declaration for the following typedef
      91                 :     struct DeadlockDetectorEntry;
      92                 : 
      93                 :     // ``DDT'' = ``Deadlock Detector Type''
      94                 :     typedef DeadlockDetector<DeadlockDetectorEntry> DDT;
      95                 : 
      96                 :     /**
      97                 :      * DeadlockDetectorEntry
      98                 :      * We free BlockingResources, but we never free entries in the
      99                 :      * deadlock detector.  This struct outlives its BlockingResource
     100                 :      * and preserves all the state needed to print subsequent
     101                 :      * error messages.
     102                 :      *
     103                 :      * These objects are owned by the deadlock detector.
     104                 :      */
     105                 :     struct DeadlockDetectorEntry
     106                 :     {
     107          182916 :         DeadlockDetectorEntry(const char* aName,
     108                 :                               BlockingResourceType aType) :
     109                 :             mName(aName),
     110                 :             mType(aType),
     111          182916 :             mAcquisitionContext(CallStack::kNone)
     112                 :         {
     113          182916 :             NS_ABORT_IF_FALSE(mName, "Name must be nonnull");
     114          182916 :         }
     115                 :         
     116                 :         /**
     117                 :          * Print
     118                 :          * Write a description of this blocking resource to |out|.  If
     119                 :          * the resource appears to be currently acquired, the current
     120                 :          * acquisition context is printed and true is returned.
     121                 :          * Otherwise, we print the context from |aFirstSeen|, the
     122                 :          * first acquisition from which the code calling |Print()|
     123                 :          * became interested in us, and return false.  |Print()| can
     124                 :          * be forced to print the context from |aFirstSeen| regardless
     125                 :          * by passing |aPrintFirstSeenCx=true|.
     126                 :          *
     127                 :          * *NOT* thread safe.  Reads |mAcquisitionContext| without
     128                 :          * synchronization, but this will not cause correctness
     129                 :          * problems.
     130                 :          *
     131                 :          * FIXME bug 456272: hack alert: because we can't write call
     132                 :          * contexts into strings, all info is written to stderr, but
     133                 :          * only some info is written into |out|
     134                 :          */
     135                 :         bool Print(const DDT::ResourceAcquisition& aFirstSeen,
     136                 :                    nsACString& out,
     137                 :                    bool aPrintFirstSeenCx=false) const;
     138                 : 
     139                 :         /**
     140                 :          * mName
     141                 :          * A descriptive name for this resource.  Used in error
     142                 :          * messages etc.
     143                 :          */
     144                 :         const char* mName;
     145                 :         /**
     146                 :          * mType
     147                 :          * The more specific type of this resource.  Used to implement
     148                 :          * special semantics (e.g., reentrancy of monitors).
     149                 :          **/
     150                 :         BlockingResourceType mType;
     151                 :         /**
     152                 :          * mAcquisitionContext
     153                 :          * The calling context from which this resource was acquired, or
     154                 :          * |CallStack::kNone| if it is currently free (or freed).
     155                 :          */
     156                 :         CallStack mAcquisitionContext;
     157                 :     };
     158                 : 
     159                 : protected:
     160                 :     /**
     161                 :      * BlockingResourceBase
     162                 :      * Initialize this blocking resource.  Also hooks the resource into
     163                 :      * instrumentation code.
     164                 :      *
     165                 :      * Thread safe.
     166                 :      *
     167                 :      * @param aName A meaningful, unique name that can be used in
     168                 :      *              error messages, et al.
     169                 :      * @param aType The specific type of |this|, if any.
     170                 :      **/
     171                 :     BlockingResourceBase(const char* aName, BlockingResourceType aType);
     172                 : 
     173                 :     ~BlockingResourceBase();
     174                 : 
     175                 :     /**
     176                 :      * CheckAcquire
     177                 :      *
     178                 :      * Thread safe.
     179                 :      *
     180                 :      * @param aCallContext the client's calling context from which the
     181                 :      *        original acquisition request was made.
     182                 :      **/
     183                 :     void CheckAcquire(const CallStack& aCallContext);
     184                 : 
     185                 :     /**
     186                 :      * Acquire
     187                 :      *
     188                 :      * *NOT* thread safe.  Requires ownership of underlying resource.
     189                 :      *
     190                 :      * @param aCallContext the client's calling context from which the
     191                 :      *        original acquisition request was made.
     192                 :      **/
     193                 :     void Acquire(const CallStack& aCallContext); //NS_NEEDS_RESOURCE(this)
     194                 : 
     195                 :     /**
     196                 :      * Release
     197                 :      * Remove this resource from the current thread's acquisition chain.
     198                 :      * The resource does not have to be at the front of the chain, although
     199                 :      * it is confusing to release resources in a different order than they
     200                 :      * are acquired.  This generates a warning.
     201                 :      *
     202                 :      * *NOT* thread safe.  Requires ownership of underlying resource.
     203                 :      **/
     204                 :     void Release();             //NS_NEEDS_RESOURCE(this)
     205                 : 
     206                 :     /**
     207                 :      * PrintCycle
     208                 :      * Append to |out| detailed information about the circular
     209                 :      * dependency in |cycle|.  Returns true if it *appears* that this
     210                 :      * cycle may represent an imminent deadlock, but this is merely a
     211                 :      * heuristic; the value returned may be a false positive or false
     212                 :      * negative.
     213                 :      *
     214                 :      * *NOT* thread safe.  Calls |Print()|.
     215                 :      *
     216                 :      * FIXME bug 456272 hack alert: because we can't write call
     217                 :      * contexts into strings, all info is written to stderr, but only
     218                 :      * some info is written into |out|
     219                 :      */
     220                 :     static bool PrintCycle(const DDT::ResourceAcquisitionArray* cycle,
     221                 :                            nsACString& out);
     222                 : 
     223                 :     /**
     224                 :      * ResourceChainFront
     225                 :      *
     226                 :      * Thread safe.
     227                 :      *
     228                 :      * @return the front of the resource acquisition chain, i.e., the last
     229                 :      *         resource acquired.
     230                 :      */
     231       128531732 :     static BlockingResourceBase* ResourceChainFront()
     232                 :     {
     233                 :         return (BlockingResourceBase*)
     234       128531732 :             PR_GetThreadPrivate(sResourceAcqnChainFrontTPI);
     235                 :     }
     236                 : 
     237                 :     /**
     238                 :      * ResourceChainPrev
     239                 :      *
     240                 :      * *NOT* thread safe.  Requires ownership of underlying resource.
     241                 :      */
     242                 :     static BlockingResourceBase*
     243          499782 :     ResourceChainPrev(const BlockingResourceBase* aResource)
     244                 :     {
     245          499782 :         return aResource->mChainPrev;
     246                 :     } //NS_NEEDS_RESOURCE(this)
     247                 : 
     248                 :     /**
     249                 :      * ResourceChainAppend
     250                 :      * Set |this| to the front of the resource acquisition chain, and link
     251                 :      * |this| to |aPrev|.
     252                 :      *
     253                 :      * *NOT* thread safe.  Requires ownership of underlying resource.
     254                 :      */
     255        26691326 :     void ResourceChainAppend(BlockingResourceBase* aPrev)
     256                 :     {
     257        26691326 :         mChainPrev = aPrev;
     258        26691326 :         PR_SetThreadPrivate(sResourceAcqnChainFrontTPI, this);
     259        26691188 :     } //NS_NEEDS_RESOURCE(this)
     260                 : 
     261                 :     /**
     262                 :      * ResourceChainRemove
     263                 :      * Remove |this| from the front of the resource acquisition chain.
     264                 :      *
     265                 :      * *NOT* thread safe.  Requires ownership of underlying resource.
     266                 :      */
     267        26691672 :     void ResourceChainRemove()
     268                 :     {
     269        26691672 :         NS_ASSERTION(this == ResourceChainFront(), "not at chain front");
     270        26691523 :         PR_SetThreadPrivate(sResourceAcqnChainFrontTPI, mChainPrev);
     271        26691252 :     } //NS_NEEDS_RESOURCE(this)
     272                 : 
     273                 :     /**
     274                 :      * GetAcquisitionContext
     275                 :      * Return the calling context from which this resource was acquired,
     276                 :      * or CallStack::kNone if it's currently free.
     277                 :      *
     278                 :      * *NOT* thread safe.  Requires ownership of underlying resource.
     279                 :      */
     280                 :     CallStack
     281          111875 :     GetAcquisitionContext()
     282                 :     {
     283          111875 :         return mDDEntry->mAcquisitionContext;
     284                 :     }
     285                 : 
     286                 :     /**
     287                 :      * SetAcquisitionContext
     288                 :      * Set the calling context from which this resource was acquired.
     289                 :      *
     290                 :      * *NOT* thread safe.  Requires ownership of underlying resource.
     291                 :      */
     292                 :     void
     293          223748 :     SetAcquisitionContext(CallStack aAcquisitionContext)
     294                 :     {
     295          223748 :         mDDEntry->mAcquisitionContext = aAcquisitionContext;
     296          223744 :     }
     297                 : 
     298                 :     /**
     299                 :      * mChainPrev
     300                 :      * A series of resource acquisitions creates a chain of orders.  This
     301                 :      * chain is implemented as a linked list; |mChainPrev| points to the
     302                 :      * resource most recently Acquire()'d before this one.
     303                 :      **/
     304                 :     BlockingResourceBase* mChainPrev;
     305                 : 
     306                 : private:
     307                 :     /**
     308                 :      * mDDEntry
     309                 :      * The key for this BlockingResourceBase in the deadlock detector.
     310                 :      */
     311                 :     DeadlockDetectorEntry* mDDEntry;
     312                 : 
     313                 :     /**
     314                 :      * sCallOnce
     315                 :      * Ensures static members are initialized only once, and in a
     316                 :      * thread-safe way.
     317                 :      */
     318                 :     static PRCallOnceType sCallOnce;
     319                 : 
     320                 :     /**
     321                 :      * sResourceAcqnChainFrontTPI
     322                 :      * Thread-private index to the front of each thread's resource
     323                 :      * acquisition chain.
     324                 :      */
     325                 :     static PRUintn sResourceAcqnChainFrontTPI;
     326                 : 
     327                 :     /**
     328                 :      * sDeadlockDetector
     329                 :      * Does as named.
     330                 :      */
     331                 :     static DDT* sDeadlockDetector;
     332                 : 
     333                 :     /**
     334                 :      * InitStatics
     335                 :      * Inititialize static members of BlockingResourceBase that can't
     336                 :      * be statically initialized.
     337                 :      *
     338                 :      * *NOT* thread safe.
     339                 :      */
     340            1446 :     static PRStatus InitStatics() {
     341            1446 :         PR_NewThreadPrivateIndex(&sResourceAcqnChainFrontTPI, 0);
     342            1446 :         sDeadlockDetector = new DDT();
     343            1446 :         if (!sDeadlockDetector)
     344               0 :             NS_RUNTIMEABORT("can't allocate deadlock detector");
     345            1446 :         return PR_SUCCESS;
     346                 :     }
     347                 : 
     348                 :     /**
     349                 :      * Shutdown
     350                 :      * Free static members.
     351                 :      *
     352                 :      * *NOT* thread safe.
     353                 :      */
     354            1442 :     static void Shutdown() {
     355            1442 :         delete sDeadlockDetector;
     356            1442 :         sDeadlockDetector = 0;
     357            1442 :     }
     358                 : 
     359                 : #  ifdef MOZILLA_INTERNAL_API
     360                 :     // so it can call BlockingResourceBase::Shutdown()
     361                 :     friend void LogTerm();
     362                 : #  endif  // ifdef MOZILLA_INTERNAL_API
     363                 : 
     364                 : #else  // non-DEBUG implementation
     365                 : 
     366                 :     BlockingResourceBase(const char* aName, BlockingResourceType aType)
     367                 :     {
     368                 :     }
     369                 : 
     370                 :     ~BlockingResourceBase()
     371                 :     {
     372                 :     }
     373                 : 
     374                 : #endif
     375                 : };
     376                 : 
     377                 : 
     378                 : } // namespace mozilla
     379                 : 
     380                 : 
     381                 : #endif // mozilla_BlockingResourceBase_h

Generated by: LCOV version 1.7