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