< prev index next >

src/share/vm/runtime/synchronizer.cpp

Print this page
rev 9030 : 8047212: runtime/ParallelClassLoading/bootstrap/random/inner-complex assert(ObjectSynchronizer::verify_objmon_isinpool(inf)) failed: monitor is invalid
Summary: Fix race between ObjectMonitor alloc and verification code; teach SA about "static pointer volatile" fields.
Reviewed-by: cvarming, dholmes, sspitsyn, coleenp

*** 147,157 **** } #define NINFLATIONLOCKS 256 static volatile intptr_t InflationLocks [NINFLATIONLOCKS] ; ! ObjectMonitor * ObjectSynchronizer::gBlockList = NULL ; ObjectMonitor * volatile ObjectSynchronizer::gFreeList = NULL ; ObjectMonitor * volatile ObjectSynchronizer::gOmInUseList = NULL ; int ObjectSynchronizer::gOmInUseCount = 0; static volatile intptr_t ListLock = 0 ; // protects global monitor free-list cache static volatile int MonitorFreeCount = 0 ; // # on gFreeList --- 147,157 ---- } #define NINFLATIONLOCKS 256 static volatile intptr_t InflationLocks [NINFLATIONLOCKS] ; ! ObjectMonitor * volatile ObjectSynchronizer::gBlockList = NULL; ObjectMonitor * volatile ObjectSynchronizer::gFreeList = NULL ; ObjectMonitor * volatile ObjectSynchronizer::gOmInUseList = NULL ; int ObjectSynchronizer::gOmInUseCount = 0; static volatile intptr_t ListLock = 0 ; // protects global monitor free-list cache static volatile int MonitorFreeCount = 0 ; // # on gFreeList
*** 828,849 **** return NULL; } // Visitors ... void ObjectSynchronizer::monitors_iterate(MonitorClosure* closure) { ! ObjectMonitor* block = gBlockList; ! ObjectMonitor* mid; ! while (block) { assert(block->object() == CHAINMARKER, "must be a block header"); for (int i = _BLOCKSIZE - 1; i > 0; i--) { ! mid = block + i; ! oop object = (oop) mid->object(); if (object != NULL) { closure->do_monitor(mid); } } ! block = (ObjectMonitor*) block->FreeNext; } } // Get the next block in the block list. static inline ObjectMonitor* next(ObjectMonitor* block) { --- 828,849 ---- return NULL; } // Visitors ... void ObjectSynchronizer::monitors_iterate(MonitorClosure* closure) { ! ObjectMonitor* block = ! (ObjectMonitor*)OrderAccess::load_ptr_acquire(&gBlockList); ! while (block != NULL) { assert(block->object() == CHAINMARKER, "must be a block header"); for (int i = _BLOCKSIZE - 1; i > 0; i--) { ! ObjectMonitor* mid = (ObjectMonitor *)(block + i); ! oop object = (oop)mid->object(); if (object != NULL) { closure->do_monitor(mid); } } ! block = (ObjectMonitor*)block->FreeNext; } } // Get the next block in the block list. static inline ObjectMonitor* next(ObjectMonitor* block) {
*** 854,864 **** } void ObjectSynchronizer::oops_do(OopClosure* f) { assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); ! for (ObjectMonitor* block = gBlockList; block != NULL; block = next(block)) { assert(block->object() == CHAINMARKER, "must be a block header"); for (int i = 1; i < _BLOCKSIZE; i++) { ObjectMonitor* mid = &block[i]; if (mid->object() != NULL) { f->do_oop((oop*)mid->object_addr()); --- 854,866 ---- } void ObjectSynchronizer::oops_do(OopClosure* f) { assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); ! ObjectMonitor* block = ! (ObjectMonitor*)OrderAccess::load_ptr_acquire(&gBlockList); ! for (; block != NULL; block = (ObjectMonitor *)next(block)) { assert(block->object() == CHAINMARKER, "must be a block header"); for (int i = 1; i < _BLOCKSIZE; i++) { ObjectMonitor* mid = &block[i]; if (mid->object() != NULL) { f->do_oop((oop*)mid->object_addr());
*** 1057,1067 **** // Add the new block to the list of extant blocks (gBlockList). // The very first objectMonitor in a block is reserved and dedicated. // It serves as blocklist "next" linkage. temp[0].FreeNext = gBlockList; ! gBlockList = temp; // Add the new string of objectMonitors to the global free list temp[_BLOCKSIZE - 1].FreeNext = gFreeList ; gFreeList = temp + 1; Thread::muxRelease (&ListLock) ; --- 1059,1071 ---- // Add the new block to the list of extant blocks (gBlockList). // The very first objectMonitor in a block is reserved and dedicated. // It serves as blocklist "next" linkage. temp[0].FreeNext = gBlockList; ! // There are lock-free uses of gBlockList so make sure that ! // the previous stores happen before we update gBlockList. ! OrderAccess::release_store_ptr(&gBlockList, temp); // Add the new string of objectMonitors to the global free list temp[_BLOCKSIZE - 1].FreeNext = gFreeList ; gFreeList = temp + 1; Thread::muxRelease (&ListLock) ;
*** 1534,1566 **** gOmInUseCount-= deflatedcount; nScavenged += deflatedcount; nInuse += gOmInUseCount; } ! } else for (ObjectMonitor* block = gBlockList; block != NULL; block = next(block)) { // Iterate over all extant monitors - Scavenge all idle monitors. assert(block->object() == CHAINMARKER, "must be a block header"); ! nInCirculation += _BLOCKSIZE ; ! for (int i = 1 ; i < _BLOCKSIZE; i++) { ! ObjectMonitor* mid = &block[i]; ! oop obj = (oop) mid->object(); ! if (obj == NULL) { // The monitor is not associated with an object. // The monitor should either be a thread-specific private // free list or the global free list. // obj == NULL IMPLIES mid->is_busy() == 0 ! guarantee (!mid->is_busy(), "invariant") ; ! continue ; } deflated = deflate_monitor(mid, obj, &FreeHead, &FreeTail); - if (deflated) { ! mid->FreeNext = NULL ; ! nScavenged ++ ; } else { ! nInuse ++; } } } MonitorFreeCount += nScavenged; --- 1538,1572 ---- gOmInUseCount-= deflatedcount; nScavenged += deflatedcount; nInuse += gOmInUseCount; } ! } else { ! ObjectMonitor* block = ! (ObjectMonitor*)OrderAccess::load_ptr_acquire(&gBlockList); ! for (; block != NULL; block = (ObjectMonitor*)next(block)) { // Iterate over all extant monitors - Scavenge all idle monitors. assert(block->object() == CHAINMARKER, "must be a block header"); ! nInCirculation += _BLOCKSIZE; ! for (int i = 1; i < _BLOCKSIZE; i++) { ! ObjectMonitor* mid = (ObjectMonitor*)&block[i]; ! oop obj = (oop)mid->object(); if (obj == NULL) { // The monitor is not associated with an object. // The monitor should either be a thread-specific private // free list or the global free list. // obj == NULL IMPLIES mid->is_busy() == 0 ! guarantee(!mid->is_busy(), "invariant"); ! continue; } deflated = deflate_monitor(mid, obj, &FreeHead, &FreeTail); if (deflated) { ! mid->FreeNext = NULL; ! nScavenged++; } else { ! nInuse++; ! } } } } MonitorFreeCount += nScavenged;
*** 1691,1707 **** #ifndef PRODUCT // Verify all monitors in the monitor cache, the verification is weak. void ObjectSynchronizer::verify() { ! ObjectMonitor* block = gBlockList; ! ObjectMonitor* mid; ! while (block) { assert(block->object() == CHAINMARKER, "must be a block header"); for (int i = 1; i < _BLOCKSIZE; i++) { ! mid = block + i; ! oop object = (oop) mid->object(); if (object != NULL) { mid->verify(); } } block = (ObjectMonitor*) block->FreeNext; --- 1697,1713 ---- #ifndef PRODUCT // Verify all monitors in the monitor cache, the verification is weak. void ObjectSynchronizer::verify() { ! ObjectMonitor* block = ! (ObjectMonitor *)OrderAccess::load_ptr_acquire(&gBlockList); ! while (block != NULL) { assert(block->object() == CHAINMARKER, "must be a block header"); for (int i = 1; i < _BLOCKSIZE; i++) { ! ObjectMonitor* mid = (ObjectMonitor *)(block + i); ! oop object = (oop)mid->object(); if (object != NULL) { mid->verify(); } } block = (ObjectMonitor*) block->FreeNext;
*** 1711,1732 **** // Check if monitor belongs to the monitor cache // The list is grow-only so it's *relatively* safe to traverse // the list of extant blocks without taking a lock. int ObjectSynchronizer::verify_objmon_isinpool(ObjectMonitor *monitor) { ! ObjectMonitor* block = gBlockList; ! ! while (block) { assert(block->object() == CHAINMARKER, "must be a block header"); if (monitor > &block[0] && monitor < &block[_BLOCKSIZE]) { ! address mon = (address) monitor; ! address blk = (address) block; size_t diff = mon - blk; ! assert((diff % sizeof(ObjectMonitor)) == 0, "check"); return 1; } ! block = (ObjectMonitor*) block->FreeNext; } return 0; } #endif --- 1717,1738 ---- // Check if monitor belongs to the monitor cache // The list is grow-only so it's *relatively* safe to traverse // the list of extant blocks without taking a lock. int ObjectSynchronizer::verify_objmon_isinpool(ObjectMonitor *monitor) { ! ObjectMonitor* block = ! (ObjectMonitor*)OrderAccess::load_ptr_acquire(&gBlockList); ! while (block != NULL) { assert(block->object() == CHAINMARKER, "must be a block header"); if (monitor > &block[0] && monitor < &block[_BLOCKSIZE]) { ! address mon = (address)monitor; ! address blk = (address)block; size_t diff = mon - blk; ! assert((diff % sizeof(ObjectMonitor)) == 0, "must be aligned"); return 1; } ! block = (ObjectMonitor*)block->FreeNext; } return 0; } #endif
< prev index next >