mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 03:58:21 +00:00
96 lines
4.2 KiB
C++
96 lines
4.2 KiB
C++
/*
|
|
* Copyright (c) 2020, 2025, 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.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*
|
|
*/
|
|
|
|
#ifndef SHARE_GC_SHARED_PARTIALARRAYTASKSTEPPER_INLINE_HPP
|
|
#define SHARE_GC_SHARED_PARTIALARRAYTASKSTEPPER_INLINE_HPP
|
|
|
|
#include "gc/shared/partialArrayTaskStepper.hpp"
|
|
|
|
#include "gc/shared/partialArrayState.hpp"
|
|
#include "utilities/checkedCast.hpp"
|
|
#include "utilities/debug.hpp"
|
|
|
|
size_t PartialArrayTaskStepper::chunk_size() const {
|
|
return _chunk_size;
|
|
}
|
|
|
|
PartialArrayTaskStepper::Step
|
|
PartialArrayTaskStepper::start(size_t length) const {
|
|
size_t end = length % _chunk_size; // End of initial chunk.
|
|
// If the initial chunk is the complete array, then don't need any partial
|
|
// tasks. Otherwise, start with just one partial task; see new task
|
|
// calculation in next().
|
|
return Step{ end, (length > end) ? 1u : 0u };
|
|
}
|
|
|
|
PartialArrayTaskStepper::Step
|
|
PartialArrayTaskStepper::next_impl(size_t length, Atomic<size_t>* index_addr) const {
|
|
// The start of the next task is in the state's index.
|
|
// Atomically increment by the chunk size to claim the associated chunk.
|
|
// Because we limit the number of enqueued tasks to being no more than the
|
|
// number of remaining chunks to process, we can use an atomic add for the
|
|
// claim, rather than a CAS loop.
|
|
size_t start = index_addr->fetch_then_add(_chunk_size, memory_order_relaxed);
|
|
|
|
assert(start < length, "invariant: start %zu, length %zu", start, length);
|
|
assert(((length - start) % _chunk_size) == 0,
|
|
"invariant: start %zu, length %zu, chunk size %zu",
|
|
start, length, _chunk_size);
|
|
|
|
// Determine the number of new tasks to create.
|
|
// Zero-based index for this partial task. The initial task isn't counted.
|
|
uint task_num = checked_cast<uint>(start / _chunk_size);
|
|
// Number of tasks left to process, including this one.
|
|
uint remaining_tasks = checked_cast<uint>((length - start) / _chunk_size);
|
|
assert(remaining_tasks > 0, "invariant");
|
|
// Compute number of pending tasks, including this one. The maximum number
|
|
// of tasks is a function of task_num (N) and _task_fanout (F).
|
|
// 1 : current task
|
|
// N : number of preceding tasks
|
|
// F*N : maximum created for preceding tasks
|
|
// => F*N - N + 1 : maximum number of tasks
|
|
// => (F-1)*N + 1
|
|
assert(_task_limit > 0, "precondition");
|
|
assert(_task_fanout > 0, "precondition");
|
|
uint max_pending = (_task_fanout - 1) * task_num + 1;
|
|
|
|
// The actual pending may be less than that. Bound by remaining_tasks to
|
|
// not overrun. Also bound by _task_limit to avoid spawning an excessive
|
|
// number of tasks for a large array. The +1 is to replace the current
|
|
// task with a new task when _task_limit limited. The pending value may
|
|
// not be what's actually in the queues, because of concurrent task
|
|
// processing. That's okay; we just need to determine the correct number
|
|
// of tasks to add for this task.
|
|
uint pending = MIN3(max_pending, remaining_tasks, _task_limit);
|
|
uint ncreate = MIN2(_task_fanout, MIN2(remaining_tasks, _task_limit + 1) - pending);
|
|
return Step{ start, ncreate };
|
|
}
|
|
|
|
PartialArrayTaskStepper::Step
|
|
PartialArrayTaskStepper::next(PartialArrayState* state) const {
|
|
return next_impl(state->length(), state->index_addr());
|
|
}
|
|
|
|
#endif // SHARE_GC_SHARED_PARTIALARRAYTASKSTEPPER_INLINE_HPP
|