-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathti_thread.h
192 lines (158 loc) · 8.68 KB
/
ti_thread.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
/* Copyright (C) 2017 The Android Open Source Project
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This file implements interfaces from the file jvmti.h. This implementation
* is licensed under the same terms as the file jvmti.h. The
* copyright and license information for the file jvmti.h follows.
*
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#ifndef ART_OPENJDKJVMTI_TI_THREAD_H_
#define ART_OPENJDKJVMTI_TI_THREAD_H_
#include <unordered_map>
#include "jni.h"
#include "jvmti.h"
#include "base/macros.h"
#include "base/mutex.h"
#include "handle.h"
#include "thread.h"
namespace art {
class ArtField;
class ScopedObjectAccessAlreadyRunnable;
class Thread;
class Closure;
namespace mirror {
class Throwable;
} // namespace mirror
} // namespace art
namespace openjdkjvmti {
class EventHandler;
// Gains the user_code_suspension_lock_ and ensures that the code will not suspend for user-code.
class SCOPED_CAPABILITY ScopedNoUserCodeSuspension {
public:
explicit ScopedNoUserCodeSuspension(art::Thread* self)
ACQUIRE(art::Locks::user_code_suspension_lock_);
~ScopedNoUserCodeSuspension() RELEASE(art::Locks::user_code_suspension_lock_);
private:
art::Thread* self_;
};
// The struct that we store in the art::Thread::custom_tls_ that maps the jvmtiEnvs to the data
// stored with that thread. This is needed since different jvmtiEnvs are not supposed to share TLS
// data but we only have a single slot in Thread objects to store data.
struct JvmtiGlobalTLSData : public art::TLSData {
std::unordered_map<jvmtiEnv*, const void*> data GUARDED_BY(art::Locks::thread_list_lock_);
// The depth of the last frame where popping using PopFrame it is not allowed. It is set to
// kNoDisallowedPopFrame if all frames can be popped. See b/117615146 for more information.
static constexpr size_t kNoDisallowedPopFrame = -1;
size_t disable_pop_frame_depth = kNoDisallowedPopFrame;
};
class ThreadUtil {
public:
static void Register(EventHandler* event_handler);
static void Unregister();
// To be called when it is safe to cache data. This means that we have at least entered the
// RuntimePhase::kInit but we might or might not have already called VMInit event.
static void CacheData();
// Called just after we have sent the VMInit callback so that ThreadUtil can do final setup. This
// ensures that there are no timing issues between the two callbacks.
static void VMInitEventSent() REQUIRES_SHARED(art::Locks::mutator_lock_);
// Handle a jvmtiEnv going away.
static void RemoveEnvironment(jvmtiEnv* env);
static jvmtiError GetAllThreads(jvmtiEnv* env, jint* threads_count_ptr, jthread** threads_ptr);
static jvmtiError GetCurrentThread(jvmtiEnv* env, jthread* thread_ptr);
static jvmtiError GetThreadInfo(jvmtiEnv* env, jthread thread, jvmtiThreadInfo* info_ptr);
static jvmtiError GetThreadState(jvmtiEnv* env, jthread thread, jint* thread_state_ptr);
static jvmtiError SetThreadLocalStorage(jvmtiEnv* env, jthread thread, const void* data);
static jvmtiError GetThreadLocalStorage(jvmtiEnv* env, jthread thread, void** data_ptr);
static jvmtiError RunAgentThread(jvmtiEnv* env,
jthread thread,
jvmtiStartFunction proc,
const void* arg,
jint priority);
static jvmtiError SuspendThread(jvmtiEnv* env, jthread thread);
static jvmtiError ResumeThread(jvmtiEnv* env, jthread thread);
static jvmtiError SuspendThreadList(jvmtiEnv* env,
jint request_count,
const jthread* threads,
jvmtiError* results);
static jvmtiError ResumeThreadList(jvmtiEnv* env,
jint request_count,
const jthread* threads,
jvmtiError* results);
static jvmtiError StopThread(jvmtiEnv* env, jthread thr, jobject exception);
static jvmtiError InterruptThread(jvmtiEnv* env, jthread thr);
// Returns true if we decoded the thread and it is alive, false otherwise with an appropriate
// error placed into 'err'. A thread is alive if it has had it's 'start' function called and has
// (or at least could have) executed managed code and has not yet returned past it's first managed
// frame. This means that the thread returned might have IsStillStarting() return true. Code that
// does not consider that alive should check manually.
static bool GetAliveNativeThread(jthread thread,
const art::ScopedObjectAccessAlreadyRunnable& soa,
/*out*/ art::Thread** thr,
/*out*/ jvmtiError* err)
REQUIRES_SHARED(art::Locks::mutator_lock_)
REQUIRES(art::Locks::thread_list_lock_);
// Returns true if we decoded the thread, false otherwise with an appropriate error placed into
// 'err'
static bool GetNativeThread(jthread thread,
const art::ScopedObjectAccessAlreadyRunnable& soa,
/*out*/ art::Thread** thr,
/*out*/ jvmtiError* err)
REQUIRES_SHARED(art::Locks::mutator_lock_)
REQUIRES(art::Locks::thread_list_lock_);
// Go to sleep if this thread is suspended.
static void SuspendCheck(art::Thread* self)
REQUIRES(!art::Locks::mutator_lock_, !art::Locks::user_code_suspension_lock_);
// Returns true if the thread would be suspended if it locks the mutator-lock or calls
// SuspendCheck. This function is called with the user_code_suspension_lock already held.
static bool WouldSuspendForUserCodeLocked(art::Thread* self)
REQUIRES(art::Locks::user_code_suspension_lock_,
!art::Locks::thread_suspend_count_lock_);
// Returns true if this thread would go to sleep if it locks the mutator-lock or calls
// SuspendCheck.
static bool WouldSuspendForUserCode(art::Thread* self)
REQUIRES(!art::Locks::user_code_suspension_lock_,
!art::Locks::thread_suspend_count_lock_);
static JvmtiGlobalTLSData* GetGlobalTLSData(art::Thread* thread)
REQUIRES(art::Locks::thread_list_lock_);
static JvmtiGlobalTLSData* GetOrCreateGlobalTLSData(art::Thread* thread)
REQUIRES(art::Locks::thread_list_lock_);
private:
// We need to make sure only one thread tries to suspend threads at a time so we can get the
// 'suspend-only-once' behavior the spec requires. Internally, ART considers suspension to be a
// counted state, allowing a single thread to be suspended multiple times by different users. This
// makes mapping into the JVMTI idea of thread suspension difficult. We have decided to split the
// difference and ensure that JVMTI tries to treat suspension as the boolean flag as much as
// possible with the suspend/resume methods but only do best effort. On the other hand
// GetThreadState will be totally accurate as much as possible. This means that calling
// ResumeThread on a thread that has state JVMTI_THREAD_STATE_SUSPENDED will not necessarily
// cause the thread to wake up if the thread is suspended for the debugger or gc or something.
static jvmtiError SuspendSelf(art::Thread* self)
REQUIRES(!art::Locks::mutator_lock_, !art::Locks::user_code_suspension_lock_);
static jvmtiError SuspendOther(art::Thread* self, jthread target_jthread)
REQUIRES(!art::Locks::mutator_lock_, !art::Locks::user_code_suspension_lock_);
static art::ArtField* context_class_loader_;
};
} // namespace openjdkjvmti
#endif // ART_OPENJDKJVMTI_TI_THREAD_H_