< 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 >