Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/gtest/gc/g1/test_g1BatchedGangTask.cpp
41149 views
1
/*
2
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*
23
*/
24
25
#include "precompiled.hpp"
26
27
#include "gc/g1/g1BatchedGangTask.hpp"
28
#include "gc/shared/workgroup.hpp"
29
#include "runtime/atomic.hpp"
30
#include "unittest.hpp"
31
32
class G1BatchedGangTaskWorkers : AllStatic {
33
static WorkGang* _work_gang;
34
static WorkGang* work_gang() {
35
if (_work_gang == nullptr) {
36
_work_gang = new WorkGang("G1 Small Workers", MaxWorkers, false, false);
37
_work_gang->initialize_workers();
38
_work_gang->update_active_workers(MaxWorkers);
39
}
40
return _work_gang;
41
}
42
43
public:
44
static const uint MaxWorkers = 4;
45
static void run_task(AbstractGangTask* task) {
46
work_gang()->run_task(task);
47
}
48
};
49
50
WorkGang* G1BatchedGangTaskWorkers::_work_gang = nullptr;
51
52
class G1TestSubTask : public G1AbstractSubTask {
53
mutable uint _phase;
54
volatile uint _num_do_work; // Amount of do_work() has been called.
55
56
void check_and_inc_phase(uint expected) const {
57
ASSERT_EQ(_phase, expected);
58
_phase++;
59
}
60
61
bool volatile* _do_work_called_by;
62
63
protected:
64
uint _max_workers;
65
66
void do_work_called(uint worker_id) {
67
Atomic::inc(&_num_do_work);
68
bool orig_value = Atomic::cmpxchg(&_do_work_called_by[worker_id], false, true);
69
ASSERT_EQ(orig_value, false);
70
}
71
72
void verify_do_work_called_by(uint num_workers) {
73
ASSERT_EQ(Atomic::load(&_num_do_work), num_workers);
74
// Do not need to check the _do_work_called_by array. The count is already verified
75
// by above statement, and we already check that a given flag is only set once.
76
}
77
78
public:
79
// Actual use of GCParPhasesSentinel will cause an assertion failure when trying
80
// to add timing information - this should be disabled here.
81
G1TestSubTask() : G1AbstractSubTask(G1GCPhaseTimes::GCParPhasesSentinel),
82
_phase(0),
83
_num_do_work(0),
84
_do_work_called_by(nullptr),
85
_max_workers(0) {
86
check_and_inc_phase(0);
87
}
88
89
~G1TestSubTask() {
90
check_and_inc_phase(3);
91
FREE_C_HEAP_ARRAY(bool, _do_work_called_by);
92
}
93
94
double worker_cost() const override {
95
check_and_inc_phase(1);
96
return 1.0;
97
}
98
99
// Called by G1BatchedGangTask to provide information about the the maximum
100
// number of workers for all subtasks after it has been determined.
101
void set_max_workers(uint max_workers) override {
102
assert(max_workers >= 1, "must be");
103
check_and_inc_phase(2);
104
105
_do_work_called_by = NEW_C_HEAP_ARRAY(bool, max_workers, mtInternal);
106
for (uint i = 0; i < max_workers; i++) {
107
_do_work_called_by[i] = false;
108
}
109
_max_workers = max_workers;
110
}
111
112
void do_work(uint worker_id) override {
113
do_work_called(worker_id);
114
}
115
};
116
117
class G1SerialTestSubTask : public G1TestSubTask {
118
public:
119
G1SerialTestSubTask() : G1TestSubTask() { }
120
~G1SerialTestSubTask() {
121
verify_do_work_called_by(1);
122
}
123
124
double worker_cost() const override {
125
G1TestSubTask::worker_cost();
126
return 1.0;
127
}
128
};
129
130
class G1ParallelTestSubTask : public G1TestSubTask {
131
public:
132
G1ParallelTestSubTask() : G1TestSubTask() { }
133
~G1ParallelTestSubTask() {
134
verify_do_work_called_by(_max_workers);
135
}
136
137
double worker_cost() const override {
138
G1TestSubTask::worker_cost();
139
return 2.0;
140
}
141
};
142
143
class G1TestBatchedGangTask : public G1BatchedGangTask {
144
public:
145
G1TestBatchedGangTask() : G1BatchedGangTask("Batched Gang Test Task", nullptr) {
146
add_serial_task(new G1SerialTestSubTask());
147
add_parallel_task(new G1ParallelTestSubTask());
148
}
149
};
150
151
TEST_VM(G1BatchedGangTask, check) {
152
G1TestBatchedGangTask task;
153
uint tasks = task.num_workers_estimate();
154
ASSERT_EQ(tasks, 3u);
155
task.set_max_workers(G1BatchedGangTaskWorkers::MaxWorkers);
156
G1BatchedGangTaskWorkers::run_task(&task);
157
}
158
159