Path: blob/master/test/hotspot/gtest/utilities/test_globalCounter_nested.cpp
41144 views
/*1* Copyright (c) 2018, 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*/2223#include "precompiled.hpp"24#include "runtime/atomic.hpp"25#include "runtime/os.hpp"26#include "utilities/globalCounter.hpp"27#include "utilities/globalCounter.inline.hpp"28#include "utilities/spinYield.hpp"29#include "threadHelper.inline.hpp"3031enum NestedTestState {32START,33START_WAIT,34OUTER_ENTERED,35INNER_ENTERED,36INNER_EXITED,37OUTER_EXITED,38SYNCHRONIZING,39SYNCHRONIZED40};4142class RCUNestedThread : public JavaTestThread {43volatile NestedTestState _state;44volatile bool _proceed;4546protected:47RCUNestedThread(Semaphore* post) :48JavaTestThread(post),49_state(START),50_proceed(false)51{}5253~RCUNestedThread() {}5455void set_state(NestedTestState new_state) {56Atomic::release_store(&_state, new_state);57}5859void wait_with_state(NestedTestState new_state) {60SpinYield spinner;61Atomic::release_store(&_state, new_state);62while (!Atomic::load_acquire(&_proceed)) {63spinner.wait();64}65Atomic::release_store(&_proceed, false);66}6768public:69NestedTestState state() const {70return Atomic::load_acquire(&_state);71}7273void wait_for_state(NestedTestState goal) {74SpinYield spinner;75while (state() != goal) {76spinner.wait();77}78}7980void proceed() {81Atomic::release_store(&_proceed, true);82}83};8485class RCUNestedReaderThread : public RCUNestedThread {86public:87RCUNestedReaderThread(Semaphore* post) :88RCUNestedThread(post)89{}9091virtual void main_run();92};9394void RCUNestedReaderThread::main_run() {95wait_with_state(START_WAIT);96{97GlobalCounter::CriticalSection outer(Thread::current());98wait_with_state(OUTER_ENTERED);99{100GlobalCounter::CriticalSection inner(Thread::current());101wait_with_state(INNER_ENTERED);102}103wait_with_state(INNER_EXITED);104}105wait_with_state(OUTER_EXITED);106}107108109class RCUNestedWriterThread : public RCUNestedThread {110public:111RCUNestedWriterThread(Semaphore* post) :112RCUNestedThread(post)113{}114115virtual void main_run();116};117118void RCUNestedWriterThread::main_run() {119wait_with_state(START_WAIT);120set_state(SYNCHRONIZING);121GlobalCounter::write_synchronize();122wait_with_state(SYNCHRONIZED);123}124125TEST_VM(GlobalCounter, nested_critical_section) {126Semaphore post;127RCUNestedReaderThread* reader = new RCUNestedReaderThread(&post);128RCUNestedWriterThread* outer = new RCUNestedWriterThread(&post);129RCUNestedWriterThread* inner = new RCUNestedWriterThread(&post);130131reader->doit();132outer->doit();133inner->doit();134135reader->wait_for_state(START_WAIT);136outer->wait_for_state(START_WAIT);137inner->wait_for_state(START_WAIT);138EXPECT_EQ(START_WAIT, reader->state());139EXPECT_EQ(START_WAIT, outer->state());140EXPECT_EQ(START_WAIT, inner->state());141142reader->proceed();143reader->wait_for_state(OUTER_ENTERED);144EXPECT_EQ(OUTER_ENTERED, reader->state());145EXPECT_EQ(START_WAIT, outer->state());146EXPECT_EQ(START_WAIT, inner->state());147148outer->proceed();149outer->wait_for_state(SYNCHRONIZING);150EXPECT_EQ(OUTER_ENTERED, reader->state());151EXPECT_EQ(SYNCHRONIZING, outer->state());152EXPECT_EQ(START_WAIT, inner->state());153154os::naked_short_sleep(100); // Give outer time in synchronization.155EXPECT_EQ(OUTER_ENTERED, reader->state());156EXPECT_EQ(SYNCHRONIZING, outer->state());157EXPECT_EQ(START_WAIT, inner->state());158159reader->proceed();160reader->wait_for_state(INNER_ENTERED);161EXPECT_EQ(INNER_ENTERED, reader->state());162EXPECT_EQ(SYNCHRONIZING, outer->state());163EXPECT_EQ(START_WAIT, inner->state());164165inner->proceed();166inner->wait_for_state(SYNCHRONIZING);167EXPECT_EQ(INNER_ENTERED, reader->state());168EXPECT_EQ(SYNCHRONIZING, outer->state());169EXPECT_EQ(SYNCHRONIZING, inner->state());170171os::naked_short_sleep(100); // Give writers time in synchronization.172EXPECT_EQ(INNER_ENTERED, reader->state());173EXPECT_EQ(SYNCHRONIZING, outer->state());174EXPECT_EQ(SYNCHRONIZING, inner->state());175176reader->proceed();177reader->wait_for_state(INNER_EXITED);178// inner does *not* complete synchronization here.179EXPECT_EQ(INNER_EXITED, reader->state());180EXPECT_EQ(SYNCHRONIZING, outer->state());181EXPECT_EQ(SYNCHRONIZING, inner->state());182183os::naked_short_sleep(100); // Give writers more time in synchronization.184EXPECT_EQ(INNER_EXITED, reader->state());185EXPECT_EQ(SYNCHRONIZING, outer->state());186EXPECT_EQ(SYNCHRONIZING, inner->state());187188reader->proceed();189reader->wait_for_state(OUTER_EXITED);190// Both inner and outer can synchronize now.191outer->wait_for_state(SYNCHRONIZED);192inner->wait_for_state(SYNCHRONIZED);193EXPECT_EQ(OUTER_EXITED, reader->state());194EXPECT_EQ(SYNCHRONIZED, outer->state());195EXPECT_EQ(SYNCHRONIZED, inner->state());196197// Wait for reader, outer, and inner to complete.198reader->proceed();199outer->proceed();200inner->proceed();201for (uint i = 0; i < 3; ++i) {202post.wait();203}204}205206207