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 "runtime/atomic.hpp"
26#include "runtime/orderAccess.hpp"
27#include "runtime/os.hpp"
28#include "utilities/globalCounter.hpp"
29#include "utilities/globalCounter.inline.hpp"
30#include "threadHelper.inline.hpp"
31
32#define GOOD_VALUE 1337
33#define BAD_VALUE 4711
34
35struct TestData {
36 long test_value;
37};
38
39class RCUReaderThread : public JavaTestThread {
40public:
41 static volatile bool _exit;
42 volatile TestData** _test;
43 Semaphore* _wrt_start;
44 RCUReaderThread(Semaphore* post, volatile TestData** test, Semaphore* wrt_start)
45 : JavaTestThread(post), _test(test), _wrt_start(wrt_start) {};
46 virtual ~RCUReaderThread(){}
47 void main_run() {
48 _wrt_start->signal();
49 while (!_exit) {
50 GlobalCounter::CSContext cs_context = GlobalCounter::critical_section_begin(this);
51 volatile TestData* test = OrderAccess::load_acquire(_test);
52 long value = OrderAccess::load_acquire(&test->test_value);
53 ASSERT_EQ(value, GOOD_VALUE);
54 GlobalCounter::critical_section_end(this, cs_context);
55 {
56 GlobalCounter::CriticalSection cs(this);
57 volatile TestData* test = OrderAccess::load_acquire(_test);
58 long value = OrderAccess::load_acquire(&test->test_value);
59 ASSERT_EQ(value, GOOD_VALUE);
60 }
61 }
62 }
63};
64
65volatile bool RCUReaderThread::_exit = false;
66
67class RCUWriterThread : public JavaTestThread {
68public:
69 RCUWriterThread(Semaphore* post) : JavaTestThread(post) {
70 };
71 virtual ~RCUWriterThread(){}
72 void main_run() {
73 static const int NUMBER_OF_READERS = 4;
74 Semaphore post;
75 Semaphore wrt_start;
76 volatile TestData* test = NULL;
77
78 RCUReaderThread* reader1 = new RCUReaderThread(&post, &test, &wrt_start);
79 RCUReaderThread* reader2 = new RCUReaderThread(&post, &test, &wrt_start);
80 RCUReaderThread* reader3 = new RCUReaderThread(&post, &test, &wrt_start);
81 RCUReaderThread* reader4 = new RCUReaderThread(&post, &test, &wrt_start);
82
83 TestData* tmp = new TestData();
84 tmp->test_value = GOOD_VALUE;
85 OrderAccess::release_store_fence(&test, tmp);
86
87 reader1->doit();
88 reader2->doit();
89 reader3->doit();
90 reader4->doit();
91
92 int nw = NUMBER_OF_READERS;
93 while (nw > 0) {
94 wrt_start.wait();
95 --nw;
96 }
97 jlong stop_ms = os::javaTimeMillis() + 1000; // 1 seconds max test time
98 for (int i = 0; i < 100000 && stop_ms > os::javaTimeMillis(); i++) {
99 volatile TestData* free_tmp = test;
100 tmp = new TestData();
101 tmp->test_value = GOOD_VALUE;
102 OrderAccess::release_store(&test, tmp);
103 GlobalCounter::write_synchronize();
104 free_tmp->test_value = BAD_VALUE;
105 delete free_tmp;
106 }
107 RCUReaderThread::_exit = true;
108 for (int i = 0; i < NUMBER_OF_READERS; i++) {
109 post.wait();
110 }
111 }
112};
113
114TEST_VM(GlobalCounter, critical_section) {
115 RCUReaderThread::_exit = false;
116 mt_test_doer<RCUWriterThread>();
117}
118