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
25#include "precompiled.hpp"
26#include "runtime/interfaceSupport.inline.hpp"
27#include "runtime/orderAccess.hpp"
28#include "runtime/os.hpp"
29#include "runtime/thread.hpp"
30#include "utilities/debug.hpp"
31#include "utilities/globalCounter.inline.hpp"
32#include "utilities/globalDefinitions.hpp"
33#include "utilities/ostream.hpp"
34#include "utilities/singleWriterSynchronizer.hpp"
35#include "threadHelper.inline.hpp"
36#include "unittest.hpp"
37
38class SingleWriterSynchronizerTestReader : public JavaTestThread {
39 SingleWriterSynchronizer* _synchronizer;
40 volatile uintx* _synchronized_value;
41 volatile int* _continue_running;
42
43 static const uint reader_iterations = 10;
44
45public:
46 SingleWriterSynchronizerTestReader(Semaphore* post,
47 SingleWriterSynchronizer* synchronizer,
48 volatile uintx* synchronized_value,
49 volatile int* continue_running) :
50 JavaTestThread(post),
51 _synchronizer(synchronizer),
52 _synchronized_value(synchronized_value),
53 _continue_running(continue_running)
54 {}
55
56 virtual void main_run() {
57 size_t iterations = 0;
58 size_t values_changed = 0;
59 while (OrderAccess::load_acquire(_continue_running) != 0) {
60 { ThreadBlockInVM tbiv(this); } // Safepoint check outside critical section.
61 ++iterations;
62 SingleWriterSynchronizer::CriticalSection cs(_synchronizer);
63 uintx value = OrderAccess::load_acquire(_synchronized_value);
64 uintx new_value = value;
65 for (uint i = 0; i < reader_iterations; ++i) {
66 new_value = OrderAccess::load_acquire(_synchronized_value);
67 // A reader can see either the value it first read after
68 // entering the critical section, or that value + 1. No other
69 // values are possible.
70 if (value != new_value) {
71 ASSERT_EQ((value + 1), new_value);
72 }
73 }
74 if (value != new_value) {
75 ++values_changed;
76 }
77 }
78 tty->print_cr("reader iterations: " SIZE_FORMAT ", changes: " SIZE_FORMAT,
79 iterations, values_changed);
80 }
81};
82
83class SingleWriterSynchronizerTestWriter : public JavaTestThread {
84 SingleWriterSynchronizer* _synchronizer;
85 volatile uintx* _synchronized_value;
86 volatile int* _continue_running;
87
88public:
89 SingleWriterSynchronizerTestWriter(Semaphore* post,
90 SingleWriterSynchronizer* synchronizer,
91 volatile uintx* synchronized_value,
92 volatile int* continue_running) :
93 JavaTestThread(post),
94 _synchronizer(synchronizer),
95 _synchronized_value(synchronized_value),
96 _continue_running(continue_running)
97 {}
98
99 virtual void main_run() {
100 while (OrderAccess::load_acquire(_continue_running) != 0) {
101 ++*_synchronized_value;
102 _synchronizer->synchronize();
103 { ThreadBlockInVM tbiv(this); } // Safepoint check.
104 }
105 tty->print_cr("writer iterations: " UINTX_FORMAT, *_synchronized_value);
106 }
107};
108
109const uint nreaders = 5;
110const uint milliseconds_to_run = 1000;
111
112TEST_VM(TestSingleWriterSynchronizer, stress) {
113 Semaphore post;
114 SingleWriterSynchronizer synchronizer;
115 volatile uintx synchronized_value = 0;
116 volatile int continue_running = 1;
117
118 JavaTestThread* readers[nreaders] = {};
119 for (uint i = 0; i < nreaders; ++i) {
120 readers[i] = new SingleWriterSynchronizerTestReader(&post,
121 &synchronizer,
122 &synchronized_value,
123 &continue_running);
124 readers[i]->doit();
125 }
126
127 JavaTestThread* writer =
128 new SingleWriterSynchronizerTestWriter(&post,
129 &synchronizer,
130 &synchronized_value,
131 &continue_running);
132
133 writer->doit();
134
135 tty->print_cr("Stressing synchronizer for %u ms", milliseconds_to_run);
136 {
137 ThreadInVMfromNative invm(JavaThread::current());
138 os::sleep(Thread::current(), milliseconds_to_run, true);
139 }
140 continue_running = 0;
141 for (uint i = 0; i < nreaders + 1; ++i) {
142 post.wait();
143 }
144}
145