test/hotspot/gtest/utilities/test_globalCounter_nested.cpp
changeset 52332 d2a3503c72f7
child 59247 56bf71d64d51
equal deleted inserted replaced
52331:8d8702585652 52332:d2a3503c72f7
       
     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 
       
    34 enum NestedTestState {
       
    35   START,
       
    36   START_WAIT,
       
    37   OUTER_ENTERED,
       
    38   INNER_ENTERED,
       
    39   INNER_EXITED,
       
    40   OUTER_EXITED,
       
    41   SYNCHRONIZING,
       
    42   SYNCHRONIZED
       
    43 };
       
    44 template<> struct IsRegisteredEnum<NestedTestState> : public TrueType {};
       
    45 
       
    46 class RCUNestedThread : public JavaTestThread {
       
    47   volatile NestedTestState _state;
       
    48   volatile bool _proceed;
       
    49 
       
    50 protected:
       
    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 
       
    72 public:
       
    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 
       
    89 class RCUNestedReaderThread : public RCUNestedThread {
       
    90 public:
       
    91   RCUNestedReaderThread(Semaphore* post) :
       
    92     RCUNestedThread(post)
       
    93   {}
       
    94 
       
    95   virtual void main_run();
       
    96 };
       
    97 
       
    98 void 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 
       
   113 class RCUNestedWriterThread : public RCUNestedThread {
       
   114 public:
       
   115   RCUNestedWriterThread(Semaphore* post) :
       
   116     RCUNestedThread(post)
       
   117   {}
       
   118 
       
   119   virtual void main_run();
       
   120 };
       
   121 
       
   122 void RCUNestedWriterThread::main_run() {
       
   123   wait_with_state(START_WAIT);
       
   124   set_state(SYNCHRONIZING);
       
   125   GlobalCounter::write_synchronize();
       
   126   wait_with_state(SYNCHRONIZED);
       
   127 }
       
   128 
       
   129 TEST_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 }