提交 5071c50f 编写于 作者: S sla

8057535: add a thread extension class

Reviewed-by: mgerdin, bdelsart, jcoomes
上级 41c1b635
......@@ -860,6 +860,7 @@ void Thread::print_on(outputStream* st) const {
st->print("os_prio=%d ", os_prio);
}
st->print("tid=" INTPTR_FORMAT " ", this);
ext().print_on(st);
osthread()->print_on(st);
}
debug_only(if (WizardMode) print_owned_locks_on(st);)
......@@ -3021,6 +3022,8 @@ void JavaThread::prepare(jobject jni_thread, ThreadPriority prio) {
// Push the Java priority down to the native thread; needs Threads_lock
Thread::set_priority(this, prio);
prepare_ext();
// Add the new thread to the Threads list and set it in motion.
// We must have threads lock in order to call Threads::add.
// It is crucial that we do not block before the thread is
......@@ -3875,6 +3878,24 @@ void Threads::create_vm_init_libraries() {
}
}
JavaThread* Threads::find_java_thread_from_java_tid(jlong java_tid) {
assert(Threads_lock->owned_by_self(), "Must hold Threads_lock");
JavaThread* java_thread = NULL;
// Sequential search for now. Need to do better optimization later.
for (JavaThread* thread = Threads::first(); thread != NULL; thread = thread->next()) {
oop tobj = thread->threadObj();
if (!thread->is_exiting() &&
tobj != NULL &&
java_tid == java_lang_Thread::thread_id(tobj)) {
java_thread = thread;
break;
}
}
return java_thread;
}
// Last thread running calls java.lang.Shutdown.shutdown()
void JavaThread::invoke_shutdown_hooks() {
HandleMark hm(this);
......
......@@ -40,6 +40,7 @@
#include "runtime/safepoint.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/threadLocalStorage.hpp"
#include "runtime/thread_ext.hpp"
#include "runtime/unhandledOops.hpp"
#include "utilities/macros.hpp"
......@@ -257,6 +258,8 @@ class Thread: public ThreadShadow {
TRACE_DATA _trace_data; // Thread-local data for tracing
ThreadExt _ext;
int _vm_operation_started_count; // VM_Operation support
int _vm_operation_completed_count; // VM_Operation support
......@@ -436,6 +439,9 @@ class Thread: public ThreadShadow {
TRACE_DATA* trace_data() { return &_trace_data; }
const ThreadExt& ext() const { return _ext; }
ThreadExt& ext() { return _ext; }
// VM operation support
int vm_operation_ticket() { return ++_vm_operation_started_count; }
int vm_operation_completed_count() { return _vm_operation_completed_count; }
......@@ -1002,6 +1008,7 @@ class JavaThread: public Thread {
// not specified, use the priority of the thread object. Threads_lock
// must be held while this function is called.
void prepare(jobject jni_thread, ThreadPriority prio=NoPriority);
void prepare_ext();
void set_saved_exception_pc(address pc) { _saved_exception_pc = pc; }
address saved_exception_pc() { return _saved_exception_pc; }
......@@ -1956,6 +1963,8 @@ class Threads: AllStatic {
// Deoptimizes all frames tied to marked nmethods
static void deoptimized_wrt_marked_nmethods();
static JavaThread* find_java_thread_from_java_tid(jlong java_tid);
};
......
/*
* Copyright (c) 2014, 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.
*
* 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.
*
*/
#include "precompiled.hpp"
#include "runtime/thread.hpp"
#include "runtime/thread_ext.hpp"
void JavaThread::prepare_ext() {
}
/*
* Copyright (c) 2014, 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.
*
* 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 SHARE_VM_RUNTIME_THREAD_EXT_HPP
#define SHARE_VM_RUNTIME_THREAD_EXT_HPP
#include "memory/allocation.hpp"
class ThreadExt VALUE_OBJ_CLASS_SPEC {
public:
void print_on(outputStream* st) const {};
};
#endif // SHARE_VM_RUNTIME_THREAD_EXT_HPP
......@@ -389,23 +389,6 @@ instanceOop Management::create_thread_info_instance(ThreadSnapshot* snapshot,
return (instanceOop) element();
}
// Helper functions
static JavaThread* find_java_thread_from_id(jlong thread_id) {
assert(Threads_lock->owned_by_self(), "Must hold Threads_lock");
JavaThread* java_thread = NULL;
// Sequential search for now. Need to do better optimization later.
for (JavaThread* thread = Threads::first(); thread != NULL; thread = thread->next()) {
oop tobj = thread->threadObj();
if (!thread->is_exiting() &&
tobj != NULL &&
thread_id == java_lang_Thread::thread_id(tobj)) {
java_thread = thread;
break;
}
}
return java_thread;
}
static GCMemoryManager* get_gc_memory_manager_from_jobject(jobject mgr, TRAPS) {
if (mgr == NULL) {
......@@ -442,6 +425,8 @@ static MemoryPool* get_memory_pool_from_jobject(jobject obj, TRAPS) {
return MemoryService::get_memory_pool(ph);
}
#endif // INCLUDE_MANAGEMENT
static void validate_thread_id_array(typeArrayHandle ids_ah, TRAPS) {
int num_threads = ids_ah->length();
......@@ -457,6 +442,8 @@ static void validate_thread_id_array(typeArrayHandle ids_ah, TRAPS) {
}
}
#if INCLUDE_MANAGEMENT
static void validate_thread_info_array(objArrayHandle infoArray_h, TRAPS) {
// check if the element of infoArray is of type ThreadInfo class
Klass* threadinfo_klass = Management::java_lang_management_ThreadInfo_klass(CHECK);
......@@ -820,45 +807,6 @@ JVM_ENTRY(jlong, jmm_SetPoolThreshold(JNIEnv* env, jobject obj, jmmThresholdType
return prev;
JVM_END
// Gets an array containing the amount of memory allocated on the Java
// heap for a set of threads (in bytes). Each element of the array is
// the amount of memory allocated for the thread ID specified in the
// corresponding entry in the given array of thread IDs; or -1 if the
// thread does not exist or has terminated.
JVM_ENTRY(void, jmm_GetThreadAllocatedMemory(JNIEnv *env, jlongArray ids,
jlongArray sizeArray))
// Check if threads is null
if (ids == NULL || sizeArray == NULL) {
THROW(vmSymbols::java_lang_NullPointerException());
}
ResourceMark rm(THREAD);
typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(ids));
typeArrayHandle ids_ah(THREAD, ta);
typeArrayOop sa = typeArrayOop(JNIHandles::resolve_non_null(sizeArray));
typeArrayHandle sizeArray_h(THREAD, sa);
// validate the thread id array
validate_thread_id_array(ids_ah, CHECK);
// sizeArray must be of the same length as the given array of thread IDs
int num_threads = ids_ah->length();
if (num_threads != sizeArray_h->length()) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"The length of the given long array does not match the length of "
"the given array of thread IDs");
}
MutexLockerEx ml(Threads_lock);
for (int i = 0; i < num_threads; i++) {
JavaThread* java_thread = find_java_thread_from_id(ids_ah->long_at(i));
if (java_thread != NULL) {
sizeArray_h->long_at_put(i, java_thread->cooked_allocated_bytes());
}
}
JVM_END
// Returns a java/lang/management/MemoryUsage object representing
// the memory usage for the heap or non-heap memory.
JVM_ENTRY(jobject, jmm_GetMemoryUsage(JNIEnv* env, jboolean heap))
......@@ -1164,7 +1112,7 @@ static void do_thread_dump(ThreadDumpResult* dump_result,
MutexLockerEx ml(Threads_lock);
for (int i = 0; i < num_threads; i++) {
jlong tid = ids_ah->long_at(i);
JavaThread* jt = find_java_thread_from_id(tid);
JavaThread* jt = Threads::find_java_thread_from_java_tid(tid);
oop thread_obj = (jt != NULL ? jt->threadObj() : (oop)NULL);
instanceHandle threadObj_h(THREAD, (instanceOop) thread_obj);
thread_handle_array->append(threadObj_h);
......@@ -1243,7 +1191,7 @@ JVM_ENTRY(jint, jmm_GetThreadInfo(JNIEnv *env, jlongArray ids, jint maxDepth, jo
MutexLockerEx ml(Threads_lock);
for (int i = 0; i < num_threads; i++) {
jlong tid = ids_ah->long_at(i);
JavaThread* jt = find_java_thread_from_id(tid);
JavaThread* jt = Threads::find_java_thread_from_java_tid(tid);
ThreadSnapshot* ts;
if (jt == NULL) {
// if the thread does not exist or now it is terminated,
......@@ -1489,7 +1437,7 @@ JVM_ENTRY(jboolean, jmm_ResetStatistic(JNIEnv *env, jvalue obj, jmmStatisticType
}
} else {
// reset contention statistics for a given thread
JavaThread* java_thread = find_java_thread_from_id(tid);
JavaThread* java_thread = Threads::find_java_thread_from_java_tid(tid);
if (java_thread == NULL) {
return false;
}
......@@ -1558,7 +1506,7 @@ JVM_ENTRY(jlong, jmm_GetThreadCpuTime(JNIEnv *env, jlong thread_id))
return os::current_thread_cpu_time();
} else {
MutexLockerEx ml(Threads_lock);
java_thread = find_java_thread_from_id(thread_id);
java_thread = Threads::find_java_thread_from_java_tid(thread_id);
if (java_thread != NULL) {
return os::thread_cpu_time((Thread*) java_thread);
}
......@@ -1566,78 +1514,6 @@ JVM_ENTRY(jlong, jmm_GetThreadCpuTime(JNIEnv *env, jlong thread_id))
return -1;
JVM_END
// Returns the CPU time consumed by a given thread (in nanoseconds).
// If thread_id == 0, CPU time for the current thread is returned.
// If user_sys_cpu_time = true, user level and system CPU time of
// a given thread is returned; otherwise, only user level CPU time
// is returned.
JVM_ENTRY(jlong, jmm_GetThreadCpuTimeWithKind(JNIEnv *env, jlong thread_id, jboolean user_sys_cpu_time))
if (!os::is_thread_cpu_time_supported()) {
return -1;
}
if (thread_id < 0) {
THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
"Invalid thread ID", -1);
}
JavaThread* java_thread = NULL;
if (thread_id == 0) {
// current thread
return os::current_thread_cpu_time(user_sys_cpu_time != 0);
} else {
MutexLockerEx ml(Threads_lock);
java_thread = find_java_thread_from_id(thread_id);
if (java_thread != NULL) {
return os::thread_cpu_time((Thread*) java_thread, user_sys_cpu_time != 0);
}
}
return -1;
JVM_END
// Gets an array containing the CPU times consumed by a set of threads
// (in nanoseconds). Each element of the array is the CPU time for the
// thread ID specified in the corresponding entry in the given array
// of thread IDs; or -1 if the thread does not exist or has terminated.
// If user_sys_cpu_time = true, the sum of user level and system CPU time
// for the given thread is returned; otherwise, only user level CPU time
// is returned.
JVM_ENTRY(void, jmm_GetThreadCpuTimesWithKind(JNIEnv *env, jlongArray ids,
jlongArray timeArray,
jboolean user_sys_cpu_time))
// Check if threads is null
if (ids == NULL || timeArray == NULL) {
THROW(vmSymbols::java_lang_NullPointerException());
}
ResourceMark rm(THREAD);
typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(ids));
typeArrayHandle ids_ah(THREAD, ta);
typeArrayOop tia = typeArrayOop(JNIHandles::resolve_non_null(timeArray));
typeArrayHandle timeArray_h(THREAD, tia);
// validate the thread id array
validate_thread_id_array(ids_ah, CHECK);
// timeArray must be of the same length as the given array of thread IDs
int num_threads = ids_ah->length();
if (num_threads != timeArray_h->length()) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"The length of the given long array does not match the length of "
"the given array of thread IDs");
}
MutexLockerEx ml(Threads_lock);
for (int i = 0; i < num_threads; i++) {
JavaThread* java_thread = find_java_thread_from_id(ids_ah->long_at(i));
if (java_thread != NULL) {
timeArray_h->long_at_put(i, os::thread_cpu_time((Thread*)java_thread,
user_sys_cpu_time != 0));
}
}
JVM_END
// Returns a String array of all VM global flag names
JVM_ENTRY(jobjectArray, jmm_GetVMGlobalNames(JNIEnv *env))
// last flag entry is always NULL, so subtract 1
......@@ -2323,7 +2199,122 @@ jlong Management::ticks_to_ms(jlong ticks) {
return (jlong)(((double)ticks / (double)os::elapsed_frequency())
* (double)1000.0);
}
#endif // INCLUDE_MANAGEMENT
// Gets an array containing the amount of memory allocated on the Java
// heap for a set of threads (in bytes). Each element of the array is
// the amount of memory allocated for the thread ID specified in the
// corresponding entry in the given array of thread IDs; or -1 if the
// thread does not exist or has terminated.
JVM_ENTRY(void, jmm_GetThreadAllocatedMemory(JNIEnv *env, jlongArray ids,
jlongArray sizeArray))
// Check if threads is null
if (ids == NULL || sizeArray == NULL) {
THROW(vmSymbols::java_lang_NullPointerException());
}
ResourceMark rm(THREAD);
typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(ids));
typeArrayHandle ids_ah(THREAD, ta);
typeArrayOop sa = typeArrayOop(JNIHandles::resolve_non_null(sizeArray));
typeArrayHandle sizeArray_h(THREAD, sa);
// validate the thread id array
validate_thread_id_array(ids_ah, CHECK);
// sizeArray must be of the same length as the given array of thread IDs
int num_threads = ids_ah->length();
if (num_threads != sizeArray_h->length()) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"The length of the given long array does not match the length of "
"the given array of thread IDs");
}
MutexLockerEx ml(Threads_lock);
for (int i = 0; i < num_threads; i++) {
JavaThread* java_thread = Threads::find_java_thread_from_java_tid(ids_ah->long_at(i));
if (java_thread != NULL) {
sizeArray_h->long_at_put(i, java_thread->cooked_allocated_bytes());
}
}
JVM_END
// Returns the CPU time consumed by a given thread (in nanoseconds).
// If thread_id == 0, CPU time for the current thread is returned.
// If user_sys_cpu_time = true, user level and system CPU time of
// a given thread is returned; otherwise, only user level CPU time
// is returned.
JVM_ENTRY(jlong, jmm_GetThreadCpuTimeWithKind(JNIEnv *env, jlong thread_id, jboolean user_sys_cpu_time))
if (!os::is_thread_cpu_time_supported()) {
return -1;
}
if (thread_id < 0) {
THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
"Invalid thread ID", -1);
}
JavaThread* java_thread = NULL;
if (thread_id == 0) {
// current thread
return os::current_thread_cpu_time(user_sys_cpu_time != 0);
} else {
MutexLockerEx ml(Threads_lock);
java_thread = Threads::find_java_thread_from_java_tid(thread_id);
if (java_thread != NULL) {
return os::thread_cpu_time((Thread*) java_thread, user_sys_cpu_time != 0);
}
}
return -1;
JVM_END
// Gets an array containing the CPU times consumed by a set of threads
// (in nanoseconds). Each element of the array is the CPU time for the
// thread ID specified in the corresponding entry in the given array
// of thread IDs; or -1 if the thread does not exist or has terminated.
// If user_sys_cpu_time = true, the sum of user level and system CPU time
// for the given thread is returned; otherwise, only user level CPU time
// is returned.
JVM_ENTRY(void, jmm_GetThreadCpuTimesWithKind(JNIEnv *env, jlongArray ids,
jlongArray timeArray,
jboolean user_sys_cpu_time))
// Check if threads is null
if (ids == NULL || timeArray == NULL) {
THROW(vmSymbols::java_lang_NullPointerException());
}
ResourceMark rm(THREAD);
typeArrayOop ta = typeArrayOop(JNIHandles::resolve_non_null(ids));
typeArrayHandle ids_ah(THREAD, ta);
typeArrayOop tia = typeArrayOop(JNIHandles::resolve_non_null(timeArray));
typeArrayHandle timeArray_h(THREAD, tia);
// validate the thread id array
validate_thread_id_array(ids_ah, CHECK);
// timeArray must be of the same length as the given array of thread IDs
int num_threads = ids_ah->length();
if (num_threads != timeArray_h->length()) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"The length of the given long array does not match the length of "
"the given array of thread IDs");
}
MutexLockerEx ml(Threads_lock);
for (int i = 0; i < num_threads; i++) {
JavaThread* java_thread = Threads::find_java_thread_from_java_tid(ids_ah->long_at(i));
if (java_thread != NULL) {
timeArray_h->long_at_put(i, os::thread_cpu_time((Thread*)java_thread,
user_sys_cpu_time != 0));
}
}
JVM_END
#if INCLUDE_MANAGEMENT
const struct jmmInterface_1_ jmm_interface = {
NULL,
NULL,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册