1 /*
2 * Copyright (c) 2018, 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 #include "precompiled.hpp"
25 #include "metaprogramming/isRegisteredEnum.hpp"
26 #include "runtime/atomic.hpp"
27 #include "runtime/os.hpp"
28 #include "utilities/globalCounter.hpp"
29 #include "utilities/globalCounter.inline.hpp"
30 #include "utilities/spinYield.hpp"
31 #include "threadHelper.inline.hpp"
32
33 enum NestedTestState {
34 START,
35 START_WAIT,
36 OUTER_ENTERED,
37 INNER_ENTERED,
38 INNER_EXITED,
39 OUTER_EXITED,
40 SYNCHRONIZING,
41 SYNCHRONIZED
42 };
43 template<> struct IsRegisteredEnum<NestedTestState> : public TrueType {};
44
45 class RCUNestedThread : public JavaTestThread {
46 volatile NestedTestState _state;
47 volatile bool _proceed;
48
49 protected:
RCUNestedThread(Semaphore * post)50 RCUNestedThread(Semaphore* post) :
51 JavaTestThread(post),
52 _state(START),
53 _proceed(false)
54 {}
55
~RCUNestedThread()56 ~RCUNestedThread() {}
57
set_state(NestedTestState new_state)58 void set_state(NestedTestState new_state) {
59 Atomic::release_store(&_state, new_state);
60 }
61
wait_with_state(NestedTestState new_state)62 void wait_with_state(NestedTestState new_state) {
63 SpinYield spinner;
64 Atomic::release_store(&_state, new_state);
65 while (!Atomic::load_acquire(&_proceed)) {
66 spinner.wait();
67 }
68 Atomic::release_store(&_proceed, false);
69 }
70
71 public:
state() const72 NestedTestState state() const {
73 return Atomic::load_acquire(&_state);
74 }
75
wait_for_state(NestedTestState goal)76 void wait_for_state(NestedTestState goal) {
77 SpinYield spinner;
78 while (state() != goal) {
79 spinner.wait();
80 }
81 }
82
proceed()83 void proceed() {
84 Atomic::release_store(&_proceed, true);
85 }
86 };
87
88 class RCUNestedReaderThread : public RCUNestedThread {
89 public:
RCUNestedReaderThread(Semaphore * post)90 RCUNestedReaderThread(Semaphore* post) :
91 RCUNestedThread(post)
92 {}
93
94 virtual void main_run();
95 };
96
main_run()97 void RCUNestedReaderThread::main_run() {
98 wait_with_state(START_WAIT);
99 {
100 GlobalCounter::CriticalSection outer(Thread::current());
101 wait_with_state(OUTER_ENTERED);
102 {
103 GlobalCounter::CriticalSection inner(Thread::current());
104 wait_with_state(INNER_ENTERED);
105 }
106 wait_with_state(INNER_EXITED);
107 }
108 wait_with_state(OUTER_EXITED);
109 }
110
111
112 class RCUNestedWriterThread : public RCUNestedThread {
113 public:
RCUNestedWriterThread(Semaphore * post)114 RCUNestedWriterThread(Semaphore* post) :
115 RCUNestedThread(post)
116 {}
117
118 virtual void main_run();
119 };
120
main_run()121 void RCUNestedWriterThread::main_run() {
122 wait_with_state(START_WAIT);
123 set_state(SYNCHRONIZING);
124 GlobalCounter::write_synchronize();
125 wait_with_state(SYNCHRONIZED);
126 }
127
TEST_VM(GlobalCounter,nested_critical_section)128 TEST_VM(GlobalCounter, nested_critical_section) {
129 Semaphore post;
130 RCUNestedReaderThread* reader = new RCUNestedReaderThread(&post);
131 RCUNestedWriterThread* outer = new RCUNestedWriterThread(&post);
132 RCUNestedWriterThread* inner = new RCUNestedWriterThread(&post);
133
134 reader->doit();
135 outer->doit();
136 inner->doit();
137
138 reader->wait_for_state(START_WAIT);
139 outer->wait_for_state(START_WAIT);
140 inner->wait_for_state(START_WAIT);
141 EXPECT_EQ(START_WAIT, reader->state());
142 EXPECT_EQ(START_WAIT, outer->state());
143 EXPECT_EQ(START_WAIT, inner->state());
144
145 reader->proceed();
146 reader->wait_for_state(OUTER_ENTERED);
147 EXPECT_EQ(OUTER_ENTERED, reader->state());
148 EXPECT_EQ(START_WAIT, outer->state());
149 EXPECT_EQ(START_WAIT, inner->state());
150
151 outer->proceed();
152 outer->wait_for_state(SYNCHRONIZING);
153 EXPECT_EQ(OUTER_ENTERED, reader->state());
154 EXPECT_EQ(SYNCHRONIZING, outer->state());
155 EXPECT_EQ(START_WAIT, inner->state());
156
157 os::naked_short_sleep(100); // Give outer time in synchronization.
158 EXPECT_EQ(OUTER_ENTERED, reader->state());
159 EXPECT_EQ(SYNCHRONIZING, outer->state());
160 EXPECT_EQ(START_WAIT, inner->state());
161
162 reader->proceed();
163 reader->wait_for_state(INNER_ENTERED);
164 EXPECT_EQ(INNER_ENTERED, reader->state());
165 EXPECT_EQ(SYNCHRONIZING, outer->state());
166 EXPECT_EQ(START_WAIT, inner->state());
167
168 inner->proceed();
169 inner->wait_for_state(SYNCHRONIZING);
170 EXPECT_EQ(INNER_ENTERED, reader->state());
171 EXPECT_EQ(SYNCHRONIZING, outer->state());
172 EXPECT_EQ(SYNCHRONIZING, inner->state());
173
174 os::naked_short_sleep(100); // Give writers time in synchronization.
175 EXPECT_EQ(INNER_ENTERED, reader->state());
176 EXPECT_EQ(SYNCHRONIZING, outer->state());
177 EXPECT_EQ(SYNCHRONIZING, inner->state());
178
179 reader->proceed();
180 reader->wait_for_state(INNER_EXITED);
181 // inner does *not* complete synchronization here.
182 EXPECT_EQ(INNER_EXITED, reader->state());
183 EXPECT_EQ(SYNCHRONIZING, outer->state());
184 EXPECT_EQ(SYNCHRONIZING, inner->state());
185
186 os::naked_short_sleep(100); // Give writers more time in synchronization.
187 EXPECT_EQ(INNER_EXITED, reader->state());
188 EXPECT_EQ(SYNCHRONIZING, outer->state());
189 EXPECT_EQ(SYNCHRONIZING, inner->state());
190
191 reader->proceed();
192 reader->wait_for_state(OUTER_EXITED);
193 // Both inner and outer can synchronize now.
194 outer->wait_for_state(SYNCHRONIZED);
195 inner->wait_for_state(SYNCHRONIZED);
196 EXPECT_EQ(OUTER_EXITED, reader->state());
197 EXPECT_EQ(SYNCHRONIZED, outer->state());
198 EXPECT_EQ(SYNCHRONIZED, inner->state());
199
200 // Wait for reader, outer, and inner to complete.
201 reader->proceed();
202 outer->proceed();
203 inner->proceed();
204 for (uint i = 0; i < 3; ++i) {
205 post.wait();
206 }
207 }
208