Path: blob/master/test/hotspot/gtest/gc/g1/test_g1BatchedGangTask.cpp
41149 views
/*1* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"2526#include "gc/g1/g1BatchedGangTask.hpp"27#include "gc/shared/workgroup.hpp"28#include "runtime/atomic.hpp"29#include "unittest.hpp"3031class G1BatchedGangTaskWorkers : AllStatic {32static WorkGang* _work_gang;33static WorkGang* work_gang() {34if (_work_gang == nullptr) {35_work_gang = new WorkGang("G1 Small Workers", MaxWorkers, false, false);36_work_gang->initialize_workers();37_work_gang->update_active_workers(MaxWorkers);38}39return _work_gang;40}4142public:43static const uint MaxWorkers = 4;44static void run_task(AbstractGangTask* task) {45work_gang()->run_task(task);46}47};4849WorkGang* G1BatchedGangTaskWorkers::_work_gang = nullptr;5051class G1TestSubTask : public G1AbstractSubTask {52mutable uint _phase;53volatile uint _num_do_work; // Amount of do_work() has been called.5455void check_and_inc_phase(uint expected) const {56ASSERT_EQ(_phase, expected);57_phase++;58}5960bool volatile* _do_work_called_by;6162protected:63uint _max_workers;6465void do_work_called(uint worker_id) {66Atomic::inc(&_num_do_work);67bool orig_value = Atomic::cmpxchg(&_do_work_called_by[worker_id], false, true);68ASSERT_EQ(orig_value, false);69}7071void verify_do_work_called_by(uint num_workers) {72ASSERT_EQ(Atomic::load(&_num_do_work), num_workers);73// Do not need to check the _do_work_called_by array. The count is already verified74// by above statement, and we already check that a given flag is only set once.75}7677public:78// Actual use of GCParPhasesSentinel will cause an assertion failure when trying79// to add timing information - this should be disabled here.80G1TestSubTask() : G1AbstractSubTask(G1GCPhaseTimes::GCParPhasesSentinel),81_phase(0),82_num_do_work(0),83_do_work_called_by(nullptr),84_max_workers(0) {85check_and_inc_phase(0);86}8788~G1TestSubTask() {89check_and_inc_phase(3);90FREE_C_HEAP_ARRAY(bool, _do_work_called_by);91}9293double worker_cost() const override {94check_and_inc_phase(1);95return 1.0;96}9798// Called by G1BatchedGangTask to provide information about the the maximum99// number of workers for all subtasks after it has been determined.100void set_max_workers(uint max_workers) override {101assert(max_workers >= 1, "must be");102check_and_inc_phase(2);103104_do_work_called_by = NEW_C_HEAP_ARRAY(bool, max_workers, mtInternal);105for (uint i = 0; i < max_workers; i++) {106_do_work_called_by[i] = false;107}108_max_workers = max_workers;109}110111void do_work(uint worker_id) override {112do_work_called(worker_id);113}114};115116class G1SerialTestSubTask : public G1TestSubTask {117public:118G1SerialTestSubTask() : G1TestSubTask() { }119~G1SerialTestSubTask() {120verify_do_work_called_by(1);121}122123double worker_cost() const override {124G1TestSubTask::worker_cost();125return 1.0;126}127};128129class G1ParallelTestSubTask : public G1TestSubTask {130public:131G1ParallelTestSubTask() : G1TestSubTask() { }132~G1ParallelTestSubTask() {133verify_do_work_called_by(_max_workers);134}135136double worker_cost() const override {137G1TestSubTask::worker_cost();138return 2.0;139}140};141142class G1TestBatchedGangTask : public G1BatchedGangTask {143public:144G1TestBatchedGangTask() : G1BatchedGangTask("Batched Gang Test Task", nullptr) {145add_serial_task(new G1SerialTestSubTask());146add_parallel_task(new G1ParallelTestSubTask());147}148};149150TEST_VM(G1BatchedGangTask, check) {151G1TestBatchedGangTask task;152uint tasks = task.num_workers_estimate();153ASSERT_EQ(tasks, 3u);154task.set_max_workers(G1BatchedGangTaskWorkers::MaxWorkers);155G1BatchedGangTaskWorkers::run_task(&task);156}157158159