1/*
2 * Copyright (c) 2018, 2019, 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#ifndef GTEST_THREADHELPER_INLINE_HPP
25#define GTEST_THREADHELPER_INLINE_HPP
26
27#include "runtime/mutex.hpp"
28#include "runtime/semaphore.hpp"
29#include "runtime/thread.inline.hpp"
30#include "runtime/vmThread.hpp"
31#include "runtime/vmOperations.hpp"
32#include "unittest.hpp"
33
34class VM_StopSafepoint : public VM_Operation {
35public:
36 Semaphore* _running;
37 Semaphore* _test_complete;
38 VM_StopSafepoint(Semaphore* running, Semaphore* wait_for) :
39 _running(running), _test_complete(wait_for) {}
40 VMOp_Type type() const { return VMOp_None; }
41 Mode evaluation_mode() const { return _no_safepoint; }
42 bool is_cheap_allocated() const { return false; }
43 void doit() { _running->signal(); _test_complete->wait(); }
44};
45
46// This class and thread keep the non-safepoint op running while we do our testing.
47class VMThreadBlocker : public JavaThread {
48public:
49 Semaphore _ready;
50 Semaphore _unblock;
51 VMThreadBlocker() {}
52 virtual ~VMThreadBlocker() {}
53 const char* get_thread_name_string(char* buf, int buflen) const {
54 return "VMThreadBlocker";
55 }
56 void run() {
57 this->set_thread_state(_thread_in_vm);
58 {
59 MutexLocker ml(Threads_lock);
60 Threads::add(this);
61 }
62 VM_StopSafepoint ss(&_ready, &_unblock);
63 VMThread::execute(&ss);
64 }
65
66 // Override as JavaThread::post_run() calls JavaThread::exit which
67 // expects a valid thread object oop.
68 virtual void post_run() {
69 Threads::remove(this, false);
70 this->smr_delete();
71 }
72
73 void doit() {
74 if (os::create_thread(this, os::os_thread)) {
75 os::start_thread(this);
76 } else {
77 ASSERT_TRUE(false);
78 }
79 }
80 void ready() {
81 _ready.wait();
82 }
83 void release() {
84 _unblock.signal();
85 }
86};
87
88// For testing in a real JavaThread.
89class JavaTestThread : public JavaThread {
90public:
91 Semaphore* _post;
92 JavaTestThread(Semaphore* post)
93 : _post(post) {
94 }
95 virtual ~JavaTestThread() {}
96
97 const char* get_thread_name_string(char* buf, int buflen) const {
98 return "JavaTestThread";
99 }
100
101 void pre_run() {
102 this->set_thread_state(_thread_in_vm);
103 {
104 MutexLocker ml(Threads_lock);
105 Threads::add(this);
106 }
107 {
108 MutexLocker ml(SR_lock(), Mutex::_no_safepoint_check_flag);
109 }
110 }
111
112 virtual void main_run() = 0;
113
114 void run() {
115 main_run();
116 }
117
118 // Override as JavaThread::post_run() calls JavaThread::exit which
119 // expects a valid thread object oop. And we need to call signal.
120 void post_run() {
121 Threads::remove(this, false);
122 _post->signal();
123 this->smr_delete();
124 }
125
126 void doit() {
127 if (os::create_thread(this, os::os_thread)) {
128 os::start_thread(this);
129 } else {
130 ASSERT_TRUE(false);
131 }
132 }
133};
134
135template <typename FUNC>
136class SingleTestThread : public JavaTestThread {
137public:
138 FUNC& _f;
139 SingleTestThread(Semaphore* post, FUNC& f)
140 : JavaTestThread(post), _f(f) {
141 }
142
143 virtual ~SingleTestThread(){}
144
145 virtual void main_run() {
146 _f(this);
147 }
148};
149
150template <typename TESTFUNC>
151static void nomt_test_doer(TESTFUNC &f) {
152 Semaphore post;
153
154 VMThreadBlocker* blocker = new VMThreadBlocker();
155 blocker->doit();
156 blocker->ready();
157
158 SingleTestThread<TESTFUNC>* stt = new SingleTestThread<TESTFUNC>(&post, f);
159 stt->doit();
160 post.wait();
161
162 blocker->release();
163}
164
165template <typename RUNNER>
166static void mt_test_doer() {
167 Semaphore post;
168
169 VMThreadBlocker* blocker = new VMThreadBlocker();
170 blocker->doit();
171 blocker->ready();
172
173 RUNNER* runner = new RUNNER(&post);
174 runner->doit();
175 post.wait();
176
177 blocker->release();
178}
179
180#endif // include guard
181