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