VirtualBox

Changeset 8639 in vbox for trunk


Ignore:
Timestamp:
May 6, 2008 8:05:44 PM (17 years ago)
Author:
vboxsync
Message:

Main/AutoLock: More debugging.

Location:
trunk/src/VBox/Main
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/AutoLock.cpp

    r8508 r8639  
    2020 */
    2121
     22#ifdef VBOX_MAIN_AUTOLOCK_TRAP
     23// workaround for compile problems on gcc 4.1
     24# ifdef __GNUC__
     25#  pragma GCC visibility push(default)
     26# endif
     27#endif
     28
    2229#include "AutoLock.h"
    2330
    2431#include "Logging.h"
    2532
     33#include <iprt/string.h>
     34
     35#ifdef VBOX_MAIN_AUTOLOCK_TRAP
     36# if defined (RT_OS_LINUX)
     37#  include <signal.h>
     38#  include <execinfo.h>
     39/* get REG_EIP from ucontext.h */
     40#  ifndef __USE_GNU
     41#  define __USE_GNU
     42#  endif
     43#  include <ucontext.h>
     44#  ifdef RT_ARCH_AMD64
     45#   define REG_PC REG_RIP
     46#  else
     47#   define REG_PC REG_EIP
     48#  endif
     49# endif
     50#endif /* VBOX_MAIN_AUTOLOCK_TRAP */
     51
    2652namespace util
    2753{
     54
     55#ifdef VBOX_MAIN_AUTOLOCK_TRAP
     56
     57namespace internal
     58{
     59
     60struct TLS
     61{
     62    struct Uint32_t
     63    {
     64        Uint32_t() : raw (0) {}
     65        operator uint32_t &() { return raw; }
     66        uint32_t raw;
     67    };
     68
     69    typedef std::map <RWLockHandle *, Uint32_t> HandleMap;
     70    HandleMap handles; /*< handle reference counter on the current thread */
     71};
     72
     73/**
     74 * Global module initialization structure.
     75 *
     76 * The constructor and destructor of this structure are used to perform global
     77 * module initiaizaton and cleanup. Thee must be only one global variable of
     78 * this structure.
     79 */
     80static
     81class Global
     82{
     83public:
     84
     85    Global() : tlsID (NIL_RTTLS)
     86    {
     87#if defined (RT_OS_LINUX)
     88        int vrc = RTTlsAllocEx (&tlsID, TLSDestructor);
     89        AssertRC (vrc);
     90#else
     91        tlsID = RTTlsAlloc();
     92        Assert (tlsID != NIL_RTTLS);
     93#endif
     94    }
     95
     96    ~Global()
     97    {
     98        RTTlsFree (tlsID);
     99    }
     100
     101    TLS *tls() const
     102    {
     103        TLS *tls = NULL;
     104        if (tlsID != NIL_RTTLS)
     105        {
     106            tls = static_cast <TLS *> (RTTlsGet (tlsID));
     107            if (tls == NULL)
     108            {
     109                tls = new TLS();
     110                RTTlsSet (tlsID, tls);
     111            }
     112        }
     113
     114        return tls;
     115    }
     116
     117    RTTLS tlsID;
     118}
     119gGlobal;
     120
     121DECLCALLBACK(void) TLSDestructor (void *aValue)
     122{
     123    if (aValue != NULL)
     124    {
     125        TLS *tls = static_cast <TLS *> (aValue);
     126        RWLockHandle::TLSDestructor (tls);
     127        delete tls;
     128    }
     129}
     130
     131} /* namespace internal */
     132
     133#endif /* VBOX_MAIN_AUTOLOCK_TRAP */
    28134
    29135
     
    107213        if (mReadLockCount != 0)
    108214        {
    109             ReaderMap::const_iterator reader = mReaders.find (threadSelf);
    110             if (reader != mReaders.end() && reader->second != 0)
    111             {
    112                 AssertReleaseMsgFailedReturnVoid ((
    113                     "SELF DEADLOCK DETECTED on Thread %0x: lockWrite() after "
    114                     "lockRead(): reader count = %d!\n",
    115                     threadSelf, reader->second));
     215            using namespace internal;
     216            TLS *tls = gGlobal.tls();
     217            if (tls != NULL)
     218            {
     219                TLS::HandleMap::const_iterator it = tls->handles.find (this);
     220                if (it != tls->handles.end() && it->second.raw != 0)
     221                {
     222                    /* if there is a writer then the handle reference counter equals
     223                     * to the number of readers on the current thread plus 1 */
     224
     225                    uint32_t readers = it->second.raw;
     226                    if (mWriteLockThread != NIL_RTNATIVETHREAD)
     227                        -- readers;
     228
     229                    std::string info;
     230                    gatherInfo (info);
     231
     232                    AssertReleaseMsgFailedReturnVoid ((
     233                        "DETECTED SELF DEADLOCK on Thread %08x: lockWrite() after "
     234                        "lockRead(): reader count = %d!\n%s\n",
     235                        threadSelf, readers, info.c_str()));
     236                }
    116237            }
    117238        }
     
    140261    Assert (mWriteLockLevel != 0 /* overflow */);
    141262
     263# ifdef VBOX_MAIN_AUTOLOCK_TRAP
     264    logOp (LockWrite);
     265# endif
     266
    142267    RTCritSectLeave (&mCritSect);
    143268
     
    177302    }
    178303
     304# ifdef VBOX_MAIN_AUTOLOCK_TRAP
     305    logOp (UnlockWrite);
     306# endif
     307
    179308    RTCritSectLeave (&mCritSect);
    180309
     
    197326
    198327# ifdef VBOX_MAIN_AUTOLOCK_TRAP
    199     if (!mReaders.count (threadSelf))
    200         mReaders [threadSelf] = 0;
    201     ++ mReaders [threadSelf];
     328    logOp (LockRead);
    202329# endif /* VBOX_MAIN_AUTOLOCK_TRAP */
    203330
     
    277404
    278405# ifdef VBOX_MAIN_AUTOLOCK_TRAP
    279                 -- mReaders [threadSelf];
     406                logOp (UnlockRead);
    280407# endif /* VBOX_MAIN_AUTOLOCK_TRAP */
    281408            }
     
    297424
    298425# ifdef VBOX_MAIN_AUTOLOCK_TRAP
    299             -- mReaders [threadSelf];
     426            logOp (UnlockRead);
    300427# endif /* VBOX_MAIN_AUTOLOCK_TRAP */
    301428        }
     
    324451
    325452
     453#ifdef VBOX_MAIN_AUTOLOCK_TRAP
     454
     455void RWLockHandle::logOp (Operation aOp)
     456{
     457    std::string info;
     458
     459    char buf [256];
     460    RTStrPrintf (buf, sizeof (buf), "[%c] Thread %08x (%s)\n",
     461                 aOp == LockRead ? 'r' : aOp == LockWrite ? 'w' : '?',
     462                 RTThreadNativeSelf(), RTThreadGetName (RTThreadSelf()));
     463    info += buf;
     464
     465# if defined (RT_OS_LINUX)
     466
     467    void *trace [16];
     468    char **messages = (char **) NULL;
     469    int i, trace_size = 0;
     470    trace_size = backtrace (trace, 16);
     471
     472    messages = backtrace_symbols (trace, trace_size);
     473    /* skip first stack frame (points here) and the second stack frame (points
     474     * to lockRead()/lockWrite() */
     475    for (i = 2; i < trace_size; ++i)
     476        (info += messages[i]) += "\n";
     477
     478    free (messages);
     479
     480# endif /* defined (RT_OS_LINUX) */
     481
     482    internal::TLS *tls = internal::gGlobal.tls();
     483    if (tls != NULL)
     484    {
     485
     486        switch (aOp)
     487        {
     488            case LockRead:
     489            {
     490                mReaderInfo.push_back (info);
     491                ++ tls->handles [this];
     492                break;
     493            }
     494            case UnlockRead:
     495            {
     496                mReaderInfo.pop_back();
     497                -- tls->handles [this];
     498                break;
     499            }
     500            case LockWrite:
     501            {
     502                mWriterInfo = info;
     503                ++ tls->handles [this];
     504                break;
     505            }
     506            case UnlockWrite:
     507            {
     508                mWriterInfo.clear();;
     509                -- tls->handles [this];
     510                break;
     511            }
     512        }
     513    }
     514}
     515
     516void RWLockHandle::gatherInfo (std::string &aInfo)
     517{
     518    char buf [256];
     519    RTStrPrintf (buf, sizeof (buf),
     520                 "[*] RWLockHandle %x:\n", this,
     521                 RTThreadNativeSelf(), RTThreadGetName (RTThreadSelf()));
     522    aInfo += buf;
     523
     524    /* add reader info */
     525    for (ReaderInfo::const_iterator it = mReaderInfo.begin();
     526         it != mReaderInfo.end(); ++ it)
     527    {
     528        aInfo += *it;
     529    }
     530    /* add writer info */
     531    if (!mWriterInfo.empty())
     532        aInfo += mWriterInfo;
     533}
     534
     535/* static */
     536void RWLockHandle::TLSDestructor (internal::TLS *aTLS)
     537{
     538    using namespace internal;
     539
     540    if (aTLS != NULL && aTLS->handles.size())
     541    {
     542        std::string info;
     543        size_t cnt = 0;
     544
     545        for (TLS::HandleMap::const_iterator it = aTLS->handles.begin();
     546             it != aTLS->handles.end(); ++ it)
     547        {
     548            if (it->second.raw != 0)
     549            {
     550                it->first->gatherInfo (info);
     551                ++ cnt;
     552            }
     553        }
     554
     555        if (cnt != 0)
     556        {
     557            AssertReleaseMsgFailed ((
     558                "DETECTED %d HELD RWLockHandle's on Thread %08x!\n%s\n",
     559                cnt, RTThreadNativeSelf(), info.c_str()));
     560        }
     561    }
     562}
     563
     564#endif /* ifdef VBOX_MAIN_AUTOLOCK_TRAP */
     565
     566
    326567} /* namespace util */
    327568
  • trunk/src/VBox/Main/include/AutoLock.h

    r8511 r8639  
    4141# ifdef VBOX_MAIN_AUTOLOCK_TRAP
    4242#  include <map>
     43#  include <list>
     44#  include <string>
    4345# endif
    4446#endif
     
    4648namespace util
    4749{
     50
     51#ifdef VBOX_MAIN_AUTOLOCK_TRAP
     52namespace internal
     53{
     54    struct TLS;
     55    DECLCALLBACK(void) TLSDestructor (void *aValue);
     56}
     57#endif /* VBOX_MAIN_AUTOLOCK_TRAP */
    4858
    4959/**
     
    205215# ifdef VBOX_MAIN_AUTOLOCK_TRAP
    206216
    207     typedef std::map <RTNATIVETHREAD, uint32_t> ReaderMap;
    208     ReaderMap mReaders;
     217    enum Operation { LockRead, UnlockRead, LockWrite, UnlockWrite };
     218    void logOp (Operation aOp);
     219    void gatherInfo (std::string &aInfo);
     220
     221    friend DECLCALLBACK(void) internal::TLSDestructor (void *aValue);
     222    static void TLSDestructor (internal::TLS *aTLS);
     223
     224    typedef std::list <std::string> ReaderInfo;
     225    ReaderInfo mReaderInfo;
     226    std::string mWriterInfo;
    209227
    210228# endif /* VBOX_MAIN_AUTOLOCK_TRAP */
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