xpcom/glue/BlockingResourceBase.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  * vim: sw=4 ts=4 et :
     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/. */
     8 #ifndef mozilla_BlockingResourceBase_h
     9 #define mozilla_BlockingResourceBase_h
    11 #include "prlog.h"
    13 #include "nscore.h"
    14 #include "nsDebug.h"
    15 #include "nsError.h"
    16 #include "nsISupportsImpl.h"
    18 #ifdef DEBUG
    19 #include "prinit.h"
    20 #include "prthread.h"
    22 #include "nsStringGlue.h"
    24 #include "mozilla/DeadlockDetector.h"
    25 #include "nsXPCOM.h"
    26 #endif
    28 //
    29 // This header is not meant to be included by client code.
    30 //
    32 namespace mozilla {
    35 /**
    36  * BlockingResourceBase
    37  * Base class of resources that might block clients trying to acquire them.  
    38  * Does debugging and deadlock detection in DEBUG builds.
    39  **/
    40 class NS_COM_GLUE BlockingResourceBase
    41 {
    42 public:
    43     // Needs to be kept in sync with kResourceTypeNames.
    44     enum BlockingResourceType { eMutex, eReentrantMonitor, eCondVar };
    46     /**
    47      * kResourceTypeName
    48      * Human-readable version of BlockingResourceType enum.
    49      */
    50     static const char* const kResourceTypeName[];
    53 #ifdef DEBUG
    55 private:
    56     // forward declaration for the following typedef
    57     struct DeadlockDetectorEntry;
    59     // ``DDT'' = ``Deadlock Detector Type''
    60     typedef DeadlockDetector<DeadlockDetectorEntry> DDT;
    62     /**
    63      * DeadlockDetectorEntry
    64      * We free BlockingResources, but we never free entries in the
    65      * deadlock detector.  This struct outlives its BlockingResource
    66      * and preserves all the state needed to print subsequent
    67      * error messages.
    68      *
    69      * These objects are owned by the deadlock detector.
    70      */
    71     struct DeadlockDetectorEntry
    72     {
    73         DeadlockDetectorEntry(const char* aName,
    74                               BlockingResourceType aType) :
    75             mName(aName),
    76             mType(aType),
    77             mAcquisitionContext(CallStack::kNone)
    78         {
    79             NS_ABORT_IF_FALSE(mName, "Name must be nonnull");
    80         }
    82         /**
    83          * Print
    84          * Write a description of this blocking resource to |out|.  If
    85          * the resource appears to be currently acquired, the current
    86          * acquisition context is printed and true is returned.
    87          * Otherwise, we print the context from |aFirstSeen|, the
    88          * first acquisition from which the code calling |Print()|
    89          * became interested in us, and return false.  |Print()| can
    90          * be forced to print the context from |aFirstSeen| regardless
    91          * by passing |aPrintFirstSeenCx=true|.
    92          *
    93          * *NOT* thread safe.  Reads |mAcquisitionContext| without
    94          * synchronization, but this will not cause correctness
    95          * problems.
    96          *
    97          * FIXME bug 456272: hack alert: because we can't write call
    98          * contexts into strings, all info is written to stderr, but
    99          * only some info is written into |out|
   100          */
   101         bool Print(const DDT::ResourceAcquisition& aFirstSeen,
   102                    nsACString& out,
   103                    bool aPrintFirstSeenCx=false) const;
   105         /**
   106          * mName
   107          * A descriptive name for this resource.  Used in error
   108          * messages etc.
   109          */
   110         const char* mName;
   111         /**
   112          * mType
   113          * The more specific type of this resource.  Used to implement
   114          * special semantics (e.g., reentrancy of monitors).
   115          **/
   116         BlockingResourceType mType;
   117         /**
   118          * mAcquisitionContext
   119          * The calling context from which this resource was acquired, or
   120          * |CallStack::kNone| if it is currently free (or freed).
   121          */
   122         CallStack mAcquisitionContext;
   123     };
   125 protected:
   126     /**
   127      * BlockingResourceBase
   128      * Initialize this blocking resource.  Also hooks the resource into
   129      * instrumentation code.
   130      *
   131      * Thread safe.
   132      *
   133      * @param aName A meaningful, unique name that can be used in
   134      *              error messages, et al.
   135      * @param aType The specific type of |this|, if any.
   136      **/
   137     BlockingResourceBase(const char* aName, BlockingResourceType aType);
   139     ~BlockingResourceBase();
   141     /**
   142      * CheckAcquire
   143      *
   144      * Thread safe.
   145      *
   146      * @param aCallContext the client's calling context from which the
   147      *        original acquisition request was made.
   148      **/
   149     void CheckAcquire(const CallStack& aCallContext);
   151     /**
   152      * Acquire
   153      *
   154      * *NOT* thread safe.  Requires ownership of underlying resource.
   155      *
   156      * @param aCallContext the client's calling context from which the
   157      *        original acquisition request was made.
   158      **/
   159     void Acquire(const CallStack& aCallContext); //NS_NEEDS_RESOURCE(this)
   161     /**
   162      * Release
   163      * Remove this resource from the current thread's acquisition chain.
   164      * The resource does not have to be at the front of the chain, although
   165      * it is confusing to release resources in a different order than they
   166      * are acquired.  This generates a warning.
   167      *
   168      * *NOT* thread safe.  Requires ownership of underlying resource.
   169      **/
   170     void Release();             //NS_NEEDS_RESOURCE(this)
   172     /**
   173      * PrintCycle
   174      * Append to |out| detailed information about the circular
   175      * dependency in |cycle|.  Returns true if it *appears* that this
   176      * cycle may represent an imminent deadlock, but this is merely a
   177      * heuristic; the value returned may be a false positive or false
   178      * negative.
   179      *
   180      * *NOT* thread safe.  Calls |Print()|.
   181      *
   182      * FIXME bug 456272 hack alert: because we can't write call
   183      * contexts into strings, all info is written to stderr, but only
   184      * some info is written into |out|
   185      */
   186     static bool PrintCycle(const DDT::ResourceAcquisitionArray* cycle,
   187                            nsACString& out);
   189     /**
   190      * ResourceChainFront
   191      *
   192      * Thread safe.
   193      *
   194      * @return the front of the resource acquisition chain, i.e., the last
   195      *         resource acquired.
   196      */
   197     static BlockingResourceBase* ResourceChainFront()
   198     {
   199         return (BlockingResourceBase*)
   200             PR_GetThreadPrivate(sResourceAcqnChainFrontTPI);
   201     }
   203     /**
   204      * ResourceChainPrev
   205      *
   206      * *NOT* thread safe.  Requires ownership of underlying resource.
   207      */
   208     static BlockingResourceBase*
   209     ResourceChainPrev(const BlockingResourceBase* aResource)
   210     {
   211         return aResource->mChainPrev;
   212     } //NS_NEEDS_RESOURCE(this)
   214     /**
   215      * ResourceChainAppend
   216      * Set |this| to the front of the resource acquisition chain, and link
   217      * |this| to |aPrev|.
   218      *
   219      * *NOT* thread safe.  Requires ownership of underlying resource.
   220      */
   221     void ResourceChainAppend(BlockingResourceBase* aPrev)
   222     {
   223         mChainPrev = aPrev;
   224         PR_SetThreadPrivate(sResourceAcqnChainFrontTPI, this);
   225     } //NS_NEEDS_RESOURCE(this)
   227     /**
   228      * ResourceChainRemove
   229      * Remove |this| from the front of the resource acquisition chain.
   230      *
   231      * *NOT* thread safe.  Requires ownership of underlying resource.
   232      */
   233     void ResourceChainRemove()
   234     {
   235         NS_ASSERTION(this == ResourceChainFront(), "not at chain front");
   236         PR_SetThreadPrivate(sResourceAcqnChainFrontTPI, mChainPrev);
   237     } //NS_NEEDS_RESOURCE(this)
   239     /**
   240      * GetAcquisitionContext
   241      * Return the calling context from which this resource was acquired,
   242      * or CallStack::kNone if it's currently free.
   243      *
   244      * *NOT* thread safe.  Requires ownership of underlying resource.
   245      */
   246     CallStack
   247     GetAcquisitionContext()
   248     {
   249         return mDDEntry->mAcquisitionContext;
   250     }
   252     /**
   253      * SetAcquisitionContext
   254      * Set the calling context from which this resource was acquired.
   255      *
   256      * *NOT* thread safe.  Requires ownership of underlying resource.
   257      */
   258     void
   259     SetAcquisitionContext(CallStack aAcquisitionContext)
   260     {
   261         mDDEntry->mAcquisitionContext = aAcquisitionContext;
   262     }
   264     /**
   265      * mChainPrev
   266      * A series of resource acquisitions creates a chain of orders.  This
   267      * chain is implemented as a linked list; |mChainPrev| points to the
   268      * resource most recently Acquire()'d before this one.
   269      **/
   270     BlockingResourceBase* mChainPrev;
   272 private:
   273     /**
   274      * mDDEntry
   275      * The key for this BlockingResourceBase in the deadlock detector.
   276      */
   277     DeadlockDetectorEntry* mDDEntry;
   279     /**
   280      * sCallOnce
   281      * Ensures static members are initialized only once, and in a
   282      * thread-safe way.
   283      */
   284     static PRCallOnceType sCallOnce;
   286     /**
   287      * sResourceAcqnChainFrontTPI
   288      * Thread-private index to the front of each thread's resource
   289      * acquisition chain.
   290      */
   291     static unsigned sResourceAcqnChainFrontTPI;
   293     /**
   294      * sDeadlockDetector
   295      * Does as named.
   296      */
   297     static DDT* sDeadlockDetector;
   299     /**
   300      * InitStatics
   301      * Inititialize static members of BlockingResourceBase that can't
   302      * be statically initialized.
   303      *
   304      * *NOT* thread safe.
   305      */
   306     static PRStatus InitStatics() {
   307         PR_NewThreadPrivateIndex(&sResourceAcqnChainFrontTPI, 0);
   308         sDeadlockDetector = new DDT();
   309         if (!sDeadlockDetector)
   310             NS_RUNTIMEABORT("can't allocate deadlock detector");
   311         return PR_SUCCESS;
   312     }
   314     /**
   315      * Shutdown
   316      * Free static members.
   317      *
   318      * *NOT* thread safe.
   319      */
   320     static void Shutdown() {
   321         delete sDeadlockDetector;
   322         sDeadlockDetector = 0;
   323     }
   325 #  ifdef MOZILLA_INTERNAL_API
   326     // so it can call BlockingResourceBase::Shutdown()
   327     friend void LogTerm();
   328 #  endif  // ifdef MOZILLA_INTERNAL_API
   330 #else  // non-DEBUG implementation
   332     BlockingResourceBase(const char* aName, BlockingResourceType aType)
   333     {
   334     }
   336     ~BlockingResourceBase()
   337     {
   338     }
   340 #endif
   341 };
   344 } // namespace mozilla
   347 #endif // mozilla_BlockingResourceBase_h

mercurial