hotspot/src/share/vm/utilities/workgroup.cpp
changeset 1374 4c24294029a9
parent 1 489c9b5090e2
child 5547 f4b087cbb361
equal deleted inserted replaced
615:570062d730b2 1374:4c24294029a9
    26 # include "incls/_workgroup.cpp.incl"
    26 # include "incls/_workgroup.cpp.incl"
    27 
    27 
    28 // Definitions of WorkGang methods.
    28 // Definitions of WorkGang methods.
    29 
    29 
    30 AbstractWorkGang::AbstractWorkGang(const char* name,
    30 AbstractWorkGang::AbstractWorkGang(const char* name,
    31                                    bool  are_GC_threads) :
    31                                    bool  are_GC_task_threads,
       
    32                                    bool  are_ConcurrentGC_threads) :
    32   _name(name),
    33   _name(name),
    33   _are_GC_threads(are_GC_threads) {
    34   _are_GC_task_threads(are_GC_task_threads),
       
    35   _are_ConcurrentGC_threads(are_ConcurrentGC_threads) {
       
    36 
       
    37   assert(!(are_GC_task_threads && are_ConcurrentGC_threads),
       
    38          "They cannot both be STW GC and Concurrent threads" );
       
    39 
    34   // Other initialization.
    40   // Other initialization.
    35   _monitor = new Monitor(/* priority */       Mutex::leaf,
    41   _monitor = new Monitor(/* priority */       Mutex::leaf,
    36                          /* name */           "WorkGroup monitor",
    42                          /* name */           "WorkGroup monitor",
    37                          /* allow_vm_block */ are_GC_threads);
    43                          /* allow_vm_block */ are_GC_task_threads);
    38   assert(monitor() != NULL, "Failed to allocate monitor");
    44   assert(monitor() != NULL, "Failed to allocate monitor");
    39   _terminate = false;
    45   _terminate = false;
    40   _task = NULL;
    46   _task = NULL;
    41   _sequence_number = 0;
    47   _sequence_number = 0;
    42   _started_workers = 0;
    48   _started_workers = 0;
    43   _finished_workers = 0;
    49   _finished_workers = 0;
    44 }
    50 }
    45 
    51 
    46 WorkGang::WorkGang(const char* name,
    52 WorkGang::WorkGang(const char* name,
    47                    int           workers,
    53                    int         workers,
    48                    bool          are_GC_threads) :
    54                    bool        are_GC_task_threads,
    49   AbstractWorkGang(name, are_GC_threads) {
    55                    bool        are_ConcurrentGC_threads) :
       
    56   AbstractWorkGang(name, are_GC_task_threads, are_ConcurrentGC_threads)
       
    57 {
    50   // Save arguments.
    58   // Save arguments.
    51   _total_workers = workers;
    59   _total_workers = workers;
       
    60 
    52   if (TraceWorkGang) {
    61   if (TraceWorkGang) {
    53     tty->print_cr("Constructing work gang %s with %d threads", name, workers);
    62     tty->print_cr("Constructing work gang %s with %d threads", name, workers);
    54   }
    63   }
    55   _gang_workers = NEW_C_HEAP_ARRAY(GangWorker*, workers);
    64   _gang_workers = NEW_C_HEAP_ARRAY(GangWorker*, workers);
    56   assert(gang_workers() != NULL, "Failed to allocate gang workers");
    65   if (gang_workers() == NULL) {
       
    66     vm_exit_out_of_memory(0, "Cannot create GangWorker array.");
       
    67   }
    57   for (int worker = 0; worker < total_workers(); worker += 1) {
    68   for (int worker = 0; worker < total_workers(); worker += 1) {
    58     GangWorker* new_worker = new GangWorker(this, worker);
    69     GangWorker* new_worker = new GangWorker(this, worker);
    59     assert(new_worker != NULL, "Failed to allocate GangWorker");
    70     assert(new_worker != NULL, "Failed to allocate GangWorker");
    60     _gang_workers[worker] = new_worker;
    71     _gang_workers[worker] = new_worker;
    61     if (new_worker == NULL || !os::create_thread(new_worker, os::pgc_thread))
    72     if (new_worker == NULL || !os::create_thread(new_worker, os::pgc_thread))
   283     previous_sequence_number = data.sequence_number();
   294     previous_sequence_number = data.sequence_number();
   284   }
   295   }
   285 }
   296 }
   286 
   297 
   287 bool GangWorker::is_GC_task_thread() const {
   298 bool GangWorker::is_GC_task_thread() const {
   288   return gang()->are_GC_threads();
   299   return gang()->are_GC_task_threads();
       
   300 }
       
   301 
       
   302 bool GangWorker::is_ConcurrentGC_thread() const {
       
   303   return gang()->are_ConcurrentGC_threads();
   289 }
   304 }
   290 
   305 
   291 void GangWorker::print_on(outputStream* st) const {
   306 void GangWorker::print_on(outputStream* st) const {
   292   st->print("\"%s\" ", name());
   307   st->print("\"%s\" ", name());
   293   Thread::print_on(st);
   308   Thread::print_on(st);
   310 
   325 
   311 // *** WorkGangBarrierSync
   326 // *** WorkGangBarrierSync
   312 
   327 
   313 WorkGangBarrierSync::WorkGangBarrierSync()
   328 WorkGangBarrierSync::WorkGangBarrierSync()
   314   : _monitor(Mutex::safepoint, "work gang barrier sync", true),
   329   : _monitor(Mutex::safepoint, "work gang barrier sync", true),
   315     _n_workers(0), _n_completed(0) {
   330     _n_workers(0), _n_completed(0), _should_reset(false) {
   316 }
   331 }
   317 
   332 
   318 WorkGangBarrierSync::WorkGangBarrierSync(int n_workers, const char* name)
   333 WorkGangBarrierSync::WorkGangBarrierSync(int n_workers, const char* name)
   319   : _monitor(Mutex::safepoint, name, true),
   334   : _monitor(Mutex::safepoint, name, true),
   320     _n_workers(n_workers), _n_completed(0) {
   335     _n_workers(n_workers), _n_completed(0), _should_reset(false) {
   321 }
   336 }
   322 
   337 
   323 void WorkGangBarrierSync::set_n_workers(int n_workers) {
   338 void WorkGangBarrierSync::set_n_workers(int n_workers) {
   324   _n_workers   = n_workers;
   339   _n_workers   = n_workers;
   325   _n_completed = 0;
   340   _n_completed = 0;
       
   341   _should_reset = false;
   326 }
   342 }
   327 
   343 
   328 void WorkGangBarrierSync::enter() {
   344 void WorkGangBarrierSync::enter() {
   329   MutexLockerEx x(monitor(), Mutex::_no_safepoint_check_flag);
   345   MutexLockerEx x(monitor(), Mutex::_no_safepoint_check_flag);
       
   346   if (should_reset()) {
       
   347     // The should_reset() was set and we are the first worker to enter
       
   348     // the sync barrier. We will zero the n_completed() count which
       
   349     // effectively resets the barrier.
       
   350     zero_completed();
       
   351     set_should_reset(false);
       
   352   }
   330   inc_completed();
   353   inc_completed();
   331   if (n_completed() == n_workers()) {
   354   if (n_completed() == n_workers()) {
       
   355     // At this point we would like to reset the barrier to be ready in
       
   356     // case it is used again. However, we cannot set n_completed() to
       
   357     // 0, even after the notify_all(), given that some other workers
       
   358     // might still be waiting for n_completed() to become ==
       
   359     // n_workers(). So, if we set n_completed() to 0, those workers
       
   360     // will get stuck (as they will wake up, see that n_completed() !=
       
   361     // n_workers() and go back to sleep). Instead, we raise the
       
   362     // should_reset() flag and the barrier will be reset the first
       
   363     // time a worker enters it again.
       
   364     set_should_reset(true);
   332     monitor()->notify_all();
   365     monitor()->notify_all();
   333   }
   366   } else {
   334   else {
       
   335     while (n_completed() != n_workers()) {
   367     while (n_completed() != n_workers()) {
   336       monitor()->wait(/* no_safepoint_check */ true);
   368       monitor()->wait(/* no_safepoint_check */ true);
   337     }
   369     }
   338   }
   370   }
   339 }
   371 }
   440     clear();
   472     clear();
   441     return true;
   473     return true;
   442   }
   474   }
   443   return false;
   475   return false;
   444 }
   476 }
       
   477 
       
   478 bool FreeIdSet::_stat_init = false;
       
   479 FreeIdSet* FreeIdSet::_sets[NSets];
       
   480 bool FreeIdSet::_safepoint;
       
   481 
       
   482 FreeIdSet::FreeIdSet(int sz, Monitor* mon) :
       
   483   _sz(sz), _mon(mon), _hd(0), _waiters(0), _index(-1), _claimed(0)
       
   484 {
       
   485   _ids = new int[sz];
       
   486   for (int i = 0; i < sz; i++) _ids[i] = i+1;
       
   487   _ids[sz-1] = end_of_list; // end of list.
       
   488   if (_stat_init) {
       
   489     for (int j = 0; j < NSets; j++) _sets[j] = NULL;
       
   490     _stat_init = true;
       
   491   }
       
   492   // Add to sets.  (This should happen while the system is still single-threaded.)
       
   493   for (int j = 0; j < NSets; j++) {
       
   494     if (_sets[j] == NULL) {
       
   495       _sets[j] = this;
       
   496       _index = j;
       
   497       break;
       
   498     }
       
   499   }
       
   500   guarantee(_index != -1, "Too many FreeIdSets in use!");
       
   501 }
       
   502 
       
   503 FreeIdSet::~FreeIdSet() {
       
   504   _sets[_index] = NULL;
       
   505 }
       
   506 
       
   507 void FreeIdSet::set_safepoint(bool b) {
       
   508   _safepoint = b;
       
   509   if (b) {
       
   510     for (int j = 0; j < NSets; j++) {
       
   511       if (_sets[j] != NULL && _sets[j]->_waiters > 0) {
       
   512         Monitor* mon = _sets[j]->_mon;
       
   513         mon->lock_without_safepoint_check();
       
   514         mon->notify_all();
       
   515         mon->unlock();
       
   516       }
       
   517     }
       
   518   }
       
   519 }
       
   520 
       
   521 #define FID_STATS 0
       
   522 
       
   523 int FreeIdSet::claim_par_id() {
       
   524 #if FID_STATS
       
   525   thread_t tslf = thr_self();
       
   526   tty->print("claim_par_id[%d]: sz = %d, claimed = %d\n", tslf, _sz, _claimed);
       
   527 #endif
       
   528   MutexLockerEx x(_mon, Mutex::_no_safepoint_check_flag);
       
   529   while (!_safepoint && _hd == end_of_list) {
       
   530     _waiters++;
       
   531 #if FID_STATS
       
   532     if (_waiters > 5) {
       
   533       tty->print("claim_par_id waiting[%d]: %d waiters, %d claimed.\n",
       
   534                  tslf, _waiters, _claimed);
       
   535     }
       
   536 #endif
       
   537     _mon->wait(Mutex::_no_safepoint_check_flag);
       
   538     _waiters--;
       
   539   }
       
   540   if (_hd == end_of_list) {
       
   541 #if FID_STATS
       
   542     tty->print("claim_par_id[%d]: returning EOL.\n", tslf);
       
   543 #endif
       
   544     return -1;
       
   545   } else {
       
   546     int res = _hd;
       
   547     _hd = _ids[res];
       
   548     _ids[res] = claimed;  // For debugging.
       
   549     _claimed++;
       
   550 #if FID_STATS
       
   551     tty->print("claim_par_id[%d]: returning %d, claimed = %d.\n",
       
   552                tslf, res, _claimed);
       
   553 #endif
       
   554     return res;
       
   555   }
       
   556 }
       
   557 
       
   558 bool FreeIdSet::claim_perm_id(int i) {
       
   559   assert(0 <= i && i < _sz, "Out of range.");
       
   560   MutexLockerEx x(_mon, Mutex::_no_safepoint_check_flag);
       
   561   int prev = end_of_list;
       
   562   int cur = _hd;
       
   563   while (cur != end_of_list) {
       
   564     if (cur == i) {
       
   565       if (prev == end_of_list) {
       
   566         _hd = _ids[cur];
       
   567       } else {
       
   568         _ids[prev] = _ids[cur];
       
   569       }
       
   570       _ids[cur] = claimed;
       
   571       _claimed++;
       
   572       return true;
       
   573     } else {
       
   574       prev = cur;
       
   575       cur = _ids[cur];
       
   576     }
       
   577   }
       
   578   return false;
       
   579 
       
   580 }
       
   581 
       
   582 void FreeIdSet::release_par_id(int id) {
       
   583   MutexLockerEx x(_mon, Mutex::_no_safepoint_check_flag);
       
   584   assert(_ids[id] == claimed, "Precondition.");
       
   585   _ids[id] = _hd;
       
   586   _hd = id;
       
   587   _claimed--;
       
   588 #if FID_STATS
       
   589   tty->print("[%d] release_par_id(%d), waiters =%d,  claimed = %d.\n",
       
   590              thr_self(), id, _waiters, _claimed);
       
   591 #endif
       
   592   if (_waiters > 0)
       
   593     // Notify all would be safer, but this is OK, right?
       
   594     _mon->notify_all();
       
   595 }