VirtualBox

Changeset 65406 in vbox for trunk/src/libs


Ignore:
Timestamp:
Jan 23, 2017 3:47:55 PM (8 years ago)
Author:
vboxsync
Message:

XPCOM/nsISupportsImpl.h: switch to an extremely paranoid AddRef/Release implementation for the threadsafe variant

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/libs/xpcom18a4/xpcom/glue/nsISupportsImpl.h

    r1 r65406  
    5050
    5151#include "nsDebug.h"
    52 #include "nsTraceRefcnt.h"
     52#include "nsTraceRefcnt.h"
     53#ifdef VBOX
     54# include "iprt/asm.h"
     55# include "iprt/assert.h"
     56#endif
    5357
    5458////////////////////////////////////////////////////////////////////////////////
     
    8084
    8185 public:
    82     nsAutoRefCnt() : mValue(0) {}
     86    nsAutoRefCnt() : mValue(0)
     87#ifdef VBOX
     88        , mState(0)
     89#endif
     90    {}
    8391    nsAutoRefCnt(nsrefcnt aValue) : mValue(aValue) {}
    8492
     
    8694    nsrefcnt operator++() { return ++mValue; }
    8795    nsrefcnt operator--() { return --mValue; }
    88    
     96
    8997    nsrefcnt operator=(nsrefcnt aValue) { return (mValue = aValue); }
    9098    operator nsrefcnt() const { return mValue; }
    9199    nsrefcnt get() const { return mValue; }
     100#ifdef VBOX
     101    nsrefcnt *ref() { return &mValue; }
     102    PRUint32 getState() const { return mState; }
     103    PRUint32 *refState() { return &mState; }
     104#endif
    92105 private:
    93106    // do not define these to enforce the faster prefix notation
     
    95108    nsrefcnt operator--(int);
    96109    nsrefcnt mValue;
     110#ifdef VBOX
     111    PRUint32 mState;
     112#endif
    97113};
    98114
     
    685701 */
    686702
     703#ifdef VBOX
     704#define NS_IMPL_THREADSAFE_ADDREF(_class)                                     \
     705NS_IMETHODIMP_(nsrefcnt) _class::AddRef(void)                                 \
     706{                                                                             \
     707  nsrefcnt count = mRefCnt.get();                                             \
     708  PRUint32 state = mRefCnt.getState();                                        \
     709  AssertReleaseMsg(   state <= 1                                              \
     710                   && (   (state == 0 && count == 0)                          \
     711                       || (state == 1 && count < PR_UINT32_MAX/2)),           \
     712                   ("AddRef: illegal refcnt=%u state=%d\n", count, state));   \
     713  switch (state)                                                              \
     714  {                                                                           \
     715    case 0:                                                                   \
     716      if (!ASMAtomicCmpXchgU32(mRefCnt.refState(), 1, 0))                     \
     717        AssertReleaseMsgFailed(("AddRef: racing for first increment\n"));     \
     718      count = ASMAtomicIncU32(mRefCnt.ref());                                 \
     719      AssertReleaseMsg(count == 1,                                            \
     720                       ("AddRef: unexpected refcnt=%u\n", count));            \
     721      break;                                                                  \
     722    case 1:                                                                   \
     723      count = ASMAtomicIncU32(mRefCnt.ref());                                 \
     724      AssertReleaseMsg(count <= PR_UINT32_MAX/2,                              \
     725                       ("AddRef: unexpected refcnt=%u\n", count));            \
     726      break;                                                                  \
     727    case 2:                                                                   \
     728      AssertReleaseMsgFailed(("AddRef: freed object\n"));                     \
     729      break;                                                                  \
     730    default:                                                                  \
     731      AssertReleaseMsgFailed(("AddRef: garbage object\n"));                   \
     732  }                                                                           \
     733  NS_LOG_ADDREF(this, count, #_class, sizeof(*this));                         \
     734  return count;                                                               \
     735}
     736#else
    687737#define NS_IMPL_THREADSAFE_ADDREF(_class)                                     \
    688738NS_IMETHODIMP_(nsrefcnt) _class::AddRef(void)                                 \
     
    694744  return count;                                                               \
    695745}
     746#endif
    696747
    697748/**
     
    700751 */
    701752
     753#ifdef VBOX
     754#define NS_IMPL_THREADSAFE_RELEASE(_class)                                    \
     755NS_IMETHODIMP_(nsrefcnt) _class::Release(void)                                \
     756{                                                                             \
     757  nsrefcnt count = mRefCnt.get();                                             \
     758  PRUint32 state = mRefCnt.getState();                                        \
     759  AssertReleaseMsg(state == 1 && count <= PR_UINT32_MAX/2,                    \
     760                   ("Release: illegal refcnt=%u state=%d\n", count, state));  \
     761  switch (state)                                                              \
     762  {                                                                           \
     763    case 0:                                                                   \
     764      AssertReleaseMsgFailed(("Release: new object\n"));                      \
     765      break;                                                                  \
     766    case 1:                                                                   \
     767      count = ASMAtomicDecU32(mRefCnt.ref());                                 \
     768      AssertReleaseMsg(count < PR_UINT32_MAX/2,                               \
     769                       ("Release: unexpected refcnt=%u\n", count));           \
     770      if (count == 0)                                                         \
     771      {                                                                       \
     772        if (!ASMAtomicCmpXchgU32(mRefCnt.refState(), 2, 1))                   \
     773          AssertReleaseMsgFailed(("Release: racing for state free\n"));       \
     774        /* Use better stabilization: reserve everything with top bit set. */  \
     775        if (!ASMAtomicCmpXchgU32(mRefCnt.ref(), PR_UINT32_MAX/4*3, 0))        \
     776          AssertReleaseMsgFailed(("Release: racing for refcnt stabilize\n")); \
     777        NS_DELETEXPCOM(this);                                                 \
     778      }                                                                       \
     779      break;                                                                  \
     780    case 2:                                                                   \
     781      AssertReleaseMsgFailed(("Release: freed object\n"));                    \
     782      break;                                                                  \
     783    default:                                                                  \
     784      AssertReleaseMsgFailed(("Release: garbage object\n"));                  \
     785  }                                                                           \
     786  NS_LOG_RELEASE(this, count, #_class);                                       \
     787  return count;                                                               \
     788}
     789#else
    702790#define NS_IMPL_THREADSAFE_RELEASE(_class)                                    \
    703791NS_IMETHODIMP_(nsrefcnt) _class::Release(void)                                \
     
    716804  return count;                                                               \
    717805}
     806#endif
    718807
    719808#define NS_IMPL_THREADSAFE_ISUPPORTS0(_class)                                 \
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette