< prev index next >
src/hotspot/share/gc/shared/taskqueue.cpp
Print this page
rev 57895 : [mq]: 8215297-remove-ptt
*** 1,7 ****
/*
! * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
--- 1,7 ----
/*
! * Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*** 31,46 ****
#include "runtime/os.hpp"
#include "runtime/thread.inline.hpp"
#include "utilities/debug.hpp"
#include "utilities/stack.inline.hpp"
- #ifdef TRACESPINNING
- uint ParallelTaskTerminator::_total_yields = 0;
- uint ParallelTaskTerminator::_total_spins = 0;
- uint ParallelTaskTerminator::_total_peeks = 0;
- #endif
-
#if TASKQUEUE_STATS
const char * const TaskQueueStats::_names[last_stat_id] = {
"qpush", "qpop", "qpop-s", "qattempt", "qsteal", "opush", "omax"
};
--- 31,40 ----
*** 110,282 ****
get(overflow_max_len), get(overflow));
}
#endif // ASSERT
#endif // TASKQUEUE_STATS
- ParallelTaskTerminator::
- ParallelTaskTerminator(uint n_threads, TaskQueueSetSuper* queue_set) :
- _n_threads(n_threads),
- _queue_set(queue_set),
- _offered_termination(0) {}
-
- ParallelTaskTerminator::~ParallelTaskTerminator() {
- assert(_offered_termination == 0 || !peek_in_queue_set(), "Precondition");
- assert(_offered_termination == 0 || _offered_termination == _n_threads, "Terminated or aborted" );
- }
-
- bool ParallelTaskTerminator::peek_in_queue_set() {
- return _queue_set->peek();
- }
-
- void ParallelTaskTerminator::yield() {
- assert(_offered_termination <= _n_threads, "Invariant");
- os::naked_yield();
- }
-
- void ParallelTaskTerminator::sleep(uint millis) {
- assert(_offered_termination <= _n_threads, "Invariant");
- os::naked_sleep(millis);
- }
-
- bool
- ParallelTaskTerminator::offer_termination(TerminatorTerminator* terminator) {
- assert(_n_threads > 0, "Initialization is incorrect");
- assert(_offered_termination < _n_threads, "Invariant");
- Atomic::inc(&_offered_termination);
-
- uint yield_count = 0;
- // Number of hard spin loops done since last yield
- uint hard_spin_count = 0;
- // Number of iterations in the hard spin loop.
- uint hard_spin_limit = WorkStealingHardSpins;
-
- // If WorkStealingSpinToYieldRatio is 0, no hard spinning is done.
- // If it is greater than 0, then start with a small number
- // of spins and increase number with each turn at spinning until
- // the count of hard spins exceeds WorkStealingSpinToYieldRatio.
- // Then do a yield() call and start spinning afresh.
- if (WorkStealingSpinToYieldRatio > 0) {
- hard_spin_limit = WorkStealingHardSpins >> WorkStealingSpinToYieldRatio;
- hard_spin_limit = MAX2(hard_spin_limit, 1U);
- }
- // Remember the initial spin limit.
- uint hard_spin_start = hard_spin_limit;
-
- // Loop waiting for all threads to offer termination or
- // more work.
- while (true) {
- assert(_offered_termination <= _n_threads, "Invariant");
- // Are all threads offering termination?
- if (_offered_termination == _n_threads) {
- assert(!peek_in_queue_set(), "Precondition");
- return true;
- } else {
- // Look for more work.
- // Periodically sleep() instead of yield() to give threads
- // waiting on the cores the chance to grab this code
- if (yield_count <= WorkStealingYieldsBeforeSleep) {
- // Do a yield or hardspin. For purposes of deciding whether
- // to sleep, count this as a yield.
- yield_count++;
-
- // Periodically call yield() instead spinning
- // After WorkStealingSpinToYieldRatio spins, do a yield() call
- // and reset the counts and starting limit.
- if (hard_spin_count > WorkStealingSpinToYieldRatio) {
- yield();
- hard_spin_count = 0;
- hard_spin_limit = hard_spin_start;
- #ifdef TRACESPINNING
- _total_yields++;
- #endif
- } else {
- // Hard spin this time
- // Increase the hard spinning period but only up to a limit.
- hard_spin_limit = MIN2(2*hard_spin_limit,
- (uint) WorkStealingHardSpins);
- for (uint j = 0; j < hard_spin_limit; j++) {
- SpinPause();
- }
- hard_spin_count++;
- #ifdef TRACESPINNING
- _total_spins++;
- #endif
- }
- } else {
- log_develop_trace(gc, task)("ParallelTaskTerminator::offer_termination() thread " PTR_FORMAT " sleeps after %u yields",
- p2i(Thread::current()), yield_count);
- yield_count = 0;
- // A sleep will cause this processor to seek work on another processor's
- // runqueue, if it has nothing else to run (as opposed to the yield
- // which may only move the thread to the end of the this processor's
- // runqueue).
- sleep(WorkStealingSleepMillis);
- }
-
- #ifdef TRACESPINNING
- _total_peeks++;
- #endif
- if (peek_in_queue_set() ||
- (terminator != NULL && terminator->should_exit_termination())) {
- return complete_or_exit_termination();
- }
- }
- }
- }
-
- #ifdef TRACESPINNING
- void ParallelTaskTerminator::print_termination_counts() {
- log_trace(gc, task)("ParallelTaskTerminator Total yields: %u"
- " Total spins: %u Total peeks: %u",
- total_yields(),
- total_spins(),
- total_peeks());
- }
- #endif
-
- bool ParallelTaskTerminator::complete_or_exit_termination() {
- // If termination is ever reached, terminator should stay in such state,
- // so that all threads see the same state
- uint current_offered = _offered_termination;
- uint expected_value;
- do {
- if (current_offered == _n_threads) {
- assert(!peek_in_queue_set(), "Precondition");
- return true;
- }
- expected_value = current_offered;
- } while ((current_offered = Atomic::cmpxchg(&_offered_termination, current_offered, current_offered - 1)) != expected_value);
-
- assert(_offered_termination < _n_threads, "Invariant");
- return false;
- }
-
- void ParallelTaskTerminator::reset_for_reuse() {
- if (_offered_termination != 0) {
- assert(_offered_termination == _n_threads,
- "Terminator may still be in use");
- _offered_termination = 0;
- }
- }
-
#ifdef ASSERT
bool ObjArrayTask::is_valid() const {
return _obj != NULL && _obj->is_objArray() && _index >= 0 &&
_index < objArrayOop(_obj)->length();
}
#endif // ASSERT
-
- void ParallelTaskTerminator::reset_for_reuse(uint n_threads) {
- reset_for_reuse();
- _n_threads = n_threads;
- }
-
- TaskTerminator::TaskTerminator(uint n_threads, TaskQueueSetSuper* queue_set) :
- _terminator(UseOWSTTaskTerminator ? new OWSTTaskTerminator(n_threads, queue_set)
- : new ParallelTaskTerminator(n_threads, queue_set)) {
- }
-
- TaskTerminator::~TaskTerminator() {
- if (_terminator != NULL) {
- delete _terminator;
- }
- }
--- 104,114 ----
< prev index next >