diff -r fd16c54261b3 -r 90ce3da70b43 jdk/src/share/back/ThreadReferenceImpl.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/back/ThreadReferenceImpl.c Sat Dec 01 00:00:00 2007 +0000 @@ -0,0 +1,683 @@ +/* + * Copyright 1998-2005 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +#include "util.h" +#include "ThreadReferenceImpl.h" +#include "eventHandler.h" +#include "threadControl.h" +#include "inStream.h" +#include "outStream.h" +#include "FrameID.h" + +static jboolean +name(PacketInputStream *in, PacketOutputStream *out) +{ + JNIEnv *env; + jthread thread; + + env = getEnv(); + + thread = inStream_readThreadRef(env, in); + if (inStream_error(in)) { + return JNI_TRUE; + } + + if (threadControl_isDebugThread(thread)) { + outStream_setError(out, JDWP_ERROR(INVALID_THREAD)); + return JNI_TRUE; + } + + WITH_LOCAL_REFS(env, 1) { + + jvmtiThreadInfo info; + jvmtiError error; + + (void)memset(&info, 0, sizeof(info)); + + error = JVMTI_FUNC_PTR(gdata->jvmti,GetThreadInfo) + (gdata->jvmti, thread, &info); + + if (error != JVMTI_ERROR_NONE) { + outStream_setError(out, map2jdwpError(error)); + } else { + (void)outStream_writeString(out, info.name); + } + + if ( info.name != NULL ) + jvmtiDeallocate(info.name); + + } END_WITH_LOCAL_REFS(env); + + return JNI_TRUE; +} + +static jboolean +suspend(PacketInputStream *in, PacketOutputStream *out) +{ + jvmtiError error; + jthread thread; + + thread = inStream_readThreadRef(getEnv(), in); + if (inStream_error(in)) { + return JNI_TRUE; + } + + if (threadControl_isDebugThread(thread)) { + outStream_setError(out, JDWP_ERROR(INVALID_THREAD)); + return JNI_TRUE; + } + error = threadControl_suspendThread(thread, JNI_FALSE); + if (error != JVMTI_ERROR_NONE) { + outStream_setError(out, map2jdwpError(error)); + } + return JNI_TRUE; +} + +static jboolean +resume(PacketInputStream *in, PacketOutputStream *out) +{ + jvmtiError error; + jthread thread; + + thread = inStream_readThreadRef(getEnv(), in); + if (inStream_error(in)) { + return JNI_TRUE; + } + + if (threadControl_isDebugThread(thread)) { + outStream_setError(out, JDWP_ERROR(INVALID_THREAD)); + return JNI_TRUE; + } + + /* true means it is okay to unblock the commandLoop thread */ + error = threadControl_resumeThread(thread, JNI_TRUE); + if (error != JVMTI_ERROR_NONE) { + outStream_setError(out, map2jdwpError(error)); + } + return JNI_TRUE; +} + +static jboolean +status(PacketInputStream *in, PacketOutputStream *out) +{ + jdwpThreadStatus threadStatus; + jint statusFlags; + jvmtiError error; + jthread thread; + + thread = inStream_readThreadRef(getEnv(), in); + if (inStream_error(in)) { + return JNI_TRUE; + } + + if (threadControl_isDebugThread(thread)) { + outStream_setError(out, JDWP_ERROR(INVALID_THREAD)); + return JNI_TRUE; + } + + error = threadControl_applicationThreadStatus(thread, &threadStatus, + &statusFlags); + if (error != JVMTI_ERROR_NONE) { + outStream_setError(out, map2jdwpError(error)); + return JNI_TRUE; + } + (void)outStream_writeInt(out, threadStatus); + (void)outStream_writeInt(out, statusFlags); + return JNI_TRUE; +} + +static jboolean +threadGroup(PacketInputStream *in, PacketOutputStream *out) +{ + JNIEnv *env; + jthread thread; + + env = getEnv(); + + thread = inStream_readThreadRef(env, in); + if (inStream_error(in)) { + return JNI_TRUE; + } + + if (threadControl_isDebugThread(thread)) { + outStream_setError(out, JDWP_ERROR(INVALID_THREAD)); + return JNI_TRUE; + } + + WITH_LOCAL_REFS(env, 1) { + + jvmtiThreadInfo info; + jvmtiError error; + + (void)memset(&info, 0, sizeof(info)); + + error = JVMTI_FUNC_PTR(gdata->jvmti,GetThreadInfo) + (gdata->jvmti, thread, &info); + + if (error != JVMTI_ERROR_NONE) { + outStream_setError(out, map2jdwpError(error)); + } else { + (void)outStream_writeObjectRef(env, out, info.thread_group); + } + + if ( info.name!=NULL ) + jvmtiDeallocate(info.name); + + } END_WITH_LOCAL_REFS(env); + + return JNI_TRUE; +} + +static jboolean +validateSuspendedThread(PacketOutputStream *out, jthread thread) +{ + jvmtiError error; + jint count; + + error = threadControl_suspendCount(thread, &count); + if (error != JVMTI_ERROR_NONE) { + outStream_setError(out, map2jdwpError(error)); + return JNI_FALSE; + } + + if (count == 0) { + outStream_setError(out, JDWP_ERROR(THREAD_NOT_SUSPENDED)); + return JNI_FALSE; + } + + return JNI_TRUE; +} + +static jboolean +frames(PacketInputStream *in, PacketOutputStream *out) +{ + jvmtiError error; + FrameNumber fnum; + jint count; + JNIEnv *env; + jthread thread; + jint startIndex; + jint length; + + env = getEnv(); + + thread = inStream_readThreadRef(env, in); + if (inStream_error(in)) { + return JNI_TRUE; + } + startIndex = inStream_readInt(in); + if (inStream_error(in)) { + return JNI_TRUE; + } + length = inStream_readInt(in); + if (inStream_error(in)) { + return JNI_TRUE; + } + + if (threadControl_isDebugThread(thread)) { + outStream_setError(out, JDWP_ERROR(INVALID_THREAD)); + return JNI_TRUE; + } + + if (!validateSuspendedThread(out, thread)) { + return JNI_TRUE; + } + + error = JVMTI_FUNC_PTR(gdata->jvmti,GetFrameCount) + (gdata->jvmti, thread, &count); + if (error != JVMTI_ERROR_NONE) { + outStream_setError(out, map2jdwpError(error)); + return JNI_TRUE; + } + + if (length == -1) { + length = count - startIndex; + } + + if (length == 0) { + (void)outStream_writeInt(out, 0); + return JNI_TRUE; + } + + if ((startIndex < 0) || (startIndex > count - 1)) { + outStream_setError(out, JDWP_ERROR(INVALID_INDEX)); + return JNI_TRUE; + } + + if ((length < 0) || (length + startIndex > count)) { + outStream_setError(out, JDWP_ERROR(INVALID_LENGTH)); + return JNI_TRUE; + } + + (void)outStream_writeInt(out, length); + + for(fnum = startIndex ; fnum < startIndex+length ; fnum++ ) { + + WITH_LOCAL_REFS(env, 1) { + + jclass clazz; + jmethodID method; + jlocation location; + + /* Get location info */ + error = JVMTI_FUNC_PTR(gdata->jvmti,GetFrameLocation) + (gdata->jvmti, thread, fnum, &method, &location); + if (error == JVMTI_ERROR_OPAQUE_FRAME) { + clazz = NULL; + location = -1L; + error = JVMTI_ERROR_NONE; + } else if ( error == JVMTI_ERROR_NONE ) { + error = methodClass(method, &clazz); + if ( error == JVMTI_ERROR_NONE ) { + FrameID frame; + frame = createFrameID(thread, fnum); + (void)outStream_writeFrameID(out, frame); + writeCodeLocation(out, clazz, method, location); + } + } + + } END_WITH_LOCAL_REFS(env); + + if (error != JVMTI_ERROR_NONE) + break; + + } + + if (error != JVMTI_ERROR_NONE) { + outStream_setError(out, map2jdwpError(error)); + } + return JNI_TRUE; +} + +static jboolean +getFrameCount(PacketInputStream *in, PacketOutputStream *out) +{ + jvmtiError error; + jint count; + jthread thread; + + thread = inStream_readThreadRef(getEnv(), in); + if (inStream_error(in)) { + return JNI_TRUE; + } + + if (threadControl_isDebugThread(thread)) { + outStream_setError(out, JDWP_ERROR(INVALID_THREAD)); + return JNI_TRUE; + } + + if (!validateSuspendedThread(out, thread)) { + return JNI_TRUE; + } + + error = JVMTI_FUNC_PTR(gdata->jvmti,GetFrameCount) + (gdata->jvmti, thread, &count); + if (error != JVMTI_ERROR_NONE) { + outStream_setError(out, map2jdwpError(error)); + return JNI_TRUE; + } + (void)outStream_writeInt(out, count); + + return JNI_TRUE; +} + +static jboolean +ownedMonitors(PacketInputStream *in, PacketOutputStream *out) +{ + JNIEnv *env; + jthread thread; + + env = getEnv(); + + thread = inStream_readThreadRef(env, in); + if (inStream_error(in)) { + return JNI_TRUE; + } + + if (threadControl_isDebugThread(thread)) { + outStream_setError(out, JDWP_ERROR(INVALID_THREAD)); + return JNI_TRUE; + } + + if (!validateSuspendedThread(out, thread)) { + return JNI_TRUE; + } + + WITH_LOCAL_REFS(env, 1) { + + jvmtiError error; + jint count = 0; + jobject *monitors = NULL; + + error = JVMTI_FUNC_PTR(gdata->jvmti,GetOwnedMonitorInfo) + (gdata->jvmti, thread, &count, &monitors); + if (error != JVMTI_ERROR_NONE) { + outStream_setError(out, map2jdwpError(error)); + } else { + int i; + (void)outStream_writeInt(out, count); + for (i = 0; i < count; i++) { + jobject monitor = monitors[i]; + (void)outStream_writeByte(out, specificTypeKey(env, monitor)); + (void)outStream_writeObjectRef(env, out, monitor); + } + } + if (monitors != NULL) + jvmtiDeallocate(monitors); + + } END_WITH_LOCAL_REFS(env); + + return JNI_TRUE; +} + +static jboolean +currentContendedMonitor(PacketInputStream *in, PacketOutputStream *out) +{ + JNIEnv *env; + jthread thread; + + env = getEnv(); + + thread = inStream_readThreadRef(env, in); + if (inStream_error(in)) { + return JNI_TRUE; + } + + if (thread == NULL || threadControl_isDebugThread(thread)) { + outStream_setError(out, JDWP_ERROR(INVALID_THREAD)); + return JNI_TRUE; + } + + if (!validateSuspendedThread(out, thread)) { + return JNI_TRUE; + } + + WITH_LOCAL_REFS(env, 1) { + + jobject monitor; + jvmtiError error; + + error = JVMTI_FUNC_PTR(gdata->jvmti,GetCurrentContendedMonitor) + (gdata->jvmti, thread, &monitor); + + if (error != JVMTI_ERROR_NONE) { + outStream_setError(out, map2jdwpError(error)); + } else { + (void)outStream_writeByte(out, specificTypeKey(env, monitor)); + (void)outStream_writeObjectRef(env, out, monitor); + } + + } END_WITH_LOCAL_REFS(env); + + return JNI_TRUE; +} + +static jboolean +stop(PacketInputStream *in, PacketOutputStream *out) +{ + jvmtiError error; + jthread thread; + jobject throwable; + JNIEnv *env; + + env = getEnv(); + thread = inStream_readThreadRef(env, in); + if (inStream_error(in)) { + return JNI_TRUE; + } + throwable = inStream_readObjectRef(env, in); + if (inStream_error(in)) { + return JNI_TRUE; + } + + if (threadControl_isDebugThread(thread)) { + outStream_setError(out, JDWP_ERROR(INVALID_THREAD)); + return JNI_TRUE; + } + + error = threadControl_stop(thread, throwable); + if (error != JVMTI_ERROR_NONE) { + outStream_setError(out, map2jdwpError(error)); + } + return JNI_TRUE; +} + +static jboolean +interrupt(PacketInputStream *in, PacketOutputStream *out) +{ + jvmtiError error; + jthread thread; + + thread = inStream_readThreadRef(getEnv(), in); + if (inStream_error(in)) { + return JNI_TRUE; + } + + if (threadControl_isDebugThread(thread)) { + outStream_setError(out, JDWP_ERROR(INVALID_THREAD)); + return JNI_TRUE; + } + + error = threadControl_interrupt(thread); + if (error != JVMTI_ERROR_NONE) { + outStream_setError(out, map2jdwpError(error)); + } + return JNI_TRUE; +} + +static jboolean +suspendCount(PacketInputStream *in, PacketOutputStream *out) +{ + jvmtiError error; + jint count; + jthread thread; + + thread = inStream_readThreadRef(getEnv(), in); + if (inStream_error(in)) { + return JNI_TRUE; + } + + if (threadControl_isDebugThread(thread)) { + outStream_setError(out, JDWP_ERROR(INVALID_THREAD)); + return JNI_TRUE; + } + + error = threadControl_suspendCount(thread, &count); + if (error != JVMTI_ERROR_NONE) { + outStream_setError(out, map2jdwpError(error)); + return JNI_TRUE; + } + + (void)outStream_writeInt(out, count); + return JNI_TRUE; +} + +static jboolean +ownedMonitorsWithStackDepth(PacketInputStream *in, PacketOutputStream *out) +{ + JNIEnv *env; + jthread thread; + + thread = inStream_readThreadRef(getEnv(), in); + if (inStream_error(in)) { + return JNI_TRUE; + } + + if (thread == NULL || threadControl_isDebugThread(thread)) { + outStream_setError(out, JDWP_ERROR(INVALID_THREAD)); + return JNI_TRUE; + } + + if (!validateSuspendedThread(out, thread)) { + return JNI_TRUE; + } + + env = getEnv(); + + WITH_LOCAL_REFS(env, 1) { + + jvmtiError error = JVMTI_ERROR_NONE; + jint count = 0; + jint depth; + jvmtiMonitorStackDepthInfo *monitors=NULL; + + error = JVMTI_FUNC_PTR(gdata->jvmti,GetOwnedMonitorStackDepthInfo) + (gdata->jvmti, thread, &count, &monitors); + + if (error != JVMTI_ERROR_NONE) { + outStream_setError(out, map2jdwpError(error)); + } else { + int i; + (void)outStream_writeInt(out, count); + for (i = 0; i < count; i++) { + jobject monitor = monitors[i].monitor; + (void)outStream_writeByte(out, specificTypeKey(env, monitor)); + (void)outStream_writeObjectRef(getEnv(), out, monitor); + (void)outStream_writeInt(out,monitors[i].stack_depth); + } + } + if (monitors != NULL) { + jvmtiDeallocate(monitors); + } + + } END_WITH_LOCAL_REFS(env); + + return JNI_TRUE; +} + +static jboolean +forceEarlyReturn(PacketInputStream *in, PacketOutputStream *out) +{ + JNIEnv *env; + jthread thread; + jvalue value; + jbyte typeKey; + jvmtiError error; + + env = getEnv(); + thread = inStream_readThreadRef(env, in); + if (inStream_error(in)) { + return JNI_TRUE; + } + + if (threadControl_isDebugThread(thread)) { + outStream_setError(out, JDWP_ERROR(INVALID_THREAD)); + return JNI_TRUE; + } + + typeKey = inStream_readByte(in); + if (inStream_error(in)) { + return JNI_TRUE; + } + + if (isObjectTag(typeKey)) { + value.l = inStream_readObjectRef(env, in); + error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnObject) + (gdata->jvmti, thread, value.l); + } else { + switch (typeKey) { + case JDWP_TAG(VOID): + error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnVoid) + (gdata->jvmti, thread); + break; + case JDWP_TAG(BYTE): + value.b = inStream_readByte(in); + error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnInt) + (gdata->jvmti, thread, value.b); + break; + + case JDWP_TAG(CHAR): + value.c = inStream_readChar(in); + error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnInt) + (gdata->jvmti, thread, value.c); + break; + + case JDWP_TAG(FLOAT): + value.f = inStream_readFloat(in); + error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnFloat) + (gdata->jvmti, thread, value.f); + break; + + case JDWP_TAG(DOUBLE): + value.d = inStream_readDouble(in); + error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnDouble) + (gdata->jvmti, thread, value.d); + break; + + case JDWP_TAG(INT): + value.i = inStream_readInt(in); + error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnInt) + (gdata->jvmti, thread, value.i); + break; + + case JDWP_TAG(LONG): + value.j = inStream_readLong(in); + error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnLong) + (gdata->jvmti, thread, value.j); + break; + + case JDWP_TAG(SHORT): + value.s = inStream_readShort(in); + error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnInt) + (gdata->jvmti, thread, value.s); + break; + + case JDWP_TAG(BOOLEAN): + value.z = inStream_readBoolean(in); + error = JVMTI_FUNC_PTR(gdata->jvmti,ForceEarlyReturnInt) + (gdata->jvmti, thread, value.z); + break; + + default: + error = AGENT_ERROR_INVALID_TAG; + break; + } + } + { + jdwpError serror = map2jdwpError(error); + if (serror != JDWP_ERROR(NONE)) { + outStream_setError(out, serror); + } + } + return JNI_TRUE; +} + + +void *ThreadReference_Cmds[] = { (void *)14, + (void *)name, + (void *)suspend, + (void *)resume, + (void *)status, + (void *)threadGroup, + (void *)frames, + (void *)getFrameCount, + (void *)ownedMonitors, + (void *)currentContendedMonitor, + (void *)stop, + (void *)interrupt, + (void *)suspendCount, + (void *)ownedMonitorsWithStackDepth, + (void *)forceEarlyReturn + };