3535#include " runtime/os.hpp"
3636#include " runtime/perfData.inline.hpp"
3737#include " utilities/exceptions.hpp"
38+ #include " utilities/globalCounter.inline.hpp"
3839#include " utilities/globalDefinitions.hpp"
3940
4041PerfDataList* PerfDataManager::_all = nullptr ;
@@ -251,15 +252,13 @@ void PerfDataManager::destroy() {
251252 // destroy already called, or initialization never happened
252253 return ;
253254
254- // Clear the flag before we free the PerfData counters. Thus begins
255- // the race between this thread and another thread that has just
256- // queried PerfDataManager::has_PerfData() and gotten back 'true'.
257- // The hope is that the other thread will finish its PerfData
258- // manipulation before we free the memory. The two alternatives are
259- // 1) leak the PerfData memory or 2) do some form of synchronized
260- // access or check before every PerfData operation.
261- _has_PerfData = false ;
262- os::naked_short_sleep (1 ); // 1ms sleep to let other thread(s) run
255+ // About to delete the counters than might still be accessed by other threads.
256+ // The shutdown is performed in two stages: a) clear the flag to notify future
257+ // counter users that we are at shutdown; b) sync up with current users, waiting
258+ // for them to finish with counters.
259+ //
260+ Atomic::store (&_has_PerfData, false );
261+ GlobalCounter::write_synchronize ();
263262
264263 log_debug (perf, datacreation)(" Total = %d, Sampled = %d, Constants = %d" ,
265264 _all->length (), _sampled == nullptr ? 0 : _sampled->length (),
@@ -286,7 +285,7 @@ void PerfDataManager::add_item(PerfData* p, bool sampled) {
286285 // Default sizes determined using -Xlog:perf+datacreation=debug
287286 if (_all == nullptr ) {
288287 _all = new PerfDataList (191 );
289- _has_PerfData = true ;
288+ Atomic::release_store (& _has_PerfData, true ) ;
290289 }
291290
292291 assert (!_all->contains (p->name ()), " duplicate name added" );
0 commit comments