< prev index next >

src/share/vm/prims/jvmtiTagMap.cpp

Print this page
rev 9028 : 8223177: Data race on JvmtiEnvBase::_tag_map in double-checked locking
Summary: Add memory fences on accesses to JvmtiEnvBase::_tag_map
Reviewed-by: dholmes, jcbeyler, sspitsyn


 413       _trace_threshold += medium_trace_threshold;
 414     } else {
 415       _trace_threshold += large_trace_threshold;
 416     }
 417   }
 418 }
 419 
 420 // create a JvmtiTagMap
 421 JvmtiTagMap::JvmtiTagMap(JvmtiEnv* env) :
 422   _env(env),
 423   _lock(Mutex::nonleaf+2, "JvmtiTagMap._lock", false),
 424   _free_entries(NULL),
 425   _free_entries_count(0)
 426 {
 427   assert(JvmtiThreadState_lock->is_locked(), "sanity check");
 428   assert(((JvmtiEnvBase *)env)->tag_map() == NULL, "tag map already exists for environment");
 429 
 430   _hashmap = new JvmtiTagHashmap();
 431 
 432   // finally add us to the environment
 433   ((JvmtiEnvBase *)env)->set_tag_map(this);
 434 }
 435 
 436 
 437 // destroy a JvmtiTagMap
 438 JvmtiTagMap::~JvmtiTagMap() {
 439 
 440   // no lock acquired as we assume the enclosing environment is
 441   // also being destroryed.
 442   ((JvmtiEnvBase *)_env)->set_tag_map(NULL);
 443 
 444   JvmtiTagHashmapEntry** table = _hashmap->table();
 445   for (int j = 0; j < _hashmap->size(); j++) {
 446     JvmtiTagHashmapEntry* entry = table[j];
 447     while (entry != NULL) {
 448       JvmtiTagHashmapEntry* next = entry->next();
 449       delete entry;
 450       entry = next;
 451     }
 452   }
 453 


 482   }
 483   return entry;
 484 }
 485 
 486 // destroy an entry by returning it to the free list
 487 void JvmtiTagMap::destroy_entry(JvmtiTagHashmapEntry* entry) {
 488   assert(SafepointSynchronize::is_at_safepoint() || is_locked(), "checking");
 489   // limit the size of the free list
 490   if (_free_entries_count >= max_free_entries) {
 491     delete entry;
 492   } else {
 493     entry->set_next(_free_entries);
 494     _free_entries = entry;
 495     _free_entries_count++;
 496   }
 497 }
 498 
 499 // returns the tag map for the given environments. If the tag map
 500 // doesn't exist then it is created.
 501 JvmtiTagMap* JvmtiTagMap::tag_map_for(JvmtiEnv* env) {
 502   JvmtiTagMap* tag_map = ((JvmtiEnvBase*)env)->tag_map();
 503   if (tag_map == NULL) {
 504     MutexLocker mu(JvmtiThreadState_lock);
 505     tag_map = ((JvmtiEnvBase*)env)->tag_map();
 506     if (tag_map == NULL) {
 507       tag_map = new JvmtiTagMap(env);
 508     }
 509   } else {
 510     CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
 511   }
 512   return tag_map;
 513 }
 514 
 515 // iterate over all entries in the tag map.
 516 void JvmtiTagMap::entry_iterate(JvmtiTagHashmapEntryClosure* closure) {
 517   hashmap()->entry_iterate(closure);
 518 }
 519 
 520 // returns true if the hashmaps are empty
 521 bool JvmtiTagMap::is_empty() {
 522   assert(SafepointSynchronize::is_at_safepoint() || is_locked(), "checking");


3265   oop obj = JNIHandles::resolve(object);
3266   Handle initial_object(Thread::current(), obj);
3267 
3268   MutexLocker ml(Heap_lock);
3269   AdvancedHeapWalkContext context(heap_filter, klass, callbacks);
3270   VM_HeapWalkOperation op(this, initial_object, context, user_data);
3271   VMThread::execute(&op);
3272 }
3273 
3274 
3275 void JvmtiTagMap::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f) {
3276   // No locks during VM bring-up (0 threads) and no safepoints after main
3277   // thread creation and before VMThread creation (1 thread); initial GC
3278   // verification can happen in that window which gets to here.
3279   assert(Threads::number_of_threads() <= 1 ||
3280          SafepointSynchronize::is_at_safepoint(),
3281          "must be executed at a safepoint");
3282   if (JvmtiEnv::environments_might_exist()) {
3283     JvmtiEnvIterator it;
3284     for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) {
3285       JvmtiTagMap* tag_map = env->tag_map();
3286       if (tag_map != NULL && !tag_map->is_empty()) {
3287         tag_map->do_weak_oops(is_alive, f);
3288       }
3289     }
3290   }
3291 }
3292 
3293 void JvmtiTagMap::do_weak_oops(BoolObjectClosure* is_alive, OopClosure* f) {
3294 
3295   // does this environment have the OBJECT_FREE event enabled
3296   bool post_object_free = env()->is_enabled(JVMTI_EVENT_OBJECT_FREE);
3297 
3298   // counters used for trace message
3299   int freed = 0;
3300   int moved = 0;
3301 
3302   JvmtiTagHashmap* hashmap = this->hashmap();
3303 
3304   // reenable sizing (if disabled)
3305   hashmap->set_resizing_enabled(true);




 413       _trace_threshold += medium_trace_threshold;
 414     } else {
 415       _trace_threshold += large_trace_threshold;
 416     }
 417   }
 418 }
 419 
 420 // create a JvmtiTagMap
 421 JvmtiTagMap::JvmtiTagMap(JvmtiEnv* env) :
 422   _env(env),
 423   _lock(Mutex::nonleaf+2, "JvmtiTagMap._lock", false),
 424   _free_entries(NULL),
 425   _free_entries_count(0)
 426 {
 427   assert(JvmtiThreadState_lock->is_locked(), "sanity check");
 428   assert(((JvmtiEnvBase *)env)->tag_map() == NULL, "tag map already exists for environment");
 429 
 430   _hashmap = new JvmtiTagHashmap();
 431 
 432   // finally add us to the environment
 433   ((JvmtiEnvBase *)env)->release_set_tag_map(this);
 434 }
 435 
 436 
 437 // destroy a JvmtiTagMap
 438 JvmtiTagMap::~JvmtiTagMap() {
 439 
 440   // no lock acquired as we assume the enclosing environment is
 441   // also being destroryed.
 442   ((JvmtiEnvBase *)_env)->set_tag_map(NULL);
 443 
 444   JvmtiTagHashmapEntry** table = _hashmap->table();
 445   for (int j = 0; j < _hashmap->size(); j++) {
 446     JvmtiTagHashmapEntry* entry = table[j];
 447     while (entry != NULL) {
 448       JvmtiTagHashmapEntry* next = entry->next();
 449       delete entry;
 450       entry = next;
 451     }
 452   }
 453 


 482   }
 483   return entry;
 484 }
 485 
 486 // destroy an entry by returning it to the free list
 487 void JvmtiTagMap::destroy_entry(JvmtiTagHashmapEntry* entry) {
 488   assert(SafepointSynchronize::is_at_safepoint() || is_locked(), "checking");
 489   // limit the size of the free list
 490   if (_free_entries_count >= max_free_entries) {
 491     delete entry;
 492   } else {
 493     entry->set_next(_free_entries);
 494     _free_entries = entry;
 495     _free_entries_count++;
 496   }
 497 }
 498 
 499 // returns the tag map for the given environments. If the tag map
 500 // doesn't exist then it is created.
 501 JvmtiTagMap* JvmtiTagMap::tag_map_for(JvmtiEnv* env) {
 502   JvmtiTagMap* tag_map = ((JvmtiEnvBase*)env)->acquire_tag_map();
 503   if (tag_map == NULL) {
 504     MutexLocker mu(JvmtiThreadState_lock);
 505     tag_map = ((JvmtiEnvBase*)env)->tag_map();
 506     if (tag_map == NULL) {
 507       tag_map = new JvmtiTagMap(env);
 508     }
 509   } else {
 510     CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
 511   }
 512   return tag_map;
 513 }
 514 
 515 // iterate over all entries in the tag map.
 516 void JvmtiTagMap::entry_iterate(JvmtiTagHashmapEntryClosure* closure) {
 517   hashmap()->entry_iterate(closure);
 518 }
 519 
 520 // returns true if the hashmaps are empty
 521 bool JvmtiTagMap::is_empty() {
 522   assert(SafepointSynchronize::is_at_safepoint() || is_locked(), "checking");


3265   oop obj = JNIHandles::resolve(object);
3266   Handle initial_object(Thread::current(), obj);
3267 
3268   MutexLocker ml(Heap_lock);
3269   AdvancedHeapWalkContext context(heap_filter, klass, callbacks);
3270   VM_HeapWalkOperation op(this, initial_object, context, user_data);
3271   VMThread::execute(&op);
3272 }
3273 
3274 
3275 void JvmtiTagMap::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f) {
3276   // No locks during VM bring-up (0 threads) and no safepoints after main
3277   // thread creation and before VMThread creation (1 thread); initial GC
3278   // verification can happen in that window which gets to here.
3279   assert(Threads::number_of_threads() <= 1 ||
3280          SafepointSynchronize::is_at_safepoint(),
3281          "must be executed at a safepoint");
3282   if (JvmtiEnv::environments_might_exist()) {
3283     JvmtiEnvIterator it;
3284     for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) {
3285       JvmtiTagMap* tag_map = env->acquire_tag_map();
3286       if (tag_map != NULL && !tag_map->is_empty()) {
3287         tag_map->do_weak_oops(is_alive, f);
3288       }
3289     }
3290   }
3291 }
3292 
3293 void JvmtiTagMap::do_weak_oops(BoolObjectClosure* is_alive, OopClosure* f) {
3294 
3295   // does this environment have the OBJECT_FREE event enabled
3296   bool post_object_free = env()->is_enabled(JVMTI_EVENT_OBJECT_FREE);
3297 
3298   // counters used for trace message
3299   int freed = 0;
3300   int moved = 0;
3301 
3302   JvmtiTagHashmap* hashmap = this->hashmap();
3303 
3304   // reenable sizing (if disabled)
3305   hashmap->set_resizing_enabled(true);


< prev index next >