- Timestamp:
- May 6, 2008 8:05:44 PM (17 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/AutoLock.cpp
r8508 r8639 20 20 */ 21 21 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 22 29 #include "AutoLock.h" 23 30 24 31 #include "Logging.h" 25 32 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 26 52 namespace util 27 53 { 54 55 #ifdef VBOX_MAIN_AUTOLOCK_TRAP 56 57 namespace internal 58 { 59 60 struct 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 */ 80 static 81 class Global 82 { 83 public: 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 } 119 gGlobal; 120 121 DECLCALLBACK(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 */ 28 134 29 135 … … 107 213 if (mReadLockCount != 0) 108 214 { 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 } 116 237 } 117 238 } … … 140 261 Assert (mWriteLockLevel != 0 /* overflow */); 141 262 263 # ifdef VBOX_MAIN_AUTOLOCK_TRAP 264 logOp (LockWrite); 265 # endif 266 142 267 RTCritSectLeave (&mCritSect); 143 268 … … 177 302 } 178 303 304 # ifdef VBOX_MAIN_AUTOLOCK_TRAP 305 logOp (UnlockWrite); 306 # endif 307 179 308 RTCritSectLeave (&mCritSect); 180 309 … … 197 326 198 327 # ifdef VBOX_MAIN_AUTOLOCK_TRAP 199 if (!mReaders.count (threadSelf)) 200 mReaders [threadSelf] = 0; 201 ++ mReaders [threadSelf]; 328 logOp (LockRead); 202 329 # endif /* VBOX_MAIN_AUTOLOCK_TRAP */ 203 330 … … 277 404 278 405 # ifdef VBOX_MAIN_AUTOLOCK_TRAP 279 -- mReaders [threadSelf];406 logOp (UnlockRead); 280 407 # endif /* VBOX_MAIN_AUTOLOCK_TRAP */ 281 408 } … … 297 424 298 425 # ifdef VBOX_MAIN_AUTOLOCK_TRAP 299 -- mReaders [threadSelf];426 logOp (UnlockRead); 300 427 # endif /* VBOX_MAIN_AUTOLOCK_TRAP */ 301 428 } … … 324 451 325 452 453 #ifdef VBOX_MAIN_AUTOLOCK_TRAP 454 455 void 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 516 void 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 */ 536 void 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 326 567 } /* namespace util */ 327 568 -
trunk/src/VBox/Main/include/AutoLock.h
r8511 r8639 41 41 # ifdef VBOX_MAIN_AUTOLOCK_TRAP 42 42 # include <map> 43 # include <list> 44 # include <string> 43 45 # endif 44 46 #endif … … 46 48 namespace util 47 49 { 50 51 #ifdef VBOX_MAIN_AUTOLOCK_TRAP 52 namespace internal 53 { 54 struct TLS; 55 DECLCALLBACK(void) TLSDestructor (void *aValue); 56 } 57 #endif /* VBOX_MAIN_AUTOLOCK_TRAP */ 48 58 49 59 /** … … 205 215 # ifdef VBOX_MAIN_AUTOLOCK_TRAP 206 216 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; 209 227 210 228 # endif /* VBOX_MAIN_AUTOLOCK_TRAP */
Note:
See TracChangeset
for help on using the changeset viewer.