test/hotspot/gtest/utilities/test_waitBarrier.cpp
author stefank
Mon, 25 Nov 2019 12:22:13 +0100
changeset 59247 56bf71d64d51
parent 53254 47bc06170313
permissions -rw-r--r--
8234562: Move OrderAccess::release_store*/load_acquire to Atomic Reviewed-by: rehn, dholmes
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
53254
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
     1
/*
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
     2
 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
     4
 *
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
     7
 * published by the Free Software Foundation.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
     8
 *
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    13
 * accompanied this code).
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    14
 *
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    18
 *
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    20
 * or visit www.oracle.com if you need additional information or have any
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    21
 * questions.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    22
 */
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    23
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    24
#include "precompiled.hpp"
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    25
#include "runtime/atomic.hpp"
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    26
#include "runtime/orderAccess.hpp"
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    27
#include "runtime/os.hpp"
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    28
#include "utilities/spinYield.hpp"
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    29
#include "utilities/waitBarrier.hpp"
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    30
#include "threadHelper.inline.hpp"
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    31
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    32
static volatile int wait_tag = 0;
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    33
static volatile int valid_value = 0;
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    34
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    35
template <typename WaitBarrierImpl>
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    36
class WBThread : public JavaTestThread {
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    37
public:
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    38
  static volatile bool _exit;
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    39
  WaitBarrierType<WaitBarrierImpl>* _wait_barrier;
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    40
  Semaphore* _wrt_start;
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    41
  volatile int _on_barrier;
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    42
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    43
  WBThread(Semaphore* post, WaitBarrierType<WaitBarrierImpl>* wb, Semaphore* wrt_start)
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    44
    : JavaTestThread(post), _wait_barrier(wb), _wrt_start(wrt_start) {};
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    45
  virtual ~WBThread(){}
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    46
  void main_run() {
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    47
    _wrt_start->signal();
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    48
    int vv, tag;
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    49
    // Similar to how a JavaThread would stop in a safepoint.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    50
    while (!_exit) {
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    51
      // Load the published tag.
59247
56bf71d64d51 8234562: Move OrderAccess::release_store*/load_acquire to Atomic
stefank
parents: 53254
diff changeset
    52
      tag = Atomic::load_acquire(&wait_tag);
53254
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    53
      // Publish the tag this thread is going to wait for.
59247
56bf71d64d51 8234562: Move OrderAccess::release_store*/load_acquire to Atomic
stefank
parents: 53254
diff changeset
    54
      Atomic::release_store(&_on_barrier, tag);
53254
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    55
      if (_on_barrier == 0) {
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    56
        SpinPause();
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    57
        continue;
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    58
      }
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    59
      OrderAccess::storeload(); // Loads in WB must not float up.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    60
      // Wait until we are woken.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    61
      _wait_barrier->wait(tag);
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    62
      // Verify that we do not see an invalid value.
59247
56bf71d64d51 8234562: Move OrderAccess::release_store*/load_acquire to Atomic
stefank
parents: 53254
diff changeset
    63
      vv = Atomic::load_acquire(&valid_value);
53254
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    64
      ASSERT_EQ((vv & 0x1), 0);
59247
56bf71d64d51 8234562: Move OrderAccess::release_store*/load_acquire to Atomic
stefank
parents: 53254
diff changeset
    65
      Atomic::release_store(&_on_barrier, 0);
53254
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    66
    }
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    67
  }
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    68
};
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    69
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    70
template <typename WaitBarrierImpl>
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    71
volatile bool WBThread<WaitBarrierImpl>::_exit = false;
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    72
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    73
template <typename WaitBarrierImpl>
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    74
class WBArmerThread : public JavaTestThread {
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    75
public:
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    76
  WBArmerThread(Semaphore* post) : JavaTestThread(post) {
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    77
  };
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    78
  virtual ~WBArmerThread(){}
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    79
  void main_run() {
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    80
    static const int NUMBER_OF_READERS = 4;
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    81
    Semaphore post;
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    82
    Semaphore wrt_start;
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    83
    WaitBarrierType<WaitBarrierImpl> wb(this);
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    84
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    85
    WBThread<WaitBarrierImpl>* reader1 = new WBThread<WaitBarrierImpl>(&post, &wb, &wrt_start);
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    86
    WBThread<WaitBarrierImpl>* reader2 = new WBThread<WaitBarrierImpl>(&post, &wb, &wrt_start);
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    87
    WBThread<WaitBarrierImpl>* reader3 = new WBThread<WaitBarrierImpl>(&post, &wb, &wrt_start);
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    88
    WBThread<WaitBarrierImpl>* reader4 = new WBThread<WaitBarrierImpl>(&post, &wb, &wrt_start);
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    89
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    90
    reader1->doit();
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    91
    reader2->doit();
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    92
    reader3->doit();
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    93
    reader4->doit();
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    94
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    95
    int nw = NUMBER_OF_READERS;
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    96
    while (nw > 0) {
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    97
      wrt_start.wait();
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    98
      --nw;
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    99
    }
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   100
    jlong stop_ms = os::javaTimeMillis() + 1000; // 1 seconds max test time
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   101
    int next_tag = 1;
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   102
    // Similar to how the VM thread would use a WaitBarrier in a safepoint.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   103
    while (stop_ms > os::javaTimeMillis()) {
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   104
      // Arm next tag.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   105
      wb.arm(next_tag);
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   106
      // Publish tag.
59247
56bf71d64d51 8234562: Move OrderAccess::release_store*/load_acquire to Atomic
stefank
parents: 53254
diff changeset
   107
      Atomic::release_store_fence(&wait_tag, next_tag);
53254
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   108
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   109
      // Wait until threads picked up new tag.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   110
      while (reader1->_on_barrier != wait_tag ||
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   111
             reader2->_on_barrier != wait_tag ||
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   112
             reader3->_on_barrier != wait_tag ||
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   113
             reader4->_on_barrier != wait_tag) {
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   114
        SpinPause();
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   115
      }
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   116
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   117
      // Set an invalid value.
59247
56bf71d64d51 8234562: Move OrderAccess::release_store*/load_acquire to Atomic
stefank
parents: 53254
diff changeset
   118
      Atomic::release_store(&valid_value, valid_value + 1); // odd
53254
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   119
      os::naked_yield();
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   120
      // Set a valid value.
59247
56bf71d64d51 8234562: Move OrderAccess::release_store*/load_acquire to Atomic
stefank
parents: 53254
diff changeset
   121
      Atomic::release_store(&valid_value, valid_value + 1); // even
53254
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   122
      // Publish inactive tag.
59247
56bf71d64d51 8234562: Move OrderAccess::release_store*/load_acquire to Atomic
stefank
parents: 53254
diff changeset
   123
      Atomic::release_store_fence(&wait_tag, 0); // Stores in WB must not float up.
53254
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   124
      wb.disarm();
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   125
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   126
      // Wait until threads done valid_value verification.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   127
      while (reader1->_on_barrier != 0 ||
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   128
             reader2->_on_barrier != 0 ||
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   129
             reader3->_on_barrier != 0 ||
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   130
             reader4->_on_barrier != 0) {
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   131
        SpinPause();
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   132
      }
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   133
      ++next_tag;
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   134
    }
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   135
    WBThread<WaitBarrierImpl>::_exit = true;
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   136
    for (int i = 0; i < NUMBER_OF_READERS; i++) {
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   137
      post.wait();
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   138
    }
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   139
  }
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   140
};
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   141
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   142
TEST_VM(WaitBarrier, default_wb) {
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   143
  WBThread<WaitBarrierDefault>::_exit = false;
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   144
  mt_test_doer<WBArmerThread<WaitBarrierDefault> >();
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   145
}
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   146
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   147
#if defined(LINUX)
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   148
TEST_VM(WaitBarrier, generic_wb) {
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   149
  WBThread<GenericWaitBarrier>::_exit = false;
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   150
  mt_test_doer<WBArmerThread<GenericWaitBarrier> >();
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   151
}
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
   152
#endif